From 91897ff584b2f957a2060a50ca6499b7a295a081 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20B=C3=A9raud?= <adrien.beraud@savoirfairelinux.com> Date: Fri, 8 Mar 2019 14:03:17 -0500 Subject: [PATCH] android: support accelerated video rotation Change-Id: Id19a9987a218ef94915e94df9635c11986d8a34e --- bin/jni/videomanager.i | 46 +++++++++++++++++--------------- src/media/video/video_sender.cpp | 22 +++++++++------ 2 files changed, 38 insertions(+), 30 deletions(-) diff --git a/bin/jni/videomanager.i b/bin/jni/videomanager.i index 2cc0d02d3d..05128aced6 100644 --- a/bin/jni/videomanager.i +++ b/bin/jni/videomanager.i @@ -149,7 +149,7 @@ int AndroidFormatToAVFormat(int androidformat) { } } -JNIEXPORT void JNICALL Java_cx_ring_daemon_RingserviceJNI_captureVideoPacket(JNIEnv *jenv, jclass jcls, jobject buffer, jint size, jint offset, jboolean keyframe, jlong timestamp) +JNIEXPORT void JNICALL Java_cx_ring_daemon_RingserviceJNI_captureVideoPacket(JNIEnv *jenv, jclass jcls, jobject buffer, jint size, jint offset, jboolean keyframe, jlong timestamp, jint rotation) { auto frame = DRing::getNewFrame(); if (not frame) @@ -163,6 +163,11 @@ JNIEXPORT void JNICALL Java_cx_ring_daemon_RingserviceJNI_captureVideoPacket(JNI av_init_packet(packet.get()); if (keyframe) packet->flags = AV_PKT_FLAG_KEY; + setRotation(rotation); + if (rotMatrix) { + auto buf = av_packet_new_side_data(packet.get(), AV_PKT_DATA_DISPLAYMATRIX, rotMatrix->size); + std::copy_n(rotMatrix->data, rotMatrix->size, buf); + } auto data = (uint8_t*)jenv->GetDirectBufferAddress(buffer); packet->data = data + offset; packet->size = size; @@ -193,7 +198,6 @@ JNIEXPORT void JNICALL Java_cx_ring_daemon_RingserviceJNI_captureVideoFrame(JNIE avframe->crop_right = avframe->width - jenv->GetIntField(crop, jenv->GetFieldID(rectClass, "right", "I")); } - bool directPointer = true; jobjectArray planes = (jobjectArray)jenv->CallObjectMethod(image, jenv->GetMethodID(imageClass, "getPlanes", "()[Landroid/media/Image$Plane;")); jsize planeCount = jenv->GetArrayLength(planes); if (avframe->format == AV_PIX_FMT_YUV420P) { @@ -243,26 +247,24 @@ JNIEXPORT void JNICALL Java_cx_ring_daemon_RingserviceJNI_captureVideoFrame(JNIE if (rotMatrix) av_frame_new_side_data_from_buf(avframe, AV_FRAME_DATA_DISPLAYMATRIX, av_buffer_ref(rotMatrix)); - if (directPointer) { - image = jenv->NewGlobalRef(image); - imageClass = (jclass)jenv->NewGlobalRef(imageClass); - frame->setReleaseCb([jenv, image, imageClass](uint8_t *) mutable { - bool justAttached = false; - int envStat = gJavaVM->GetEnv((void**)&jenv, JNI_VERSION_1_6); - if (envStat == JNI_EDETACHED) { - justAttached = true; - if (gJavaVM->AttachCurrentThread(&jenv, nullptr) != 0) - return; - } else if (envStat == JNI_EVERSION) { + image = jenv->NewGlobalRef(image); + imageClass = (jclass)jenv->NewGlobalRef(imageClass); + frame->setReleaseCb([jenv, image, imageClass](uint8_t *) mutable { + bool justAttached = false; + int envStat = gJavaVM->GetEnv((void**)&jenv, JNI_VERSION_1_6); + if (envStat == JNI_EDETACHED) { + justAttached = true; + if (gJavaVM->AttachCurrentThread(&jenv, nullptr) != 0) return; - } - jenv->CallVoidMethod(image, jenv->GetMethodID(imageClass, "close", "()V")); - jenv->DeleteGlobalRef(image); - jenv->DeleteGlobalRef(imageClass); - if (justAttached) - gJavaVM->DetachCurrentThread(); - }); - } + } else if (envStat == JNI_EVERSION) { + return; + } + jenv->CallVoidMethod(image, jenv->GetMethodID(imageClass, "close", "()V")); + jenv->DeleteGlobalRef(image); + jenv->DeleteGlobalRef(imageClass); + if (justAttached) + gJavaVM->DetachCurrentThread(); + }); DRing::publishFrame(); } @@ -382,7 +384,7 @@ JNIEXPORT void JNICALL Java_cx_ring_daemon_RingserviceJNI_unregisterVideoCallbac %native(unregisterVideoCallback) void unregisterVideoCallback(jstring, jlong); %native(captureVideoFrame) void captureVideoFrame(jobject, jint); -%native(captureVideoPacket) void captureVideoPacket(jobject, jint, jint, jboolean, jlong); +%native(captureVideoPacket) void captureVideoPacket(jobject, jint, jint, jboolean, jlong, jint); namespace DRing { diff --git a/src/media/video/video_sender.cpp b/src/media/video/video_sender.cpp index ec5ff42b54..9ee13f8514 100644 --- a/src/media/video/video_sender.cpp +++ b/src/media/video/video_sender.cpp @@ -83,6 +83,15 @@ VideoSender::encodeAndSendVideo(VideoFrame& input_frame) forceKeyFrame_ = 0; } #endif + int size {0}; + uint8_t* side_data = av_packet_get_side_data(packet, AV_PKT_DATA_DISPLAYMATRIX, &size); + auto angle = (side_data == nullptr || size == 0) ? 0 : av_display_rotation_get(reinterpret_cast<int32_t*>(side_data)); + if (rotation_ != angle) { + rotation_ = angle; + if (changeOrientationCallback_) + changeOrientationCallback_(rotation_); + } + videoEncoder_->send(*packet); } else { bool is_keyframe = forceKeyFrame_ > 0 @@ -92,14 +101,11 @@ VideoSender::encodeAndSendVideo(VideoFrame& input_frame) --forceKeyFrame_; AVFrameSideData* side_data = av_frame_get_side_data(input_frame.pointer(), AV_FRAME_DATA_DISPLAYMATRIX); - if (side_data) { - auto matrix_rotation = reinterpret_cast<int32_t*>(side_data->data); - auto angle = av_display_rotation_get(matrix_rotation); - if (rotation_ != angle) { - rotation_ = angle; - if (changeOrientationCallback_) - changeOrientationCallback_(rotation_); - } + auto angle = side_data == nullptr ? 0 : av_display_rotation_get(reinterpret_cast<int32_t*>(side_data->data)); + if (rotation_ != angle) { + rotation_ = angle; + if (changeOrientationCallback_) + changeOrientationCallback_(rotation_); } #ifdef RING_ACCEL -- GitLab