自定义视频采集和渲染

最近更新时间:2022-09-20 05:17:40

功能介绍

除了音视频 SDK 音视频模块内部默认的采集和渲染外,下场景需求默认视频模块可能无法满足需求:

  • 有自己的音频或者视频模块
  • 希望推送非采集的视频源(如屏幕数据)
  • 有自己的美颜或经过前处理后的数据
  • 有自己视频采集设备管理

anyRTC 自采集和渲染包括 Push 和 mediaIO 两种自定义视频采集方式:

**Push 方式:**调用 setExternalVideoSource 方法告知 SDK 使用外置的视频源。外置视频源通过 pushVideoFrame 发送给 SDK 。你可以使用自渲染模块对采集的视频进行渲染。

anyRTC SDK 对该模式不在支持渲染,渲染模块通过自采集自行处理;使用该模式无法切换回 SDK 采集。

**mediaIO 方式:**调用 setVideoSource 方法告知 SDK 使用外置的视频源,外置视频源通过 consumeRawVideoFrame 发送给 SDK。你可以使用自渲染模块对采集的视频进行渲染。

C++ SDK 暂不提供专门的自定义视频渲染接口。你必须通过自采集的方式实现自渲染功能。即,自渲染模块的视频帧输入只能从自采集模块获取。

实现方法(Push 方式)

操作步骤

自定义视频采集和播放前,请确保已实现基本的音视频功能。

  1. joinChannelByToken 前通过调用 setExternalVideoSource 指定外部视频采集设备。
  2. 指定外部采集设备后,开发者自行管理视频数据采集和处理。
  3. 完成视频数据处理后,再通过 pushExternalVideoFrame 发送给 SDK 进行后续操作。

为满足实际使用需求,你可以在将视频数据发送回 SDK 前,通过 ARVideoFrame 修改视频数据。比如,设置 rotation 为 180,使视频帧顺时针旋转 180 度。

API 调用时序

示例代码

// Swift
// 推入数据类型为 CVPixelBufferRef
let videoFrame = ARVideoFrame()
videoFrame.format = 12
// [NSDate date].timeIntervalSince1970 为当前时间戳;1000 表示每秒钟 1000 帧
videoFrame.time = CMTimeMakeWithSeconds([NSDate date].timeIntervalSince1970, 1000)
videoFrame.textureBuf = "Your CVPixelBufferRef"
videoFrame.ratation = 0

// 推入数据类型为 rawData
let videoFrame = ARVideoFrame()
videoFrame.format = "your data fromat"
// [NSDate date].timeIntervalSince1970 为当前时间戳;1000 表示每秒钟 1000 帧
videoFrame.time = CMTimeMakeWithSeconds([NSDate date].timeIntervalSince1970, 1000)
videoFrame.strideInPixels = "your stride"
videoFrame.height = "your height"
videoFrame.dataBuf = "your rawData"
videoFrame.ratation = 0

rtcKit.pushExternalVideoFrame(videoFrame)
// Objective-C
// 推入数据类型为 CVPixelBufferRef
ARVideoFrame *videoFrame = [[ARVideoFrame alloc] init];
videoFrame.format = 12;
// [NSDate date].timeIntervalSince1970 为当前时间戳;1000 表示每秒钟 1000 帧
videoFrame.time = CMTimeMakeWithSeconds([NSDate date].timeIntervalSince1970, 1000);
videoFrame.textureBuf = "Your CVPixelBufferRef";
videoFrame.ratation = 0;

// 推入数据类型为 rawData
ARVideoFrame *videoFrame = [[ARVideoFrame alloc] init];
videoFrame.format = "your data fromat";
// [NSDate date].timeIntervalSince1970 为当前时间戳;1000 表示每秒钟 1000 帧
videoFrame.time = CMTimeMakeWithSeconds([NSDate date].timeIntervalSince1970, 1000);
videoFrame.strideInPixels = "your stride";
videoFrame.height = "your height";
videoFrame.dataBuf = "your rawData";
videoFrame.ratation = 0;

[rtcKit pushExternalVideoFrame: videoFrame];

API 参考

实现方法(mediaIO 方式)

anyRTC 通过 MediaIO 提供 ARVideoSourceProtocol 协议和 ARVideoFrameConsumer 类,你可以通过该类设置采集的视频数据格式,并控制外部视频的采集过程。

