From e0e7f6afb9d29aa1c1fa6f4a3681adc27209cd14 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Adrien=20B=C3=A9raud?= <adrien.beraud@savoirfairelinux.com>
Date: Wed, 9 Sep 2020 16:30:40 -0400
Subject: [PATCH] video: factor getting video orientation

Change-Id: I332fb4f341f3cb433f54b71651a02d6eb417282b
---
 src/client/videomanager.cpp        | 22 ++++++++++++++++++++
 src/dring/videomanager_interface.h |  3 +++
 src/media/media_recorder.cpp       | 10 +---------
 src/media/video/sinkclient.cpp     | 14 ++-----------
 src/media/video/video_mixer.cpp    | 12 +----------
 src/media/video/video_sender.cpp   | 32 +++++++-----------------------
 6 files changed, 36 insertions(+), 57 deletions(-)

diff --git a/src/client/videomanager.cpp b/src/client/videomanager.cpp
index 56ed87ea17..5241073595 100644
--- a/src/client/videomanager.cpp
+++ b/src/client/videomanager.cpp
@@ -49,6 +49,10 @@
 #include <cstring> // std::memset
 #include <ciso646> // fix windows compiler bug
 
+extern "C" {
+#include <libavutil/display.h>
+}
+
 namespace DRing {
 
 MediaFrame::MediaFrame()
@@ -341,6 +345,24 @@ VideoFrame::noise()
     }
 }
 
