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