Use two DjiCodecManager at the same time - android

My drone matrice 210.
DJI Android SDK 4.7.1
Device CrystalSky CS785, Android 5.1.1
I shuld display video stream from two camers at the same time, like a DJI Pilot.
My solutions:
I create two diferance DjiCodecManager, and use it in diferent VideoFeeder callbaks.
DJICodecManager primaryDJICodecManager = new DJICodecManager(Activity,
pramirySurfaceTexture,
pramirySurfaceTextureTextureWidth,
pramirySurfaceTextureTextureHeight);
DJICodecManager secondaryDJICodecManager = new DJICodecManager(Activity,
secondarySurfaceTexture,
secondarySurfaceTextureTextureWidth,
secondarySurfaceTextureTextureHeight);
pramirySurfaceTexture.setOnFrameAvailableListener(new SurfaceTexture.OnFrameAvailableListener() {
#Override
public void onFrameAvailable(SurfaceTexture surfaceTexture) {
surfaceTexture.updateTexImage();
}
});
secondarySurfaceTexture.setOnFrameAvailableListener(new SurfaceTexture.OnFrameAvailableListener() {
#Override
public void onFrameAvailable(SurfaceTexture surfaceTexture) {
surfaceTexture.updateTexImage();
}
});
VideoFeeder.VideoFeed videoFeed = VideoFeeder.getInstance().getPrimaryVideoFeed();
VideoFeeder.VideoFeed secondaryVideoFeed = VideoFeeder.getInstance().getSecondaryVideoFeed();
secondaryVideoFeed.setCallback(new VideoFeeder.VideoDataCallback() {
#Override
public void onReceive(byte[] videoBuffer, int size) {
if (DjiManagers.mSecondaryCodecManager != null) {
secondaryDJICodecManager.sendDataToDecoder(videoBuffer, size);
}
}
});
videoFeed.setCallback(new VideoFeeder.VideoDataCallback() {
#Override
public void onReceive(byte[] videoBuffer, int size) {
if (DjiManagers.mCodecManager != null) {
primaryDJICodecManager.sendDataToDecoder(videoBuffer, size);
}
}
});
But the pramirySurfaceTexture callback does not work. And on the second texture, an image from different cameras (color and grayscale (I use a thermal imaging camera)) appears alternately, but most often the texture is green.
Is it possible to create and use two DJICodecManager?
And if not, how can I show the video stream simultaneously?

DJI support answered me.
To use two DJICodecManafers. You must use the other constructor:
primaryDJICodecManager = new DJICodecManager(Activity,
djiSdkWrapper.getSurfaceTexture(),
djiSdkWrapper.getSurfaceTextureWidth(),
djiSdkWrapper.getSurfaceTextureHeight(),
videoStreamSource);
where videoStreamSource it's one of this:
UsbAccessoryService.VideoStreamSource.Camera
UsbAccessoryService.VideoStreamSource.Fpv
UsbAccessoryService.VideoStreamSource.SecondaryCamera
And when you send data to decoding you must use onother sendDataToDecode methond:
primaryDJICodecManager.sendDataToDecoder(array, size, index);
where intdex it's one of this:
UsbAccessoryService.VideoStreamSource.Camera.getIndex()
UsbAccessoryService.VideoStreamSource.Fpv.getIndex()
UsbAccessoryService.VideoStreamSource.SecondaryCamera.getIndex()
In accordance with what you specified when creating DJICodecManager.

Related

Xamarin Forms - Take photograph without any user interaction