操作步骤

  1. 实现ARVideoSourceProtocol协议。anyRTC 通过 ARVideoSourceProtocol

    协议下的各回调设置视频数据格式,并控制采集过程:

    • 收到 bufferType 回调后,在该回调的返回值中指定想要采集的视频数据格式;

    • 收到 shouldInitialize 回调后,保存该回调中的 ARVideoFrameConsumer anyRTC ARVideoFrameConsumer 对象发送和接收自定义的视频数据;

    • 收到 shouldStart 回调后,通过 ARVideoFrameConsumer 对象向 SDK 发送视频帧;

      为满足实际使用需求,你可以在将视频帧发送回 SDK 前,修改 ARVideoFrameConsumer 中视频帧参数,如 rotation。

    • 收到 shouldStop 回调后,停止使用 ARVideoFrameConsumer 对象向 SDK 发送视频帧;

    • 收到 shouldDispose 回调后,释放 ARVideoFrameConsumer 对象。

  2. 继承实现的 ARVideoSourceProtocol 协议,构建一个自定义的视频源对象。

  3. 调用 setVideoSource 方法,将自定义的视频源对象设置给 ARtcEngineKit。

  4. 根据场景需要,调用 startPreview、joinChannelByToken 等方法预览或发送自定义采集的视频数据。

API 调用时序

参考下图时序使用 MediaIO 在你的项目中实现自定义视频采集。

示例代码

  1. 遵守 ARVideoSourceProtocol 协议, 并实现接口,构建自定义的 Video Source 类。

         // 协议中的变量
         var consumer: ARVideoFrameConsumer?
         // 调用 Consumer 的方法,将视频数据推入 anyRTC SDK
    
          // 推入 rawData 类型
          consumer.consumeRawData("your rawData", withTimestamp: CMTimeMake(1, 15), format: "your data format", size: size, rotation: rotation)
    
          // 推入 CVPixelBuffer
          consumer.consumePixelBuffer("your pixelBuffer", withTimestamp: CMTimeMake(1, 15), rotation: rotation)
    
         // 协议中的方法
         // 1. 视频采集使用的 Buffer 类型
         func bufferType() -> ARVideoBufferType {
                 return bufferType
         }
    
         // 2. 在初始化视频源(shouldInitialize)中, 初始化自定义的 Video Source
         func shouldInitialize() -> Bool {
         }
    
         // 3. 自定义视频源开始采集视频数据,并通过 Consumer 推入视频数据
         func shouldStart() {
         }
    
         // 4. 自定义视频源停止采集视频数据
         func shouldStop() { 
         }
    
         // 5. 在释放自定义视频源
         func shouldDispose() {
         }
    
     // Objective-C
         // 协议中的变量
         @synthesize consumer;
         // 调用 Consumer 的方法,将视频数据推入 anyRTC SDK
    
         // 推入 rawData 类型
         [consumer consumeRawData: "your rawData" withTimestamp: CMTimeMake(1, 15) format: "your data format" size: size rotation: rotation];
    
         // 推入 CVPixelBuffer
         [consumer consumePixelBuffer: "your pixelBuffer" withTimestamp: CMTimeMake(1, 15) rotation: rotation];
    
         // 协议中的方法
         // 1. 视频采集使用的 Buffer 类型
         - (ARVideoBufferType)bufferType {
                 return ARVideoBufferTypePixelBuffer;
         }
    
         // 2. 在初始化视频源(shouldInitialize)中, 初始化自定义的 Video Source
         - (BOOL)shouldInitialize {
                 return YES;
         }
    
         // 3. 自定义视频源开始采集视频数据,并通过 Consumer 推入视频数据
         - (void)shouldStart {
         }
    
         // 4. 自定义视频源停止采集视频数据
         - (void)shouldStop {
         }
    
         // 5. 在释放自定义视频源
         - (void)shouldDispose {
         }
    
  2. 将遵守了 ARVideoSourceProtocol 协议的自定义 VideoSource 对象设给 ARtcEngineKit。

     // Swift
     rtcKit.setVideoSource(videoSource)
    
     // Objective-C
     [rtcKit setVideoSource: videoSource];
    

API 参考

自定义渲染器

通过 MediaIO 采集到的视频数据,还可以搭配 anyRTC 的 ARVideoSinkProtocol 协议使用,实现自定义渲染功能。

操作步骤

  1. 实现 ARVideoSinkProtocol协议。anyRTC 通过 ARVideoSinkProtocol

    协议下的各回调设置视频数据格式,并控制渲染过程:

    • 收到 bufferType 和 pixelFormat 回调后,在对应回调的返回值中设置你想要渲染的数据类型;
    • 根据收到的 shouldInitialize、shouldStart、shouldStop、shouldDispose 回调,控制视频数据的渲染过程;
    • 实现一个对应渲染数据类型的 ARVideoFrameConsumer 对象,以获取视频数据。
  2. 继承实现的 ARVideoSinkProtocol 协议,构建一个自定义的渲染器。

  3. 调用 setLocalVideoRenderer 或 setRemoteVideoRenderer,用于本地渲染或远端渲染。

  4. 根据场景需要,调用 startPreview 、joinChannelByToken 等方法预览或发送自定义渲染的视频数据。

