2013-05-31 13 views
5

Ho creato un codice per elaborare i file video su OSX, fotogramma per fotogramma. Quello che segue è un estratto dal codice che costruisce OK, apre il file, individua la traccia video (solo traccia) e inizia a leggere CMSampleBuffers senza problemi. Tuttavia, ogni CMSampleBufferRef I restituisce restituisce NULL quando provo ad estrarre il frame del buffer dei pixel. Non c'è alcuna indicazione nella documentazione di iOS sul motivo per cui potrei aspettarmi un valore di ritorno NULL o come potrei aspettarmi di risolvere il problema. Succede con tutti i video su cui l'ho testato, a prescindere dalla fonte di acquisizione o CODEC.Perché CMSampleBufferGetImageBuffer restituisce NULL

Qualsiasi aiuto molto apprezzato.

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

Per essere chiari, ho messo a nudo tutti gli errori controllando il codice ma senza problemi stessero indicato in tale codice. cioè l'AVAssetReader sta leggendo, CMSampleBufferRef guarda bene ecc

risposta

2

FWIW: Ecco cosa dicono documentazione ufficiale per il valore di ritorno di CMSampleBufferGetImageBuffer:.

"Il risultato è un CVImageBuffer di dati multimediali Il risultato sarà NULL se il CMSampleBuffer non contiene un CVImageBuffer o se il CMSampleBuffer contiene un CMBlockBuffer o se c'è qualche altro errore. "

Si noti inoltre che il chiamante non possiede il data buffer restituito da CMSampleBufferGetImageBuffer e deve mantenerlo esplicitamente se il chiamante deve mantenere un riferimento ad esso.

Speriamo che questa informazione aiuti.

+0

Grazie! Fuori di interesse, dove hai trovato quella citazione? Perché qui: https://developer.apple.com/library/mac/#documentation/CoreMedia/Reference/CMSampleBuffer/Reference/Reference.html e nei documenti downlaoded nella mia versione XCode non c'è assolutamente alcun commento! –

+0

Nei file di intestazione. Apple ha un documento molto detailef per ogni metodo.In xcode, fai clic con il pulsante destro del mouse sul nome del metodo nel tuo codice e fai clic su "vai alla definizione" (il testo potrebbe non essere esatto) e ti porterà al file .h corretto e alla definizione del metodo con la documentazione – Aki

+0

Doh! Immagino di aver pensato che dal momento che i documenti non erano nella documentazione generata, non erano nella fonte. Grazie ancora Aki. –

9

Non è stato specificato alcun outputSettings durante la creazione di AVAssetReaderTrackOutput. Ho riscontrato il problema quando si specifica "nil" per ricevere il formato pixel originale della traccia video quando si chiama copyNextSampleBuffer. Nella mia app volevo assicurarmi che non avvenisse alcuna conversione quando si chiamava copyNextSampleBuffer per motivi di prestazioni, se questo non è un grosso problema per te, specifica un formato pixel nelle impostazioni di output.

Di seguito sono formati pixel raccomandare di Apple basati sulle capacità hardware:

kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange kCVPixelFormatType_420YpCbCr8BiPlanarFullRange

+1

Questa risposta dovrebbe essere accettata poiché il post attualmente accettato non risolve nulla. –

+1

@nenchev come hai risolto il problema per garantire che non avvenisse alcuna conversione? –

+0

@nenchev come hai risolto il problema per garantire che non avvenisse alcuna conversione? –

2

Perché non avete fornito alcun outputSettings si è costretti a utilizzare i dati grezzi contenuti all'interno della cornice.

si deve ottenere il buffer del blocco dal buffer campione utilizzando CMSampleBufferGetDataBuffer(sampleBuffer), dopo che avete che è necessario per ottenere la posizione attuale del buffer di blocco utilizzando

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

Guardate *blockBufferPointer e decodificare i byte utilizzando le informazioni sull'intestazione del frame per il codec richiesto.