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