From 9af60e1dee598f72e0f2fa504e6c0823a5ad3788 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Adrien=20B=C3=A9raud?= <adrien.beraud@savoirfairelinux.com>
Date: Fri, 8 Feb 2019 10:42:07 -0500
Subject: [PATCH] videomanager: add AVSinkTarget

Allows clients to retrieve an AVFrame instead of a FrameBuffer

Change-Id: I19ca0935fa08b46e0261713e842e1b4f156bdbe7
Reviewed-by: Philippe Gorley <philippe.gorley@savoirfairelinux.com>
---
 src/client/videomanager.cpp        | 9 +++++++++
 src/dring/videomanager_interface.h | 6 ++++++
 src/media/video/sinkclient.cpp     | 6 +++++-
 src/media/video/sinkclient.h       | 8 ++++++++
 4 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/src/client/videomanager.cpp b/src/client/videomanager.cpp
index 9143ba12a9..7875cbb2c6 100644
--- a/src/client/videomanager.cpp
+++ b/src/client/videomanager.cpp
@@ -493,6 +493,15 @@ registerSinkTarget(const std::string& sinkId, const SinkTarget& target)
        RING_WARN("No sink found for id '%s'", sinkId.c_str());
 }
 
+void
+registerAVSinkTarget(const std::string& sinkId, const AVSinkTarget& target)
+{
+   if (auto sink = ring::Manager::instance().getSinkClient(sinkId))
+       sink->registerAVTarget(target);
+   else
+       RING_WARN("No sink found for id '%s'", sinkId.c_str());
+}
+
 std::map<std::string, std::string>
 getRenderer(const std::string& callId)
 {
diff --git a/src/dring/videomanager_interface.h b/src/dring/videomanager_interface.h
index 44bb0d144b..2fdf7ae0f3 100644
--- a/src/dring/videomanager_interface.h
+++ b/src/dring/videomanager_interface.h
@@ -151,6 +151,11 @@ private:
     void setGeometry(int format, int width, int height) noexcept;
 };
 
+struct DRING_PUBLIC AVSinkTarget {
+    std::function<void(std::unique_ptr<VideoFrame>)> push;
+    int /* AVPixelFormat */ preferredFormat {-1 /* AV_PIX_FMT_NONE */};
+};
+
 using VideoCapabilities = std::map<std::string, std::map<std::string, std::vector<std::string>>>;
 
 DRING_PUBLIC std::vector<std::string> getDeviceList();
@@ -171,6 +176,7 @@ DRING_PUBLIC void stopAudioDevice();
 DRING_PUBLIC bool switchInput(const std::string& resource);
 DRING_PUBLIC bool switchToCamera();
 DRING_PUBLIC void registerSinkTarget(const std::string& sinkId, const SinkTarget& target);
+DRING_PUBLIC void registerAVSinkTarget(const std::string& sinkId, const AVSinkTarget& target);
 DRING_PUBLIC std::map<std::string, std::string> getRenderer(const std::string& callId);
 
 DRING_PUBLIC std::string startLocalRecorder(const bool& audioOnly, const std::string& filepath);
diff --git a/src/media/video/sinkclient.cpp b/src/media/video/sinkclient.cpp
index 466c2f2798..ae3d37c933 100644
--- a/src/media/video/sinkclient.cpp
+++ b/src/media/video/sinkclient.cpp
@@ -336,9 +336,13 @@ SinkClient::update(Observable<std::shared_ptr<MediaFrame>>* /*obs*/,
     shm_->renderFrame(f);
 #endif
 
+    if (avTarget_.push) {
+        auto outFrame = std::make_unique<VideoFrame>();
+        outFrame->copyFrom(f);
+        avTarget_.push(std::move(outFrame));
+    }
     if (target_.pull) {
         VideoFrame dst;
-        VideoScaler scaler;
         const int width = f.width();
         const int height = f.height();
 #if defined(__ANDROID__) || (defined(__APPLE__) && !TARGET_OS_IPHONE)
diff --git a/src/media/video/sinkclient.h b/src/media/video/sinkclient.h
index 839e5e845e..5d76751523 100644
--- a/src/media/video/sinkclient.h
+++ b/src/media/video/sinkclient.h
@@ -62,6 +62,10 @@ class SinkClient : public VideoFramePassiveReader
             return height_;
         }
 
+        AVPixelFormat getPreferredFormat() const noexcept {
+            return (AVPixelFormat)avTarget_.preferredFormat;
+        }
+
         // as VideoFramePassiveReader
         void update(Observable<std::shared_ptr<ring::MediaFrame>>*,
                     const std::shared_ptr<ring::MediaFrame>&) override;
@@ -74,6 +78,9 @@ class SinkClient : public VideoFramePassiveReader
         void registerTarget(const DRing::SinkTarget& target) noexcept {
             target_ = target;
         }
+        void registerAVTarget(const DRing::AVSinkTarget& target) noexcept {
+            avTarget_ = target;
+        }
 
     private:
         const std::string id_;
@@ -82,6 +89,7 @@ class SinkClient : public VideoFramePassiveReader
         int height_ {0};
         bool started_ {false}; // used to arbitrate client's stop signal.
         DRing::SinkTarget target_;
+        DRing::AVSinkTarget avTarget_;
         std::unique_ptr<VideoScaler> scaler_;
 
 #ifdef DEBUG_FPS
-- 
GitLab