From fc83b1f8daf502d53eef941af0d6ace81b5c123c Mon Sep 17 00:00:00 2001
From: philippegorley <philippe.gorley@savoirfairelinux.com>
Date: Wed, 5 Dec 2018 11:31:59 -0500
Subject: [PATCH] media: make observers/obervables use MediaFrame

Makes it so observers don't need to implement Observer<T> twice to
receive audio and video frames.

Change-Id: Id73c384342bd786b4f83950937b4dbd13a31fc41
---
 src/media/audio/audio_input.cpp          |  3 ++-
 src/media/audio/audio_input.h            |  2 +-
 src/media/audio/audio_receive_thread.cpp |  4 ++-
 src/media/audio/audio_receive_thread.h   |  2 +-
 src/media/audio/audio_sender.cpp         |  6 +++--
 src/media/audio/audio_sender.h           |  6 ++---
 src/media/media_recorder.cpp             | 31 +++++++++---------------
 src/media/media_recorder.h               |  8 ++----
 src/media/video/sinkclient.cpp           |  6 ++---
 src/media/video/sinkclient.h             |  4 +--
 src/media/video/video_base.cpp           |  2 +-
 src/media/video/video_base.h             |  6 +++--
 src/media/video/video_mixer.cpp          | 12 ++++-----
 src/media/video/video_mixer.h            |  6 ++---
 src/media/video/video_sender.cpp         |  6 ++---
 src/media/video/video_sender.h           |  4 +--
 16 files changed, 51 insertions(+), 57 deletions(-)

diff --git a/src/media/audio/audio_input.cpp b/src/media/audio/audio_input.cpp
index f0e2e63f0e..96a9bc3f76 100644
--- a/src/media/audio/audio_input.cpp
+++ b/src/media/audio/audio_input.cpp
@@ -28,6 +28,7 @@
 
 #include <future>
 #include <chrono>
+#include <memory>
 
 namespace ring {
 
@@ -69,7 +70,7 @@ AudioInput::process()
     frame->pointer()->pts = sent_samples;
     sent_samples += frame->pointer()->nb_samples;
 
-    notify(frame);
+    notify(std::static_pointer_cast<MediaFrame>(frame));
 }
 
 bool
