crow-misia / libyuv-android

LibYUV for Android

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

webrtc VideoFrame I420 not compatible with

kasperdun opened this issue · comments

Hi, webrtc in your repo io.github.crow-misia.libmediasoup-android:libmediasoup-android
has VideoFrame.Buffer and this one has method toI420() that returns VideoFrame.I420Buffer
But VideoFrame.I420Buffer is not compatible with I420Buffer from libyuv-android repo.

Can you fix it?
May be add methods to convert from webrtc I420 to your I420 and back from your I420 to webrtc I420

I have VideoProcessor that has callback fun onFrameCaptured(inputVideoFrame: VideoFrame?) and I need change this frame every frame.

Now I have to convert VideoFrame.Buffer.toI240() to nv21ByteArray : ByteArray - I have big function for that with code which I don't understand.

Then convert nv21 ByteArray to ByteBuffer, else I can't convert it to your buffers

byteBuffer = ByteBuffer.allocateDirect(nv21ByteArray.size).also {
                it.put(nv21ByteArray)
            }

Then I wrap byteBuffer by your Nv21Buffer

var nv21Buffer: Nv21Buffer = Nv21Buffer.wrap(byteBuffer, frame.buffer.width, frame.buffer.height)

Then I convert nv21Buffer to AbgrBuffer, then convert it to bitmap and do blur by Toolkit from com.google.android.renderscript
And now I need convert blured bitmap back to VideoFrame

            val abgrBuffer: AbgrBuffer = AbgrBuffer.allocate( frame.buffer.width, frame.buffer.height)

            nv21Buffer.convertTo(abgrBuffer)

            val inputBitmap = abgrBuffer.asBitmap()
            Toolkit.blur(inputBitmap, 20).also {
                it.copyPixelsToBuffer(abgrBuffer.asBuffer())
                it.recycle()
            }

            abgrBuffer.convertTo(nv21Buffer)

            val outFrame = VideoFrame(getFrameBufferByNv21Buffer(nv21Buffer), frame.rotation, frame.timestampNs)

            byteBuffer?.clear()
            byteBuffer = null

            nv21Buffer.close()
            abgrBuffer.close()

            return outFrame

This way so hard and I have too much memory leaks with buffers and bitmaps, maybe you can help me with this.
Thanks.

This is not a bug.

Android I420 is formatted as I420, YV12, NV12, or NV21, depending on the device.

ByteBuffer.allocateDirect will not release memory until after GC, so it is no surprise that allocating memory on a frame-by-frame basis will result in insufficient memory.

@crow-misia Ok, maybe you know how I should do it?
Convert VideoFrame.I420Buffer to your buffer without memory leak?

This is not a bug.

Android I420 is formatted as I420, YV12, NV12, or NV21, depending on the device.

ByteBuffer.allocateDirect will not release memory until after GC, so it is no surprise that allocating memory on a frame-by-frame basis will result in insufficient memory.

How do we get than the information which format is used internally? For example when i use camerax capture use case on galaxy S8 it seems to report the image.getFormat() does provide me the information, that this is YUV_420_888, but to convert it correctly i have to use nv21 instead. Does anyone know how to robustly determine the correct image format here?

I reworked my solution, @crow-misia your library super useful thanks.