Tôi đang làm việc trên một ứng dụng Android nhỏ để phát một số cảnh quay của máy ảnh (như một loạt ảnh JPEG) sang máy tính của tôi. Khi không xử lý, bộ đệm khung sẽ nhận được hình ảnh xem trước máy ảnh ở khoảng 18 khung hình/giây. Khi tôi thêm vàoBộ mã hóa JNI JPEG của tôi cho Android thực sự chậm
YuvImage yuv = new YuvImage(data, ImageFormat.NV21, dimensions.width, dimensions.height, null);
yuv.compressToJpeg(new Rect(0, 0, dimensions.width, dimensions.height), 40, out);
tốc độ khung hình giảm xuống còn khoảng 7 khung hình/giây. Vì vậy, tôi nghĩ rằng tôi muốn viết bộ mã hóa JPEG của riêng tôi trong C và tăng tốc độ nó lên một chút. Tôi đã ngạc nhiên. Tôi hiện đang nhận được 0,4 khung hình/giây!
Vì vậy, bây giờ tôi cần phải hồ sơ và tối ưu hóa mã C của mình, nhưng tôi thực sự không biết bắt đầu từ đâu. Tôi đang sử dụng các cờ GCC này:
-Wall -std=c99 -ffast-math -O3 -funroll-loops
Tôi có thể cải thiện điều gì ở đó không?
Ngoài ra, bộ mã hóa JPEG của tôi chỉ là một triển khai thẳng về phía trước. Viết thông tin tiêu đề, viết quantization và Huffman bảng, sau đó entropy mã hóa dữ liệu. DCT đang sử dụng phương pháp của AA & N Tôi tin là cách nhanh nhất để thực hiện điều này.
Có thể có vấn đề với chi phí JNI?
Tôi đang phân bổ bộ nhớ trong Java sử dụng:
frame_buffer = ByteBuffer.allocate(raw_preview_buffer_size).array();
jpeg_buffer = ByteBuffer.allocate(10000000).array();
và sau đó kéo nó với mã này (tha thứ spaghetti vào lúc này):
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!");
}
}
Tôi có làm một cái gì đó không hiệu quả đây? Một cách tốt để cấu hình mã JNI là gì?
Khác với những thứ đó, điều duy nhất tôi có thể nghĩ đến là tôi sẽ phải đọc về NEON và vector hóa nội dung này. Ugh ...
Sử dụng một sẵn sàng thực hiện mã hóa, nơi mà một người nào đó đã làm tất cả các tối ưu hóa hợp lý, sẽ là bước đầu tiên logic. Ngoài ra, việc tách nén từ việc mua lại có thể được khuyến khích. –
Phân bổ bộ nhớ trong Java và sau đó sử dụng nó trong bản địa sẽ gây ra hiệu suất kém. Bạn có thể làm phân bổ bộ nhớ và tập tin I/O trong mã gốc và nó sẽ thực hiện tốt hơn nhiều. Tôi không thể nhận xét về mã JPEG của bạn vì bạn chưa chia sẻ nó, nhưng bộ mã hóa/giải mã JPEG gốc của tôi hoạt động tốt trên Android bằng cách giữ mọi thứ ở phía gốc. – BitBank
@Seva, nó sẽ không ở lại JPEG - nó sẽ biến thành một trong các bộ mã hóa wavelet cho video, nhưng tôi cần một đường cơ sở để đảm bảo rằng tôi nhận được mọi thứ được tối ưu hóa chính xác – Nick