2012-02-17 4 views
14

Sto cercando il modo più veloce per decodificare i frame di un video locale mpeg-4 su iPhone. Sono semplicemente interessato ai valori di luminanza dei pixel in ogni 10 fotogramma. Non ho bisogno di rendere il video da nessuna parte.Decodifica i frame video su iPhone GPU

Ho provato ffmpeg, AVAssetReader, ImageAssetGenerator, OpenCV e MPMoviePlayer ma sono tutti troppo lenti. La massima velocità che ottengo è ~ 2x (2 minuti di video scansionati in un minuto). Vorrei qualcosa di più vicino a 10x.

Supponendo che i miei tentativi sopra non abbiano utilizzato la GPU, esiste un modo per raggiungere il mio obiettivo con qualcosa che viene eseguito sulla GPU? OpenGL sembra che sia principalmente per l'output di rendering ma l'ho visto usato come filtro per i video in arrivo. Forse è un'opzione?

Grazie in anticipo!

risposta

3

Se si desidera utilizzare una soluzione solo iOS 5, dare un'occhiata all'app di esempio ChromaKey della sessione WWDC 2011 su AVCaputureSession.

Questa demo acquisisce 30 FPS di video dalla videocamera incorporata e passa ogni frame a OpenGL come trama. Quindi usa OpenGL per manipolare il frame e, facoltativamente, scrive il risultato in un file video di output.

Il codice utilizza una seria magia di basso livello per collegare un buffer Core Video Pixel da una AVCaptureSession ad OpenGL in modo che condividano la memoria nell'hardware grafico.

Dovrebbe essere abbastanza semplice modificare AVCaptureSession in modo che utilizzi un file film come input anziché come input della videocamera.

Probabilmente è possibile impostare la sessione per consegnare i frame in formato Y/UV anziché RGB, dove il componente Y è luminanza. In caso contrario, sarebbe molto semplice scrivere uno shader in grado di convertire i valori RGB per ciascun pixel in valori di luminanza.

Dovreste essere in grado di fare tutto questo su TUTTI i fotogrammi, non solo su ogni 10 fotogramma.

+0

mi sembra che debba essere un partecipante WWDC 2011 per ottenere quel campione. Continuo a preoccuparmi che questa sia effettivamente la transcodifica in tempo reale. Voglio ottenere 15x velocità (15 minuti di video scansionati in 1 minuto). Penso che il collo della bottiglia sia nella decodifica del fotogramma. –

+0

@simon.d - Descrivo la tecnica utilizzata nell'esempio ChromaKey nella mia risposta qui: http://stackoverflow.com/a/9704392/19679, e puoi prendere il mio codice GPUImage per vederlo in azione per la codifica dei film. Non ho ancora aggiornato il mio codice di lettura del film per utilizzare caricamenti di texture veloci, però. Dato che i dispositivi iOS dispongono di hardware dedicato per la decodifica H.264, mi sento ragionevolmente certo a dire che non si otterrà un parsing più veloce per i film rispetto all'utilizzo di AVFoundation con i caricamenti di texture veloci iOS 5.0. –

+0

Il codice di esempio RosyWriter di Apple mostra anche questo AVCaptureSession -> OpenGL link. Vedi [qui] (https://developer.apple.com/library/ios/samplecode/RosyWriter/Introduction/Intro.html). – bcattle

0

Apparentemente vImage potrebbe essere appropriato, presupponendo che sia possibile utilizzare iOS 5. Ogni decimo fotogramma sembra essere motivo di utilizzo di un framework come vImage. Tuttavia, qualsiasi tipo di elaborazione in tempo reale quasi certamente richiederà OpenGL.

+0

Grazie a @LucasTizma. Daremo un'occhiata a vImage. Tuttavia, il mio obiettivo è quello di avere più velocemente dell'elaborazione in tempo reale. Ecco perché volevo solo fare ogni 10 fotogramma. Quindi immagina che il video sia già registrato sul telefono e ora voglio provare a scannerizzare. Questo esclude vImage? –

+0

v L'immagine è solo un mezzo per eseguire rapidamente operazioni di elaborazione delle immagini. Penso che starai bene. Apparentemente, a parte OpenGL, questa è la soluzione più veloce possibile. Altri, sentiti libero di correggermi se sbaglio. – LucasTizma

+0

ma vImage è utile solo dopo aver decodificato il frame? Se è così, non sono sicuro di averne bisogno. Il 90% del lavoro sta effettivamente decodificando il frame, non elaborando i pixel. –

0

Supponendo che il collo di bottiglia della tua applicazione sia nel codice che converte i fotogrammi video in un formato visualizzabile (come RGB), potresti essere interessato a un codice che ho condiviso utilizzato per convert one .mp4 frame (encoded as YV12) to RGB using Qt and OpenGL. Questa applicazione carica il frame sulla GPU e attiva un GLSL fragment shader per eseguire la conversione da YV12 a RGB, in modo che possa essere visualizzato in un QImage.

static const char *p_s_fragment_shader = 
    "#extension GL_ARB_texture_rectangle : enable\n" 
    "uniform sampler2DRect tex;" 
    "uniform float ImgHeight, chromaHeight_Half, chromaWidth;" 
    "void main()" 
    "{" 
    " vec2 t = gl_TexCoord[0].xy;" // get texcoord from fixed-function pipeline 
    " float CbY = ImgHeight + floor(t.y/4.0);" 
    " float CrY = ImgHeight + chromaHeight_Half + floor(t.y/4.0);" 
    " float CbCrX = floor(t.x/2.0) + chromaWidth * floor(mod(t.y, 2.0));" 
    " float Cb = texture2DRect(tex, vec2(CbCrX, CbY)).x - .5;" 
    " float Cr = texture2DRect(tex, vec2(CbCrX, CrY)).x - .5;" 
    " float y = texture2DRect(tex, t).x;" // redundant texture read optimized away by texture cache 
    " float r = y + 1.28033 * Cr;" 
    " float g = y - .21482 * Cb - .38059 * Cr;" 
    " float b = y + 2.12798 * Cb;" 
    " gl_FragColor = vec4(r, g, b, 1.0);" 
    "}"