crow-misia / libmediasoup-android

libmediasoupclient for Android
Apache License 2.0
9 stars 9 forks source link

VideoSource is private so can't add VideoProcessor #9

Closed kasperdun closed 1 year ago

kasperdun commented 1 year ago

Hi, can you provide videoSource from RTCLocalVideoManager (RTCLocalVideoManagerImpl) as public? I need to add VideoProcessor to it

like:

localVideoManager = componentFactory.createVideoManager()

localVideoManager.initTrack(peerConnectionFactory, mediaConstraintsOption, context)

localVideoManager.videoSource.setVideoProcessor(..)
kasperdun commented 1 year ago

And one more question Can you help me with transform VideoFrame.Buffer or VideoFrame.I420Buffer to I420Buffer from your lib libyuv-android

VideoProcessor callback providing frame: VideoFrame and I can get VideoFrame.I420Buffer from that, but it is not compatible with your I420Buffer from libyuv-android. Please, I really need this conversation ability

crow-misia commented 1 year ago

RTCLocalVideoManagerImpl is a class in libwebrtc-ktx, not in this library.

libwebrtc-ktx 1.7.0 has been released and the implementation of RTCLocalVideoManager has been changed. You will be able to access source, but this instance will be nullable, so other modifications are needed

libyuv-android is not intended to be used with WebRTC, so I have not checked that it works, but you may use I420Buffer.wrap method.

kasperdun commented 1 year ago

@crow-misia I can't use I420Buffer.wrap method WebRtc frame I420 buffer is not ByteBuffer and no way found to get ByteBuffer from it I know you are busy but maybe you can try convert it? You have much more experience with it

crow-misia commented 1 year ago

libyuv-android 0.25.0 was released. You can convert it as follows.

            localVideoManager?.source?.setVideoProcessor(object : VideoProcessor {
                private var sink: VideoSink? = null

                override fun onCapturerStarted(success: Boolean) {
                }

                override fun onCapturerStopped() {
                }

                override fun onFrameCaptured(videoFrame: VideoFrame) {
                    val videoI420 = videoFrame.buffer.toI420()!!
                    val i420Buffer = I420Buffer.wrap(
                        planeY = PlanePrimitive(videoI420.strideY, videoI420.dataY),
                        planeU = PlanePrimitive(videoI420.strideU, videoI420.dataU),
                        planeV = PlanePrimitive(videoI420.strideV, videoI420.dataV),
                        width = videoI420.width,
                        height = videoI420.height,
                    )
                    i420Buffer.drawRect(300, 300, 100, 100, 255, 0, 0)
                    val newVideoFrame = VideoFrame(
                        JavaI420Buffer.wrap(
                            i420Buffer.width, i420Buffer.height,
                            i420Buffer.planeY.buffer, i420Buffer.planeY.rowStride,
                            i420Buffer.planeU.buffer, i420Buffer.planeU.rowStride,
                            i420Buffer.planeV.buffer, i420Buffer.planeV.rowStride,
                            null
                        ),
                        videoFrame.rotation,
                        videoFrame.timestampNs,
                    )
                    sink?.onFrame(newVideoFrame)
                    videoI420.release()
                }

                override fun setSink(videoSink: VideoSink?) {
                    this.sink = videoSink
                }
            })
kasperdun commented 1 year ago

@crow-misia It works. You are the best, thanks

crow-misia commented 1 year ago

@kasperdun

Added the following line Without it, memory leaks will occur.

videoI420.release()