Android 如何更改相机预览回调缓冲区的方向?
这是一个在这里经常被问到的问题的变体,但我看不出确切的情况,所以我会把它扔出去 我已设置onPreviewFrame回调。这将获取一个包含NV21数据的字节[]。我们使用h.264编码并将其作为视频流发送出去。另一方面,我们看到视频倾斜,90度或270度,取决于手机 所以问题是,如何旋转数据,而不仅仅是预览图像?Camera.Parameters.setRotation仅影响拍照,而不影响视频。Camera.setDisplayOrientation特别指出,它只影响显示预览,而不影响帧字节: 这不会影响在预览帧(字节[],照相机)、JPEG图片或录制的视频中传递的字节数组的顺序Android 如何更改相机预览回调缓冲区的方向?,android,android-camera,Android,Android Camera,这是一个在这里经常被问到的问题的变体,但我看不出确切的情况,所以我会把它扔出去 我已设置onPreviewFrame回调。这将获取一个包含NV21数据的字节[]。我们使用h.264编码并将其作为视频流发送出去。另一方面,我们看到视频倾斜,90度或270度,取决于手机 所以问题是,如何旋转数据,而不仅仅是预览图像?Camera.Parameters.setRotation仅影响拍照,而不影响视频。Camera.setDisplayOrientation特别指出,它只影响显示预览,而不影响帧字节:
那么,在任何API级别,有没有一种方法可以改变字节数组的方向呢?如果不行,你甚至可以旋转这张图片的NV21(YVU)格式,或者我需要先对其进行RGB吗?我想你需要自己旋转图片。我曾经用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);
}
jint Java_de_renard_ImageFilter_nativeProcessImage(JNIEnv*env、jobject javathis、jbyterarray frame){
....
jbyte*data\u buffer=env->GetByteArrayElements(帧,空);
l_uint8*字节缓冲区=(l_uint8*)数据缓冲区;
yuvToPixFast(字节缓冲区,mPix32,mPix8);
环境->ReleaseByteArrayElements(帧、数据缓冲区、JNI\U中止);
....
}
静态内联void yuvToPixFast(无符号字符*pY,Pix*pix32,Pix*pix8){
int i,j;
国际天然气、天然气、天然气;
内华达州新南威尔士州内特;
l_uint32*data=pixGetData(pix32);
l_uint32*data8=pixGetData(pix8);
l_int32高度=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*第8行;
//memcpy(数据8,pY,高度*宽度);
无符号字符*pUV=pY+宽度*高度;
对于(i=0;i>1)*宽度;
line8=lineptrs[i];
memcpy(第8行,pY,wpl8*4);
对于(j=0;j //nU结果表明,在发送每个帧之前,您确实需要自己旋转每个帧。我们最终使用了libyuv,它有一个非常方便的函数,可以旋转和转换它-libyuv::ConvertToI420
也许我遗漏了一些东西,但这不是一个相对简单的任务,通过矩阵运行数据,以任意方式旋转它吗?大概你知道预览的宽度和高度,所以,你应该能够将字节复制到一个新的字节数组中,并按所需的方向排序,不是吗?我知道了没有这样做,所以,也许我有点太离谱了。不,这样就可以了,但对每一帧都这样做,即使是5ps,似乎需要很多处理。但我认为这可能是唯一的方法。