AVAssetWriter
AVAssetWriterInput
は、異なるトラックを出力ファイルに統合するために、関連する でリクエストを自動的にインターリーブします。AVAssetWriterInput
持っているトラックごとに を追加してから、それぞれの を呼び出しrequestMediaDataWhenReadyOnQueue:usingBlock:
ますAVAssetWriterInput
。
を呼び出すメソッドを次に示しますrequestMediaDataWhenReadyOnQueue:usingBlock:
。私が持っている出力/入力ペアの数をループからこのメソッドを呼び出します。(個別のメソッドは、コードの読みやすさと、ループとは異なり、呼び出しごとにブロックの個別のスタック フレームが設定されるため、両方に適しています。)
必要なものは 1 つだけ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;
}
}
}
];
}