自定义视频采集

功能介绍

ARTC SDK 提供了灵活的自定义视频采集功能,支持客户根据业务需求自主管理视频采集设备。

建议优先使用 RTC SDK 内部采集,如果对视频质量、设备兼容性或采集流程有特殊要求而无法使用 SDK 内部采集,那么自定义视频采集为你提供更强的扩展性和定制能力。

示例代码

Android端自定义视频采集Android/ARTCExample/AdvancedUsage/src/main/java/com/aliyun/artc/api/advancedusage/CustomVideoCaptureAndRender/CustomVideoCaptureActivity.java

iOS端自定义视频采集iOS/ARTCExample/AdvancedUsage/CustomVideoCapture/CustomVideoCpatureVC.swift

前提条件

在设置视频配置之前,请确保达成以下条件:

功能实现

image

1. 关闭 SDK 内部采集

可以调用enableLocalVideo接口关闭 SDK 内部采集。

Android

/* 关闭内部采集 */
mAliRtcEngine.enableLocalVideo(false);

/* 打开内部采集,阿里内部默认状态是true,所以如果不需要控制的情况下不需要调用此api */
mAliRtcEngine.enableLocalVideo(true);

iOS

/* 关闭内部采集 */
[_engine enableLocalVideo:NO];

/* 打开内部采集,阿里内部默认状态是true,所以如果不需要控制的情况下不需要调用此api */
[_engine enableLocalVideo:YES];

2. 设置自定义采集视频源

调用 setExternalVideoSource 设置自定义采集视频源,主要参数:

  • enable:控制是否开启。

  • useTexture:是否使用纹理输入。

  • streamType:相机流或屏幕共享流,表示 sdk 替换哪一路流。

  • renderMode:处理模式,外部输入视频源宽高比和推流profile不一致时,会按照对应的rendermode做对应处理。

Android

YUV 输入

/* YUV方式输入 */
/* 打开外部采集,这里以camera流为例,具体可以根据sourceType指定,渲染模式也可以根据需要指定 */
mAliRtcEngine.setExternalVideoSource(true,false, AliRtcVideoTrackCamera,AliRtcRenderModeAuto );

/* 关闭外部采集,这里以camera流为例,具体可以根据sourceType指定 */
mAliRtcEngine.setExternalVideoSource(false,false, AliRtcVideoTrackCamera,AliRtcRenderModeAuto );

纹理输入

/* 纹理方式输入 */
/* 打开外部采集,这里以camera流为例,具体可以根据sourceType指定,渲染模式也可以根据需要指定 */
mAliRtcEngine.setExternalVideoSource(true,true, AliRtcVideoTrackCamera,AliRtcRenderModeAuto );

/* 关闭外部采集,这里以camera流为例,具体可以根据sourceType指定 */
mAliRtcEngine.setExternalVideoSource(false,true, AliRtcVideoTrackCamera,AliRtcRenderModeAuto );

iOS

/* 打开外部采集,这里以camera流为例,具体可以根据sourceType指定,渲染模式也可以根据需要指定 */
[_engine setExternalVideoSource:YES sourceType:AliRtcVideosourceCameraType renderMode:AliRtcRenderModeAuto]; 

/* 关闭外部采集,这里以camera流为例,具体可以根据sourceType指定 */
[_engine setExternalVideoSource:NO sourceType:AliRtcVideosourceCameraType renderMode:AliRtcRenderModeAuto]; 

3. 向 SDK 发送数据

在采集到视频

Android

YUV方式输入示例:

/* 以YUV(I420)格式为例 */
int width = 720;
int height = 1280;
AliRtcEngine.AliRtcVideoFormat videoformat = AliRtcEngine.AliRtcVideoFormat.AliRtcVideoFormatI420;
int[] lineSize = {width, width / 2, width / 2, 0};
int frameLength = width * height * 3 / 2;
byte[] buffer = new byte[frameLength];

/* 构造传入SDK的数据对象 */
AliRtcEngine.AliRtcRawDataFrame rawDataFrame
        = new AliRtcEngine.AliRtcRawDataFrame(buffer,
                                             videoformat,
                                             width, 
                                             height, 
                                             lineSize, 
                                             0, 
                                             buffer.length);

/* 调用API传入数据对象 */
int ret = mAliRtcEngine.pushExternalVideoFrame(rawDataFrame, AliRtcVideoTrackCamera);
if (ret != 0) {
    /* 打印下错误信息 */
}

纹理方式输入示例:

/* 以纹理格式为例 */
/* 构造opengl的环境 */
private static EglBase14 createEglBase14(EGLContext shareEglContext) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
        EglBase14.Context eglBase14Context = shareEglContext == null ? null : new EglBase14.Context(shareEglContext);
        EglBase14 eglBase14 = new EglBase14(eglBase14Context, EglBase.CONFIG_PIXEL_BUFFER);
        try {
            eglBase14.createDummyPbufferSurface();
            eglBase14.makeCurrent();
        } catch (RuntimeException e) {
            eglBase14.release();
            Log.e(TAG, "CreateEGLBase14Context, failed, " + e.getMessage());
        }
        return eglBase14;
    }
    return null;
}

/* 构造传入的数据上下文 */
float[] transformMatrix = {
  1, 0, 0, 0,
  0, 1, 0, 0,
  0, 0, 1, 0,
  0, 0, 0, 1
};
int frameWidth = 720; /* 图像的宽 */
int frameHeight = 1280; /* 图像的高 */
int textureID = xxx; /* 用户自己的纹理id */

AliRtcEngine.AliRtcRawDataFrame aliRawDataFrame 
  = new AliRtcEngine.AliRtcRawDataFrame(textureID,
                                        AliRtcVideoFormatTexture2D,
                                        frameWidth, 
                                        frameHeight, 
                                        transformMatrix, 
                                        0, 
                                        0, 
                                        frameWidth, 
                                        frameHeight, 
                                        mEglBase14.getEglContext());

/* 调用API传入数据对象 */
int ret = mAliRtcEngine.pushExternalVideoFrame(aliRawDataFrame, AliRtcVideoTrackCamera);
if (ret != 0) {
    /* 打印下错误信息 */
}

iOS

/* 按照自己的数据格式填写以下内容,下面以I420格式为例 */
AliRtcVideoDataSample *dataSample = [[AliRtcVideoDataSample alloc] init];
dataSample.dataPtr = (long)yuv_read_data;
dataSample.format = AliRtcVideoFormat_I420;
dataSample.type = AliRtcBufferType_Raw_Data;
dataSample.width = width;
dataSample.height = height;
dataSample.strideY = width;
dataSample.strideU = width/2;
dataSample.strideV = width/2;
dataSample.dataLength = dataSample.strideY * dataSample.height * 3/2;

/* 调用API传入数据对象 */
int ret = [self.engine pushExternalVideoFrame:dataSample sourceType:AliRtcVideosourceCameraType];
if (ret != 0) {
    /* 打印下错误信息 */
}