DJI-Mobile-SDK-Tutorials / Android-VideoStreamDecodingSample

This sample project demonstrates how to use FFmpeg for video frame parsing and to use MediaCodec for hardware decoding on DJI Products.
MIT License
169 stars 80 forks source link

Q: yuv decoding and preview - mutually exclusive? #53

Open neilyoung opened 5 years ago

neilyoung commented 5 years ago

Not a bug, just a question: I played a bit with the DJIVideoStreamDecoding example. I noticed, that whenever yuv decoding is switched on

 mCodecManager.enabledYuvData(true);
 mCodecManager.setYuvDataCallback(this);

neither of the views (texture, surface) is updated anymore.

This observation is backed up by this series of traces after the switch above:

D/SurfaceUtils: disconnecting from surface 0x7d6e1a6010, reason disconnectFromSurface
D/DJIDecodeServer: releaseDecoder() end
E/libEGL: call to OpenGL ES API with no current context (logged once per thread)
E/GLContextMgr17: OpenGL destoryed
E/GLYUVSurface: OpenGL destoryed
E/Lightbridge: startStream videoCtlobjet == NULL
D/DJIVideoDecoder: stopVideoDecoder()

Does that mean I can't video preview and yuv decode at the same time? Then I'm wondering, how I could flight if I just want to obtain the video for post processing purposes.

neilyoung commented 5 years ago

To answer my own question: Yes it is.

0xm1nam0 commented 4 years ago

I think so yea

olmanqj commented 3 years ago

I have the same issue. Any workaround?

I guess that if there is a way to manually render the decoded data (ByteBuffer) back into the Texture View it would do the job.

neilyoung commented 3 years ago

This is what I did

olmanqj commented 3 years ago

If anyone is struggling with this, what I did to see the video fee in screen and decoding frames at the same time is to convert the result byte buffer from decoding into a BitMap, then call to render the BitMap into a ImageView.

Something like this:

ByteArrayOutputStream out = new ByteArrayOutputStream();
YuvImage yuvImage = new YuvImage(bytes, ImageFormat.NV21, width, height, null);
yuvImage.compressToJpeg(new Rect(0, 0, width, height), 100, out);
byte[] imageBytes = out.toByteArray();
Bitmap image = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);

// With an ImageView from your layout
imageView.setImageBitmap(image);

Taken from stackoverflow

neilyoung commented 3 years ago

That is surely possible but not the most performant solution.

0xm1nam0 commented 3 years ago
        DJICodecManager mCodecManager = new DJICodecManager(mContext, new SurfaceTexture(-1), 1920, 1080);
        mCodecManager.enabledYuvData(true);
        mCodecManager.setYuvDataCallback(yuvDataCallback);
jeryini commented 3 years ago

Hello @0xm1nam0 !

But as mentioned above if you enable YUV decoding, it doesn't render it anymore to surface texture. How is therefore above snippet relevant?

zeusalmighty717 commented 1 year ago

This is what I did

@neilyoung Could you share more details on this?

I need to convert raw data to YUV data while keeping the preview working. I think the only option here is to do this manually rather than rely on DJI SDK.

If you could share some code or references to convert raw bytes from DJI SDK to YUV buffer then it would be really helpful.

neilyoung commented 1 year ago

I need to convert raw data to YUV data while keeping the preview working. I think the only option here is to do this manually rather than rely on DJI SDK.

What do you mean by "raw data"?

zeusalmighty717 commented 1 year ago

I need to convert raw data to YUV data while keeping the preview working. I think the only option here is to do this manually rather than rely on DJI SDK.

What do you mean by "raw data"?

Byte are received from VideoDataListener

neilyoung commented 1 year ago

So then it is H.264. You can use the DJI SDK to decode and convert it to YUV. For display (due to the mutual exclusion mentioned above) you might consider to use GLE20 code and a GLSurfaceView. Sorry, can't share code.

zeusalmighty717 commented 1 year ago

So then it is H.264. You can use the DJI SDK to decode and convert it to YUV. For display (due to the mutual exclusion mentioned above) you might consider to use GLE20 code and a GLSurfaceView. Sorry, can't share code.

When you say use DJI SDK to convert the code do you mean using DJICodecManager.YuvDataCallback?

Is it possible to the conversion manually rather that using DJI SDK method? I want to keep using FPVWidget to show drone feed.

neilyoung commented 1 year ago

Is it possible to the conversion manually rather that using DJI SDK method? I want to keep using FPVWidget to show drone feed.

This is not conversion, this is H.264 decoding. You can do this by using Android MediaCodec API https://developer.android.com/reference/android/media/MediaCodec

Never did that