diff --git a/src/media/audio/audio_input.h b/src/media/audio/audio_input.h
index 8baecb1731..5d442fb2bc 100644
--- a/src/media/audio/audio_input.h
+++ b/src/media/audio/audio_input.h
@@ -36,7 +36,7 @@ namespace ring {
 struct MediaStream;
 class Resampler;
 
-class AudioInput : public Observable<std::shared_ptr<AudioFrame>>
+class AudioInput : public Observable<std::shared_ptr<MediaFrame>>
 {
 public:
     AudioInput(const std::string& id);
diff --git a/src/media/audio/audio_receive_thread.cpp b/src/media/audio/audio_receive_thread.cpp
index bfd12b56d2..9865b5a357 100644
--- a/src/media/audio/audio_receive_thread.cpp
+++ b/src/media/audio/audio_receive_thread.cpp
@@ -30,6 +30,8 @@
 #include "ringbufferpool.h"
 #include "smartools.h"
 
+#include <memory>
+
 namespace ring {
 
 AudioReceiveThread::AudioReceiveThread(const std::string& id,
@@ -96,7 +98,7 @@ AudioReceiveThread::process()
         case MediaDecoder::Status::FrameFinished:
             audioDecoder_->writeToRingBuffer(*decodedFrame, *ringbuffer_,
                                              mainBuffFormat);
-            notify(decodedFrame);
+            notify(std::static_pointer_cast<MediaFrame>(decodedFrame));
             return;
         case MediaDecoder::Status::DecodeError:
             RING_WARN("decoding failure, trying to reset decoder...");
diff --git a/src/media/audio/audio_receive_thread.h b/src/media/audio/audio_receive_thread.h
index 11f3068c04..f67dd3fd0a 100644
--- a/src/media/audio/audio_receive_thread.h
+++ b/src/media/audio/audio_receive_thread.h
@@ -36,7 +36,7 @@ class MediaIOHandle;
 struct MediaStream;
 class RingBuffer;
 
-class AudioReceiveThread : public Observable<std::shared_ptr<AudioFrame>>
+class AudioReceiveThread : public Observable<std::shared_ptr<MediaFrame>>
 {
 public:
     AudioReceiveThread(const std::string &id,
diff --git a/src/media/audio/audio_sender.cpp b/src/media/audio/audio_sender.cpp
index 04c62f8dba..340d4ae5a6 100644
--- a/src/media/audio/audio_sender.cpp
+++ b/src/media/audio/audio_sender.cpp
@@ -30,6 +30,8 @@
 #include "resampler.h"
 #include "smartools.h"
 
+#include <memory>
+
 namespace ring {
 
 AudioSender::AudioSender(const std::string& id,
@@ -94,7 +96,7 @@ AudioSender::setup(SocketPair& socketPair)
 }
 
 void
-AudioSender::update(Observable<std::shared_ptr<ring::AudioFrame>>* /*obs*/, const std::shared_ptr<ring::AudioFrame>& framePtr)
+AudioSender::update(Observable<std::shared_ptr<ring::MediaFrame>>* /*obs*/, const std::shared_ptr<ring::MediaFrame>& framePtr)
 {
     auto frame = framePtr->pointer();
     auto ms = MediaStream("a:local", frame->format, rational<int>(1, frame->sample_rate),
@@ -103,7 +105,7 @@ AudioSender::update(Observable<std::shared_ptr<ring::AudioFrame>>* /*obs*/, cons
     ms.firstTimestamp = frame->pts;
     sent_samples += frame->nb_samples;
 
-    if (audioEncoder_->encodeAudio(*framePtr) < 0)
+    if (audioEncoder_->encodeAudio(*std::static_pointer_cast<AudioFrame>(framePtr)) < 0)
         RING_ERR("encoding failed");
 }
 
diff --git a/src/media/audio/audio_sender.h b/src/media/audio/audio_sender.h
index 3b2e9736af..673b48927b 100644
--- a/src/media/audio/audio_sender.h
+++ b/src/media/audio/audio_sender.h
@@ -33,7 +33,7 @@ class MediaEncoder;
 class MediaIOHandle;
 class Resampler;
 
-class AudioSender : public Observer<std::shared_ptr<AudioFrame>> {
+class AudioSender : public Observer<std::shared_ptr<MediaFrame>> {
 public:
     AudioSender(const std::string& id,
                 const std::string& dest,
@@ -47,8 +47,8 @@ public:
     void setMuted(bool isMuted);
     uint16_t getLastSeqValue();
 
-    void update(Observable<std::shared_ptr<ring::AudioFrame>>*,
-                const std::shared_ptr<ring::AudioFrame>&) override;
+    void update(Observable<std::shared_ptr<ring::MediaFrame>>*,
+                const std::shared_ptr<ring::MediaFrame>&) override;
 
 private:
     NON_COPYABLE(AudioSender);
diff --git a/src/media/media_recorder.cpp b/src/media/media_recorder.cpp
index 04c0f4f3c7..baf35522ec 100644
--- a/src/media/media_recorder.cpp
+++ b/src/media/media_recorder.cpp
@@ -141,36 +141,27 @@ MediaRecorder::addStream(const MediaStream& ms)
 }
 
 void
-MediaRecorder::update(Observable<std::shared_ptr<AudioFrame>>* ob, const std::shared_ptr<AudioFrame>& a)
+MediaRecorder::update(Observable<std::shared_ptr<MediaFrame>>* ob, const std::shared_ptr<MediaFrame>& m)
 {
     if (!isRecording_)
         return;
     std::string name;
     if (dynamic_cast<AudioReceiveThread*>(ob))
         name = "a:remote";
-    else // ob is of type AudioInput*
+    else if (dynamic_cast<AudioInput*>(ob))
         name = "a:local";
-    // copy frame to not mess with the original frame's pts
-    AudioFrame clone;
-    clone.copyFrom(*a);
-    clone.pointer()->pts -= streams_[name].firstTimestamp;
-    audioFilter_->feedInput(clone.pointer(), name);
-}
-
-void MediaRecorder::update(Observable<std::shared_ptr<VideoFrame>>* ob, const std::shared_ptr<VideoFrame>& v)
-{
-    if (!isRecording_)
-        return;
-    std::string name;
-    if (dynamic_cast<video::VideoReceiveThread*>(ob))
+    else if (dynamic_cast<video::VideoReceiveThread*>(ob))
         name = "v:remote";
-    else // ob is of type VideoInput*
+    else if (dynamic_cast<video::VideoInput*>(ob))
         name = "v:local";
-    // copy frame to not mess with the original frame's pts
-    VideoFrame clone;
-    clone.copyFrom(*v);
+    // copy frame to not mess with the original frame's pts (does not actually copy frame data)
+    MediaFrame clone;
+    clone.copyFrom(*m);
     clone.pointer()->pts -= streams_[name].firstTimestamp;
-    videoFilter_->feedInput(clone.pointer(), name);
+    if (clone.pointer()->width > 0 && clone.pointer()->height > 0)
+        videoFilter_->feedInput(clone.pointer(), name);
+    else
+        audioFilter_->feedInput(clone.pointer(), name);
 }
 
 int
diff --git a/src/media/media_recorder.h b/src/media/media_recorder.h
index c4796db8c2..0bcb632f0a 100644
--- a/src/media/media_recorder.h
+++ b/src/media/media_recorder.h
@@ -41,10 +41,7 @@
 
 namespace ring {
 
-class MediaRecorder : public Observer<std::shared_ptr<AudioFrame>>
-#ifdef RING_VIDEO
-                    , public video::VideoFramePassiveReader
-#endif
+class MediaRecorder : public Observer<std::shared_ptr<MediaFrame>>
                     , public std::enable_shared_from_this<MediaRecorder>
 {
 public:
@@ -104,8 +101,7 @@ public:
     /**
      * Updates the recorder with an audio or video frame.
      */
-    void update(Observable<std::shared_ptr<AudioFrame>>* ob, const std::shared_ptr<AudioFrame>& a) override;
-    void update(Observable<std::shared_ptr<VideoFrame>>* ob, const std::shared_ptr<VideoFrame>& v) override;
+    void update(Observable<std::shared_ptr<MediaFrame>>* ob, const std::shared_ptr<MediaFrame>& a) override;
 
 private:
     NON_COPYABLE(MediaRecorder);
diff --git a/src/media/video/sinkclient.cpp b/src/media/video/sinkclient.cpp
index ef4265a911..6736fe154c 100644
--- a/src/media/video/sinkclient.cpp
+++ b/src/media/video/sinkclient.cpp
@@ -313,10 +313,10 @@ SinkClient::SinkClient(const std::string& id, bool mixer)
 {}
 
 void
-SinkClient::update(Observable<std::shared_ptr<VideoFrame>>* /*obs*/,
-                   const std::shared_ptr<VideoFrame>& frame_p)
+SinkClient::update(Observable<std::shared_ptr<MediaFrame>>* /*obs*/,
+                   const std::shared_ptr<MediaFrame>& frame_p)
 {
-    auto& f = *frame_p;
+    auto& f = *std::static_pointer_cast<VideoFrame>(frame_p);
 
 #ifdef DEBUG_FPS
     auto currentTime = std::chrono::system_clock::now();
diff --git a/src/media/video/sinkclient.h b/src/media/video/sinkclient.h
index 8068e8623c..e7a8136ab4 100644
--- a/src/media/video/sinkclient.h
+++ b/src/media/video/sinkclient.h
@@ -63,8 +63,8 @@ class SinkClient : public VideoFramePassiveReader
         }
 
         // as VideoFramePassiveReader
-        void update(Observable<std::shared_ptr<ring::VideoFrame>>*,
-                    const std::shared_ptr<ring::VideoFrame>&) override;
+        void update(Observable<std::shared_ptr<ring::MediaFrame>>*,
+                    const std::shared_ptr<ring::MediaFrame>&) override;
 
         bool start() noexcept;
         bool stop() noexcept;
diff --git a/src/media/video/video_base.cpp b/src/media/video/video_base.cpp
index 4b8759c0a6..9aca094471 100644
--- a/src/media/video/video_base.cpp
+++ b/src/media/video/video_base.cpp
@@ -44,7 +44,7 @@ VideoGenerator::publishFrame()
 {
     std::lock_guard<std::mutex> lk(mutex_);
     lastFrame_ = std::move(writableFrame_);
-    notify(lastFrame_);
+    notify(std::static_pointer_cast<MediaFrame>(lastFrame_));
 }
 
 void
diff --git a/src/media/video/video_base.h b/src/media/video/video_base.h
index 6954d1aac7..d7e38727be 100644
--- a/src/media/video/video_base.h
+++ b/src/media/video/video_base.h
@@ -49,17 +49,19 @@ struct AVIOContext;
 #endif
 
 namespace DRing {
+class MediaFrame;
 class VideoFrame;
 }
 
 namespace ring {
+using MediaFrame = DRing::MediaFrame;
 using VideoFrame = DRing::VideoFrame;
 }
 
 namespace ring { namespace video {
 
-struct VideoFrameActiveWriter: Observable<std::shared_ptr<VideoFrame>> {};
-struct VideoFramePassiveReader: Observer<std::shared_ptr<VideoFrame>> {};
+struct VideoFrameActiveWriter: Observable<std::shared_ptr<MediaFrame>> {};
+struct VideoFramePassiveReader: Observer<std::shared_ptr<MediaFrame>> {};
 
 /*=== VideoGenerator =========================================================*/
 
diff --git a/src/media/video/video_mixer.cpp b/src/media/video/video_mixer.cpp
index 6757bf4c28..365f57dfd9 100644
--- a/src/media/video/video_mixer.cpp
+++ b/src/media/video/video_mixer.cpp
@@ -33,7 +33,7 @@
 namespace ring { namespace video {
 
 struct VideoMixer::VideoMixerSource {
-    Observable<std::shared_ptr<VideoFrame>>* source = nullptr;
+    Observable<std::shared_ptr<MediaFrame>>* source = nullptr;
     std::unique_ptr<VideoFrame> update_frame;
     std::unique_ptr<VideoFrame> render_frame;
     void atomic_swap_render(std::unique_ptr<VideoFrame>& other) {
@@ -77,7 +77,7 @@ VideoMixer::~VideoMixer()
 }
 
 void
-VideoMixer::attached(Observable<std::shared_ptr<VideoFrame>>* ob)
+VideoMixer::attached(Observable<std::shared_ptr<MediaFrame>>* ob)
 {
     auto lock(rwMutex_.write());
 
@@ -87,7 +87,7 @@ VideoMixer::attached(Observable<std::shared_ptr<VideoFrame>>* ob)
 }
 
 void
-VideoMixer::detached(Observable<std::shared_ptr<VideoFrame>>* ob)
+VideoMixer::detached(Observable<std::shared_ptr<MediaFrame>>* ob)
 {
     auto lock(rwMutex_.write());
 
@@ -100,8 +100,8 @@ VideoMixer::detached(Observable<std::shared_ptr<VideoFrame>>* ob)
 }
 
 void
-VideoMixer::update(Observable<std::shared_ptr<VideoFrame>>* ob,
-                   const std::shared_ptr<VideoFrame>& frame_p)
+VideoMixer::update(Observable<std::shared_ptr<MediaFrame>>* ob,
+                   const std::shared_ptr<MediaFrame>& frame_p)
 {
     auto lock(rwMutex_.read());
 
@@ -111,7 +111,7 @@ VideoMixer::update(Observable<std::shared_ptr<VideoFrame>>* ob,
                 x->update_frame.reset(new VideoFrame);
             else
                 x->update_frame->reset();
-            x->update_frame->copyFrom(*frame_p); // copy frame content, it will be destroyed after return
+            x->update_frame->copyFrom(*std::static_pointer_cast<VideoFrame>(frame_p)); // copy frame content, it will be destroyed after return
             x->atomic_swap_render(x->update_frame);
             return;
         }
diff --git a/src/media/video/video_mixer.h b/src/media/video/video_mixer.h
index a7ccc08df4..57454026bc 100644
--- a/src/media/video/video_mixer.h
+++ b/src/media/video/video_mixer.h
@@ -49,9 +49,9 @@ public:
     int getPixelFormat() const override;
 
     // as VideoFramePassiveReader
-    void update(Observable<std::shared_ptr<VideoFrame>>* ob, const std::shared_ptr<VideoFrame>& v) override;
-    void attached(Observable<std::shared_ptr<VideoFrame>>* ob) override;
-    void detached(Observable<std::shared_ptr<VideoFrame>>* ob) override;
+    void update(Observable<std::shared_ptr<MediaFrame>>* ob, const std::shared_ptr<MediaFrame>& v) override;
+    void attached(Observable<std::shared_ptr<MediaFrame>>* ob) override;
+    void detached(Observable<std::shared_ptr<MediaFrame>>* ob) override;
 
 private:
     NON_COPYABLE(VideoMixer);
diff --git a/src/media/video/video_sender.cpp b/src/media/video/video_sender.cpp
index 93cfe1e0bf..d7133641b7 100644
--- a/src/media/video/video_sender.cpp
+++ b/src/media/video/video_sender.cpp
@@ -78,10 +78,10 @@ VideoSender::encodeAndSendVideo(VideoFrame& input_frame)
 }
 
 void
-VideoSender::update(Observable<std::shared_ptr<VideoFrame>>* /*obs*/,
-                    const std::shared_ptr<VideoFrame>& frame_p)
+VideoSender::update(Observable<std::shared_ptr<MediaFrame>>* /*obs*/,
+                    const std::shared_ptr<MediaFrame>& frame_p)
 {
-    encodeAndSendVideo(*frame_p);
+    encodeAndSendVideo(*std::static_pointer_cast<VideoFrame>(frame_p));
 }
 
 void
diff --git a/src/media/video/video_sender.h b/src/media/video/video_sender.h
index 322aa61892..cf8eb81744 100644
--- a/src/media/video/video_sender.h
+++ b/src/media/video/video_sender.h
@@ -54,8 +54,8 @@ public:
     void forceKeyFrame();
 
     // as VideoFramePassiveReader
-    void update(Observable<std::shared_ptr<VideoFrame>>* obs,
-                const std::shared_ptr<VideoFrame>& frame_p) override;
+    void update(Observable<std::shared_ptr<MediaFrame>>* obs,
+                const std::shared_ptr<MediaFrame>& frame_p) override;
 
     void setMuted(bool isMuted);
     uint16_t getLastSeqValue();
-- 
GitLab