From a1b4eb2196b2c2292230faa9afc8c7b8388e936e Mon Sep 17 00:00:00 2001 From: Philipp Hancke Date: Fri, 4 Nov 2022 14:45:23 +0100 Subject: generateKeyFrame: add rids argument and do the resolution of rids to layers. This has no effect yet since the simulcast encoder adapter (SimulcastEncoderAdapter::Encode), the VP8 encoder (LibvpxVp8Encoder::Encode) and the OpenH264 encoder (H264EncoderImpl::Encode) all generate a key frame for all layers whenever a key frame is requested on one layer. BUG=chromium:1354101 Change-Id: I13f5f1bf136839a68942b0f6bf4f2d5890415250 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/280945 Commit-Queue: Ilya Nikolaevskiy Commit-Queue: Philipp Hancke Reviewed-by: Ilya Nikolaevskiy Reviewed-by: Harald Alvestrand Cr-Commit-Position: refs/heads/main@{#38565} --- video/encoder_rtcp_feedback_unittest.cc | 8 +++++--- video/test/mock_video_stream_encoder.h | 5 ++++- video/video_send_stream.cc | 19 +++++++++++++++++-- video/video_send_stream.h | 3 ++- video/video_stream_encoder.cc | 17 ++++++++++++----- video/video_stream_encoder.h | 2 +- video/video_stream_encoder_interface.h | 6 ++++-- 7 files changed, 45 insertions(+), 15 deletions(-) (limited to 'video') diff --git a/video/encoder_rtcp_feedback_unittest.cc b/video/encoder_rtcp_feedback_unittest.cc index 4cbb747e51..f1ac65d48f 100644 --- a/video/encoder_rtcp_feedback_unittest.cc +++ b/video/encoder_rtcp_feedback_unittest.cc @@ -16,6 +16,8 @@ #include "test/gtest.h" #include "video/test/mock_video_stream_encoder.h" +using ::testing::_; + namespace webrtc { class VieKeyRequestTest : public ::testing::Test { @@ -38,18 +40,18 @@ class VieKeyRequestTest : public ::testing::Test { }; TEST_F(VieKeyRequestTest, CreateAndTriggerRequests) { - EXPECT_CALL(encoder_, SendKeyFrame()).Times(1); + EXPECT_CALL(encoder_, SendKeyFrame(_)).Times(1); encoder_rtcp_feedback_.OnReceivedIntraFrameRequest(kSsrc); } TEST_F(VieKeyRequestTest, TooManyOnReceivedIntraFrameRequest) { - EXPECT_CALL(encoder_, SendKeyFrame()).Times(1); + EXPECT_CALL(encoder_, SendKeyFrame(_)).Times(1); encoder_rtcp_feedback_.OnReceivedIntraFrameRequest(kSsrc); encoder_rtcp_feedback_.OnReceivedIntraFrameRequest(kSsrc); simulated_clock_.AdvanceTimeMilliseconds(10); encoder_rtcp_feedback_.OnReceivedIntraFrameRequest(kSsrc); - EXPECT_CALL(encoder_, SendKeyFrame()).Times(1); + EXPECT_CALL(encoder_, SendKeyFrame(_)).Times(1); simulated_clock_.AdvanceTimeMilliseconds(300); encoder_rtcp_feedback_.OnReceivedIntraFrameRequest(kSsrc); encoder_rtcp_feedback_.OnReceivedIntraFrameRequest(kSsrc); diff --git a/video/test/mock_video_stream_encoder.h b/video/test/mock_video_stream_encoder.h index ff246df253..2f982158f0 100644 --- a/video/test/mock_video_stream_encoder.h +++ b/video/test/mock_video_stream_encoder.h @@ -34,7 +34,10 @@ class MockVideoStreamEncoder : public VideoStreamEncoderInterface { (override)); MOCK_METHOD(void, SetSink, (EncoderSink*, bool), (override)); MOCK_METHOD(void, SetStartBitrate, (int), (override)); - MOCK_METHOD(void, SendKeyFrame, (), (override)); + MOCK_METHOD(void, + SendKeyFrame, + (const std::vector&), + (override)); MOCK_METHOD(void, OnLossNotification, (const VideoEncoder::LossNotification&), diff --git a/video/video_send_stream.cc b/video/video_send_stream.cc index f245332753..bf5f99aca5 100644 --- a/video/video_send_stream.cc +++ b/video/video_send_stream.cc @@ -343,9 +343,24 @@ void VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) { send_stream_.DeliverRtcp(packet, length); } -void VideoSendStream::GenerateKeyFrame() { +void VideoSendStream::GenerateKeyFrame(const std::vector& rids) { + // Map rids to layers. If rids is empty, generate a keyframe for all layers. + std::vector next_frames(config_.rtp.ssrcs.size(), + VideoFrameType::kVideoFrameKey); + if (!config_.rtp.rids.empty() && !rids.empty()) { + std::fill(next_frames.begin(), next_frames.end(), + VideoFrameType::kVideoFrameDelta); + for (const auto& rid : rids) { + for (size_t i = 0; i < config_.rtp.rids.size(); i++) { + if (config_.rtp.rids[i] == rid) { + next_frames[i] = VideoFrameType::kVideoFrameKey; + break; + } + } + } + } if (video_stream_encoder_) { - video_stream_encoder_->SendKeyFrame(); + video_stream_encoder_->SendKeyFrame(next_frames); } } diff --git a/video/video_send_stream.h b/video/video_send_stream.h index a7763731b7..4174d2e5c6 100644 --- a/video/video_send_stream.h +++ b/video/video_send_stream.h @@ -13,6 +13,7 @@ #include #include +#include #include #include "api/fec_controller.h" @@ -93,7 +94,7 @@ class VideoSendStream : public webrtc::VideoSendStream { void StopPermanentlyAndGetRtpStates(RtpStateMap* rtp_state_map, RtpPayloadStateMap* payload_state_map); - void GenerateKeyFrame() override; + void GenerateKeyFrame(const std::vector& rids) override; private: friend class test::VideoSendStreamPeer; diff --git a/video/video_stream_encoder.cc b/video/video_stream_encoder.cc index 746ee79473..de40ccf348 100644 --- a/video/video_stream_encoder.cc +++ b/video/video_stream_encoder.cc @@ -1981,9 +1981,10 @@ void VideoStreamEncoder::RequestRefreshFrame() { })); } -void VideoStreamEncoder::SendKeyFrame() { +void VideoStreamEncoder::SendKeyFrame( + const std::vector& layers) { if (!encoder_queue_.IsCurrent()) { - encoder_queue_.PostTask([this] { SendKeyFrame(); }); + encoder_queue_.PostTask([this, layers] { SendKeyFrame(layers); }); return; } RTC_DCHECK_RUN_ON(&encoder_queue_); @@ -1998,9 +1999,15 @@ void VideoStreamEncoder::SendKeyFrame() { return; // Shutting down, or not configured yet. } - // TODO(webrtc:10615): Map keyframe request to spatial layer. - std::fill(next_frame_types_.begin(), next_frame_types_.end(), - VideoFrameType::kVideoFrameKey); + if (!layers.empty()) { + RTC_DCHECK_EQ(layers.size(), next_frame_types_.size()); + for (size_t i = 0; i < layers.size() && i < next_frame_types_.size(); i++) { + next_frame_types_[i] = layers[i]; + } + } else { + std::fill(next_frame_types_.begin(), next_frame_types_.end(), + VideoFrameType::kVideoFrameKey); + } } void VideoStreamEncoder::OnLossNotification( diff --git a/video/video_stream_encoder.h b/video/video_stream_encoder.h index 9af2e0bcff..e94c369a19 100644 --- a/video/video_stream_encoder.h +++ b/video/video_stream_encoder.h @@ -111,7 +111,7 @@ class VideoStreamEncoder : public VideoStreamEncoderInterface, // guaranteed that no encoded frames will be delivered to the sink. void Stop() override; - void SendKeyFrame() override; + void SendKeyFrame(const std::vector& layers = {}) override; void OnLossNotification( const VideoEncoder::LossNotification& loss_notification) override; diff --git a/video/video_stream_encoder_interface.h b/video/video_stream_encoder_interface.h index 38f180d121..e716572e68 100644 --- a/video/video_stream_encoder_interface.h +++ b/video/video_stream_encoder_interface.h @@ -97,8 +97,10 @@ class VideoStreamEncoderInterface { // resolution. Should be replaced by a construction time setting. virtual void SetStartBitrate(int start_bitrate_bps) = 0; - // Request a key frame. Used for signalling from the remote receiver. - virtual void SendKeyFrame() = 0; + // Request a key frame. Used for signalling from the remote receiver with + // no arguments and for RTCRtpSender.generateKeyFrame with a list of + // rids/layers. + virtual void SendKeyFrame(const std::vector& layers = {}) = 0; // Inform the encoder that a loss has occurred. virtual void OnLossNotification( -- cgit v1.2.3