Clean VideoReceiveStream2::HandleEncodedFrameOnDecodeQueue
Encapsulate the results in a struct and move the post back to the packet
sequence in the original method. This allows the calls to
ReceiveStatisticsProxy::OnPreDecode to be moved to the main thread
always.
Bug: webrtc:11993
Change-Id: I37516444efeabdb330868733bccb1e842ea4d54f
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/271285
Reviewed-by: Erik Språng <sprang@webrtc.org>
Commit-Queue: Evan Shrubsole <eshr@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#37823}
diff --git a/video/receive_statistics_proxy2.cc b/video/receive_statistics_proxy2.cc
index 01e4f09..073b1a6 100644
--- a/video/receive_statistics_proxy2.cc
+++ b/video/receive_statistics_proxy2.cc
@@ -959,16 +959,12 @@
}
void ReceiveStatisticsProxy::OnPreDecode(VideoCodecType codec_type, int qp) {
- RTC_DCHECK_RUN_ON(&decode_queue_);
- worker_thread_->PostTask(
- SafeTask(task_safety_.flag(), [codec_type, qp, this]() {
- RTC_DCHECK_RUN_ON(&main_thread_);
- last_codec_type_ = codec_type;
- if (last_codec_type_ == kVideoCodecVP8 && qp != -1) {
- qp_counters_.vp8.Add(qp);
- qp_sample_.Add(qp);
- }
- }));
+ RTC_DCHECK_RUN_ON(&main_thread_);
+ last_codec_type_ = codec_type;
+ if (last_codec_type_ == kVideoCodecVP8 && qp != -1) {
+ qp_counters_.vp8.Add(qp);
+ qp_sample_.Add(qp);
+ }
}
void ReceiveStatisticsProxy::OnStreamInactive() {
diff --git a/video/video_receive_stream2.cc b/video/video_receive_stream2.cc
index 553f6b4..7e3968a 100644
--- a/video/video_receive_stream2.cc
+++ b/video/video_receive_stream2.cc
@@ -801,15 +801,45 @@
const bool keyframe_request_is_due =
!last_keyframe_request_ ||
now >= (*last_keyframe_request_ + max_wait_for_keyframe_);
+ const bool received_frame_is_keyframe =
+ frame->FrameType() == VideoFrameType::kVideoFrameKey;
- decode_queue_.PostTask([this, frame = std::move(frame), now,
- keyframe_request_is_due,
+ // Current OnPreDecode only cares about QP for VP8.
+ int qp = -1;
+ if (frame->CodecSpecific()->codecType == kVideoCodecVP8) {
+ if (!vp8::GetQp(frame->data(), frame->size(), &qp)) {
+ RTC_LOG(LS_WARNING) << "Failed to extract QP from VP8 video frame";
+ }
+ }
+ stats_proxy_.OnPreDecode(frame->CodecSpecific()->codecType, qp);
+
+ decode_queue_.PostTask([this, now, keyframe_request_is_due,
+ received_frame_is_keyframe, frame = std::move(frame),
keyframe_required = keyframe_required_]() mutable {
RTC_DCHECK_RUN_ON(&decode_queue_);
if (decoder_stopped_)
return;
- HandleEncodedFrameOnDecodeQueue(std::move(frame), now,
- keyframe_request_is_due, keyframe_required);
+ DecodeFrameResult result = HandleEncodedFrameOnDecodeQueue(
+ std::move(frame), keyframe_request_is_due, keyframe_required);
+
+ // TODO(bugs.webrtc.org/11993): Make this PostTask to the network thread.
+ call_->worker_thread()->PostTask(
+ SafeTask(task_safety_.flag(),
+ [this, now, result = std::move(result),
+ received_frame_is_keyframe, keyframe_request_is_due]() {
+ RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
+ keyframe_required_ = result.keyframe_required;
+
+ if (result.decoded_frame_picture_id) {
+ rtp_video_stream_receiver_.FrameDecoded(
+ *result.decoded_frame_picture_id);
+ }
+
+ HandleKeyFrameGeneration(received_frame_is_keyframe, now,
+ result.force_request_key_frame,
+ keyframe_request_is_due);
+ buffer_->StartNextDecode(keyframe_required_);
+ }));
});
}
@@ -840,24 +870,15 @@
buffer_->StartNextDecode(keyframe_required_);
}
-void VideoReceiveStream2::HandleEncodedFrameOnDecodeQueue(
+VideoReceiveStream2::DecodeFrameResult
+VideoReceiveStream2::HandleEncodedFrameOnDecodeQueue(
std::unique_ptr<EncodedFrame> frame,
- Timestamp now,
bool keyframe_request_is_due,
bool keyframe_required) {
RTC_DCHECK_RUN_ON(&decode_queue_);
- // Current OnPreDecode only cares about QP for VP8.
- int qp = -1;
- if (frame->CodecSpecific()->codecType == kVideoCodecVP8) {
- if (!vp8::GetQp(frame->data(), frame->size(), &qp)) {
- RTC_LOG(LS_WARNING) << "Failed to extract QP from VP8 video frame";
- }
- }
- stats_proxy_.OnPreDecode(frame->CodecSpecific()->codecType, qp);
-
bool force_request_key_frame = false;
- int64_t decoded_frame_picture_id = -1;
+ absl::optional<int64_t> decoded_frame_picture_id;
if (!video_receiver_.IsExternalDecoderRegistered(frame->PayloadType())) {
// Look for the decoder with this payload type.
@@ -870,8 +891,6 @@
}
int64_t frame_id = frame->Id();
- bool received_frame_is_keyframe =
- frame->FrameType() == VideoFrameType::kVideoFrameKey;
int decode_result = DecodeAndMaybeDispatchEncodedFrame(std::move(frame));
if (decode_result == WEBRTC_VIDEO_CODEC_OK ||
decode_result == WEBRTC_VIDEO_CODEC_OK_REQUEST_KEYFRAME) {
@@ -889,24 +908,11 @@
force_request_key_frame = true;
}
- {
- // TODO(bugs.webrtc.org/11993): Make this PostTask to the network thread.
- call_->worker_thread()->PostTask(SafeTask(
- task_safety_.flag(), [this, now, received_frame_is_keyframe,
- force_request_key_frame, decoded_frame_picture_id,
- keyframe_request_is_due, keyframe_required]() {
- RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
- keyframe_required_ = keyframe_required;
-
- if (decoded_frame_picture_id != -1)
- rtp_video_stream_receiver_.FrameDecoded(decoded_frame_picture_id);
-
- HandleKeyFrameGeneration(received_frame_is_keyframe, now,
- force_request_key_frame,
- keyframe_request_is_due);
- buffer_->StartNextDecode(keyframe_required_);
- }));
- }
+ return DecodeFrameResult{
+ .force_request_key_frame = force_request_key_frame,
+ .decoded_frame_picture_id = std::move(decoded_frame_picture_id),
+ .keyframe_required = keyframe_required,
+ };
}
int VideoReceiveStream2::DecodeAndMaybeDispatchEncodedFrame(
diff --git a/video/video_receive_stream2.h b/video/video_receive_stream2.h
index 4fbb66d..c16e418 100644
--- a/video/video_receive_stream2.h
+++ b/video/video_receive_stream2.h
@@ -203,11 +203,33 @@
void OnDecodableFrameTimeout(TimeDelta wait) override;
void CreateAndRegisterExternalDecoder(const Decoder& decoder);
- void HandleEncodedFrameOnDecodeQueue(std::unique_ptr<EncodedFrame> frame,
- Timestamp now,
- bool keyframe_request_is_due,
- bool keyframe_required)
- RTC_RUN_ON(decode_queue_);
+
+ struct DecodeFrameResult {
+ DecodeFrameResult(const DecodeFrameResult&) = delete;
+ DecodeFrameResult& operator=(const DecodeFrameResult&) = delete;
+ DecodeFrameResult(DecodeFrameResult&&) = default;
+ DecodeFrameResult& operator=(DecodeFrameResult&&) = default;
+
+ // True if the decoder returned code WEBRTC_VIDEO_CODEC_OK_REQUEST_KEYFRAME,
+ // or if the decoder failed and a keyframe is required. When true, a
+ // keyframe request should be sent even if a keyframe request was sent
+ // recently.
+ bool force_request_key_frame;
+
+ // The picture id of the frame that was decoded, or nullopt if the frame was
+ // not decoded.
+ absl::optional<int64_t> decoded_frame_picture_id;
+
+ // True if the next frame decoded must be a keyframe. This value will set
+ // the value of `keyframe_required_`, which will force the frame buffer to
+ // drop all frames that are not keyframes.
+ bool keyframe_required;
+ };
+
+ DecodeFrameResult HandleEncodedFrameOnDecodeQueue(
+ std::unique_ptr<EncodedFrame> frame,
+ bool keyframe_request_is_due,
+ bool keyframe_required) RTC_RUN_ON(decode_queue_);
void UpdatePlayoutDelays() const
RTC_EXCLUSIVE_LOCKS_REQUIRED(worker_sequence_checker_);
void RequestKeyFrame(Timestamp now) RTC_RUN_ON(packet_sequence_checker_);