如何改变摄像头预览callback缓冲区的方向?

这是一个经常被问到的问题上的变化,但是我没有看到这个确切的情况,所以我会把它扔在那里。

我有一个onPreviewFramecallback设置。 这会得到一个带有NV21数据的字节[]。 我们h.264将其编码并将其作为videostream发送出去。 另一方面,我们看到video倾斜,90或270度,取决于电话。

所以问题是,如何旋转数据 ,而不仅仅是预览图像? Camera.Parameters.setRotation只影响拍摄的照片,而不是video。 Camera.setDisplayOrientation专门说它只影响显示预览,而不是帧字节:

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

那么有没有办法在任何API级别改变字节数组的方向? 如果不这样做,你甚至可以旋转NV21(YVU)格式,或者我需要首先RGB?

Solutions Collecting From Web of "如何改变摄像头预览callback缓冲区的方向?"

事实certificate,你需要自己旋转每一帧之前发送它。 我们结束了使用libyuv,它有一个非常方便的function,旋转和转换它 – libyuv :: ConvertToI420

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

我认为你需要自己旋转图片。 我曾经使用过NDK和leptonica库。 看看我的代码应该让你开始。 三星Galaxy S2的性能performance还不错(我想我大概有15帧左右)。 因为我把结果推到openGL纹理中,所以我也必须调整周围的颜色字节。你可以通过在解码yuv数据的循环中直接旋转图像来加速它。

mPix32和mPix8以前被分配来保存转换的数据。您将需要replace您自己的图像数据结构当然..

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