私は小さなAndroidアプリで、カメラの映像を(一連のJPEGとして)コンピューターにストリーミングしています。処理なしの場合、フレームバッファは約18fpsでカメラプレビュー画像を受信します。追加すると
YuvImage yuv = new YuvImage(data, ImageFormat.NV21, dimensions.width, dimensions.height, null);
yuv.compressToJpeg(new Rect(0, 0, dimensions.width, dimensions.height), 40, out);
フレームレートは約7fpsに低下します。だから私は自分のJPEGエンコーダーをCで書いて、それを少しスピードアップしようと思いました。さて、私は驚きました。私は今0.4fpsを取得しています!
したがって、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について読んで、このことをベクトル化する必要があるということだけです。うーん...