From f8bd331d66ad263b23c0cb9fe12bdf27ffbf095f Mon Sep 17 00:00:00 2001
From: philippegorley <philippe.gorley@savoirfairelinux.com>
Date: Tue, 10 Jul 2018 14:20:36 -0400
Subject: [PATCH] recorder: use video input as source

MediaRecorder no longer uses VideoSender (encoder) as a source for its
local video and will directly use VideoInput (decoder), as it is earlier
in the pipeline.

This is the first step to support switching inputs while recording.

Change-Id: Ia163efa3b20a349a93fc7b05213ec5e00de1704e
Reviewed-by: Sebastien Blin <sebastien.blin@savoirfairelinux.com>
---
 src/media/media_decoder.cpp           |  5 +++--
 src/media/media_encoder.cpp           | 25 ++++++++++++-------------
 src/media/video/video_input.cpp       |  7 +++++++
 src/media/video/video_input.h         |  3 +++
 src/media/video/video_rtp_session.cpp | 10 ++++------
 src/media/video/video_sender.cpp      |  7 -------
 src/media/video/video_sender.h        |  3 ---
 7 files changed, 29 insertions(+), 31 deletions(-)

diff --git a/src/media/media_decoder.cpp b/src/media/media_decoder.cpp
index 9c3dfa2d89..b450b6def3 100644
--- a/src/media/media_decoder.cpp
+++ b/src/media/media_decoder.cpp
@@ -295,16 +295,17 @@ MediaDecoder::decode(VideoFrame& result)
             static_cast<AVRounding>(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));
 
         if (auto rec = recorder_.lock()) {
+            bool fromPeer = (inputCtx_->iformat->name == std::string("sdp"));
             if (!recordingStarted_) {
                 auto ms = MediaStream("", decoderCtx_, frame->pts);
                 ms.format = frame->format; // might not match avStream_ if accel is used
-                if (rec->addStream(true, true, ms) >= 0)
+                if (rec->addStream(true, fromPeer, ms) >= 0)
                     recordingStarted_ = true;
                 else
                     recorder_ = std::weak_ptr<MediaRecorder>();
             }
             if (recordingStarted_)
-                rec->recordData(frame, true, true);
+                rec->recordData(frame, true, fromPeer);
         }
 
         if (emulateRate_ and packetTimestamp != AV_NOPTS_VALUE) {
diff --git a/src/media/media_encoder.cpp b/src/media/media_encoder.cpp
index 029d566af8..44034e5b89 100644
--- a/src/media/media_encoder.cpp
+++ b/src/media/media_encoder.cpp
@@ -443,6 +443,18 @@ int MediaEncoder::encode_audio(const AudioBuffer &buffer)
         nb_frames -= frame->nb_samples;
         offset_ptr += frame->nb_samples * buffer.channels();
 
+        if (auto rec = recorder_.lock()) {
+            if (!recordingStarted_) {
+                auto ms = MediaStream("", encoders_[currentStreamIdx_], frame->pts);
+                if (rec->addStream(false, false, ms) >= 0)
+                    recordingStarted_ = true;
+                else
+                    recorder_ = std::weak_ptr<MediaRecorder>();
+            }
+            if (recordingStarted_)
+                rec->recordData(frame, false, false);
+        }
+
         encode(frame, currentStreamIdx_);
         av_frame_free(&frame);
     }
@@ -460,19 +472,6 @@ MediaEncoder::encode(AVFrame* frame, int streamIdx)
     pkt.data = nullptr; // packet data will be allocated by the encoder
     pkt.size = 0;
 
-    if (auto rec = recorder_.lock()) {
-        bool isVideo = encoderCtx->codec_type == AVMEDIA_TYPE_VIDEO;
-        if (!recordingStarted_) {
-            auto ms = MediaStream("", encoderCtx, frame->pts);
-            if (rec->addStream(isVideo, false, ms) >= 0)
-                recordingStarted_ = true;
-            else
-                recorder_ = std::weak_ptr<MediaRecorder>();
-        }
-        if (recordingStarted_)
-            rec->recordData(frame, isVideo, false);
-    }
-
     ret = avcodec_send_frame(encoderCtx, frame);
     if (ret < 0)
         return -1;
