From 87624f98c0cf9bb68eeb6bbf7f1107346b082f65 Mon Sep 17 00:00:00 2001 From: Eloi BAIL <eloi.bail@savoirfairelinux.com> Date: Thu, 27 Aug 2015 10:22:53 -0400 Subject: [PATCH] daemon: force keyframe rate on encoder at 5 seconds Some codecs, as h264, use a default keyframe rate based on frame count. As example, on h264 this rate is one IFrame each 250 frames. So this rate is sensible to fps changes, that ofen happens with output type (images, frame size, screen casting, etc). Using a rate based on fps seems more viable solution. Moreover, in order to handle video artifacts in case of missed packets, we want to send more keyframes so that artifacts will be seen for a shorter period. Note: the drawback of this solution is an average bitrate higher than before as I frames are bigger than P frames. Issue: #79690 Change-Id: I0b9daef8723c84b5998c9eb156d1e73538e8abed Signed-off-by: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com> --- src/media/video/video_sender.cpp | 8 ++++++-- src/media/video/video_sender.h | 5 ++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/media/video/video_sender.cpp b/src/media/video/video_sender.cpp index 087d142791..e8e332fb0b 100644 --- a/src/media/video/video_sender.cpp +++ b/src/media/video/video_sender.cpp @@ -50,6 +50,7 @@ VideoSender::VideoSender(const std::string& dest, const DeviceParams& dev, , videoEncoder_(new MediaEncoder) { videoEncoder_->setDeviceOptions(dev); + keyFrameFreq_ = dev.framerate.numerator() * KEY_FRAME_PERIOD; videoEncoder_->openOutput(dest.c_str(), args); videoEncoder_->setInitSeqVal(seqVal); videoEncoder_->setIOContext(muxContext_); @@ -66,10 +67,13 @@ VideoSender::~VideoSender() void VideoSender::encodeAndSendVideo(VideoFrame& input_frame) { - bool is_keyframe = forceKeyFrame_ > 0; + bool is_keyframe = forceKeyFrame_ > 0 \ + or (keyFrameFreq_ > 0 and (frameNumber_ % keyFrameFreq_) == 0); - if (is_keyframe) + if (is_keyframe) { + RING_DBG("keyframe requested"); --forceKeyFrame_; + } if (videoEncoder_->encode(input_frame, is_keyframe, frameNumber_++) < 0) RING_ERR("encoding failed"); diff --git a/src/media/video/video_sender.h b/src/media/video/video_sender.h index cac8f30d85..d1d1fd6452 100644 --- a/src/media/video/video_sender.h +++ b/src/media/video/video_sender.h @@ -74,6 +74,9 @@ public: bool useCodec(const AccountVideoCodecInfo* codec) const; private: + static constexpr int KEYFRAMES_AT_START {3}; // Number of keyframes to enforce at stream startup + static constexpr unsigned KEY_FRAME_PERIOD {5}; // seconds before forcing a keyframe + NON_COPYABLE(VideoSender); void encodeAndSendVideo(VideoFrame&); @@ -82,8 +85,8 @@ private: std::unique_ptr<MediaIOHandle> muxContext_ = nullptr; std::unique_ptr<MediaEncoder> videoEncoder_ = nullptr; - static constexpr int KEYFRAMES_AT_START {3}; // Number of keyframes to enforce at stream startup std::atomic<int> forceKeyFrame_ {KEYFRAMES_AT_START}; + int keyFrameFreq_ {0}; // Set keyframe rate, 0 to disable auto-keyframe. Computed in constructor int64_t frameNumber_ = 0; std::string sdp_ = ""; }; -- GitLab