如何更改相机预览回调缓冲区的方向?

时间:2011-12-08 18:30:10

标签: android android-camera

这是常见问题的变体,但我没有看到这种情况,所以我会把它扔出去。

我有一个onPreviewFrame回调设置。这会得到一个包含NV21数据的byte []。我们对它进行h.264编码并将其作为视频流发送出去。另一方面,我们看到视频偏向90度或270度,具体取决于手机。

所以问题是,如何旋转数据,而不仅仅是预览图像? Camera.Parameters.setRotation仅影响拍照,而不影响视频。 Camera.setDisplayOrientation明确表示它只影响显示预览,而不影响帧字节:

  

这不会影响onPreviewFrame(byte [],Camera),JPEG图片或录制视频中传递的字节数组的顺序。

那么在任何API级别都有一种方法可以改变字节数组的方向吗?如果不这样做,你甚至可以旋转这种格式的NV21(YVU)格式,还是首先需要RGB格式呢?

2 个答案:

答案 0 :(得分:1)

原来你需要在发送之前自己旋转每一帧。我们最终使用了libyuv,它具有非常方便的功能,可以旋转并转换它 - libyuv :: ConvertToI420

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

答案 1 :(得分:0)

我认为您需要自己旋转图片。我使用NDK和leptonica库做了一次。看看我的代码应该让你入门。在三星Galaxy S2上表现还不错(我觉得我大约有15帧左右)。由于我将结果推入openGL纹理,我不得不调整周围的颜色字节.. 您可以通过直接在循环中旋转图像来加速它,该循环解码yuv数据。

之前已经分配了mPix32和mPix8来保存转换后的数据。当然,您需要替换自己的图像数据结构。

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

}