From 53fbc0a60a1830c1c34bfb3e064df1cbbcb89ded Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20B=C3=A9raud?= <adrien.beraud@savoirfairelinux.com> Date: Sat, 25 Sep 2021 16:54:29 -0400 Subject: [PATCH] android video: use sinkclient custom buffer to avoid copy Pixel 4 XL, 720p: before: 6.69 ms (14,9 fps) after: 5.92 ms (16,9 fps) Change-Id: I8a2bdbed7388efbf95b066ace2f8032684a87a2e --- bin/jni/videomanager.i | 54 +++++++++++++++--------------------------- 1 file changed, 19 insertions(+), 35 deletions(-) diff --git a/bin/jni/videomanager.i b/bin/jni/videomanager.i index 9dfed0b1b8..945d78daab 100644 --- a/bin/jni/videomanager.i +++ b/bin/jni/videomanager.i @@ -290,7 +290,6 @@ JNIEXPORT jlong JNICALL Java_net_jami_daemon_JamiServiceJNI_acquireNativeWindow( JNIEXPORT void JNICALL Java_net_jami_daemon_JamiServiceJNI_releaseNativeWindow(JNIEnv *jenv, jclass jcls, jlong window_) { - std::lock_guard<std::mutex> guard(windows_mutex); ANativeWindow *window = (ANativeWindow*)((intptr_t) window_); ANativeWindow_release(window); } @@ -298,37 +297,17 @@ JNIEXPORT void JNICALL Java_net_jami_daemon_JamiServiceJNI_releaseNativeWindow(J JNIEXPORT void JNICALL Java_net_jami_daemon_JamiServiceJNI_setNativeWindowGeometry(JNIEnv *jenv, jclass jcls, jlong window_, int width, int height) { ANativeWindow *window = (ANativeWindow*)((intptr_t) window_); - ANativeWindow_setBuffersGeometry(window, width, height, WINDOW_FORMAT_RGBA_8888); + ANativeWindow_setBuffersGeometry(window, width, height, WINDOW_FORMAT_RGBX_8888); } void AndroidDisplayCb(ANativeWindow *window, std::unique_ptr<DRing::FrameBuffer> frame) { - std::unique_lock<std::mutex> guard(windows_mutex, std::defer_lock); - if (!guard.try_lock()) - return; + ANativeWindow_unlockAndPost(window); + std::unique_lock<std::mutex> guard(windows_mutex); try { - auto& i = windows.at(window); - ANativeWindow_Buffer buffer; - if (ANativeWindow_lock(window, &buffer, NULL) == 0) { - if (buffer.bits && frame && frame->ptr) { - if (buffer.stride == frame->width) - memcpy(buffer.bits, frame->ptr, frame->width * frame->height * 4); - else { - size_t line_size_in = frame->width * 4; - size_t line_size_out = buffer.stride * 4; - for (size_t i=0, n=frame->height; i<n; i++) - memcpy((uint8_t*)buffer.bits + line_size_out * i, frame->ptr + line_size_in * i, line_size_in); - } - } - else - __android_log_print(ANDROID_LOG_WARN, TAG, "Can't copy surface"); - ANativeWindow_unlockAndPost(window); - } else { - __android_log_print(ANDROID_LOG_WARN, TAG, "Can't lock surface"); - } - i = std::move(frame); + windows.at(window) = std::move(frame); } catch (...) { - __android_log_print(ANDROID_LOG_WARN, TAG, "Can't copy frame: no window"); + __android_log_print(ANDROID_LOG_WARN, TAG, "Can't move frame: no window"); } } @@ -340,17 +319,20 @@ std::unique_ptr<DRing::FrameBuffer> sinkTargetPullCallback(ANativeWindow *window std::lock_guard<std::mutex> guard(windows_mutex); ret = std::move(windows.at(window)); } - if (not ret) { - __android_log_print(ANDROID_LOG_WARN, TAG, "Creating new video buffer of %zu kib", bytes/1024); - ret.reset(new DRing::FrameBuffer()); + if (ret) { + ANativeWindow_Buffer buffer; + if (ANativeWindow_lock(window, &buffer, nullptr) == 0) { + ret->avframe->format = AV_PIX_FMT_RGBA; + ret->avframe->width = buffer.width; + ret->avframe->height = buffer.height; + ret->avframe->data[0] = (uint8_t *) buffer.bits; + ret->avframe->linesize[0] = buffer.stride * 4; + } + return ret; } - ret->storage.resize(bytes); - ret->ptr = ret->storage.data(); - ret->ptrSize = bytes; - return ret; } catch (...) { - return {}; } + return {}; } JNIEXPORT void JNICALL Java_net_jami_daemon_JamiServiceJNI_registerVideoCallback(JNIEnv *jenv, jclass jcls, jstring sinkId, jlong window) @@ -371,7 +353,9 @@ JNIEXPORT void JNICALL Java_net_jami_daemon_JamiServiceJNI_registerVideoCallback { std::lock_guard<std::mutex> guard(windows_mutex); - windows.emplace(nativeWindow, nullptr); + auto buf = std::make_unique<DRing::FrameBuffer>(); + buf->avframe.reset(av_frame_alloc()); + windows.emplace(nativeWindow, std::move(buf)); } DRing::registerSinkTarget(sink, DRing::SinkTarget {.pull=p_display_cb, .push=f_display_cb}); } -- GitLab