本章节为您介绍了iOS的输入外部视频流和音频流的接口示例。
输入外部视频流
注意 增加自定义视频输入时,建议您提前进行采集,RTC入会之前开始送入数据,避免看到摄像头数据。
- 打开外部视频输入开关。
接口说明如下所示。
/** * @brief 启用外部视频输入源 * @param enable YES:开启,NO:关闭 * @param useTexture 是否使用texture模式 * @param type 流类型 */ - (int)setExternalVideoSource:(BOOL)enable useTexture:(BOOL)useTexture sourceType:(AliRtcVideoSource)type;
说明 目前userTexture暂不支持,type仅支持AliRtcVideosourceCameraLargeType(视频流)。示例方法如下所示。
int ret = [self.engine setExternalVideoSource:YES useTexture:NO sourceType:AliRtcVideosourceCameraLargeType];
- 输入视频数据。
接口说明如下所示。
/** * @brief 输入视频数据 * @param frame 帧数据 * @param type 流类型 * @return 返回>=0表示成功,<0表示失败 */ - (int)pushExternalVideoFrame:(AliRtcVideoDataSample *)frame sourceType:(AliRtcVideoSource)type;
参数说明,AliRtcVideoDataSample必填项如下所示。
参数 说明 dataPtr 数据句柄 format 数据类型,目前仅支持AliRtcVideoFormat_I420 width 视频流宽 height 视频流高 datalength 数据buffer length 说明 需要APP开启线程进行push;type仅支持AliRtcVideosourceCameraLargeType(视频流)。示例方法如下所示。
float pcmHzFloat; int yuvDataWidth; int yuvDataHeight; NSThread * yuvInputThread; FILE * yuvInputFile; - (void)inputYUVRun { int width = yuvDataWidth; int height = yuvDataHeight; int dataSize = width*height*3/2; char *yuv_read_data = (char *)malloc(dataSize); while (true) { if ([yuvInputThread isCancelled]) { break; } size_t read = fread(yuv_read_data,dataSize, 1, yuvInputFile); if (read > dataSize) { break; } if (read == 0) { fseek(yuvInputFile, 0,SEEK_SET); NSLog(@"input yuv reset head!"); if (yuvInputThread) { continue; } else { break; } } bool push_error = false; while (true) { if (![yuvInputThread isExecuting]) { push_error = YES; break; } AliRtcVideoDataSample *dataSample = [[AliRtcVideoDataSample alloc] init]; dataSample.dataPtr = (long)yuv_read_data; dataSample.format = AliRtcVideoFormat_I420; 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; //加判断是否开启输入屏幕共享 int ret = 0; if (yuvShareState != YES) { } else { ret = [self.engine pushExternalVideoFrame:dataSample sourceType:AliRtcVideosourceScreenShareType]; } if (ret == AliRtcErrAudioBufferFull && [yuvInputThread isCancelled] == NO) { } else { if (ret < 0) { push_error = true ; } } //加判断频率, 默认为60hz(30毫秒) if (pcmHzFloat > 0) { float hz = 1.0/pcmHzFloat; [NSThread sleepForTimeInterval:hz]; // 指定频率 } else { [NSThread sleepForTimeInterval:0.03]; // 默认30毫秒 (加延迟操作播放出流畅的画面) } break; } if (push_error) { break ; } } free(yuv_read_data); fclose(yuvInputFile); yuvInputFile = NULL ; }
输入外部音频流
- 打开外部音频输入开关。
接口如下所示。
/** * @brief 设置是否启用外部音频输入源 * @param enable YES 开启,NO 关闭 * @param sampleRate 采样率 16k, 48k等 * @param channelsPerFrame 声道数 1, 2 * @return 返回>=0表示成功, <0表示失败 */ - (int)setExternalAudioSource:(BOOL)enable withSampleRate:(NSUInteger)sampleRate channelsPerFrame:(NSUInteger)channelsPerFrame; /** * @brief 设置是否与麦克风采集音频混合 * @param mixed YES:混音,NO:完全替换麦克风采集数据 */ - (int)setMixedWithMic:(BOOL)mixed;
说明 目前仅支持PCM数据。示例方法如下:
int ret = [self.engine setExternalAudioSource:YES withSampleRate:pcmSampleRate channelsPerFrame:pcmChannels]; // 完全替代麦克风采集 [self.engine setMixedWithMic:NO];
- 输入音频数据。
接口方法如下所示。
/** * @brief 输入音频数据 * @param data 音频数据 不建议超过40ms数据 * @param samples 采样率 * @param timestamp 时间戳 * @return 返回>=0表示成功,<0表示失败 * @note 如果返回值为errorCode中的AliRtcErrAudioBufferFull,代表当前buffer队列塞满,需要等待后再继续输送数据,,建议等待20ms */ - (int)pushExternalAudioFrameRawData:(void *_Nonnull)data samples:(NSUInteger)samples timestamp:(NSTimeInterval)timestamp;
说明 如果返回值为errorCode中的AliRtcErrAudioBufferFull,代表当前buffer队列塞满,需要等待后再继续输送数据,建议您等待20ms。示例方法如下所示。
int pcmSampleRate; int pcmChannels; NSThread * pcmInputThread; FILE * pcmInputFile; - (void)inputPCMRun { // 40ms int readbufSize = (pcmSampleRate/100)*4*sizeof(int16_t)*pcmChannels ; while (true) { if ([pcmInputThread isCancelled]) { break; } size_t read = fread(pcmData, 1, readbufSize, pcmInputFile) ; if (read > readbufSize) { break; } if (read == 0) { fseek(pcmInputFile, 0, SEEK_SET) ; NSLog(@"input pcm reset head!"); if (pcmInputThread) { continue; } else { break; } } bool push_error = false; while (true) { if (![pcmInputThread isExecuting]) { push_error = YES; break; } int rc = [self.engine pushExternalAudioFrameRawData:pcmData samples:read timestamp:0]; if ( rc == AliRtcErrAudioBufferFull && [pcmInputThread isCancelled ] == NO ) { [NSThread sleepForTimeInterval:0.08] ; } else { if (rc < 0) { push_error = true ; } break; } } if (push_error) { break; } } fclose(pcmInputFile); pcmInputFile = NULL ; }
在文档使用中是否遇到以下问题
更多建议
匿名提交