From ee3d995091daa5b6d8c8ee5d6379d4bc5d502a7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20M=C3=B6ller?= Date: Mon, 9 Sep 2019 12:51:55 +0200 Subject: [PATCH] New class VideoReceiver2, a trimmed-down vcm::VideoReceiver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The vcm::VideoReceiver class is used by both VideoReceiveStream and the legacy api VideoCodingModule. They have different requirements, since the latter uses the old jitterbuffer and runs the code on a ProcessThread. By making a copy and trimming it down to what's actually used by VideoReceiveStream, we can drop the dependency on the old jitterbuffer, without breaking the legacy api. This should also make it easier to do follow-up refactorings to trim down the class further, and ultimately remove it. Bug: webrtc:7408 Change-Id: Iec8a167fe5d0425114b0b67a5b4c2fd5fc4fa150 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/151910 Commit-Queue: Niels Moller Reviewed-by: Erik Språng Reviewed-by: Philip Eliasson Cr-Commit-Position: refs/heads/master@{#29108} --- modules/video_coding/BUILD.gn | 2 + modules/video_coding/video_receiver2.cc | 126 ++++++++++++++++++++++++ modules/video_coding/video_receiver2.h | 77 +++++++++++++++ video/video_receive_stream.h | 4 +- video/video_stream_decoder.cc | 5 +- video/video_stream_decoder.h | 9 +- 6 files changed, 212 insertions(+), 11 deletions(-) create mode 100644 modules/video_coding/video_receiver2.cc create mode 100644 modules/video_coding/video_receiver2.h diff --git a/modules/video_coding/BUILD.gn b/modules/video_coding/BUILD.gn index dc9f018942..3f8a3dd270 100644 --- a/modules/video_coding/BUILD.gn +++ b/modules/video_coding/BUILD.gn @@ -140,6 +140,8 @@ rtc_static_library("video_coding") { "video_coding_impl.cc", "video_coding_impl.h", "video_receiver.cc", + "video_receiver2.cc", + "video_receiver2.h", ] deps += [ diff --git a/modules/video_coding/video_receiver2.cc b/modules/video_coding/video_receiver2.cc new file mode 100644 index 0000000000..0a9ec49b29 --- /dev/null +++ b/modules/video_coding/video_receiver2.cc @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include + +#include +#include + +#include "modules/video_coding/video_receiver2.h" + +#include "api/video_codecs/video_codec.h" +#include "api/video_codecs/video_decoder.h" +#include "modules/video_coding/decoder_database.h" +#include "modules/video_coding/encoded_frame.h" +#include "modules/video_coding/generic_decoder.h" +#include "modules/video_coding/include/video_coding_defines.h" +#include "modules/video_coding/timing.h" +#include "rtc_base/checks.h" +#include "rtc_base/trace_event.h" +#include "system_wrappers/include/clock.h" + +namespace webrtc { + +VideoReceiver2::VideoReceiver2(Clock* clock, VCMTiming* timing) + : clock_(clock), + timing_(timing), + decodedFrameCallback_(timing_, clock_), + codecDataBase_() { + decoder_thread_checker_.Detach(); +} + +VideoReceiver2::~VideoReceiver2() { + RTC_DCHECK_RUN_ON(&construction_thread_checker_); +} + +// Register a receive callback. Will be called whenever there is a new frame +// ready for rendering. +int32_t VideoReceiver2::RegisterReceiveCallback( + VCMReceiveCallback* receiveCallback) { + RTC_DCHECK_RUN_ON(&construction_thread_checker_); + RTC_DCHECK(!IsDecoderThreadRunning()); + // This value is set before the decoder thread starts and unset after + // the decoder thread has been stopped. + decodedFrameCallback_.SetUserReceiveCallback(receiveCallback); + return VCM_OK; +} + +// Register an externally defined decoder object. +void VideoReceiver2::RegisterExternalDecoder(VideoDecoder* externalDecoder, + uint8_t payloadType) { + RTC_DCHECK_RUN_ON(&construction_thread_checker_); + RTC_DCHECK(!IsDecoderThreadRunning()); + if (externalDecoder == nullptr) { + RTC_CHECK(codecDataBase_.DeregisterExternalDecoder(payloadType)); + return; + } + codecDataBase_.RegisterExternalDecoder(externalDecoder, payloadType); +} + +void VideoReceiver2::TriggerDecoderShutdown() { + RTC_DCHECK_RUN_ON(&construction_thread_checker_); + RTC_DCHECK(IsDecoderThreadRunning()); +} + +void VideoReceiver2::DecoderThreadStarting() { + RTC_DCHECK_RUN_ON(&construction_thread_checker_); + RTC_DCHECK(!IsDecoderThreadRunning()); +#if RTC_DCHECK_IS_ON + decoder_thread_is_running_ = true; +#endif +} + +void VideoReceiver2::DecoderThreadStopped() { + RTC_DCHECK_RUN_ON(&construction_thread_checker_); + RTC_DCHECK(IsDecoderThreadRunning()); +#if RTC_DCHECK_IS_ON + decoder_thread_is_running_ = false; + decoder_thread_checker_.Detach(); +#endif +} + +// Must be called from inside the receive side critical section. +int32_t VideoReceiver2::Decode(const VCMEncodedFrame* frame) { + RTC_DCHECK_RUN_ON(&decoder_thread_checker_); + TRACE_EVENT0("webrtc", "VideoReceiver2::Decode"); + // Change decoder if payload type has changed + VCMGenericDecoder* decoder = + codecDataBase_.GetDecoder(*frame, &decodedFrameCallback_); + if (decoder == nullptr) { + return VCM_NO_CODEC_REGISTERED; + } + return decoder->Decode(*frame, clock_->TimeInMilliseconds()); +} + +// Register possible receive codecs, can be called multiple times +int32_t VideoReceiver2::RegisterReceiveCodec(const VideoCodec* receiveCodec, + int32_t numberOfCores, + bool requireKeyFrame) { + RTC_DCHECK_RUN_ON(&construction_thread_checker_); + RTC_DCHECK(!IsDecoderThreadRunning()); + if (receiveCodec == nullptr) { + return VCM_PARAMETER_ERROR; + } + if (!codecDataBase_.RegisterReceiveCodec(receiveCodec, numberOfCores, + requireKeyFrame)) { + return -1; + } + return 0; +} + +bool VideoReceiver2::IsDecoderThreadRunning() { +#if RTC_DCHECK_IS_ON + return decoder_thread_is_running_; +#else + return true; +#endif +} + +} // namespace webrtc diff --git a/modules/video_coding/video_receiver2.h b/modules/video_coding/video_receiver2.h new file mode 100644 index 0000000000..1ab8a1e186 --- /dev/null +++ b/modules/video_coding/video_receiver2.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef MODULES_VIDEO_CODING_VIDEO_RECEIVER2_H_ +#define MODULES_VIDEO_CODING_VIDEO_RECEIVER2_H_ + +#include "modules/video_coding/decoder_database.h" +#include "modules/video_coding/encoded_frame.h" +#include "modules/video_coding/generic_decoder.h" +#include "modules/video_coding/timing.h" +#include "rtc_base/thread_checker.h" +#include "system_wrappers/include/clock.h" + +namespace webrtc { + +// This class is a copy of vcm::VideoReceiver, trimmed down to what's used by +// VideoReceive stream, with the aim to incrementally trim it down further and +// ultimately delete it. It's difficult to do this incrementally with the +// original VideoReceiver class, since it is used by the legacy +// VideoCodingModule api. +class VideoReceiver2 { + public: + VideoReceiver2(Clock* clock, VCMTiming* timing); + ~VideoReceiver2(); + + int32_t RegisterReceiveCodec(const VideoCodec* receiveCodec, + int32_t numberOfCores, + bool requireKeyFrame); + + void RegisterExternalDecoder(VideoDecoder* externalDecoder, + uint8_t payloadType); + int32_t RegisterReceiveCallback(VCMReceiveCallback* receiveCallback); + + int32_t Decode(const webrtc::VCMEncodedFrame* frame); + + void TriggerDecoderShutdown(); + + // Notification methods that are used to check our internal state and validate + // threading assumptions. These are called by VideoReceiveStream. + // See |IsDecoderThreadRunning()| for more details. + void DecoderThreadStarting(); + void DecoderThreadStopped(); + + private: + // Used for DCHECKing thread correctness. + // In build where DCHECKs are enabled, will return false before + // DecoderThreadStarting is called, then true until DecoderThreadStopped + // is called. + // In builds where DCHECKs aren't enabled, it will return true. + bool IsDecoderThreadRunning(); + + rtc::ThreadChecker construction_thread_checker_; + rtc::ThreadChecker decoder_thread_checker_; + Clock* const clock_; + VCMTiming* timing_; + VCMDecodedFrameCallback decodedFrameCallback_; + + // Callbacks are set before the decoder thread starts. + // Once the decoder thread has been started, usage of |_codecDataBase| moves + // over to the decoder thread. + VCMDecoderDataBase codecDataBase_; + +#if RTC_DCHECK_IS_ON + bool decoder_thread_is_running_ = false; +#endif +}; + +} // namespace webrtc + +#endif // MODULES_VIDEO_CODING_VIDEO_RECEIVER2_H_ diff --git a/video/video_receive_stream.h b/video/video_receive_stream.h index 06713ddad3..65c9601844 100644 --- a/video/video_receive_stream.h +++ b/video/video_receive_stream.h @@ -22,7 +22,7 @@ #include "modules/rtp_rtcp/include/flexfec_receiver.h" #include "modules/rtp_rtcp/source/source_tracker.h" #include "modules/video_coding/frame_buffer2.h" -#include "modules/video_coding/video_coding_impl.h" +#include "modules/video_coding/video_receiver2.h" #include "rtc_base/synchronization/sequence_checker.h" #include "rtc_base/task_queue.h" #include "system_wrappers/include/clock.h" @@ -173,7 +173,7 @@ class VideoReceiveStream : public webrtc::VideoReceiveStream, const std::unique_ptr rtp_receive_statistics_; std::unique_ptr timing_; // Jitter buffer experiment. - vcm::VideoReceiver video_receiver_; + VideoReceiver2 video_receiver_; std::unique_ptr> incoming_video_stream_; RtpVideoStreamReceiver rtp_video_stream_receiver_; std::unique_ptr video_stream_decoder_; diff --git a/video/video_stream_decoder.cc b/video/video_stream_decoder.cc index 29156f4aca..49021bc06f 100644 --- a/video/video_stream_decoder.cc +++ b/video/video_stream_decoder.cc @@ -10,15 +10,14 @@ #include "video/video_stream_decoder.h" -#include "modules/video_coding/include/video_coding.h" -#include "modules/video_coding/video_coding_impl.h" +#include "modules/video_coding/video_receiver2.h" #include "rtc_base/checks.h" #include "video/receive_statistics_proxy.h" namespace webrtc { VideoStreamDecoder::VideoStreamDecoder( - vcm::VideoReceiver* video_receiver, + VideoReceiver2* video_receiver, ReceiveStatisticsProxy* receive_statistics_proxy, rtc::VideoSinkInterface* incoming_video_stream) : video_receiver_(video_receiver), diff --git a/video/video_stream_decoder.h b/video/video_stream_decoder.h index 97c7a8c25c..6b040c6a6f 100644 --- a/video/video_stream_decoder.h +++ b/video/video_stream_decoder.h @@ -26,15 +26,12 @@ namespace webrtc { class ReceiveStatisticsProxy; - -namespace vcm { -class VideoReceiver; -} // namespace vcm +class VideoReceiver2; class VideoStreamDecoder : public VCMReceiveCallback { public: VideoStreamDecoder( - vcm::VideoReceiver* video_receiver, + VideoReceiver2* video_receiver, ReceiveStatisticsProxy* receive_statistics_proxy, rtc::VideoSinkInterface* incoming_video_stream); ~VideoStreamDecoder() override; @@ -55,7 +52,7 @@ class VideoStreamDecoder : public VCMReceiveCallback { // Used for all registered callbacks except rendering. rtc::CriticalSection crit_; - vcm::VideoReceiver* const video_receiver_; + VideoReceiver2* const video_receiver_; ReceiveStatisticsProxy* const receive_stats_callback_; rtc::VideoSinkInterface* const incoming_video_stream_;