2011-12-08 10 views
9

Questa è una variazione su una domanda spesso posta qui, ma non vedo questa situazione esatta, quindi la lancerò lì.Come modificare l'orientamento del buffer di richiamata dell'anteprima della videocamera?

Ho impostato un callback suPreviewFrame. Questo ottiene un byte [] con i dati NV21 al suo interno. H.264 lo codifichiamo e lo inviamo come flusso video. Dall'altro lato, vediamo il video inclinato, a 90 o 270 gradi, a seconda del telefono.

Quindi la domanda è, come ruotare i dati , non solo l'immagine di anteprima? Camera.Parameters.setRotation riguarda solo scattare la foto, non il video. Camera.setDisplayOrientation specificamente dice che influenza solo l'anteprima la visualizzazione, non i byte del telaio:

Ciò non pregiudica l'ordine dei byte passato in onPreviewFrame (byte [], Camera), immagini JPEG o video registrati.

Quindi esiste un modo, a qualsiasi livello API, per modificare l'orientamento della matrice di byte? In caso contrario, è possibile ruotare anche il formato NV21 (YVU) in cui è presente, oppure è necessario prima eseguire l'RGB?

+2

Forse mi manca qualcosa, ma non è un compito relativamente semplice in avanti di corsa i dati attraverso una matrice per ruotarlo come preferisci? Presumibilmente, conoscete la larghezza e l'altezza dell'anteprima, quindi dovreste essere in grado di copiare semplicemente i byte in un nuovo array di byte che li ha ordinati nell'orientamento desiderato, no? Non l'ho fatto, quindi, forse sono tristemente fuori base. –

+0

No, lo farebbe, ma farlo per ogni fotogramma, anche a dire 5ps, sembra un sacco di elaborazione. Ma penso che potrebbe essere l'unico modo. – Hieronymus

risposta

1

scopre che c'è bisogno di ruotare ogni fotogramma te stesso prima di inviarlo via. Abbiamo finito per usare libyuv, che ha una funzione molto comoda che sia ruota e lo converte - libyuv :: ConvertToI420

https://code.google.com/p/libyuv/

0

Penso che sarebbe necessario ruotare l'immagine da soli. L'ho fatto una volta usando l'NDK e la libreria leptonica. Uno sguardo al mio codice dovrebbe iniziare. Le prestazioni erano okay su un Samsung Galaxy S2 (penso di avere circa 15 fotogrammi o giù di lì). Dato che stavo spingendo il risultato in una trama openGL ho dovuto anche scambiare i byte di colore intorno. Puoi accelerarlo ruotando l'immagine direttamente nel ciclo che decodifica i dati yuv ..

mPix32 e mPix8 erano in precedenza assegnato a contenere il convertito data.You avrebbe bisogno di sostituire con la propria struttura dei dati immagine, naturalmente ..

jint Java_de_renard_ImageFilter_nativeProcessImage(JNIEnv *env, jobject javathis, jbyteArray frame) { 
    .... 
    jbyte *data_buffer = env->GetByteArrayElements(frame, NULL); 
    l_uint8 *byte_buffer = (l_uint8 *) data_buffer; 
    yuvToPixFast(byte_buffer, mPix32, mPix8); 
    env->ReleaseByteArrayElements(frame, data_buffer, JNI_ABORT); 
    .... 
} 

static inline void yuvToPixFast(unsigned char* pY, Pix* pix32, Pix* pix8) { 
    int i, j; 
    int nR, nG, nB; 
    int nY, nU, nV; 
    l_uint32* data = pixGetData(pix32); 
    l_uint32* data8 = pixGetData(pix8); 
    l_int32 height = pixGetHeight(pix32); 
    l_int32 width = pixGetWidth(pix32); 
    l_int32 wpl = pixGetWpl(pix32); 
    l_int32 wpl8 = pixGetWpl(pix8); 
    l_uint8 **lineptrs = pixSetupByteProcessing(pix8, NULL, NULL); 
    l_uint8* line8; 

    //memcpy(data8,pY,height*width); 

    unsigned char* pUV = pY + width * height; 

    for (i = 0; i < height; i++) { 
     nU = 0; 
     nV = 0; 
     unsigned char* uvp = pUV + (i >> 1) * width; 
     line8 = lineptrs[i]; 
     memcpy(line8, pY, wpl8 * 4); 

     for (j = 0; j < width; j++) { 

      if ((j & 1) == 0) { 
       nV = (0xff & *uvp++) - 128; 
       nU = (0xff & *uvp++) - 128; 
      } 
      // Yuv Convert 
      nY = *(pY++); 
      //*line8++ = (l_uint8) nY; 
      nY -= -16; 

      if (nY < 0) { 
       nY = 0; 
      } 
      int y1192 = nY * 1192; 

      /*double saturation to increase cartoon effect*/ 
      //nU<<=1; 
      //nV<<=1; 

      nB = y1192 + 2066 * nU; 
      nG = y1192 - 833 * nV - 400 * nU; 
      nR = y1192 + 1634 * nV; 

      if (nR < 0) { 
       nR = 0; 
      } else if (nR > 262143) { 
       nR = 262143; 
      } 
      if (nG < 0) { 
       nG = 0; 
      } else if (nG > 262143) { 
       nG = 262143; 
      } 
      if (nB < 0) { 
       nB = 0; 
      } else if (nB > 262143) { 
       nB = 262143; 
      } 
      //RGBA 
      //ABGR 
      *data++ = ((nR << 14) & 0xff000000) | ((nG << 6) & 0xff0000) | ((nB >> 2) & 0xff00) | (0xff); 
      //*data++ = (0x00 << 24) | (0xff<<16) | (0x00<<8) | (0xff) ; 
      //*data++ = (0xff << 24) | ((nB << 6) & 0xff0000) | ((nG >> 2) & 0xff00) | ((nR >> 10) & 0xff); 
     } 
    } 
    pixCleanupByteProcessing(pix8, lineptrs); 

} 
Problemi correlati