Request keyframe via setParameters

after the W3C changes in approach documented here:
  https://github.com/w3c/webrtc-extensions/pull/167

chromium CL: https://chromium-review.googlesource.com/c/chromium/src/+/4643591

Note that this does not follow the route taken by the W3C API but
still considers this flag a part of the encodingParameters.

BUG=chromium:1354101

Change-Id: If0f0ec09bebddea1f01dd8afbe4747c21afe6793
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/286741
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Commit-Queue: Philipp Hancke <phancke@microsoft.com>
Cr-Commit-Position: refs/heads/main@{#40656}
This commit is contained in:
Philipp Hancke 2023-08-28 11:11:06 +02:00 committed by WebRTC LUCI CQ
parent 36500ab634
commit 82c56ca794
5 changed files with 105 additions and 1 deletions

View File

@ -515,6 +515,7 @@ struct RTC_EXPORT RtpEncodingParameters {
// Value to use for RID RTP header extension.
// Called "encodingId" in ORTC.
std::string rid;
bool request_key_frame = false;
// Allow dynamic frame length changes for audio:
// https://w3c.github.io/webrtc-extensions/#dom-rtcrtpencodingparameters-adaptiveptime

View File

@ -383,6 +383,11 @@ void FakeVideoSendStream::SetSource(
: rtc::VideoSinkWants());
}
void FakeVideoSendStream::GenerateKeyFrame(
const std::vector<std::string>& rids) {
keyframes_requested_by_rid_ = rids;
}
void FakeVideoSendStream::InjectVideoSinkWants(
const rtc::VideoSinkWants& wants) {
sink_wants_ = wants;

View File

@ -188,7 +188,10 @@ class FakeVideoSendStream final
rtc::VideoSourceInterface<webrtc::VideoFrame>* source() const {
return source_;
}
void GenerateKeyFrame(const std::vector<std::string>& rids) override {}
void GenerateKeyFrame(const std::vector<std::string>& rids);
const std::vector<std::string>& GetKeyFramesRequested() const {
return keyframes_requested_by_rid_;
}
private:
// rtc::VideoSinkInterface<VideoFrame> implementation.
@ -231,6 +234,7 @@ class FakeVideoSendStream final
absl::optional<webrtc::VideoFrame> last_frame_;
webrtc::VideoSendStream::Stats stats_;
int num_encoder_reconfigurations_ = 0;
std::vector<std::string> keyframes_requested_by_rid_;
};
class FakeVideoReceiveStream final

View File

@ -1965,6 +1965,22 @@ WebRtcVideoSendChannel::WebRtcVideoSendStream::SetRtpParameters(
stream_->SetSource(source_, GetDegradationPreference());
}
}
// Check if a key frame was requested via setParameters.
std::vector<std::string> key_frames_requested_by_rid;
for (const auto& encoding : rtp_parameters_.encodings) {
if (encoding.request_key_frame) {
key_frames_requested_by_rid.push_back(encoding.rid);
}
}
if (!key_frames_requested_by_rid.empty()) {
if (key_frames_requested_by_rid.size() == 1 &&
key_frames_requested_by_rid[0] == "") {
// For non-simulcast cases there is no rid,
// request a keyframe on all layers.
key_frames_requested_by_rid.clear();
}
GenerateKeyFrame(key_frames_requested_by_rid);
}
return webrtc::InvokeSetParametersCallback(callback, webrtc::RTCError::OK());
}

View File

