2012-06-14 8 views
5

Pracuję nad niewielką aplikacją na Androida, aby przesłać niektóre pliki z kamery (w postaci serii plików JPEG) do mojego komputera. Bez przetwarzania, bufor ramki otrzymuje obrazy z podglądu z kamery przy około 18 fps. Gdy dodaję liczbę klatek na sekundę, spada do około 7 klatek na sekundę. Pomyślałem więc, że napiszę własny koder JPEG w C i trochę go przyspieszę. Cóż, byłem zaskoczony. Teraz otrzymuję 0,4 fps!Mój koder JNI dla Androida jest bardzo wolny.

Teraz muszę profilować i optymalizować mój kod C, ale tak naprawdę nie wiem od czego zacząć. Używam tych flag GCC:

-Wall -std=c99 -ffast-math -O3 -funroll-loops 

Czy mogę coś poprawić?

Poza tym mój koder JPEG to prosta implementacja. Napisz informacje o nagłówku, wpisz kwantyzację i tabele Huffmana, a następnie entropij koduj dane. DCT używa metody AA & N, uważam, że jest to najszybszy sposób robienia tego.

Być może istnieje problem z obciążeniem JNI?

mam alokacji pamięci w Javie przy użyciu:

frame_buffer = ByteBuffer.allocate(raw_preview_buffer_size).array(); 
jpeg_buffer = ByteBuffer.allocate(10000000).array(); 

a potem pociągając w tym kodem (przepraszam spaghetti w tej chwili):

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!"); 
     } 

    } 

robię coś nieefektywne tutaj? Jaki jest dobry sposób na profilowanie kodu JNI?

Oprócz tych rzeczy, jedyne, co mogę wymyślić to to, że będę musiał przeczytać o NEON i wektoryzować te rzeczy. Fuj ...

+2

Korzystanie z gotowych Encoder, gdzie ktoś już zrobił wszystko odczuwalną optymalizacji byłoby logicznym pierwszy krok. Również wskazane może być oddzielenie kompresji od akwizycji. –

+1

Przydzielanie pamięci w Javie, a następnie używanie jej w trybie macierzystym, powoduje niską wydajność. Możesz dokonać alokacji pamięci i plików we/wy w natywnym kodzie, a to będzie działać znacznie lepiej. Nie mogę komentować Twojego kodu JPEG, ponieważ nie udostępniłeś go, ale mój natywny kodek/dekoder JPEG działa dobrze na Androidzie, zachowując wszystko po stronie natywnej. – BitBank

+0

@Seva, to nie pozostanie JPEG - w końcu zmieni się w jeden z koderów falkowych dla wideo, ale potrzebuję linii bazowej, aby upewnić się, że wszystko jest poprawnie zoptymalizowane – Nick

Odpowiedz

0

Spróbuj użyć Wbudowany enkoder:

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 góry mojego wpisu, tak naprawdę to robię pierwotnie. Nie jest to jednak wystarczająco szybkie.Dzięki procesorowi 800 MHz, który ma mój telefon, to około 96 cykli zegarowych na próbkę koloru, aby utrzymać 18 klatek na sekundę. Z pewnością powinno być możliwe w ten czy inny sposób. – Nick

+0

Proponuję sprawdzić, która funkcja zajmuje najwięcej czasu obliczeniowego, po prostu pomijając jedną lub więcej funkcji i mierząc czas odbierania po stronie komputera. Pamiętaj też, że istnieje streamer h264 dla Androida, http://code.google.com/p/ipcamera-for-android/ –

Powiązane problemy