我正在製作一個小型Android應用程序,將一些相機鏡頭(作爲一系列JPEG)流式傳輸到我的電腦。在沒有處理的情況下,幀緩衝器以約18fps的速度接收相機預覽圖像。當我加入我的用於Android的JNI JPEG編碼器非常慢
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正在使用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並將這些東西進行向量化。唉......
使用現成的編碼器,其中有人已經做了所有明智的優化,將是順理成章的第一步。此外,從收購中解壓縮可能是明智的。 –
在Java中分配內存然後在本機中使用它會導致較差的性能。您可以在本機代碼中執行內存分配和文件I/O,並且性能會更好。我不能評論你的JPEG代碼,因爲你沒有分享它,但是我的本地JPEG編碼器/解碼器在Android上保持了一切,只要保持原生一面。 – BitBank
@Seva,它不會保留JPEG - 它最終會變成視頻的小波編碼器之一,但我需要一個基線來確保我能夠正確地優化所有內容 – Nick