Używanie AVAssetWriter z surowymi jednostkami NAL
Zauważyłem w dokumentacji iOS dlaAVAssetWriterInput
możesz przejśćnil
dlaoutputSettings
słownik określający, że dane wejściowe nie powinny być ponownie kodowane.
Ustawienia używane do kodowania nośników dołączonych do wyjścia. Podaj zero, aby określić, że dołączone próbki nie powinny być ponownie kodowane.
Chcę skorzystać z tej funkcji, aby przekazać strumień surowych NAL H.264, ale mam problem z dostosowaniem strumieni surowego bajtu doCMSampleBuffer
że mogę przejść do AVAssetWriterInput'sappendSampleBuffer
metoda. Mój strumień NAL zawiera tylko SPS / PPS / IDR / P NAL (1, 5, 7, 8). Nie udało mi się znaleźć dokumentacji ani rozstrzygającej odpowiedzi na temat używania wstępnie zakodowanych danych H264 za pomocą AVAssetWriter. Wynikowy plik wideo nie może być odtwarzany.
Jak mogę poprawnie spakować jednostki NAL doCMSampleBuffers
? Czy muszę użyć prefiksu kodu startowego? Prefiks długości? Czy muszę upewnić się, że umieściłem tylko jeden NAL naCMSampleBuffer
? Moim celem jest stworzenie kontenera MP4 lub MOV z H264 / AAC.
Oto kod, z którym grałem:
-(void)addH264NAL:(NSData *)nal
{
dispatch_async(recordingQueue, ^{
//Adapting the raw NAL into a CMSampleBuffer
CMSampleBufferRef sampleBuffer = NULL;
CMBlockBufferRef blockBuffer = NULL;
CMFormatDescriptionRef formatDescription = NULL;
CMItemCount numberOfSampleTimeEntries = 1;
CMItemCount numberOfSamples = 1;
CMVideoFormatDescriptionCreate(kCFAllocatorDefault, kCMVideoCodecType_H264, 480, 360, nil, &formatDescription);
OSStatus result = CMBlockBufferCreateWithMemoryBlock(kCFAllocatorDefault, NULL, [nal length], kCFAllocatorDefault, NULL, 0, [nal length], kCMBlockBufferAssureMemoryNowFlag, &blockBuffer);
if(result != noErr)
{
NSLog(@"Error creating CMBlockBuffer");
return;
}
result = CMBlockBufferReplaceDataBytes([nal bytes], blockBuffer, 0, [nal length]);
if(result != noErr)
{
NSLog(@"Error filling CMBlockBuffer");
return;
}
const size_t sampleSizes = [nal length];
CMSampleTimingInfo timing = { 0 };
result = CMSampleBufferCreate(kCFAllocatorDefault, blockBuffer, YES, NULL, NULL, formatDescription, numberOfSamples, numberOfSampleTimeEntries, &timing, 1, &sampleSizes, &sampleBuffer);
if(result != noErr)
{
NSLog(@"Error creating CMSampleBuffer");
}
[self writeSampleBuffer:sampleBuffer ofType:AVMediaTypeVideo];
});
}
Zauważ, że dzwonięCMSampleBufferSetOutputPresentationTimeStamp
w buforze próbki wewnątrzwriteSampleBuffer
metoda z tym, co uważam za prawidłowy czas, zanim faktycznie próbuję ją dołączyć.
Każda pomoc jest doceniana.