Keep the video send stream alive if the encoder drop frames.
The encoder can drop all frames for extended periods if it has produced over budget. After 2 seconds without any encoded frames, the video send stream times out and deallocates the stream.
Ideally the send stream should keep track if frames are captured instead of encoded, but keeping the stream alive using OnDroppedFrame can work as a proxy for that.
Bug: webrtc:11062
Change-Id: Id7ec1ff333427643453c4a36d1db03ca826cd9ea
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/158700
Reviewed-by: Erik Språng <sprang@webrtc.org>
Commit-Queue: Jakob Ivarsson <jakobi@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29662}
diff --git a/video/video_send_stream_impl.cc b/video/video_send_stream_impl.cc
index 26f55ff..31dddcc 100644
--- a/video/video_send_stream_impl.cc
+++ b/video/video_send_stream_impl.cc
@@ -627,6 +627,11 @@
return result;
}
+void VideoSendStreamImpl::OnDroppedFrame(
+ EncodedImageCallback::DropReason reason) {
+ activity_ = true;
+}
+
std::map<uint32_t, RtpState> VideoSendStreamImpl::GetRtpStates() const {
return rtp_video_sender_->GetRtpStates();
}
diff --git a/video/video_send_stream_impl.h b/video/video_send_stream_impl.h
index 7b7136f..091ac0f 100644
--- a/video/video_send_stream_impl.h
+++ b/video/video_send_stream_impl.h
@@ -128,6 +128,9 @@
const CodecSpecificInfo* codec_specific_info,
const RTPFragmentationHeader* fragmentation) override;
+ // Implements EncodedImageCallback.
+ void OnDroppedFrame(EncodedImageCallback::DropReason reason) override;
+
// Implements VideoBitrateAllocationObserver.
void OnBitrateAllocationUpdated(
const VideoBitrateAllocation& allocation) override;
diff --git a/video/video_send_stream_impl_unittest.cc b/video/video_send_stream_impl_unittest.cc
index 2bbdefb..ce88a36 100644
--- a/video/video_send_stream_impl_unittest.cc
+++ b/video/video_send_stream_impl_unittest.cc
@@ -858,5 +858,41 @@
ASSERT_TRUE(done.Wait(10000));
}
+TEST_F(VideoSendStreamImplTest, KeepAliveOnDroppedFrame) {
+ std::unique_ptr<VideoSendStreamImpl> vss_impl;
+ test_queue_.SendTask(
+ [&] {
+ vss_impl = CreateVideoSendStreamImpl(
+ kDefaultInitialBitrateBps, kDefaultBitratePriority,
+ VideoEncoderConfig::ContentType::kRealtimeVideo);
+ vss_impl->Start();
+ const uint32_t kBitrateBps = 100000;
+ EXPECT_CALL(rtp_video_sender_, GetPayloadBitrateBps())
+ .Times(1)
+ .WillOnce(Return(kBitrateBps));
+ static_cast<BitrateAllocatorObserver*>(vss_impl.get())
+ ->OnBitrateUpdated(CreateAllocation(kBitrateBps));
+
+ // Keep the stream from deallocating by dropping a frame.
+ static_cast<EncodedImageCallback*>(vss_impl.get())
+ ->OnDroppedFrame(
+ EncodedImageCallback::DropReason::kDroppedByEncoder);
+ EXPECT_CALL(bitrate_allocator_, RemoveObserver(vss_impl.get()))
+ .Times(0);
+ },
+ RTC_FROM_HERE);
+
+ rtc::Event done;
+ test_queue_.PostDelayedTask(
+ [&] {
+ testing::Mock::VerifyAndClearExpectations(&bitrate_allocator_);
+ vss_impl->Stop();
+ vss_impl.reset();
+ done.Set();
+ },
+ 2000);
+ ASSERT_TRUE(done.Wait(5000));
+}
+
} // namespace internal
} // namespace webrtc
diff --git a/video/video_stream_encoder.cc b/video/video_stream_encoder.cc
index a986baf..6be0276 100644
--- a/video/video_stream_encoder.cc
+++ b/video/video_stream_encoder.cc
@@ -1776,6 +1776,7 @@
});
break;
}
+ sink_->OnDroppedFrame(reason);
}
void VideoStreamEncoder::OnBitrateUpdated(DataRate target_bitrate,