I have a requirement to take a photograph of a user in Xamarin Forms without them having to press the shutter button. For example, when the app launches it should show a preview and count down from 5 seconds (to give the user chance to get in position) then take a picture automatically.
I have tried the Xamarin Media Plugin library however this stackoverflow post and this GitHub issue state that this feature is not a supported.
I have seen a number of dead discussions such as this with people asking similar questions without resoltion.
I tried the LeadTools AutoCapture sample but this only seems to work for documents/text and not people (unless I am missing something??).
I am now working my way through the Camera2Basic sample which is quite old and only targets Android via android.hardware.camera2.
Are there any samples out there (or 3rd party libraries) that can acheive this requirement? Ideally I would like it to be cross platform (iOS and Android) but currently the main focus is Android.
You can create the Custom View Renderer on Android to achieve that.
And based on this offical sample is more convenient, just modify code as follow can achieve your wants.
This official sample can preview camera view in Xamarin Forms App, we just need to add a Timer to call the Frame from Camera after 5 seconds.The modified Renderer code as follow:
public class CameraPreviewRenderer : ViewRenderer<CustomRenderer.CameraPreview, CustomRenderer.Droid.CameraPreview>, Camera.IPreviewCallback
{
CameraPreview cameraPreview;
byte[] tmpData;
public CameraPreviewRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<CustomRenderer.CameraPreview> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
// Unsubscribe
cameraPreview.Click -= OnCameraPreviewClicked;
}
if (e.NewElement != null)
{
if (Control == null)
{
cameraPreview = new CameraPreview(Context);
SetNativeControl(cameraPreview);
}
Control.Preview = Camera.Open((int)e.NewElement.Camera);
// Subscribe
cameraPreview.Click += OnCameraPreviewClicked;
}
}
protected override void OnAttachedToWindow()
{
base.OnAttachedToWindow();
// call the timer method to get the current frame.
Device.StartTimer(new TimeSpan(0, 0, 5), () =>
{
// do something every 5 seconds
Device.BeginInvokeOnMainThread(() =>
{
Console.WriteLine("get data"+tmpData);
// using MessagingCenter to pass data to forms
MessagingCenter.Send<object, byte[]>(this, "CameraData", tmpData);
cameraPreview.Preview.StopPreview();
cameraPreview.IsPreviewing = false;
// interact with UI elements
});
return false; // runs again, or false to stop
});
}
void OnCameraPreviewClicked(object sender, EventArgs e)
{
if (cameraPreview.IsPreviewing)
{
cameraPreview.Preview.StopPreview();
cameraPreview.IsPreviewing = false;
}
else
{
cameraPreview.Preview.SetPreviewCallback(this);
cameraPreview.Preview.StartPreview();
cameraPreview.IsPreviewing = true;
}
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
Control.Preview.Release();
}
base.Dispose(disposing);
}
// get frame all the time
public void OnPreviewFrame(byte[] data, Camera camera)
{
tmpData = data;
}
}
Now, Xamarin Forms can receive the data from MessagingCenter:
MessagingCenter.Subscribe<object, byte[]>(this, "CameraData", async (sender, arg) =>
{
MemoryStream stream = new MemoryStream(arg);
if (stream != null)
{
//image is defined in Xaml
image.Source = ImageSource.FromStream(() => stream);
}
});
image is defined in XAML: <Image x:Name="image" WidthRequest="200" HeightRequest="200"/>

Using .getSpeedLimit() also makes warning sounds . How to Override?

