AVAssetWriter
автоматически чередует запросы на связанных 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;
}
}
}
];
}