API 调用时序

参考下图时序使用 MediaIO 在你的项目中实现自定义视频渲染。

示例代码

参考下文代码使用 MediaIO 在你的项目中实现自定义视频渲染。

  1. 遵守 ARVideoSinkProtocol 协议, 并实现接口,构建自定义的 Video Renderer 类。

     // Swift
         // 协议中的方法
         // 1. 希望 anyRTC SDK 抛出的视频 Buffer 类型
         func bufferType() -> ARVideoBufferType {
                 return bufferType
         }
    
         // 希望 anyRTC SDK 抛出的视频数据格式
         func pixelFormat() -> ARVideoPixelFormat {
                 return pixelFormat
         }
    
         // 2. 初始化自定义的 Video Renderer
         func shouldInitialize() -> Bool {
                 return true
         }
    
         // 3. 启动自定义的 Video Renderer   
         func shouldStart() {
    
         }
    
         // 4. anyRTC SDK 停止抛出视频数据
         func shouldStop() {
    
         }
    
         // 5. 自定义的 Video Renderer 可以被释放   
         func shouldDispose() {
    
         }
    
         // 6. anyRTC SDK 通过该接口抛出 CVPixelBuffer 类型的视频数据, 自定义 Video Renderer 可以获取数据进行渲染
         func renderPixelBuffer(_ pixelBuffer: CVPixelBuffer, rotation: ARVideoRotation) {
         }
    
         anyRTC SDK 通过该接口抛出 rawData 类型的视频数据, 自定义 Video Renderer 可以获取数据进行渲染
         func renderRawData(_ rawData: UnsafeMutableRawPointer, size: CGSize, rotation: ARVideoRotation) {
         }
     }
    
     // Objective-C
         // 协议中的方法
         // 1. 希望 anyRTC SDK 抛出的视频 Buffer 类型
         - (ARVideoBufferType)bufferType {
                 return ARVideoBufferTypePixelBuffer;
         }
    
         // 希望 anyRTC SDK 抛出的视频数据格式
         - (ARVideoPixelFormat)pixelFormat {
              return ARVideoPixelFormatI420;
         }
    
         // 2. 初始化自定义的 Video Renderer
         - (BOOL)shouldInitialize {
             return YES;
         }
    
         // 3. 启动自定义的 Video Renderer 
         - (void)shouldStart {
         }
    
         // 4. anyRTC SDK 停止抛出视频数据
         - (void)shouldStop {
         }
    
         // 5. 自定义的 Video Renderer 可以被释放   
         - (void)shouldDispose {
         }
    
         // 6. anyRTC SDK 通过该接口抛出 CVPixelBuffer 类型的视频数据, 自定义 Video Renderer 可以获取数据进行渲染
         - (void)renderPixelBuffer:(CVPixelBufferRef _Nonnull)pixelBuffer rotation:(ARVideoRotation)rotation {
         }
    
         // anyRTC SDK 通过该接口抛出 rawData 类型的视频数据, 自定义 Video Renderer 可以获取数据进行渲染
         - (void)renderRawData:(void * _Nonnull)rawData size:(CGSize)size rotation:(ARVideoRotation)rotation {
         }
    
  2. 将遵守了 ARVideoSourceProtocol 协议的自定义 VideoRenderer 对象设给 ARtcEngineKit。

     // Swift
     rtcKit.setLocalVideoRenderer(videoRenderer)
     rtcKit.setRemoteVideoRenderer(videoRenderer, forUserId: uid)
    
     // Objective-C
     [rtcKit setLocalVideoRenderer: videoRenderer];
     [rtcKit setRemoteVideoRenderer: videoRenderer, uid];
    

API 参考

开发注意事项

  • 自定义视频采集和渲染场景中,需要开发者具有采集或渲染视频的能力:
    • 自定义视频采集场景中,你需要自行管理视频数据的采集和处理。
    • 自定义视频渲染场景中,你需要自行管理视频数据的处理和显示。
  • 自定义视频渲染场景中,当 renderPixelBuffer 或 renderRawData 报告 rotation 不为 0 时,自渲染视频会呈一定角度。该角度可能由 SDK 采集或自采集的设置引起,你需要能根据实际使用需求处理自渲染的视频角度。

相关文档

如果你还想在项目中实现自定义的音频采集和渲染功能,请参考文档自定义音频采集和播放