跳转至

常见功能实现

SDK 提供丰富的音视频 API 来对美颜、水印、音效处理、会控等上层逻辑提供支持

美颜和水印功能

此功能是通过 RongRTCVideoCMSampleBufferCallback 的两上 block 上报的摄像头采集到的 CMSampleBufferRef 数据, 在 UI 层进行同步处理后实现的, 具体实现可参照源码中 ChatGPUImageHandler.m 中的实现, 具体步骤如下:

1、在工程中引用我们提供的 GPUImage.framework (也可以自行编译和导入其他美颜类库) 和 Demo 中 GPUImageBeautyFilter、GPUImageOutputCamera 两个类

2、videoSendBufferCallback 的实现

[RongRTCAVCapturer sharedInstance].videoSendBufferCallback = ^CMSampleBufferRef _Nullable(BOOL valid, CMSampleBufferRef  _Nullable sampleBuffer) {
            CMSampleBufferRef processedSampleBuffer = [self.chatGPUImageHandler onGPUFilterSource:sampleBuffer];
            return processedSampleBuffer;
        };

3、ChatGPUImageHandler 中美颜关键实现

- (CMSampleBufferRef)onGPUFilterSource:(CMSampleBufferRef)sampleBuffer
{
    if (!self.filter || !sampleBuffer)
        return nil;
    // 检查视频帧是否有效
    if (!CMSampleBufferIsValid(sampleBuffer))
        return nil;

    // 调用美颜滤镜方法,使用下一帧作为图片采集的来源
    [self.filter useNextFrameForImageCapture];
    CFRetain(sampleBuffer);

    // 美颜滤镜处理
    [self.outputCamera processVideoSampleBuffer:sampleBuffer];

    CMTime currentTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
    CFRelease(sampleBuffer);
    // 获取美颜之后的视频帧,并构建 CMSampleBufferRef 对象传给 RTCLib,(注意,RTCLib 内部会自动对引用计数做减一操作)
    GPUImageFramebuffer *framebuff = [self.filter framebufferForOutput];
    CVPixelBufferRef pixelBuff = [framebuff pixelBuffer];
    CVPixelBufferLockBaseAddress(pixelBuff, 0);

    CMVideoFormatDescriptionRef videoInfo = NULL;
    CMVideoFormatDescriptionCreateForImageBuffer(NULL, pixelBuff, &videoInfo);

    CMSampleTimingInfo timing = {currentTime, currentTime, kCMTimeInvalid};

    CMSampleBufferRef processedSampleBuffer = NULL;
    CMSampleBufferCreateForImageBuffer(kCFAllocatorDefault, pixelBuff, YES, NULL, NULL, videoInfo, &timing, &processedSampleBuffer);

    if (videoInfo == NULL)
        return nil;

    CFRelease(videoInfo);
    CVPixelBufferUnlockBaseAddress(pixelBuff, 0);
    // 视频帧返回给 RTCLib 进行传输
    return processedSampleBuffer;
}

查看 美颜 Demo

会议控制

会控主要通过设置房间属性,标识当前用户权限级别,再配合通道消息发送接口的 API 来完成,以下为会控功能的实现逻辑,具体的代码需要 App 来实现:

一、确定会议主持人:

假定第一个加入房间的用户作为主持人,负责控制音视频房间的所有人员角色,需要调用设置房间属性,给当前房间设置主持人属性,权限等信息,同时选择发送一条消息到房间中让房间成员知道。 二、房间成员申请升级音视频权限:

第二个加入房间的人员为普通用户,先获取此房间属性,判断房间主持人。

使用通道消息发送接口,向房间中发送一条请求发言或请求视频通话的指令消息(该消息由开发者自定义)。

主持人收到房间内的指令消息后,判断消息类型,执行同意或拒绝操作,同时将操作结果通过通道消息发送接口,发送到房间中。

用户收到主持人操作后的消息,判断消息类型,如消息指令为通过则调用发布流接口发布音视频流,远端用户收到流之后订阅即可

三、主持人调整房间用户音视频权限:

主持人如果不想房间中某一个人发言或者发布视频,可以通过[通道消息发送]接口,向房间中发送一条消息,消息中需要指定被调整用户 ID 及此条消息的指令类型(如:禁止发言)。

房间中用户收到此条消息后,判断是否为对自已的权限操作,如是对自已权限的调整的指令消息,则根据指令对本端设备进行相关权限设置(如:关闭本地摄像头或者麦克风),否则抛弃此消息,达到资源控制的逻辑。

远端用户收到禁用资源的命令之后自动关闭本地摄像头或者麦克风,达到资源控制的逻辑

说明:

会控功能主要是利用发布控制类消息,设置房间属性和成员属性的 API 来完成,合理利用这几个 API 即可实现会控功能。详细查参考 SealClass 开源项目

白板功能实现

融云的 SealClass 开源项目中,实现了白板功能,可供开发者进行参考。