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.

questionAnswers(1)

yourAnswerToTheQuestion