2014-09-28 20 views
5

Po szczegółowym przeglądzie WWDC2014, Session513, próbuję napisać moją aplikację na IOS8.0, aby odkodować i wyświetlić jeden strumień H.264 na żywo. Przede wszystkim konstruuję zestaw parametrów H264 z powodzeniem. Kiedy dostaję jedną, ramki z 4-bitowym kodem startowym, podobnie jak "0x00 0x00 0x00 0x01 0x65 ...", umieszczam go w CMblockBuffer. Następnie buduję CMSampleBuffer za pomocą podglądu CMBlockBuffer. Następnie umieściłem CMSampleBuffer w AVSampleBufferDisplayLayer. Wszystko jest w porządku (sprawdziłem zwróconą wartość), z tym że AVSampleBufferDisplayLayer nie wyświetla żadnego obrazu wideo. Ponieważ te interfejsy API są dość nowe dla wszystkich, nie mogłem znaleźć żadnego organu, który mógłby rozwiązać ten problem.Umieszczanie ramki H.264 I na AVSampleBufferDisplayLayer bez wyświetlania obrazu wideo

Podam kluczowe kody w następujący sposób i naprawdę to doceniam, jeśli możesz pomóc w ustaleniu, dlaczego nie można wyświetlić obrazu wideo. Wielkie dzięki.

(1) Zainicjowano AVSampleBufferDisplayLayer. dsplayer to instancja objc mojego głównego kontrolera widoku.

@property(nonatomic,strong)AVSampleBufferDisplayLayer *dspLayer; 

if(!_dspLayer) 
{ 
    _dspLayer = [[AVSampleBufferDisplayLayer alloc]init]; 
    [_dspLayer setFrame:CGRectMake(90,551,557,389)]; 
    _dspLayer.videoGravity = AVLayerVideoGravityResizeAspect; 
    _dspLayer.backgroundColor = [UIColor grayColor].CGColor; 
    CMTimebaseRef tmBase = nil; 
    CMTimebaseCreateWithMasterClock(NULL,CMClockGetHostTimeClock(),&tmBase); 
    _dspLayer.controlTimebase = tmBase; 
    CMTimebaseSetTime(_dspLayer.controlTimebase, kCMTimeZero); 
    CMTimebaseSetRate(_dspLayer.controlTimebase, 1.0); 

    [self.view.layer addSublayer:_dspLayer]; 

} 

(2) W innym wątku, otrzymuję jedną ramkę H.264 I. // budować h.264 ustawić parametr ok

CMVideoFormatDescriptionRef formatDesc; 
    OSStatus formatCreateResult = 
    CMVideoFormatDescriptionCreateFromH264ParameterSets(NULL, ppsNum+1, props, sizes, 4, &formatDesc); 
    NSLog([NSString stringWithFormat:@"construct h264 param set:%ld",formatCreateResult]); 

// skonstruować cmBlockbuffer. // databuf wskazuje na dane H.264. zaczyna się od "0x00 0x00 0x00 0x01 0x65 ........"

CMBlockBufferRef blockBufferOut = nil; 
    CMBlockBufferCreateEmpty (0,0,kCMBlockBufferAlwaysCopyDataFlag, &blockBufferOut); 
    CMBlockBufferAppendMemoryBlock(blockBufferOut, 
            dataBuf, 
            dataLen, 
            NULL, 
            NULL, 
            0, 
            dataLen, 
            kCMBlockBufferAlwaysCopyDataFlag); 

// skonstruowania cmsamplebuffer ok

size_t sampleSizeArray[1] = {0}; 
    sampleSizeArray[0] = CMBlockBufferGetDataLength(blockBufferOut); 
    CMSampleTiminginfo tmInfos[1] = { 
     {CMTimeMake(5,1), CMTimeMake(5,1), CMTimeMake(5,1)} 
    }; 
    CMSampleBufferRef sampBuf = nil; 
    formatCreateResult = CMSampleBufferCreate(kCFAllocatorDefault, 
         blockBufferOut, 
         YES, 
         NULL, 
         NULL, 
         formatDesc, 
         1, 
         1, 
         tmInfos, 
         1, 
         sampleSizeArray, 
         &sampBuf); 

// poddana AVSampleBufferdisplayLayer, tylko jedną klatkę. Ale nie widzę żadnego klatkę wideo moim zdaniem

if([self.dspLayer isReadyForMoreMediaData]) 
    { 
    [self.dspLayer enqueueSampleBuffer:sampBuf]; 
    } 
    [self.dspLayer setNeedsDisplay]; 
+0

Odpowiedź Scythe42 prawdopodobnie rozwiąże problemy, które masz. Miałem też problemy z uruchomieniem go. Ale w końcu to zrobiłem. Powinieneś [rzucić okiem] (http://stackoverflow.com/questions/25980070/how-to-use-avsamplebufferdisplaylayer-in-ios-8-for-rtp-h264-streams- with-gstream). – Zappel

+0

to samo tutaj. dostałem vail & ready CMSampleBuffer, ale nie wyświetli się on na ekranie ... :( – zaxy78

Odpowiedz

4

swoje początkowe jednostki NAL kody 0x00 0x00 0x01 0x00 0x00 0x00 lub 0x01 muszą zostać zastąpione przez nagłówka długości.

Zostało to wyraźnie stwierdzone w sesji WWDC, które odnoszą się do tego, że kod startowy Aneksu B musi być zastąpiony nagłówkiem długości zgodnym z AVCC. Zasadniczo remuxing do formatu pliku MP4 z formatu strumienia załącznika B w locie tutaj (uproszczony opis oczywiście).

Twoje połączenie podczas tworzenia zestawu parametrów to "4", dlatego musisz poprzedzić swoje jednostki VCL NAL prefiksem o długości 4 bajtów. To dlatego określasz to tak, jak w formacie AVCC, nagłówek długości może być krótszy.

Cokolwiek włożymy do CMSampleBuffer będzie w porządku, nie ma sprawdzenia poprawności, jeśli zawartość może zostać zdekodowana, tylko że spełnione zostały wymagane parametry dla bycia dowolnymi danymi w połączeniu z informacjami o taktowaniu i zestawem parametrów.

Zasadniczo dane, które wprowadziłeś, mówiły, że jednostki VCL NAL mają długość 1 bajta. Dekoder nie otrzymuje pełnej jednostki NAL i otrzymuje błąd z powodu błędu.

Upewnij się również, że podczas używania utwórz zestaw parametrów, do którego nie dodano dodawanej długości i czy kod startowy z załącznika B jest również usunięty.

Polecam także, aby nie używać AVSampleBufferDisplayLayer, ale przejść przez VTDecompressionSession, dzięki czemu można zrobić rzeczy takie jak korekcja kolorów lub inne rzeczy, które są potrzebne wewnątrz modułu cieniującego pikseli.

+2

Należy również pamiętać, że kody długości NAL muszą być w kolejności bajtów wielko-endianowych. – Greg

0

Początkowo można użyć ramki DecompressionSessionDecode, ponieważ pozwoli to uzyskać pewne informacje zwrotne na temat sukcesu dekodowania. Jeśli wystąpi problem z dekodowaniem, warstwa AVSampleBufferDisplay nie powie Ci, że po prostu nic nie wyświetla. Mogę podać ci kod, aby w razie potrzeby pomóc, daj mi znać, jak sobie radzisz, ponieważ próbuję to samo :)