集成 RTCLib 的用户如何接入使用第三方美颜水印

RTCLib 版本 >= 5.1.14

针对集成 RongRTCLib 版本 >= 5.1.14 的用户,使用下面方法接入:

  1. 以 CVPixelBufferRef 初始化 videoFrame:

    [RCRTCEngine sharedInstance].defaultVideoStream.videoFrameSendCallback = ^RCRTCVideoFrame * _Nullable(BOOL valid, RCRTCVideoFrame * _Nullable videoFrame) {
            if (!videoFrame) {
                return NULL;
            }
            CVPixelBufferRef pixelBuffer = videoFrame.pixelBuffer;
            
            // 在这里对pixelBuffer做处理...
            CVPixelBufferRef newPixelBuffer = <#...#>
            
            // 用pixelBuffer重新生成一个videoFrame返回
            RCRTCVideoFrame *newVideoFrame = [[RCRTCVideoFrame alloc] initWithPixelBuffer:pixelBuffer
                                                                              timeStampNs:videoFrame.timeStampNs
                                                                                 rotation:videoFrame.rotation];
            /*
             注意:
             1.如果newPixelBuffer是用户自己创建的请在这里做一次release,因为RCRTCVideoFrame内部会持有
             pixelBuffer,所以这里如果忘记release会导致内存泄漏。
             2.如果newPixelBuffer就是原pixelBuffer,不需要release
             3.请保证newPixelBuffer的颜色空间格式是NV12格式,否则会生成RCRTCVideoFrame失败
             */
            CVBufferRelease(newPixelBuffer);
            return newVideoFrame;
        };
    
  2. 以 CMSampleBufferRef 初始化 videoFrame:

    [RCRTCEngine sharedInstance].defaultVideoStream.videoFrameSendCallback = ^RCRTCVideoFrame * _Nullable(BOOL valid, RCRTCVideoFrame * _Nullable videoFrame) {
            if (!videoFrame) {
                return NULL;
            }
            CVPixelBufferRef pixelBuffer = videoFrame.pixelBuffer;
            
            // 在这里对pixelBuffer做处理...
            CVPixelBufferRef newPixelBuffer = <#...#>
            
            // 使用 newPixelBuffer 生成一个 CMSampleBufferRef
            CMSampleTimingInfo timingInfo;
            timingInfo.presentationTimeStamp = CMTimeMake(videoFrame.timeStampNs, 1000000000);
            CMVideoFormatDescriptionRef videoInfo = NULL;
            OSStatus result = CMVideoFormatDescriptionCreateForImageBuffer(NULL, newPixelBuffer, &videoInfo);
            if (result != noErr || !videoInfo) {
                return videoFrame;
            }
            CMSampleBufferRef sampleBuffer = NULL;
            result = CMSampleBufferCreateForImageBuffer(kCFAllocatorDefault,
                                                        newPixelBuffer,
                                                        true, NULL, NULL,
                                                        videoInfo,
                                                        &timingInfo,
                                                        &sampleBuffer);
            if (videoInfo) {
                CFRelease(videoInfo);
            }
            if (result != noErr || !sampleBuffer) {
                return videoFrame;
            }
            CFArrayRef attachments = CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, YES);
            CFMutableDictionaryRef dict = (CFMutableDictionaryRef)CFArrayGetValueAtIndex(attachments, 0);
            CFDictionarySetValue(dict, kCMSampleAttachmentKey_DisplayImmediately, kCFBooleanTrue);
            /*
             注意:
             1.如果newPixelBuffer是用户自己创建的请在这里做一次release,否则会导致内存泄漏
             2.如果newPixelBuffer就是原pixelBuffer,不需要release
             */
            CVBufferRelease(newPixelBuffer);
            
            // 用sampleBuffer重新生成一个videoFrame返回
            RCRTCVideoFrame *newVideoFrame = [[RCRTCVideoFrame alloc] initWithSampleBuffer:sampleBuffer
                                                                                  rotation:videoFrame.rotation];
            CFRelease(sampleBuffer);
            
            return newVideoFrame;
        };
    

RTCLib 版本 < 5.1.14 以及 4.X

针对集成 RongRTCLib 版本 < 5.1.14 以及使用 4.X 的用户,使用下面方法接入:

[RCRTCEngine sharedInstance].defaultVideoStream.videoSendBufferCallback =^CMSampleBufferRef _Nullable(BOOL valid, CMSampleBufferRef  _Nullable sampleBuffer) {
    if ( !strongSelf.openBeauty&&!strongSelf.openWaterMark ) {
        return sampleBuffer;
    }
    // 返回处理后的 CMSampleBufferRef 数据
    CMSampleBufferRef processedSampleBuffer = 处理后数据;
    return processedSampleBuffer ?: sampleBuffer;};