2013-05-31 22 views
5

Mam wbudowany kod do przetwarzania plików wideo na OSX, klatka po klatce. Poniżej znajduje się wyciąg z kodu, który buduje OK, otwiera plik, lokalizuje ścieżkę wideo (tylko ścieżkę) i rozpoczyna czytanie CMSampleBuffers bez problemu. Jednak każdy CMSampleBufferRef I uzyskać zwraca NULL, gdy próbuję wyodrębnić ramki bufora pikseli. W dokumentacji systemu iOS nie ma informacji, dlaczego mogłem oczekiwać wartości zwracanej wartości NULL lub w jaki sposób mogłem oczekiwać rozwiązania problemu. Dzieje się tak w przypadku wszystkich filmów, na których testowałem, niezależnie od źródła przechwytywania lub kodu CODEC.Dlaczego CMSampleBufferGetImageBuffer zwraca NULL

Każda pomoc bardzo ceniona.

NSString *assetInPath = @"/Users/Dave/Movies/movie.mp4"; 
NSURL *assetInUrl = [NSURL fileURLWithPath:assetInPath]; 
AVAsset *assetIn = [AVAsset assetWithURL:assetInUrl]; 

NSError *error; 
AVAssetReader *assetReader = [AVAssetReader assetReaderWithAsset:assetIn error:&error]; 
AVAssetTrack *track = [assetIn.tracks objectAtIndex:0]; 
AVAssetReaderOutput *assetReaderOutput = [[AVAssetReaderTrackOutput alloc] 
               initWithTrack:track 
               outputSettings:nil]; 
[assetReader addOutput:assetReaderOutput]; 

// Start reading 
[assetReader startReading]; 

CMSampleBufferRef sampleBuffer; 
do { 
     sampleBuffer = [assetReaderOutput copyNextSampleBuffer]; 

     /** 
     ** At this point, sampleBuffer is non-null, has all appropriate attributes to indicate that 
     ** it's a video frame, 320x240 or whatever and looks perfectly fine. But the next 
     ** line always returns NULL without logging any obvious error message 
     **/ 

     CVImageBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 

     if(pixelBuffer != NULL) { 
      size_t width = CVPixelBufferGetWidth(pixelBuffer); 
      size_t height = CVPixelBufferGetHeight(pixelBuffer); 
      CVPixelBufferLockBaseAddress(pixelBuffer, 0); 
      ... 
      other processing removed here for clarity 
     } 
} while(...); 

Dla jasności usunąłem cały kod sprawdzania błędów, ale w tym kodzie nie stwierdzono żadnych problemów. czyli AVAssetReader czyta CMSampleBufferRef wygląda dobrze itd

Odpowiedz

2

FWIW: Oto co mówią oficjalne docs dla wartości zwracanej CMSampleBufferGetImageBuffer.

„Rezultatem jest CVImageBuffer danych multimedialnych Rezultatem będzie NULL jeśli CMSampleBuffer nie zawiera CVImageBuffer lub jeśli CMSampleBuffer zawiera CMBlockBuffer, lub jeśli jest jakiś inny błąd. "

Należy również pamiętać, że osoba wywołująca nie jest właścicielem zwróconego obiektu dataBuffer z CMSampleBufferGetImageBuffer i musi zachować go jawnie, jeśli osoba wywołująca musi zachować odniesienie do niego.

Mam nadzieję, że ta informacja pomaga.

+0

Dzięki! Ciekawe, gdzie znalazłeś ten cytat? Ponieważ tutaj: https://developer.apple.com/library/mac/#documentation/CoreMedia/Reference/CMSampleBuffer/Reference/Reference.html oraz w dokumentach skopiowanych w mojej wersji XCode nie ma absolutnie żadnego komentarza! –

+0

W plikach nagłówkowych. Apple ma bardzo szczegółowe dokumenty dla każdej metody.W kodzie xcode kliknij prawym przyciskiem myszy nazwę metody w kodzie i kliknij "przejdź do definicji" (treść może nie być dokładna), a przeniesie Cię do poprawnej definicji pliku i metody .h wraz z dokumentacją – Aki

+0

Doh! Sądzę, że założyłem, że skoro dokumenty nie znajdowały się w wygenerowanej dokumentacji, nie były one w źródle. Jeszcze raz dziękuję Aki. –

9

Nie określiłeś żadnego outputSettings podczas tworzenia swojego AVAssetReaderTrackOutput. Wystąpiłam w twoim problemie, określając "zero", aby otrzymać oryginalny format piksela ścieżki wideo, dzwoniąc pod numer copyNextSampleBuffer. W mojej aplikacji chciałem upewnić się, że żadna konwersja nie zadziała podczas wywoływania copyNextSampleBuffer ze względu na wydajność, jeśli nie jest to dla ciebie dużym problemem, określ format pikseli w ustawieniach wyjściowych.

zalecane są następujące formaty pikseli Apple oparte na możliwościach sprzętowych:

kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange kCVPixelFormatType_420YpCbCr8BiPlanarFullRange

+1

To powinna być akceptowana odpowiedź, ponieważ aktualnie przyjęty post niczego nie rozwiązuje. –

+1

@nenchev jak poradziłeś sobie z tym problemem, aby upewnić się, że nie nastąpiła żadna konwersja? –

+0

@nenchev jak poradziłeś sobie z tym problemem, aby upewnić się, że nie nastąpiła żadna konwersja? –

2

Ponieważ nie dostarczyły żadnych outputSettings jesteś zmuszony do korzystania surowe dane zawarte w ramce.

Musisz dostać bufor bloku z bufora próbek stosując CMSampleBufferGetDataBuffer(sampleBuffer), po trzeba, że ​​trzeba uzyskać rzeczywiste położenie bufora bloków przy użyciu

size_t blockBufferLength; char *blockBufferPointer; CMBlockBufferGetDataPointer(blockBuffer, 0, NULL, &blockBufferLength, &blockBufferPointer);

Spójrz na *blockBufferPointer i zdekodować bajty przy użyciu informacji o nagłówku ramki dla wymaganego kodeka.

Powiązane problemy