2013-05-31 20 views
5

Ich habe Code erstellt, um Videodateien unter OSX Frame für Frame zu verarbeiten. Das Folgende ist ein Auszug aus dem Code, der OK baut, die Datei öffnet, die Videospur (nur Spur) lokalisiert und CMSampleBuffers ohne Probleme zu lesen beginnt. Jedoch gibt jedes CMSampleBufferRef I erhalten NULL zurück, wenn ich versuche, den Pixelpufferrahmen zu extrahieren. In der iOS-Dokumentation gibt es keine Hinweise darauf, warum ich einen NULL-Rückgabewert erwarten könnte oder wie ich das Problem beheben könnte. Es passiert mit allen Videos, auf denen ich es getestet habe, unabhängig von der Aufnahmequelle oder CODEC.Warum gibt CMSampleBufferGetImageBuffer NULL zurück

Jede Hilfe sehr geschätzt.

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(...); 

Um klar zu sein, habe ich alle Fehler Prüfcode entfernt, aber keine Probleme wurden in diesem Code angezeigt. dh die AVAssetReader liest, sieht CMSampleBufferRef fein usw.

Antwort

2

FWIW: Hier ist, was offizielle Dokumentation für den Rückgabewert von CMSampleBufferGetImageBuffer sagen:.

„Das Ergebnis ist ein CVImageBuffer von Mediendaten Das Ergebnis NULL sein wird, wenn die CMSampleBuffer enthält keinen CVImageBuffer, oder wenn der CMSampleBuffer einen CMBlockBuffer enthält oder wenn ein anderer Fehler vorliegt. "

Beachten Sie außerdem, dass der zurückgegebene dataBuffer nicht von CMSampleBufferGetImageBuffer dem Aufrufer gehört, und muss es explizit beibehalten, wenn der Aufrufer einen Verweis auf es beibehalten muss.

Hoffentlich hilft diese Info.

+0

Danke! Aus Interesse, wo haben Sie dieses Zitat gefunden? Denn hier: https://developer.apple.com/library/mac/#documentation/CoreMedia/Reference/CMSampleBuffer/Reference/Reference.html und in den in meiner XCode-Version herunterladbaren Dokumenten gibt es überhaupt keine Kommentare! –

+0

In den Header-Dateien. Apple hat eine sehr detaillierte Dokumentation für jede Methode.Klicken Sie in xcode mit der rechten Maustaste auf den Methodennamen in Ihrem Code und klicken Sie auf "Gehe zur Definition" (Der Wortlaut ist möglicherweise nicht exakt), und Sie gelangen zur richtigen .h-Datei und Methodendefinition mit Dokumentation – Aki

+0

Doh! Ich nehme an, dass, da die Dokumente nicht in der generierten Dokumentation waren, sie nicht in der Quelle waren. Danke nochmal Aki. –

9

Sie haben outputSettings bei der Erstellung Ihres AVAssetReaderTrackOutput nicht angegeben. Ich habe bei der Angabe von "nil" auf Ihr Problem gestoßen, um das ursprüngliche Pixelformat der Videospur beim Aufruf von copyNextSampleBuffer zu erhalten. In meiner App wollte ich sicherstellen, dass keine Konvertierung stattfand, wenn copyNextSampleBuffer aus Gründen der Leistung aufgerufen wird, wenn dies kein großes Problem für Sie ist, geben Sie ein Pixelformat in den Ausgabeeinstellungen an.

Die folgenden sind Apples empfehlen Pixelformate auf der Basis der Hardwarefunktionen:

kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange kCVPixelFormatType_420YpCbCr8BiPlanarFullRange

+1

Dies sollte als Antwort angenommen werden, da der aktuell akzeptierte Beitrag nichts löst. –

+1

@nenchev Wie haben Sie das Problem gelöst, um sicherzustellen, dass keine Konvertierung stattgefunden hat? –

+0

@nenchev Wie haben Sie das Problem behoben, um sicherzustellen, dass keine Konvertierung stattgefunden hat? –

2

Weil Sie haben keine Output versorgt Sie zu verwenden sind gezwungen, die Rohdaten, die in dem Rahmen enthalten sind.

Sie haben die Blockpuffer aus dem Probenpuffer erhalten CMSampleBufferGetDataBuffer(sampleBuffer) verwenden, nachdem Sie haben, dass Sie den aktuellen Standort des Blockpuffer mit

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

Blick auf *blockBufferPointer und dekodieren die Bytes erhalten müssen Verwenden Sie die Frame-Header-Informationen für Ihren erforderlichen Codec.

Verwandte Themen