@ -9540,6 +9540,84 @@ TEST_F(WebRtcVideoChannelTest,
EXPECT_TRUE(stream->GetEncoderConfig().is_quality_scaling_allowed);
}
TEST_F(WebRtcVideoChannelTest, GenerateKeyFrameSinglecast) {
FakeVideoSendStream* stream = AddSendStream();
webrtc::RtpParameters rtp_parameters =
send_channel_->GetRtpSendParameters(last_ssrc_);
ASSERT_EQ(1u, rtp_parameters.encodings.size());
EXPECT_EQ(rtp_parameters.encodings[0].rid, "");
EXPECT_TRUE(
send_channel_->SetRtpSendParameters(last_ssrc_, rtp_parameters).ok());
EXPECT_THAT(stream->GetKeyFramesRequested(), std::vector<std::string>({}));
// Manually set the key frames requested to check they are cleared by the next
// call.
stream->GenerateKeyFrame({"bogus"});
rtp_parameters.encodings[0].request_key_frame = true;
EXPECT_TRUE(
send_channel_->SetRtpSendParameters(last_ssrc_, rtp_parameters).ok());
EXPECT_THAT(stream->GetKeyFramesRequested(),
ElementsAreArray(std::vector<std::string>({})));
}
TEST_F(WebRtcVideoChannelTest, GenerateKeyFrameSimulcast) {
StreamParams stream_params = CreateSimStreamParams("cname", {123, 456, 789});
std::vector<std::string> rids = {"f", "h", "q"};
std::vector<cricket::RidDescription> rid_descriptions;
for (const auto& rid : rids) {
rid_descriptions.emplace_back(rid, cricket::RidDirection::kSend);
}
stream_params.set_rids(rid_descriptions);
FakeVideoSendStream* stream = AddSendStream(stream_params);
webrtc::RtpParameters rtp_parameters =
send_channel_->GetRtpSendParameters(last_ssrc_);
ASSERT_EQ(3u, rtp_parameters.encodings.size());
EXPECT_EQ(rtp_parameters.encodings[0].rid, "f");
EXPECT_EQ(rtp_parameters.encodings[1].rid, "h");
EXPECT_EQ(rtp_parameters.encodings[2].rid, "q");
EXPECT_TRUE(
send_channel_->SetRtpSendParameters(last_ssrc_, rtp_parameters).ok());
EXPECT_THAT(stream->GetKeyFramesRequested(),
ElementsAreArray(std::vector<std::string>({})));
rtp_parameters.encodings[0].request_key_frame = true;
EXPECT_TRUE(
send_channel_->SetRtpSendParameters(last_ssrc_, rtp_parameters).ok());
EXPECT_THAT(stream->GetKeyFramesRequested(), ElementsAreArray({"f"}));
rtp_parameters.encodings[0].request_key_frame = true;
rtp_parameters.encodings[1].request_key_frame = true;
EXPECT_TRUE(
send_channel_->SetRtpSendParameters(last_ssrc_, rtp_parameters).ok());
EXPECT_THAT(stream->GetKeyFramesRequested(), ElementsAreArray({"f", "h"}));
rtp_parameters.encodings[0].request_key_frame = true;
rtp_parameters.encodings[1].request_key_frame = true;
rtp_parameters.encodings[2].request_key_frame = true;
EXPECT_TRUE(
send_channel_->SetRtpSendParameters(last_ssrc_, rtp_parameters).ok());
EXPECT_THAT(stream->GetKeyFramesRequested(),
ElementsAreArray({"f", "h", "q"}));
rtp_parameters.encodings[0].request_key_frame = true;
rtp_parameters.encodings[1].request_key_frame = false;
rtp_parameters.encodings[2].request_key_frame = true;
EXPECT_TRUE(
send_channel_->SetRtpSendParameters(last_ssrc_, rtp_parameters).ok());
EXPECT_THAT(stream->GetKeyFramesRequested(), ElementsAreArray({"f", "q"}));
rtp_parameters.encodings[0].request_key_frame = false;
rtp_parameters.encodings[1].request_key_frame = false;
rtp_parameters.encodings[2].request_key_frame = true;
EXPECT_TRUE(
send_channel_->SetRtpSendParameters(last_ssrc_, rtp_parameters).ok());
EXPECT_THAT(stream->GetKeyFramesRequested(), ElementsAreArray({"q"}));
}
class WebRtcVideoChannelSimulcastTest : public ::testing::Test {
public:
WebRtcVideoChannelSimulcastTest()