2012-06-14 26 views
5

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 ...

+2

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. –

+1

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

+0

@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

Trả lời

0

Hãy thử sử dụng xây dựng trong bộ mã hóa:

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(); 
    } 
+1

Ở đầu bài đăng của tôi, đó thực sự là những gì tôi làm ban đầu. Nó không đủ nhanh.Với bộ xử lý 800 MHz mà điện thoại của tôi có, đó là khoảng 96 chu kỳ đồng hồ trên mỗi mẫu màu để duy trì 18 khung hình/giây. Nó chắc chắn sẽ có thể theo cách này hay cách khác. – Nick

+0

Tôi khuyên bạn nên kiểm tra chức năng nào chiếm thời gian tính toán nhiều nhất, đơn giản bằng cách bỏ qua một hàm quặng khác và đo thời gian nhận ở phía máy tính. Cũng lưu ý rằng có một streamer h264 cho android, http://code.google.com/p/ipcamera-for-android/ –

Các vấn đề liên quan