diff --git a/src/media/video/video_input.cpp b/src/media/video/video_input.cpp
index 5853697e5d..367c1c6984 100644
--- a/src/media/video/video_input.cpp
+++ b/src/media/video/video_input.cpp
@@ -587,4 +587,11 @@ VideoInput::foundDecOpts(const DeviceParams& params)
     }
 }
 
+void
+VideoInput::startRecorder(std::shared_ptr<MediaRecorder>& rec)
+{
+    if (decoder_)
+        decoder_->startRecorder(rec);
+}
+
 }} // namespace ring::video
diff --git a/src/media/video/video_input.h b/src/media/video/video_input.h
index f6a4c0b44f..4ddcc81ade 100644
--- a/src/media/video/video_input.h
+++ b/src/media/video/video_input.h
@@ -42,6 +42,7 @@
 
 namespace ring {
 class MediaDecoder;
+class MediaRecorder;
 }
 
 namespace ring { namespace video {
@@ -88,6 +89,8 @@ public:
     void releaseFrame(void *frame);
 #endif
 
+    void startRecorder(std::shared_ptr<MediaRecorder>& rec);
+
 private:
     NON_COPYABLE(VideoInput);
 
diff --git a/src/media/video/video_rtp_session.cpp b/src/media/video/video_rtp_session.cpp
index 6818967188..50d7f8a245 100644
--- a/src/media/video/video_rtp_session.cpp
+++ b/src/media/video/video_rtp_session.cpp
@@ -571,14 +571,12 @@ VideoRtpSession::startRecorder(std::shared_ptr<MediaRecorder>& rec)
     const constexpr int keyframes = 3;
     if (receiveThread_)
         receiveThread_->startRecorder(rec);
-    if (sender_)
-        sender_->startRecorder(rec);
-    for (int i = 0; i < keyframes; ++i) {
+    if (auto vidInput = std::static_pointer_cast<VideoInput>(videoLocal_))
+        vidInput->startRecorder(rec);
+    for (int i = 0; i < keyframes; ++i)
         if (receiveThread_)
             receiveThread_->triggerKeyFrameRequest();
-        if (sender_)
-            sender_->forceKeyFrame();
-    }
+    // TODO trigger keyframes for local video
 }
 
 }} // namespace ring::video
diff --git a/src/media/video/video_sender.cpp b/src/media/video/video_sender.cpp
index ca58aae129..8fb9916e0e 100644
--- a/src/media/video/video_sender.cpp
+++ b/src/media/video/video_sender.cpp
@@ -106,11 +106,4 @@ VideoSender::useCodec(const ring::AccountVideoCodecInfo* codec) const
     return videoEncoder_->useCodec(codec);
 }
 
-void
-VideoSender::startRecorder(std::shared_ptr<MediaRecorder>& rec)
-{
-    if (videoEncoder_)
-        videoEncoder_->startRecorder(rec);
-}
-
 }} // namespace ring::video
diff --git a/src/media/video/video_sender.h b/src/media/video/video_sender.h
index 875b17fa2f..322aa61892 100644
--- a/src/media/video/video_sender.h
+++ b/src/media/video/video_sender.h
@@ -35,7 +35,6 @@
 namespace ring {
 class SocketPair;
 struct AccountVideoCodecInfo;
-class MediaRecorder;
 }
 
 namespace ring { namespace video {
@@ -63,8 +62,6 @@ public:
 
     bool useCodec(const AccountVideoCodecInfo* codec) const;
 
-    void startRecorder(std::shared_ptr<MediaRecorder>& rec);
-
 private:
     static constexpr int KEYFRAMES_AT_START {4}; // Number of keyframes to enforce at stream startup
     static constexpr unsigned KEY_FRAME_PERIOD {0}; // seconds before forcing a keyframe
-- 
GitLab