Unable to override Here SDK to disable sound effect on the onSpeedExceeded event.
Using the Here Developer tutorial, (https://developer.here.com/blog/android-premium-sdk-speed-limit-warning-example), I succeeded in running the sample app. But...
While driving, when I exceed the speed limit, there is a doot doot doot. I want to override this behaviour as I intend to use my own sounds.
I guessed that I might override the code by creating a NavigationManager.SpeedWarningListener. Unfortunately I can not disable or defeat the 'onSpeedExceeded' sound effects.
NavigationManager.SpeedWarningListener speedWarningListener = new NavigationManager.SpeedWarningListener() {
#Override
public void onSpeedExceeded(String s, float v) {
//super.onSpeedExceeded(s, v);
//Log.v(Global.TAG, "onSpeedExceeded");
Global.SpeedLimitExceeded = true;
}
#Override
public void onSpeedExceededEnd(String s, float v) {
//super.onSpeedExceededEnd(s, v);
//Log.v(Global.TAG, "onSpeedExceededEnd");
Global.SpeedLimitExceeded = false;
}
};
EDITED ANSWER: This method needs to be amended to stop the speed warning:
private void startNavigationManager() {
NavigationManager.Error navError = NavigationManager.getInstance().startTracking();
// added by suggestion from stackoverflow
NavigationManager.getInstance().stopSpeedWarning();
if (navError != NavigationManager.Error.NONE) {
Log.d(Global.TAG, "NavigationManager: false");
//handle error navError.toString());
} else {
//Log.d(Global.TAG, "NavigationManager: true");
}
}
Please set speedWarningEnabled accordingly for NMANavigationManager
navigationManager:didUpdateSpeedingStatus:forCurrentSpeed:speedLimit: will be sent to the delegate when speeding is detected or when a correction is made.
Also refer http://developer.here.com/documentation/ios-premium/api_reference_jazzy/Classes/NMANavigationManager.html

Use webrtc VideoCapturer without peerconnection?

Is it possible to use webrtc VideoCapturer without peerconnection?
We have a working androidapp app (from examples/androidapp). We have taken following code from the working app into a separate activity where we use camera capturer directly without creating peerconnection. We create a video capturer (camera2) using an instance of CapturerObserver and then try to render it to org.webrtc.SurfaceViewRenderer. Below is the code.
As expected, onFrameCaptured of the CapturerObserver is being called multiple times with valid videoFrame object. From there, we pass it to SurfaceViewRenderer. However, video does not render and SurfaceViewRenderer remains black.
Is that a correct way of using VideoCapturer and SurfaceViewRenderer? Does it require any format conversion before sending to SurfaceViewRenderer?
private class MyCapturerObserver implements CapturerObserver {
#Override
public void onCapturerStarted(boolean b) {
Log.e(TAG, "capture started: " + b);
}
#Override
public void onCapturerStopped() {
Log.e(TAG, "capture stopped");
}
#Override
public void onFrameCaptured(final VideoFrame videoFrame) {
//fullscreenRenderer.onFrame(videoFrame);
runOnUiThread(new Runnable() {
#Override
public void run() {
fullscreenRenderer.onFrame(videoFrame);
}
});
}
}
capturer = createVideoCapturer();
captureObserver = new MyCapturerObserver();
surfaceTextureHelper =
SurfaceTextureHelper.create("CaptureThread", eglBase.getEglBaseContext());
capturer.initialize(surfaceTextureHelper, getApplicationContext(), captureObserver);
capturer.startCapture(1280, 720, 30);
Use factory.createVideoSource. You can use it before creating peerconnection. You can refer source code in the PeerConnectionClient.java
public VideoTrack createVideoTrack(VideoCapturer capturer) {
surfaceTextureHelper = SurfaceTextureHelper.create("CaptureThread", rootEglBase.getEglBaseContext());
videoSource = factory.createVideoSource(capturer.isScreencast());
capturer.initialize(surfaceTextureHelper, appContext, videoSource.getCapturerObserver());
capturer.startCapture(videoWidth, videoHeight, videoFps);
localVideoTrack = factory.createVideoTrack(VIDEO_TRACK_ID, videoSource);
localVideoTrack.setEnabled(renderVideo);
localVideoTrack.addSink(localRender);
return localVideoTrack;
}

DJI Phantom 3 camera having problems with openCV in Android Studio

I am trying to get the camera from DJI and use OpenCV with it, the problem relies on how to set OpenCv to get the video previewer that DJI is recording while the drone is active. The drone is actually working on streaming the video to my cellphone but when I try to use my OpenCV code to get the video preview id from the layout in the project I have in Android Studio, the app crashes every time I try to go to the camera view part of the app. Here is code that I use to initialize the OpenCv object to the video previewer captured by the DJI camera.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.activity_main);
openCvCameraView = (JavaCameraView)findViewById(R.id.video_previewer_surface);
openCvCameraView.setVisibility(SurfaceView.VISIBLE);
openCvCameraView.setCvCameraViewListener(this);
initUI();
// The callback for receiving the raw H264 video data for camera live view
mReceivedVideoDataCallBack = new CameraReceivedVideoDataCallback() {
#Override
public void onResult(byte[] videoBuffer, int size) {
if(mCodecManager != null){
// Send the raw H264 video data to codec manager for decoding
mCodecManager.sendDataToDecoder(videoBuffer, size);
}else {
Log.e(TAG, "mCodecManager is null");
}
}
};
DJICamera camera = FPVDemoApplication.getCameraInstance();
if (camera != null) {
camera.setDJICameraUpdatedSystemStateCallback(new DJICamera.CameraUpdatedSystemStateCallback() {
#Override
public void onResult(CameraSystemState cameraSystemState) {
if (null != cameraSystemState) {
int recordTime = cameraSystemState.getCurrentVideoRecordingTimeInSeconds();
int minutes = (recordTime % 3600) / 60;
int seconds = recordTime % 60;
final String timeString = String.format("%02d:%02d", minutes, seconds);
final boolean isVideoRecording = cameraSystemState.isRecording();
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
recordingTime.setText(timeString);
/*
* Update recordingTime TextView visibility and mRecordBtn's check state
*/
if (isVideoRecording){
recordingTime.setVisibility(View.VISIBLE);
}else
{
recordingTime.setVisibility(View.INVISIBLE);
}
}
});
}
}
});
}
}
It may be that you are using JavaCameraView which according to this post: What is the difference between `opencv.android.JavaCameraView` and `opencv.android.NativeCameraView`
The org.opencv.android.JavaCameraView class is implemented inside OpenCV library. It is inherited from CameraBridgeViewBase, that extends SurfaceView and uses standard Android camera API.
You are using the video feed from the DJI SDK and not the phone's hardware camera so that may explain the crash as when you invoke OpenCV it is in conflict with the incoming feed.
As I don't have a drone, my only suggestion is to look at the other DJI sample on Video Stream Decoding
https://github.com/DJI-Mobile-SDK-Tutorials/Android-VideoStreamDecodingSample
And instead of decoding the stream send the data to OpenCV perhaps in JNI (C/C++).

Gdx.input.justTouched() is not working on all devices

I am developing a game in LibGdx for android device. I could see a strange issue in using Gdx.input.justTouched(). It is working in some device and not in some device. Could you please help me if my code needs any correction?
#Override
public void create() {
Gdx.input.setInputProcessor(this);
Gdx.input.setCatchBackKey(true);
}
public void render(SpriteBatch sb) {
if (Gdx.input.justTouched()){
System.out.println("inside : " );
dragNew = new Vector2(Gdx.input.getX(), Gdx.input.getY());
dragOld = dragNew;
}
}

Categories

Resources