Мой кодировщик JNI JPEG для Android очень медленный

Я работаю над небольшим Android-приложением, чтобы передать некоторые кадры камеры (как серии JPEG) на мой компьютер. Без обработки буфер кадра получает предварительные изображения камеры со скоростью около 18 кадров в секунду. Когда я добавляю

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 кадров в секунду. Поэтому я решил написать свой собственный кодировщик JPEG на C и немного ускорить его. Ну, я был удивлен. Теперь я получаю 0,4 кадра в секунду!

Так что теперь мне нужно профилировать и оптимизировать мой 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 и векторизовать этот материал. Тьфу …

Попробуйте использовать встроенный кодировщик:

  private byte[] compressYuvToJpeg(final byte[] yuvData) { mJpegCompressionBuffer.reset(); YuvImage yuvImage = new YuvImage(yuvData, ImageFormat.NV21, mPreviewWidth, mPreviewHeight, null); yuvImage.compressToJpeg(new Rect(0, 0, mPreviewWidth, mPreviewHeight), mJpegQuality, mJpegCompressionBuffer); return mJpegCompressionBuffer.toByteArray(); }