From f6f8a83754351d640b90026d1c6b59b2b6ed1393 Mon Sep 17 00:00:00 2001
From: agsantos <aline.gondimsantos@savoirfairelinux.com>
Date: Wed, 16 Mar 2022 11:30:21 -0400
Subject: [PATCH] conference: make single transfer to main memory

While in a conference, the video split added a transfer to
main memory for each of the participants. This makes the sinkClient
a observable and the participants sinks are attached to the main
conference sink. The main sink has its frame transferred and the
subsequent observers do not need to repeat the process.

GitLab: #709
Change-Id: I1f4ea9460c052a100b4809101c35d196cd79acbe
---
 src/conference.cpp                     | 18 ++++++++++--------
 src/manager.cpp                        |  3 +--
 src/manager.h                          |  4 ++--
 src/media/video/sinkclient.cpp         |  4 +++-
 src/media/video/sinkclient.h           | 12 ++++++++----
 src/media/video/video_mixer.h          |  2 ++
 src/media/video/video_receive_thread.h |  1 +
 src/sip/sipcall.cpp                    | 20 +++++++++++---------
 8 files changed, 38 insertions(+), 26 deletions(-)

diff --git a/src/conference.cpp b/src/conference.cpp
index 81911aa214..5054a2f7e1 100644
--- a/src/conference.cpp
+++ b/src/conference.cpp
@@ -200,11 +200,13 @@ Conference::~Conference()
         if (call->isPeerRecording())
             call->peerRecording(true);
     });
-    for (auto it = confSinksMap_.begin(); it != confSinksMap_.end();) {
-        if (videoMixer_)
-            videoMixer_->detach(it->second.get());
-        it->second->stop();
-        it = confSinksMap_.erase(it);
+    if (videoMixer_) {
+        auto& sink = videoMixer_->getSink();
+        for (auto it = confSinksMap_.begin(); it != confSinksMap_.end();) {
+            sink->detach(it->second.get());
+            it->second->stop();
+            it = confSinksMap_.erase(it);
+        }
     }
 #endif // ENABLE_VIDEO
 #ifdef ENABLE_PLUGIN
@@ -761,11 +763,11 @@ Conference::createSinks(const ConfInfo& infos)
     std::lock_guard<std::mutex> lk(sinksMtx_);
     if (!videoMixer_)
         return;
-
+    auto& sink = videoMixer_->getSink();
     Manager::instance().createSinkClients(getConfId(),
                                           infos,
-                                          std::static_pointer_cast<video::VideoGenerator>(
-                                              videoMixer_),
+                                          std::static_pointer_cast<video::VideoFrameActiveWriter>(
+                                              sink),
                                           confSinksMap_);
 }
 
diff --git a/src/manager.cpp b/src/manager.cpp
index 8787b5748f..b07364e482 100644
--- a/src/manager.cpp
+++ b/src/manager.cpp
@@ -3031,7 +3031,7 @@ Manager::createSinkClient(const std::string& id, bool mixer)
 void
 Manager::createSinkClients(const std::string& callId,
                            const ConfInfo& infos,
-                           const std::shared_ptr<video::VideoGenerator>& videoStream,
+                           const std::shared_ptr<video::VideoFrameActiveWriter>& videoStream,
                            std::map<std::string, std::shared_ptr<video::SinkClient>>& sinksMap)
 {
     std::lock_guard<std::mutex> lk(pimpl_->sinksMutex_);
@@ -3048,7 +3048,6 @@ Manager::createSinkClients(const std::string& callId,
             auto currentSink = getSinkClient(sinkId);
             if (currentSink) {
                 currentSink->setCrop(participant.x, participant.y, participant.w, participant.h);
-                currentSink->setFrameSize(participant.w, participant.h);
                 sinkIdsList.emplace(sinkId);
                 continue;
             }
diff --git a/src/manager.h b/src/manager.h
index 5956feb7c5..f560e570fe 100644
--- a/src/manager.h
+++ b/src/manager.h
@@ -810,12 +810,12 @@ public:
      * cache as a weak_ptr and populates sinksMap with sink ids and shared_ptrs.
      * @param callId
      * @param infos ConferenceInfos that will create the sinks
-     * @param videoStream the the VideoGenerator to with the sinks should be attached
+     * @param videoStream the the VideoFrameActiveWriter to which the sinks should be attached
      * @param sinksMap A map between sink ids and the respective shared pointer.
      */
     void createSinkClients(const std::string& callId,
                            const ConfInfo& infos,
-                           const std::shared_ptr<video::VideoGenerator>& videoStream,
+                           const std::shared_ptr<video::VideoFrameActiveWriter>& videoStream,
                            std::map<std::string, std::shared_ptr<video::SinkClient>>& sinksMap);
 
     /**
diff --git a/src/media/video/sinkclient.cpp b/src/media/video/sinkclient.cpp
index 4391faa39c..4dcbf2bba5 100644
--- a/src/media/video/sinkclient.cpp
+++ b/src/media/video/sinkclient.cpp
@@ -369,6 +369,7 @@ SinkClient::update(Observable<std::shared_ptr<MediaFrame>>* /*obs*/,
             setFrameSize(outFrame->width(), outFrame->height());
             return;
         }
+        notify(std::static_pointer_cast<MediaFrame>(frame_p));
         avTarget_.push(std::move(outFrame));
         return;
     }
