我正在开发一个小型 Android 应用程序,以将一些相机镜头(作为一系列 JPEG)流式传输到我的计算机。在不进行任何处理的情况下,帧缓冲区以大约 18 fps 的速度接收相机预览图像。当我添加
YuvImage yuv = new YuvImage(data, ImageFormat.NV21, dimensions.width, dimensions.height, null);
yuv.compressToJpeg(new Rect(0, 0, dimensions.width, dimensions.height), 40, out);
帧速率下降到约 7 fps。所以我想我会用 C 语言编写自己的 JPEG 编码器并加快速度。好吧,我是一个惊喜。我现在得到 0.4 fps!
所以现在我需要分析和优化我的 C 代码,但我真的不知道从哪里开始。我正在使用这些 GCC 标志:
-Wall -std=c99 -ffast-math -O3 -funroll-loops
那里有什么我可以改进的吗?
除此之外,我的 JPEG 编码器只是一个简单的实现。写头信息,写量化和霍夫曼表,然后对数据进行熵编码。DCT 正在使用 AA&N 的方法,我相信这是最快的方法。
也许 JNI 开销有问题?
我正在使用 Java 分配内存:
frame_buffer = ByteBuffer.allocate(raw_preview_buffer_size).array();
jpeg_buffer = ByteBuffer.allocate(10000000).array();
然后用这段代码把它拉进去(现在请原谅意大利面):
void Java_com_nechtan_limelight_activities_CameraPreview_handleFrame(JNIEnv* env, jobject this, jbyteArray nv21data, jbyteArray jpeg_buffer) {
jboolean isCopyNV21;
jboolean isCopyJPEG;
int jpeg_size = 0;
jbyte* nv21databytes = (*env)->GetByteArrayElements(env, nv21data, &isCopyNV21);
jbyte* jpeg_buffer_bytes = (*env)->GetByteArrayElements(env, jpeg_buffer, &isCopyJPEG);
if (nv21databytes != NULL) {
if (jpeg_buffer_bytes != NULL) {
jpeg_size = compressToJpeg((UCHAR*) nv21databytes, (UCHAR*) jpeg_buffer_bytes, 640, 480);
(*env)->ReleaseByteArrayElements(env, jpeg_buffer, jpeg_buffer_bytes, 0);
(*env)->ReleaseByteArrayElements(env, nv21data, nv21databytes, JNI_ABORT);
}
else {
__android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "JPEG data null!");
}
}
else {
__android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NV21 data null!");
}
}
我在这里做一些低效的事情吗?什么是分析 JNI 代码的好方法?
除了这些,我唯一能想到的就是我将不得不阅读关于 NEON 的内容并将这些东西矢量化。啊...