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_;