功能介紹
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。
前提條件
在設定視頻配置之前,請確保達成以下條件:
功能實現
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) {
/* 列印下錯誤資訊 */
}