@@ -382,7 +383,7 @@ SinkClient::update(Observable<std::shared_ptr<MediaFrame>>* /*obs*/,
         std::shared_ptr<VideoFrame> frame = std::make_shared<VideoFrame>();
 #ifdef RING_ACCEL
         auto desc = av_pix_fmt_desc_get(
-            (AVPixelFormat) (std::static_pointer_cast<VideoFrame>(frame_p))->format());
+            (AVPixelFormat)(std::static_pointer_cast<VideoFrame>(frame_p))->format());
         if (desc && (desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) {
             try {
                 frame = HardwareAccel::transferToMainMemory(*std::static_pointer_cast<VideoFrame>(
@@ -414,6 +415,7 @@ SinkClient::update(Observable<std::shared_ptr<MediaFrame>>* /*obs*/,
             frame = std::static_pointer_cast<VideoFrame>(
                 std::shared_ptr<MediaFrame>(filter_->readOutput()));
         }
+        notify(std::static_pointer_cast<MediaFrame>(frame));
 
         if (crop_.w || crop_.h) {
             frame->pointer()->crop_top = crop_.y;
diff --git a/src/media/video/sinkclient.h b/src/media/video/sinkclient.h
index 67cf65feee..f97b7fda9c 100644
--- a/src/media/video/sinkclient.h
+++ b/src/media/video/sinkclient.h
@@ -48,12 +48,12 @@ class ShmHolder;
 
 class VideoScaler;
 
-class SinkClient : public VideoFramePassiveReader
+class SinkClient : public VideoFramePassiveReader, public VideoFrameActiveWriter
 {
 public:
     SinkClient(const std::string& id = "", bool mixer = false);
 
-    const std::string& getId() const noexcept {return id_;}
+    const std::string& getId() const noexcept { return id_; }
 
     std::string openedName() const noexcept;
 
@@ -76,7 +76,8 @@ public:
     void setFrameSize(int width, int height);
     void setCrop(int x, int y, int w, int h);
 
-    void registerTarget(const DRing::SinkTarget& target) noexcept {
+    void registerTarget(const DRing::SinkTarget& target) noexcept
+    {
         std::lock_guard<std::mutex> lock(mtx_);
         target_ = target;
     }
@@ -93,7 +94,10 @@ private:
     int width_ {0};
     int height_ {0};
 
-    struct Rect { int x {0}, y {0}, w {0}, h {0}; };
+    struct Rect
+    {
+        int x {0}, y {0}, w {0}, h {0};
+    };
     Rect crop_ {};
 
     bool started_ {false}; // used to arbitrate client's stop signal.
diff --git a/src/media/video/video_mixer.h b/src/media/video/video_mixer.h
index a39b9fff24..591f4d0921 100644
--- a/src/media/video/video_mixer.h
+++ b/src/media/video/video_mixer.h
@@ -91,6 +91,8 @@ public:
 
     void updateLayout();
 
+    std::shared_ptr<SinkClient>& getSink() { return sink_; }
+
 private:
     NON_COPYABLE(VideoMixer);
     struct VideoMixerSource;
diff --git a/src/media/video/video_receive_thread.h b/src/media/video/video_receive_thread.h
index 0f40bd1dec..c4b156c683 100644
--- a/src/media/video/video_receive_thread.h
+++ b/src/media/video/video_receive_thread.h
@@ -65,6 +65,7 @@ public:
     };
     void startSink();
     void stopSink();
+    std::shared_ptr<SinkClient>& getSink() { return sink_; }
 
     // as VideoGenerator
     int getWidth() const;
diff --git a/src/sip/sipcall.cpp b/src/sip/sipcall.cpp
index eb8931ae98..70cd5b24c2 100644
--- a/src/sip/sipcall.cpp
+++ b/src/sip/sipcall.cpp
@@ -2150,14 +2150,15 @@ SIPCall::stopAllMedia()
 
     {
         std::lock_guard<std::mutex> lk(sinksMtx_);
-        for (auto it = callSinksMap_.begin(); it != callSinksMap_.end();) {
-            auto& videoReceive = videoRtp->getVideoReceive();
-            if (videoReceive) {
-                videoReceive->detach(it->second.get());
+        auto& videoReceive = videoRtp->getVideoReceive();
+        if (videoReceive) {
+            auto& sink = videoReceive->getSink();
+            for (auto it = callSinksMap_.begin(); it != callSinksMap_.end();) {
+                sink->detach(it->second.get());
+
+                it->second->stop();
+                it = callSinksMap_.erase(it);
             }
-
-            it->second->stop();
-            it = callSinksMap_.erase(it);
         }
     }
 
@@ -3019,12 +3020,13 @@ SIPCall::createSinks(const ConfInfo& infos)
     auto& videoReceive = videoRtp->getVideoReceive();
     if (!videoReceive)
         return;
+    auto& sink = videoReceive->getSink();
     auto conf = conf_.lock();
     const auto& id = conf ? conf->getConfId() : getCallId();
     Manager::instance().createSinkClients(id,
                                           infos,
-                                          std::static_pointer_cast<video::VideoGenerator>(
-                                              videoReceive),
+                                          std::static_pointer_cast<video::VideoFrameActiveWriter>(
+                                              sink),
                                           callSinksMap_);
 }
 #endif
-- 
GitLab