``我想在相机的预览中使用RGB。我使用JNI进行YUV到RGB转换。我改变了RGB中的数据,然后我使用drawBitmap在预览中显示RGB。但它显示非常慢,我怎么能改进它
public void onPreviewFrame(final byte[] data, Camera camera) {
Thread showPic = new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
Canvas c = mHolder.lockCanvas(null);
try {
synchronized (mHolder) {
// TODO Auto-generated method stub
int imageWidth = mCamera.getParameters()
.getPreviewSize().width;
int imageHeight = mCamera.getParameters()
.getPreviewSize().height;
int RGBData[] = new int[imageWidth * imageHeight];
int RGBDataa[] = new int[imageWidth * imageHeight];
int RGBDatab[] = new int[imageWidth * imageHeight];
int center = imageWidth * imageHeight / 2;
Jni.decodeYUV420SP(RGBData, data, imageWidth,
imageHeight); // decode
for (int i = 0; i < center; i++)
RGBDataa[i] = RGBData[i];
for (int i = center; i < imageWidth * imageHeight; i++)
RGBDatab[i - center] = RGBData[i];
for (int i = 0; i < center; i++)
RGBData[i] = RGBDatab[i];
for (int i = center; i < imageWidth * imageHeight; i++)
RGBData[i] = RGBDataa[i - center];
c.drawBitmap(RGBData, 0, imageWidth, 0, 0, imageWidth,
imageHeight, false, new Paint());
// Bitmap bm = Bitmap.createBitmap(RGBData, imageWidth,
// imageHeight, Config.ARGB_8888);
}
} finally {
if (data != null)
mHolder.unlockCanvasAndPost(c);
}
}
});
showPic.run();
}
以下代码是Jni
public class Jni {
public native static void decodeYUV420SP(int[] rgb, byte[] yuv420sp, int width,
int height);
} 方法decodeYUV420SP由C。
完成答案 0 :(得分:0)
我遇到了这个搜索YUV420sp到RGB565转换的线程。如上所述使用decodeYUV420SP工作正常,但我想添加一些运行时注意事项。
我在 Java中使用decodeYUV420SP的第一次测试花费了74秒解码并转换了10秒.mp4 FullHD视频(使用Nexus 6 Android设备)。该分析器报告说,整个过程的96%已用于decodeYUV420SP。
将decodeYUV420SP移动到JNI / C所花费的总时间减少到32秒。打开GCC代码优化,它降至12秒。
虽然OP已经提出了这个建议,但我想强调一下,将例程移到Java上并不是一个改进。虽然它是正确的,Java和C之间的上下文变化是有代价的,但这是一个很好的例子,在本机函数中执行的昂贵操作将很容易补偿这种开销。有关间接成本的声明对于非常简单的JNI函数是有效的,并且需要来回方法和字段查找。这里没有任何内容适用于此。
为了提高OP代码的性能:摆脱为每个帧完成的内存分配并将其全局存储,摆脱RGBData *上的算法并将其移动到JNI。使用 Critical 函数,可以在JNI级别上免费访问数组。
答案 1 :(得分:-2)
不建议使用jni,因为编译器将Java代码更改为C ++的速度很慢。我认为你应该使用像这样的直接方法
public void decodeYUV420SP(int[] rgb, byte[] yuv420sp, int width, int height) {
final int frameSize = width * height;
for (int j = 0, yp = 0; j < height; j++) {
int uvp = frameSize + (j >> 1) * width, u = 0, v = 0;
for (int i = 0; i < width; i++, yp++) {
int y = (0xff & ((int) yuv420sp[yp])) - 16;
if (y < 0) y = 0;
if ((i & 1) == 0) {
v = (0xff & yuv420sp[uvp++]) - 128;
u = (0xff & yuv420sp[uvp++]) - 128;
}
int y1192 = 1192 * y;
int r = (y1192 + 1634 * v);
int g = (y1192 - 833 * v - 400 * u);
int b = (y1192 + 2066 * u);
if (r < 0) r = 0; else if (r > 262143) r = 262143;
if (g < 0) g = 0; else if (g > 262143) g = 262143;
if (b < 0) b = 0; else if (b > 262143) b = 262143;
rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff);
}
}
}
或者只是使用这个
Camera.Parameters.setPreviewFormat(ImageFormat.RGB_565);
直接将格式输出更改为rgb