+int
+VideoFrame::getOrientation() const
+{
+    int32_t* matrix {nullptr};
+    if (auto p = packet()) {
+        matrix = reinterpret_cast<int32_t*>(av_packet_get_side_data(p, AV_PKT_DATA_DISPLAYMATRIX, nullptr));
+    } else if (auto p = pointer()) {
+        if (AVFrameSideData* side_data = av_frame_get_side_data(p, AV_FRAME_DATA_DISPLAYMATRIX)) {
+            matrix = reinterpret_cast<int32_t*>(side_data->data);
+        }
+    }
+    if (matrix) {
+        double angle = av_display_rotation_get(matrix);
+        return std::isnan(angle) ? 0 : -(int)angle;
+    }
+    return 0;
+}
+
 VideoFrame*
 getNewFrame()
 {
diff --git a/src/dring/videomanager_interface.h b/src/dring/videomanager_interface.h
index 04173a3a6c..7dbcea0e75 100644
--- a/src/dring/videomanager_interface.h
+++ b/src/dring/videomanager_interface.h
@@ -149,6 +149,9 @@ public:
     // Allocate internal pixel buffers following given specifications
     void reserve(int format, int width, int height);
 
+    // Return orientation (in degrees) stored in the frame metadata, or 0 by default.
+    int getOrientation() const;
+
     // Set internal pixel buffers on given memory buffer
     // This buffer must follow given specifications.
     void setFromMemory(uint8_t* data, int format, int width, int height) noexcept;
diff --git a/src/media/media_recorder.cpp b/src/media/media_recorder.cpp
index f2ee43918a..61b195c303 100644
--- a/src/media/media_recorder.cpp
+++ b/src/media/media_recorder.cpp
@@ -39,10 +39,6 @@
 #include <sys/types.h>
 #include <ctime>
 
-extern "C" {
-#include <libavutil/display.h>
-}
-
 namespace jami {
 
 const constexpr char ROTATION_FILTER_INPUT_NAME[] = "in";
@@ -87,11 +83,7 @@ struct MediaRecorder::StreamObserver : public Observer<std::shared_ptr<MediaFram
             else
 #endif
                 framePtr = std::static_pointer_cast<VideoFrame>(m);
-            AVFrameSideData* sideData = av_frame_get_side_data(framePtr->pointer(),
-                                                               AV_FRAME_DATA_DISPLAYMATRIX);
-            int angle = sideData
-                            ? -av_display_rotation_get(reinterpret_cast<int32_t*>(sideData->data))
-                            : 0;
+            int angle = framePtr->getOrientation();
             if (angle != rotation_) {
                 videoRotationFilter_ = jami::video::getTransposeFilter(angle,
                                                                        ROTATION_FILTER_INPUT_NAME,
diff --git a/src/media/video/sinkclient.cpp b/src/media/video/sinkclient.cpp
index 02f36f7dd9..e52b0ddd54 100644
--- a/src/media/video/sinkclient.cpp
+++ b/src/media/video/sinkclient.cpp
@@ -58,10 +58,6 @@
 #include <stdexcept>
 #include <cmath>
 
-extern "C" {
-#include <libavutil/display.h>
-}
-
 namespace jami {
 namespace video {
 
@@ -367,14 +363,8 @@ SinkClient::update(Observable<std::shared_ptr<MediaFrame>>* /*obs*/,
                                                         AV_PIX_FMT_NV12);
         else
 #endif
-            frame = std::static_pointer_cast<VideoFrame>(frame_p);
-        AVFrameSideData* side_data = av_frame_get_side_data(frame->pointer(),
-                                                            AV_FRAME_DATA_DISPLAYMATRIX);
-        int angle = 0;
-        if (side_data) {
-            auto matrix_rotation = reinterpret_cast<int32_t*>(side_data->data);
-            angle = -av_display_rotation_get(matrix_rotation);
-        }
+        frame = std::static_pointer_cast<VideoFrame>(frame_p);
+        int angle = frame->getOrientation();
         if (angle != rotation_) {
             filter_ = getTransposeFilter(angle,
                                          FILTER_INPUT_NAME,
diff --git a/src/media/video/video_mixer.cpp b/src/media/video/video_mixer.cpp
index 172d1f5045..279a15ee87 100644
--- a/src/media/video/video_mixer.cpp
+++ b/src/media/video/video_mixer.cpp
@@ -38,10 +38,6 @@
 
 #include <opendht/thread_pool.h>
 
-extern "C" {
-#include <libavutil/display.h>
-}
-
 static constexpr auto MIN_LINE_ZOOM
     = 6; // Used by the ONE_BIG_WITH_SMALL layout for the small previews
 
@@ -307,13 +303,7 @@ VideoMixer::render_frame(VideoFrame& output,
     int xoff = source->x;
     int yoff = source->y;
 
-    AVFrameSideData* sideData = av_frame_get_side_data(frame->pointer(),
-                                                       AV_FRAME_DATA_DISPLAYMATRIX);
-    int angle = 0;
-    if (sideData) {
-        auto matrixRotation = reinterpret_cast<int32_t*>(sideData->data);
-        angle = -av_display_rotation_get(matrixRotation);
-    }
+    int angle = frame->getOrientation();
     const constexpr char filterIn[] = "mixin";
     if (angle != source->rotation) {
         source->rotationFilter = video::getTransposeFilter(angle,
diff --git a/src/media/video/video_sender.cpp b/src/media/video/video_sender.cpp
index 7a80811623..f643046bbd 100644
--- a/src/media/video/video_sender.cpp
+++ b/src/media/video/video_sender.cpp
@@ -36,9 +36,6 @@
 
 #include <map>
 #include <unistd.h>
-extern "C" {
-#include <libavutil/display.h>
-}
 
 namespace jami {
 namespace video {
@@ -84,6 +81,13 @@ VideoSender::~VideoSender()
 void
 VideoSender::encodeAndSendVideo(VideoFrame& input_frame)
 {
+    int angle = input_frame.getOrientation();
+    if (rotation_ != angle) {
+        rotation_ = angle;
+        if (changeOrientationCallback_)
+            changeOrientationCallback_(rotation_);
+    }
+
     if (auto packet = input_frame.packet()) {
 #if __ANDROID__
         if (forceKeyFrame_) {
@@ -91,17 +95,6 @@ VideoSender::encodeAndSendVideo(VideoFrame& input_frame)
             --forceKeyFrame_;
         }
 #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
@@ -110,17 +103,6 @@ VideoSender::encodeAndSendVideo(VideoFrame& input_frame)
         if (is_keyframe)
             --forceKeyFrame_;
 
-        AVFrameSideData* side_data = av_frame_get_side_data(input_frame.pointer(),
-                                                            AV_FRAME_DATA_DISPLAYMATRIX);
-        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_);
-        }
-
         if (videoEncoder_->encode(input_frame, is_keyframe, frameNumber_++) < 0)
             JAMI_ERR("encoding failed");
     }
-- 
GitLab