通過閱讀本文,您可以了解 iOS 輸入外部音視頻流的方法。
輸入外部視頻流
說明
SDK允許先推流然后開啟外部視頻輸入,但這種情況下,默認開始推流時,先推送出的是本地原始采集源(攝像頭或屏幕捕獲)的視頻數據,直到啟用外部輸入。
1. 調用 setExternalVideoSource 打開外部視頻輸入開關。
int ret = [DingRtcClient.instance.rtcEngine setExternalVideoSource:YES track:DingRtcVideoTrackCamera];
2. 調用 pushExternalVideoFrame 輸入視頻數據。
說明
此處需要重新開啟線程調用 pushExternalVideoFrame。
FILE * _yuvInputFile;
@property (strong, nonatomic) NSThread *yuvInputThread;
@property (assign, nonatomic) int yuvDataWidth;
@property (assign, nonatomic) int yuvDataHeight;
- (void)runInputYUV {
int width = self.yuvDataWidth;
int height = self.yuvDataHeight;
int dataSize = width * height * 3 / 2;
char *yuv_read_data = (char *)malloc(dataSize);
while (true) {
if ([self.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);
if (self.yuvInputThread) {
continue;
} else {
break;
}
}
BOOL push_error = NO;
if (![self.yuvInputThread isExecuting]) {
push_error = YES;
break;
}
DingRtcVideoFrame *frame = [[DingRtcVideoFrame alloc] init];
frame.frameType = DingRtcVideoFrameRaw;
frame.timestamp = [[NSDate date] timeIntervalSince1970] * 1000;
frame.width = width;
frame.height = height;
frame.rotation = 0;
frame.count = 3;
frame.data = (void *)yuv_read_data;
frame.offset = @[@(0), @(width * height), @(width * height * 5 / 4)];
frame.stride = @[@(width), @(width/2), @(width/2)];
frame.pixelFormat = DingRtcVideoI420;
int ret = [DingRtcClient.instance.rtcEngine pushExternalVideoFrame:frame track:DingRtcVideoTrackCamera];
if (ret != 0) {
push_error = YES;
}
//請根據實際情況控制幀率
[NSThread sleepForTimeInterval:0.03];
if (push_error) {
break;
}
}
free(yuv_read_data);
fclose(_yuvInputFile);
_yuvInputFile = NULL;
}
輸入外部音頻流
1. 調用 setExternalAudioSource 啟用外部音頻輸入。
//采樣率
@property (assign, nonatomic) int sampleRate;
//聲道數
@property (assign, nonatomic) int channels;
int ret = [DingRtcClient.instance.rtcEngine setExternalAudioSource:YES withSampleRate:self.sampleRate channelsPerFrame:self.channels];
2. 調用 pushExternalAudioFrame 輸入音頻數據。
FILE * _inputFile;
@property (strong, nonatomic) NSThread *inputThread;
//每個音頻采樣字節數, 通常是16bit(即2字節) */
@property (assign, nonatomic) int bytesPerSample;
//采樣率
@property (assign, nonatomic) int sampleRate;
//聲道數
@property (assign, nonatomic) int channels;
- (void)runInputPCM {
int freq = 40; // audio duration (ms) each time push
float samplesToRead = self.sampleRate / (1000.0 / freq);
int bufferSize = samplesToRead * self.channels * self.bytesPerSample;
char *buffer = (char *)malloc(bufferSize);
DingRtcAudioDataSample *frame = [[DingRtcAudioDataSample alloc] init];
frame.data = (void *)buffer;
frame.bytesPerSample = self.bytesPerSample;
frame.numOfChannels = self.channels;
frame.sampleRate = self.sampleRate;
while (true) {
if ([self.inputThread isCancelled]) {
break;
}
size_t readBytes = fread(buffer, 1, bufferSize, _inputFile);
if (readBytes == 0) {
fseek(_inputFile, 0, SEEK_SET);
if (self.inputThread) {
continue;
} else {
break;
}
}
BOOL push_error = NO;
if (![self.inputThread isExecuting]) {
push_error = YES;
break;
}
frame.numOfSamples = (int)(readBytes / self.bytesPerSample / selfchannels);
int ret = [DingRtcClient.instance.rtcEngine pushExternalAudioFrame:frame];
if (ret != 0) {
push_error = YES;
}
//請根據實際情況控制幀率
[NSThread sleepForTimeInterval:freq/1000.0];
if (push_error) {
break;
}
}
free(buffer);
fclose(_inputFile);
_inputFile = NULL;
}
文檔內容是否對您有幫助?