2011-12-08 9 views
9

Esta es una variación de una pregunta que se hace a menudo por los alrededores, pero no veo esta situación exacta, así que la arrojaré allí.¿Cómo cambiar la orientación del buffer de devolución de llamada de la cámara?

Tengo una configuración de devolución de llamada onPreviewFrame. Esto obtiene un byte [] con datos NV21 en él. Nosotros h.264 lo codificamos y lo enviamos como una transmisión de video. Por otro lado, vemos el video sesgado, ya sea 90 o 270 grados, dependiendo del teléfono.

Entonces la pregunta es, ¿cómo rotar los datos de , no solo la imagen de vista previa? Camera.Parameters.setRotation solo afecta la toma de la imagen, no el video. Camera.setDisplayOrientation específicamente dice que sólo afecta a la vista previa que muestra, no los bytes de la trama:

Esto no afecta el orden de la matriz de bytes aprobada en onPreviewFrame (byte [], la cámara), las imágenes JPEG o vídeos grabados.

¿Hay alguna manera, en cualquier nivel de API, de cambiar la orientación de la matriz de bytes? En su defecto, ¿puede incluso rotar el formato NV21 (YVU) que viene, o necesito RGB primero?

+2

Tal vez me falta algo, pero ¿no es una tarea relativamente sencillo de correr los datos a través de una matriz para rotarlo de la forma que desee? Presumiblemente, usted conoce el ancho y el alto de su vista previa, por lo tanto, debería poder simplemente copiar los bytes en una nueva matriz de bytes que los ordena en la orientación deseada, ¿no? No he hecho esto, entonces, quizás estoy lamentablemente fuera de la base. –

+0

No, eso lo haría, pero hacer esto para cada fotograma, incluso decir 5ps, parece mucho procesamiento. Pero creo que puede ser la única forma. – Hieronymus

Respuesta

1

Resulta que sí es necesario para hacer girar cada cuadro a sí mismo antes de enviarlo. Terminamos con libyuv, que tiene una función muy conveniente que tanto gira y lo convierte - libyuv :: ConvertToI420

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

0

Creo que tendría que rotar la imagen usted mismo. Lo hice una vez usando el NDK y la biblioteca leptonica. Una mirada a mi código debería ayudarte a comenzar. El rendimiento fue bueno en un Samsung Galaxy S2 (creo que obtuve alrededor de 15 cuadros más o menos). Como estaba insertando el resultado en una textura OpenGL, también tuve que oscilar los bytes de color alrededor de ... Se puede acelerar girando la imagen directamente en el ciclo que decodifica los datos de yuv.

mPix32 y mPix8 eran previamente asignado para contener los convertidos data.You tendría que sustituir con su propia estructura de datos de imagen, por supuesto ..

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

} 
Cuestiones relacionadas