2011-10-25 11 views
5

sto usando glReadPixels per leggere i dati in un CVPixelBufferRef. Io uso CVPixelBufferRef come input in un AVAssetWriter. Sfortunatamente i formati dei pixel sembrano non corrispondere.formati pixel, CVPixelBufferRefs e glReadPixels

Penso glReadPixels sta tornando dati pixel in RGBA formato mentre AVAssetWriter vuole dati dei pixel in formato ARGB . Qual è il modo migliore per convertire RGBA a ARGB?

Ecco quello che ho provato finora:

manipolazione
  • po 'sulla falsariga di argb = (RGBA >> 8) | (RGBA < < 24)
  • utilizzando un CGImageRef come passo intermedio

La manipolazione bit non ha funzionato perché CVPixelBufferRef non sembra supportare pedici. Il passaggio intermedio CGImageRef funziona ... ma preferirei non avere 50 righe di codice in più che potrebbero potenzialmente essere un successo in termini di prestazioni.

+2

Come si ottiene il CVPixelBufferRef?Stai chiamando CVPixelBufferCreate? In tal caso, cosa passi come parametro pixelFormatType? Che formato stai passando a glReadPixels? –

+0

Sto passando 'kCVPixelFormatType_32ARGB' a' CVPixelBufferCreate'. Passo 'GL_RBGA' a' glReadPixels'. Ho provato a passare un formato RBGA a 'CVPixelBufferCreate', ma non ha funzionato (i colori danneggiati o l'app si è bloccata). – MrDatabase

risposta

6

meglio che usare la CPU per scambiare i componenti sarebbe quello di scrivere un semplice Shader frammento di farlo in modo efficiente su la GPU mentre esegui il rendering dell'immagine.

E il modo migliore è rimuovere completamente la fase di copia utilizzando un CoreVideo CVOpenGLESTextureCache per iOS5 che consente di eseguire il rendering direttamente su CVPixelBufferRef, eliminando la chiamata a glReadPixels.

p.s. Sono abbastanza sicuro che AVAssetWriter voglia dati in formato BGRA (in realtà probabilmente lo vuole in yuv, ma questa è un'altra storia).

UPDATE: come per i collegamenti, la doco sembra essere ancora sotto NDA, ma ci sono due pezzi di codice di esempio scaricabile gratuitamente disponibili:

GLCameraRipple e RosyWriter

file L'intestazione stessi contengono una buona documentazione, e l'equivalente mac è molto simile (CVOpenGLTextureCache), quindi dovresti avere abbastanza cose da iniziare.

+0

' OpenGLTextureCache' suona bene.Con qualche link ai documenti rilevanti? – MrDatabase

+1

se hai un accesso ADC puoi ottenere i documenti, aggiunto qualche esempio codice per rispondere –

+0

Sembra davvero interessante! Grazie :-) – MrDatabase

2

È una specie di ripresa al buio, ma hai provato GL_BGRA per glReadPixels con kCVPixelFormatType_32BGRA per CVPixelBufferCreate?

Propongo questo perché Technical Q&A QA1501 non elenca qualsiasi formato RGBA come supportato.

+0

Sfortunatamente passare GL_BGRA a 'glReadPixels' fa sì che i dati del pixel di uscita siano tutti pari a zero :-( – MrDatabase

6

Per quanto riguarda la manipolazione dei bit, è possibile ottenere un puntatore ai dati grezzi del buffer di pixel:

CVPixelBufferLockBaseAddress(buffer, 0); 
size_t stride = CVPixelBufferGetBytesPerRow(buffer); 
char *data = (char *)CVPixelBufferGetBaseAddress(buffer); 
for (size_t y = 0; y < CVPixelBufferGetHeight(buffer); ++y) { 
    uint32_t *pixels = (uint32_t *)(data + stride * y); 
    for (size_t x = 0; x < CVPixelBufferGetWidth(buffer); ++x) 
     pixels[x] = (pixels[x] >> 8) | (pixels[x] << 24); 
} 
CVPixelBufferUnlockBaseAddress(buffer, 0); 
1

glReadPixels (0, 0, w * s, h * s, GL_BGRA, GL_UNSIGNED_BYTE, buffer);

Usa GL_BGRA in glReadPixels. Funziona, l'ho provato da solo.

+0

Hai ricevuto dati diversi da zero nel buffer di uscita? – MrDatabase

+0

GL_BGRA crea un carico di errori opengl. – emrahgunduz

1
glReadPixels(0, 0, width, height, GL_BGRA, GL_UNSIGNED_BYTE, _buffer); 
    CVPixelBufferRef buffer = NULL; 
    CVReturn ret = CVPixelBufferCreateWithBytes(kCFAllocatorDefault,_size.width,_size.height,kCVPixelFormatType_32BGRA,glubyte,_size.width*4,NULL,NULL,NULL,&buffer);