AVAssetWriter
将自动在其关联的 s 上交错请求AVAssetWriterInput
,以便将不同的轨道集成到输出文件中。只需AVAssetWriterInput
为您拥有的每个曲目添加一个,然后调用requestMediaDataWhenReadyOnQueue:usingBlock:
您的每个AVAssetWriterInput
s.
这是我调用的一种方法requestMediaDataWhenReadyOnQueue:usingBlock:
。我从我拥有的输出/输入对数量的循环中调用此方法。(单独的方法对代码可读性都有好处,也因为与循环不同,每次调用都会为块设置一个单独的堆栈帧。)
您只需要一个dispatch_queue_t
并且可以将其重复用于所有轨道。请注意,您绝对不应该从您的块中调用dispatch_async
,因为requestMediaDataWhenReadyOnQueue:usingBlock:
期望块会阻塞,直到它填充了所需的数据AVAssetWriterInput
量。你不想在那之前回来。
- (void)requestMediaDataForTrack:(int)i {
AVAssetReaderOutput *output = [[_reader outputs] objectAtIndex:i];
AVAssetWriterInput *input = [[_writer inputs] objectAtIndex:i];
[input requestMediaDataWhenReadyOnQueue:_processingQueue usingBlock:
^{
[self retain];
while ([input isReadyForMoreMediaData]) {
CMSampleBufferRef sampleBuffer;
if ([_reader status] == AVAssetReaderStatusReading &&
(sampleBuffer = [output copyNextSampleBuffer])) {
BOOL result = [input appendSampleBuffer:sampleBuffer];
CFRelease(sampleBuffer);
if (!result) {
[_reader cancelReading];
break;
}
} else {
[input markAsFinished];
switch ([_reader status]) {
case AVAssetReaderStatusReading:
// the reader has more for other tracks, even if this one is done
break;
case AVAssetReaderStatusCompleted:
// your method for when the conversion is done
// should call finishWriting on the writer
[self readingCompleted];
break;
case AVAssetReaderStatusCancelled:
[_writer cancelWriting];
[_delegate converterDidCancel:self];
break;
case AVAssetReaderStatusFailed:
[_writer cancelWriting];
break;
}
break;
}
}
}
];
}