From cfc8e3b9ef25eb977e55960c7bac2172298f4d27 Mon Sep 17 00:00:00 2001 From: mflodman Date: Tue, 3 May 2016 21:22:04 -0700 Subject: [PATCH] Removed all RTP dependencies from ViEChannel and renamed class. ViEChannel is now called VideoStreamReceiver. There will be a follow up CL removing all rtp references from VideoReceiveStream, but that made this CL to big and it will be done separately. BUG=webrtc:5079 Review-Url: https://codereview.webrtc.org/1929313002 Cr-Commit-Position: refs/heads/master@{#12619} --- webrtc/video/BUILD.gn | 4 +- webrtc/video/receive_statistics_proxy.h | 2 +- webrtc/video/rtp_stream_receiver.cc | 57 ++-- webrtc/video/rtp_stream_receiver.h | 57 ++-- webrtc/video/video_receive_stream.cc | 41 ++- webrtc/video/video_receive_stream.h | 7 +- webrtc/video/video_send_stream.h | 2 - webrtc/video/video_stream_decoder.cc | 132 +++++++++ .../{vie_channel.h => video_stream_decoder.h} | 90 ++---- webrtc/video/vie_channel.cc | 266 ------------------ webrtc/video/webrtc_video.gypi | 4 +- 11 files changed, 230 insertions(+), 432 deletions(-) create mode 100644 webrtc/video/video_stream_decoder.cc rename webrtc/video/{vie_channel.h => video_stream_decoder.h} (52%) delete mode 100644 webrtc/video/vie_channel.cc diff --git a/webrtc/video/BUILD.gn b/webrtc/video/BUILD.gn index 74fad8489d..9e350f0cdb 100644 --- a/webrtc/video/BUILD.gn +++ b/webrtc/video/BUILD.gn @@ -40,8 +40,8 @@ source_set("video") { "video_receive_stream.h", "video_send_stream.cc", "video_send_stream.h", - "vie_channel.cc", - "vie_channel.h", + "video_stream_decoder.cc", + "video_stream_decoder.h", "vie_encoder.cc", "vie_encoder.h", "vie_remb.cc", diff --git a/webrtc/video/receive_statistics_proxy.h b/webrtc/video/receive_statistics_proxy.h index 879100ab03..f88bbf51a2 100644 --- a/webrtc/video/receive_statistics_proxy.h +++ b/webrtc/video/receive_statistics_proxy.h @@ -22,7 +22,7 @@ #include "webrtc/common_video/include/frame_callback.h" #include "webrtc/modules/video_coding/include/video_coding_defines.h" #include "webrtc/video/report_block_stats.h" -#include "webrtc/video/vie_channel.h" +#include "webrtc/video/video_stream_decoder.h" #include "webrtc/video_receive_stream.h" namespace webrtc { diff --git a/webrtc/video/rtp_stream_receiver.cc b/webrtc/video/rtp_stream_receiver.cc index 6def90f708..ac1caa6a3f 100644 --- a/webrtc/video/rtp_stream_receiver.cc +++ b/webrtc/video/rtp_stream_receiver.cc @@ -13,6 +13,7 @@ #include #include "webrtc/base/logging.h" +#include "webrtc/common_types.h" #include "webrtc/config.h" #include "webrtc/modules/pacing/packet_router.h" #include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h" @@ -27,6 +28,7 @@ #include "webrtc/system_wrappers/include/tick_util.h" #include "webrtc/system_wrappers/include/timestamp_extrapolator.h" #include "webrtc/system_wrappers/include/trace.h" +#include "webrtc/video/receive_statistics_proxy.h" namespace webrtc { @@ -65,7 +67,6 @@ std::unique_ptr CreateRtpRtcpModule( return rtp_rtcp; } - static const int kPacketLogIntervalMs = 10000; RtpStreamReceiver::RtpStreamReceiver( @@ -74,7 +75,9 @@ RtpStreamReceiver::RtpStreamReceiver( Transport* transport, RtcpRttStats* rtt_stats, PacedSender* paced_sender, - PacketRouter* packet_router) + PacketRouter* packet_router, + const VideoReceiveStream::Config& config, + ReceiveStatisticsProxy* receive_stats_proxy) : clock_(Clock::GetRealTimeClock()), video_receiver_(video_receiver), remote_bitrate_estimator_(remote_bitrate_estimator), @@ -94,12 +97,27 @@ RtpStreamReceiver::RtpStreamReceiver( rtp_rtcp_(CreateRtpRtcpModule(rtp_receive_statistics_.get(), transport, rtt_stats, - &rtcp_packet_type_counter_observer_, + receive_stats_proxy, remote_bitrate_estimator_, paced_sender, packet_router)) { packet_router_->AddRtpModule(rtp_rtcp_.get()); + rtp_receive_statistics_->RegisterRtpStatisticsCallback(receive_stats_proxy); + rtp_receive_statistics_->RegisterRtcpStatisticsCallback(receive_stats_proxy); + + RTC_DCHECK(config.rtp.rtcp_mode != RtcpMode::kOff) + << "A stream should not be configured with RTCP disabled. This value is " + "reserved for internal usage."; + rtp_rtcp_->SetRTCPStatus(config.rtp.rtcp_mode); rtp_rtcp_->SetKeyFrameRequestMethod(kKeyFrameReqPliRtcp); + + static const int kMaxPacketAgeToNack = 450; + NACKMethod nack_method = + config.rtp.nack.rtp_history_ms > 0 ? kNackRtcp : kNackOff; + const int max_reordering_threshold = (nack_method == kNackRtcp) + ? kMaxPacketAgeToNack : kDefaultMaxReorderingThreshold; + rtp_receiver_->SetNACKStatus(nack_method); + rtp_receive_statistics_->SetMaxReorderingThreshold(max_reordering_threshold); } RtpStreamReceiver::~RtpStreamReceiver() { @@ -135,18 +153,6 @@ bool RtpStreamReceiver::SetReceiveCodec(const VideoCodec& video_codec) { 0, 0) == 0; } -void RtpStreamReceiver::SetNackStatus(bool enable, - int max_nack_reordering_threshold) { - if (!enable) { - // Reset the threshold back to the lower default threshold when NACK is - // disabled since we no longer will be receiving retransmissions. - max_nack_reordering_threshold = kDefaultMaxReorderingThreshold; - } - rtp_receive_statistics_->SetMaxReorderingThreshold( - max_nack_reordering_threshold); - rtp_receiver_->SetNACKStatus(enable ? kNackRtcp : kNackOff); -} - void RtpStreamReceiver::SetRtxPayloadType(int payload_type, int associated_payload_type) { rtp_payload_registry_.SetRtxPayloadType(payload_type, @@ -188,12 +194,6 @@ void RtpStreamReceiver::EnableReceiveRtpHeaderExtension( StringToRtpExtensionType(extension), id)); } -void RtpStreamReceiver::RegisterRtcpPacketTypeCounterObserver( - RtcpPacketTypeCounterObserver* observer) { - rtcp_packet_type_counter_observer_.Set(observer); -} - - int32_t RtpStreamReceiver::OnReceivedPayloadData( const uint8_t* payload_data, const size_t payload_size, @@ -294,6 +294,21 @@ bool RtpStreamReceiver::DeliverRtp(const uint8_t* rtp_packet, return ret; } +int32_t RtpStreamReceiver::RequestKeyFrame() { + return rtp_rtcp_->RequestKeyFrame(); +} + +int32_t RtpStreamReceiver::SliceLossIndicationRequest( + const uint64_t picture_id) { + return rtp_rtcp_->SendRTCPSliceLossIndication( + static_cast(picture_id)); +} + +int32_t RtpStreamReceiver::ResendPackets(const uint16_t* sequence_numbers, + uint16_t length) { + return rtp_rtcp_->SendNACK(sequence_numbers, length); +} + bool RtpStreamReceiver::ReceivePacket(const uint8_t* packet, size_t packet_length, const RTPHeader& header, diff --git a/webrtc/video/rtp_stream_receiver.h b/webrtc/video/rtp_stream_receiver.h index d5513fb518..bedf40b4fb 100644 --- a/webrtc/video/rtp_stream_receiver.h +++ b/webrtc/video/rtp_stream_receiver.h @@ -24,7 +24,9 @@ #include "webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h" #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h" #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" +#include "webrtc/modules/video_coding/include/video_coding_defines.h" #include "webrtc/typedefs.h" +#include "webrtc/video_receive_stream.h" namespace webrtc { @@ -33,6 +35,7 @@ class PacedSender; class PacketRouter; class RemoteNtpTimeEstimator; class ReceiveStatistics; +class ReceiveStatisticsProxy; class RemoteBitrateEstimator; class RtcpRttStats; class RtpHeaderParser; @@ -44,19 +47,22 @@ namespace vcm { class VideoReceiver; } // namespace vcm -class RtpStreamReceiver : public RtpData, public RtpFeedback { +class RtpStreamReceiver : public RtpData, public RtpFeedback, + public VCMFrameTypeCallback, + public VCMPacketRequestCallback { public: RtpStreamReceiver(vcm::VideoReceiver* video_receiver, RemoteBitrateEstimator* remote_bitrate_estimator, Transport* transport, RtcpRttStats* rtt_stats, PacedSender* paced_sender, - PacketRouter* packet_router); + PacketRouter* packet_router, + const VideoReceiveStream::Config& config, + ReceiveStatisticsProxy* receive_stats_proxy); ~RtpStreamReceiver(); bool SetReceiveCodec(const VideoCodec& video_codec); - void SetNackStatus(bool enable, int max_nack_reordering_threshold); void SetRtxPayloadType(int payload_type, int associated_payload_type); // If set to true, the RTX payload type mapping supplied in // |SetRtxPayloadType| will be used when restoring RTX packets. Without it, @@ -75,8 +81,6 @@ class RtpStreamReceiver : public RtpData, public RtpFeedback { RtpRtcp* rtp_rtcp() const { return rtp_rtcp_.get(); } void EnableReceiveRtpHeaderExtension(const std::string& extension, int id); - void RegisterRtcpPacketTypeCounterObserver( - RtcpPacketTypeCounterObserver* observer); void StartReceive(); void StopReceive(); @@ -101,43 +105,16 @@ class RtpStreamReceiver : public RtpData, public RtpFeedback { void OnIncomingSSRCChanged(const uint32_t ssrc) override; void OnIncomingCSRCChanged(const uint32_t CSRC, const bool added) override {} + // Implements VCMFrameTypeCallback. + int32_t RequestKeyFrame() override; + int32_t SliceLossIndicationRequest(const uint64_t picture_id) override; + + // Implements VCMPacketRequestCallback. + int32_t ResendPackets(const uint16_t* sequenceNumbers, + uint16_t length) override; + ReceiveStatistics* GetReceiveStatistics() const; - template - class RegisterableCallback : public T { - public: - RegisterableCallback() : callback_(nullptr) {} - - void Set(T* callback) { - rtc::CritScope lock(&critsect_); - callback_ = callback; - } - - protected: - // Note: this should be implemented with a RW-lock to allow simultaneous - // calls into the callback. However that doesn't seem to be needed for the - // current type of callbacks covered by this class. - rtc::CriticalSection critsect_; - T* callback_ GUARDED_BY(critsect_); - - private: - RTC_DISALLOW_COPY_AND_ASSIGN(RegisterableCallback); - }; - - class RegisterableRtcpPacketTypeCounterObserver - : public RegisterableCallback { - public: - void RtcpPacketTypesCounterUpdated( - uint32_t ssrc, - const RtcpPacketTypeCounter& packet_counter) override { - rtc::CritScope lock(&critsect_); - if (callback_) - callback_->RtcpPacketTypesCounterUpdated(ssrc, packet_counter); - } - - private: - } rtcp_packet_type_counter_observer_; - private: bool ReceivePacket(const uint8_t* packet, size_t packet_length, diff --git a/webrtc/video/video_receive_stream.cc b/webrtc/video/video_receive_stream.cc index 6d29336c00..670d92b2f2 100644 --- a/webrtc/video/video_receive_stream.cc +++ b/webrtc/video/video_receive_stream.cc @@ -171,29 +171,30 @@ VideoReceiveStream::VideoReceiveStream( &transport_adapter_, call_stats_->rtcp_rtt_stats(), congestion_controller_->pacer(), - congestion_controller_->packet_router()), - vie_channel_(&video_receiver_, - &rtp_stream_receiver_), + congestion_controller_->packet_router(), + config, + &stats_proxy_), + video_stream_decoder_(&video_receiver_, + &rtp_stream_receiver_, + &rtp_stream_receiver_, + config.rtp.nack.rtp_history_ms > 0, + &stats_proxy_, + &incoming_video_stream_, + this), vie_sync_(&video_receiver_), - rtp_rtcp_(vie_channel_.rtp_rtcp()) { + rtp_rtcp_(rtp_stream_receiver_.rtp_rtcp()) { LOG(LS_INFO) << "VideoReceiveStream: " << config_.ToString(); RTC_DCHECK(process_thread_); RTC_DCHECK(congestion_controller_); RTC_DCHECK(call_stats_); RTC_DCHECK(remb_); - RTC_CHECK(vie_channel_.Init() == 0); - - // Register the channel to receive stats updates. - call_stats_->RegisterStatsObserver(vie_channel_.GetStatsObserver()); - - // TODO(pbos): This is not fine grained enough... - vie_channel_.SetProtectionMode(config_.rtp.nack.rtp_history_ms > 0, false, -1, - -1); RTC_DCHECK(config_.rtp.rtcp_mode != RtcpMode::kOff) << "A stream should not be configured with RTCP disabled. This value is " "reserved for internal usage."; - rtp_rtcp_->SetRTCPStatus(config_.rtp.rtcp_mode); + + // Register the channel to receive stats updates. + call_stats_->RegisterStatsObserver(&video_stream_decoder_); RTC_DCHECK(config_.rtp.remote_ssrc != 0); // TODO(pbos): What's an appropriate local_ssrc for receive-only streams? @@ -255,14 +256,8 @@ VideoReceiveStream::VideoReceiveStream( if (config.rtp.rtcp_xr.receiver_reference_time_report) rtp_rtcp_->SetRtcpXrRrtrStatus(true); - vie_channel_.RegisterReceiveStatisticsProxy(&stats_proxy_); - rtp_stream_receiver_.GetReceiveStatistics()->RegisterRtpStatisticsCallback( - &stats_proxy_); - rtp_stream_receiver_.GetReceiveStatistics()->RegisterRtcpStatisticsCallback( - &stats_proxy_); // Stats callback for CNAME changes. rtp_rtcp_->RegisterRtcpStatisticsCallback(&stats_proxy_); - vie_channel_.RegisterRtcpPacketTypeCounterObserver(&stats_proxy_); RTC_DCHECK(!config_.decoders.empty()); std::set decoder_payload_types; @@ -286,8 +281,6 @@ VideoReceiveStream::VideoReceiveStream( video_receiver_.SetRenderDelay(config.render_delay_ms); incoming_video_stream_.SetExpectedRenderDelay(config.render_delay_ms); incoming_video_stream_.SetExternalCallback(this); - vie_channel_.SetIncomingVideoStream(&incoming_video_stream_); - vie_channel_.RegisterPreRenderCallback(this); process_thread_->RegisterModule(rtp_stream_receiver_.GetReceiveStatistics()); process_thread_->RegisterModule(rtp_stream_receiver_.rtp_rtcp()); @@ -305,16 +298,14 @@ VideoReceiveStream::~VideoReceiveStream() { process_thread_->DeRegisterModule( rtp_stream_receiver_.GetReceiveStatistics()); - // Deregister external decoders so that they are no longer running during + // Deregister external decoders so they are no longer running during // destruction. This effectively stops the VCM since the decoder thread is // stopped, the VCM is deregistered and no asynchronous decoder threads are // running. for (const Decoder& decoder : config_.decoders) video_receiver_.RegisterExternalDecoder(nullptr, decoder.payload_type); - vie_channel_.RegisterPreRenderCallback(nullptr); - - call_stats_->DeregisterStatsObserver(vie_channel_.GetStatsObserver()); + call_stats_->DeregisterStatsObserver(&video_stream_decoder_); rtp_rtcp_->SetREMBStatus(false); remb_->RemoveReceiveChannel(rtp_rtcp_); diff --git a/webrtc/video/video_receive_stream.h b/webrtc/video/video_receive_stream.h index a82ccd7c78..41fafe8075 100644 --- a/webrtc/video/video_receive_stream.h +++ b/webrtc/video/video_receive_stream.h @@ -22,9 +22,8 @@ #include "webrtc/system_wrappers/include/clock.h" #include "webrtc/video/encoded_frame_callback_adapter.h" #include "webrtc/video/receive_statistics_proxy.h" -#include "webrtc/video/vie_channel.h" -#include "webrtc/video/vie_encoder.h" -#include "webrtc/video_encoder.h" +#include "webrtc/video/rtp_stream_receiver.h" +#include "webrtc/video/video_stream_decoder.h" #include "webrtc/video_receive_stream.h" namespace webrtc { @@ -107,7 +106,7 @@ class VideoReceiveStream : public webrtc::VideoReceiveStream, IncomingVideoStream incoming_video_stream_; ReceiveStatisticsProxy stats_proxy_; RtpStreamReceiver rtp_stream_receiver_; - ViEChannel vie_channel_; + VideoStreamDecoder video_stream_decoder_; ViESyncModule vie_sync_; RtpRtcp* const rtp_rtcp_; diff --git a/webrtc/video/video_send_stream.h b/webrtc/video/video_send_stream.h index bdb0e645b0..b67e9e5328 100644 --- a/webrtc/video/video_send_stream.h +++ b/webrtc/video/video_send_stream.h @@ -25,7 +25,6 @@ #include "webrtc/video/send_delay_stats.h" #include "webrtc/video/send_statistics_proxy.h" #include "webrtc/video/video_capture_input.h" -#include "webrtc/video/vie_channel.h" #include "webrtc/video/vie_encoder.h" #include "webrtc/video_receive_stream.h" #include "webrtc/video_send_stream.h" @@ -37,7 +36,6 @@ class CallStats; class CongestionController; class ProcessThread; class RtpRtcp; -class ViEChannel; class ViEEncoder; class VieRemb; diff --git a/webrtc/video/video_stream_decoder.cc b/webrtc/video/video_stream_decoder.cc new file mode 100644 index 0000000000..527f19b7ed --- /dev/null +++ b/webrtc/video/video_stream_decoder.cc @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2012 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 "webrtc/video/video_stream_decoder.h" + +#include +#include +#include + +#include "webrtc/base/checks.h" +#include "webrtc/base/logging.h" +#include "webrtc/common_video/include/frame_callback.h" +#include "webrtc/common_video/include/incoming_video_stream.h" +#include "webrtc/modules/video_coding/video_coding_impl.h" +#include "webrtc/modules/video_processing/include/video_processing.h" +#include "webrtc/system_wrappers/include/metrics.h" +#include "webrtc/video/call_stats.h" +#include "webrtc/video/payload_router.h" +#include "webrtc/video/receive_statistics_proxy.h" + +namespace webrtc { + +VideoStreamDecoder::VideoStreamDecoder( + vcm::VideoReceiver* video_receiver, + VCMFrameTypeCallback* vcm_frame_type_callback, + VCMPacketRequestCallback* vcm_packet_request_callback, + bool enable_nack, + ReceiveStatisticsProxy* receive_statistics_proxy, + IncomingVideoStream* incoming_video_stream, + I420FrameCallback* pre_render_callback) + : video_receiver_(video_receiver), + receive_stats_callback_(receive_statistics_proxy), + incoming_video_stream_(incoming_video_stream), + pre_render_callback_(pre_render_callback), + last_rtt_ms_(0) { + RTC_DCHECK(video_receiver_); + + static const int kMaxPacketAgeToNack = 450; + static const int kMaxNackListSize = 250; + video_receiver_->SetNackSettings(kMaxNackListSize, + kMaxPacketAgeToNack, 0); + video_receiver_->RegisterReceiveCallback(this); + video_receiver_->RegisterFrameTypeCallback(vcm_frame_type_callback); + video_receiver_->RegisterReceiveStatisticsCallback(this); + video_receiver_->RegisterDecoderTimingCallback(this); + static const int kDefaultRenderDelayMs = 10; + video_receiver_->SetRenderDelay(kDefaultRenderDelayMs); + + VCMVideoProtection video_protection = enable_nack ? kProtectionNack + : kProtectionNone; + VCMDecodeErrorMode decode_error_mode = enable_nack ? kNoErrors : kWithErrors; + video_receiver_->SetVideoProtection(video_protection, true); + video_receiver_->SetDecodeErrorMode(decode_error_mode); + VCMPacketRequestCallback* packet_request_callback = + enable_nack ? vcm_packet_request_callback : nullptr; + video_receiver_->RegisterPacketRequestCallback(packet_request_callback); +} + +VideoStreamDecoder::~VideoStreamDecoder() {} + +// Do not acquire the lock of |video_receiver_| in this function. Decode +// callback won't necessarily be called from the decoding thread. The decoding +// thread may have held the lock when calling VideoDecoder::Decode, Reset, or +// Release. Acquiring the same lock in the path of decode callback can deadlock. +int32_t VideoStreamDecoder::FrameToRender(VideoFrame& video_frame) { // NOLINT + if (pre_render_callback_) + pre_render_callback_->FrameCallback(&video_frame); + + incoming_video_stream_->OnFrame(video_frame); + return 0; +} + +int32_t VideoStreamDecoder::ReceivedDecodedReferenceFrame( + const uint64_t picture_id) { + RTC_NOTREACHED(); + return 0; +} + +void VideoStreamDecoder::OnIncomingPayloadType(int payload_type) { + receive_stats_callback_->OnIncomingPayloadType(payload_type); +} + +void VideoStreamDecoder::OnDecoderImplementationName( + const char* implementation_name) { + receive_stats_callback_->OnDecoderImplementationName(implementation_name); +} + +void VideoStreamDecoder::OnReceiveRatesUpdated(uint32_t bit_rate, + uint32_t frame_rate) { + receive_stats_callback_->OnIncomingRate(frame_rate, bit_rate); +} + +void VideoStreamDecoder::OnDiscardedPacketsUpdated(int discarded_packets) { + receive_stats_callback_->OnDiscardedPacketsUpdated(discarded_packets); +} + +void VideoStreamDecoder::OnFrameCountsUpdated(const FrameCounts& frame_counts) { + receive_stats_callback_->OnFrameCountsUpdated(frame_counts); +} + +void VideoStreamDecoder::OnDecoderTiming(int decode_ms, + int max_decode_ms, + int current_delay_ms, + int target_delay_ms, + int jitter_buffer_ms, + int min_playout_delay_ms, + int render_delay_ms) { + int last_rtt = -1; + { + rtc::CritScope lock(&crit_); + last_rtt = last_rtt_ms_; + } + + receive_stats_callback_->OnDecoderTiming( + decode_ms, max_decode_ms, current_delay_ms, target_delay_ms, + jitter_buffer_ms, min_playout_delay_ms, render_delay_ms, last_rtt); +} + +void VideoStreamDecoder::OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) { + video_receiver_->SetReceiveChannelParameters(max_rtt_ms); + + rtc::CritScope lock(&crit_); + last_rtt_ms_ = avg_rtt_ms; +} +} // namespace webrtc diff --git a/webrtc/video/vie_channel.h b/webrtc/video/video_stream_decoder.h similarity index 52% rename from webrtc/video/vie_channel.h rename to webrtc/video/video_stream_decoder.h index 5a653e63a5..f3b8280f58 100644 --- a/webrtc/video/vie_channel.h +++ b/webrtc/video/video_stream_decoder.h @@ -8,8 +8,8 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_VIDEO_VIE_CHANNEL_H_ -#define WEBRTC_VIDEO_VIE_CHANNEL_H_ +#ifndef WEBRTC_VIDEO_VIDEO_STREAM_DECODER_H_ +#define WEBRTC_VIDEO_VIDEO_STREAM_DECODER_H_ #include #include @@ -20,12 +20,9 @@ #include "webrtc/base/platform_thread.h" #include "webrtc/base/scoped_ref_ptr.h" #include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h" -#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h" -#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/modules/video_coding/include/video_coding_defines.h" #include "webrtc/system_wrappers/include/tick_util.h" #include "webrtc/typedefs.h" -#include "webrtc/video/rtp_stream_receiver.h" #include "webrtc/video/vie_sync_module.h" namespace webrtc { @@ -36,12 +33,8 @@ class Config; class EncodedImageCallback; class I420FrameCallback; class IncomingVideoStream; -class PacedSender; -class PacketRouter; -class PayloadRouter; class ReceiveStatisticsProxy; -class RtcpRttStats; -class ViERTPObserver; +class VideoRenderCallback; class VoEVideoSync; namespace vcm { @@ -53,39 +46,25 @@ enum StreamType { kViEStreamTypeRtx = 1 // Retransmission media stream }; -class ViEChannel : public VCMFrameTypeCallback, - public VCMReceiveCallback, - public VCMReceiveStatisticsCallback, - public VCMDecoderTimingCallback, - public VCMPacketRequestCallback { +class VideoStreamDecoder : public VCMReceiveCallback, + public VCMReceiveStatisticsCallback, + public VCMDecoderTimingCallback, + public CallStatsObserver { public: friend class ChannelStatsObserver; - ViEChannel(vcm::VideoReceiver* video_receiver, - RtpStreamReceiver* rtp_stream_receiver); - ~ViEChannel(); - - int32_t Init(); - - RtpRtcp* rtp_rtcp() const { return rtp_rtcp_; } - - void SetProtectionMode(bool enable_nack, - bool enable_fec, - int payload_type_red, - int payload_type_fec); - - RtpState GetRtpStateForSsrc(uint32_t ssrc) const; - - - CallStatsObserver* GetStatsObserver(); + VideoStreamDecoder(vcm::VideoReceiver* video_receiver, + VCMFrameTypeCallback* vcm_frame_type_callback, + VCMPacketRequestCallback* vcm_packet_request_callback, + bool enable_nack, + ReceiveStatisticsProxy* receive_statistics_proxy, + IncomingVideoStream* incoming_video_stream, + I420FrameCallback* pre_render_callback); + ~VideoStreamDecoder(); // Implements VCMReceiveCallback. int32_t FrameToRender(VideoFrame& video_frame) override; // NOLINT - - // Implements VCMReceiveCallback. int32_t ReceivedDecodedReferenceFrame(const uint64_t picture_id) override; - - // Implements VCMReceiveCallback. void OnIncomingPayloadType(int payload_type) override; void OnDecoderImplementationName(const char* implementation_name) override; @@ -103,58 +82,31 @@ class ViEChannel : public VCMFrameTypeCallback, int min_playout_delay_ms, int render_delay_ms) override; - // Implements FrameTypeCallback. - int32_t RequestKeyFrame() override; - // Implements FrameTypeCallback. - int32_t SliceLossIndicationRequest( - const uint64_t picture_id) override; - - // Implements VideoPacketRequestCallback. - int32_t ResendPackets(const uint16_t* sequence_numbers, - uint16_t length) override; - - void RegisterPreRenderCallback(I420FrameCallback* pre_render_callback); - - void RegisterRtcpPacketTypeCounterObserver( - RtcpPacketTypeCounterObserver* observer); void RegisterReceiveStatisticsProxy( ReceiveStatisticsProxy* receive_statistics_proxy); - void SetIncomingVideoStream(IncomingVideoStream* incoming_video_stream); - protected: - void OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms); + // Implements StatsObserver. + void OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) override; private: // Assumed to be protected. void StartDecodeThread(); void StopDecodeThread(); - void ProcessNACKRequest(const bool enable); - // Compute NACK list parameters for the buffering mode. - int GetRequiredNackListSize(int target_delay_ms); - // Used for all registered callbacks except rendering. rtc::CriticalSection crit_; vcm::VideoReceiver* const video_receiver_; - RtpStreamReceiver* const rtp_stream_receiver_; - RtpRtcp* const rtp_rtcp_; - // Helper to report call statistics. - std::unique_ptr stats_observer_; + ReceiveStatisticsProxy* const receive_stats_callback_; + IncomingVideoStream* const incoming_video_stream_; - // Not owned. - ReceiveStatisticsProxy* receive_stats_callback_ GUARDED_BY(crit_); - FrameCounts receive_frame_counts_ GUARDED_BY(crit_); - IncomingVideoStream* incoming_video_stream_ GUARDED_BY(crit_); - - int max_nack_reordering_threshold_; - I420FrameCallback* pre_render_callback_ GUARDED_BY(crit_); + I420FrameCallback* const pre_render_callback_; int64_t last_rtt_ms_ GUARDED_BY(crit_); }; } // namespace webrtc -#endif // WEBRTC_VIDEO_VIE_CHANNEL_H_ +#endif // WEBRTC_VIDEO_VIDEO_STREAM_DECODER_H_ diff --git a/webrtc/video/vie_channel.cc b/webrtc/video/vie_channel.cc deleted file mode 100644 index 49af472d55..0000000000 --- a/webrtc/video/vie_channel.cc +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Copyright (c) 2012 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 "webrtc/video/vie_channel.h" - -#include -#include -#include - -#include "webrtc/base/checks.h" -#include "webrtc/base/logging.h" -#include "webrtc/common_video/include/frame_callback.h" -#include "webrtc/common_video/include/incoming_video_stream.h" -#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" -#include "webrtc/modules/rtp_rtcp/include/rtp_receiver.h" -#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h" -#include "webrtc/modules/video_coding/video_coding_impl.h" -#include "webrtc/modules/video_processing/include/video_processing.h" -#include "webrtc/system_wrappers/include/metrics.h" -#include "webrtc/video/call_stats.h" -#include "webrtc/video/payload_router.h" -#include "webrtc/video/receive_statistics_proxy.h" - -namespace webrtc { - -static const int kMaxPacketAgeToNack = 450; -static const int kMaxNackListSize = 250; - -// Helper class receiving statistics callbacks. -class ChannelStatsObserver : public CallStatsObserver { - public: - explicit ChannelStatsObserver(ViEChannel* owner) : owner_(owner) {} - virtual ~ChannelStatsObserver() {} - - // Implements StatsObserver. - virtual void OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) { - owner_->OnRttUpdate(avg_rtt_ms, max_rtt_ms); - } - - private: - ViEChannel* const owner_; -}; - -ViEChannel::ViEChannel(vcm::VideoReceiver* video_receiver, - RtpStreamReceiver* rtp_stream_receiver) - : video_receiver_(video_receiver), - rtp_stream_receiver_(rtp_stream_receiver), - rtp_rtcp_(rtp_stream_receiver_->rtp_rtcp()), - stats_observer_(new ChannelStatsObserver(this)), - receive_stats_callback_(nullptr), - incoming_video_stream_(nullptr), - max_nack_reordering_threshold_(kMaxPacketAgeToNack), - pre_render_callback_(nullptr), - last_rtt_ms_(0) { - RTC_DCHECK(video_receiver_); - video_receiver_->SetNackSettings(kMaxNackListSize, - max_nack_reordering_threshold_, 0); -} - -ViEChannel::~ViEChannel() {} - -int32_t ViEChannel::Init() { - static const int kDefaultRenderDelayMs = 10; - - if (video_receiver_->RegisterReceiveCallback(this) != 0) { - return -1; - } - video_receiver_->RegisterFrameTypeCallback(this); - video_receiver_->RegisterReceiveStatisticsCallback(this); - video_receiver_->RegisterDecoderTimingCallback(this); - video_receiver_->SetRenderDelay(kDefaultRenderDelayMs); - - return 0; -} - -void ViEChannel::SetProtectionMode(bool enable_nack, - bool enable_fec, - int payload_type_red, - int payload_type_fec) { - // Validate payload types. If either RED or FEC payload types are set then - // both should be. If FEC is enabled then they both have to be set. - if (enable_fec || payload_type_red != -1 || payload_type_fec != -1) { - RTC_DCHECK_GE(payload_type_red, 0); - RTC_DCHECK_GE(payload_type_fec, 0); - RTC_DCHECK_LE(payload_type_red, 127); - RTC_DCHECK_LE(payload_type_fec, 127); - } else { - // Payload types unset. - RTC_DCHECK_EQ(payload_type_red, -1); - RTC_DCHECK_EQ(payload_type_fec, -1); - // Set to valid uint8_ts to be castable later without signed overflows. - payload_type_red = 0; - payload_type_fec = 0; - } - - VCMVideoProtection protection_method; - if (enable_nack) { - protection_method = enable_fec ? kProtectionNackFEC : kProtectionNack; - } else { - protection_method = kProtectionNone; - } - - video_receiver_->SetVideoProtection(protection_method, true); - - // Set NACK. - ProcessNACKRequest(enable_nack); - - // Set FEC. - rtp_rtcp_->SetGenericFECStatus(enable_fec, - static_cast(payload_type_red), - static_cast(payload_type_fec)); -} - -void ViEChannel::ProcessNACKRequest(const bool enable) { - if (enable) { - // Turn on NACK. - if (rtp_rtcp_->RTCP() == RtcpMode::kOff) - return; - rtp_stream_receiver_->SetNackStatus(true, max_nack_reordering_threshold_); - video_receiver_->RegisterPacketRequestCallback(this); - // Don't introduce errors when NACK is enabled. - video_receiver_->SetDecodeErrorMode(kNoErrors); - - } else { - video_receiver_->RegisterPacketRequestCallback(nullptr); - // When NACK is off, allow decoding with errors. Otherwise, the video - // will freeze, and will only recover with a complete key frame. - video_receiver_->SetDecodeErrorMode(kWithErrors); - rtp_stream_receiver_->SetNackStatus(false, max_nack_reordering_threshold_); - } -} - -int ViEChannel::GetRequiredNackListSize(int target_delay_ms) { - // The max size of the nack list should be large enough to accommodate the - // the number of packets (frames) resulting from the increased delay. - // Roughly estimating for ~40 packets per frame @ 30fps. - return target_delay_ms * 40 * 30 / 1000; -} - -RtpState ViEChannel::GetRtpStateForSsrc(uint32_t ssrc) const { - RTC_DCHECK(!rtp_rtcp_->Sending()); - RTC_DCHECK_EQ(ssrc, rtp_rtcp_->SSRC()); - return rtp_rtcp_->GetRtpState(); -} - -void ViEChannel::RegisterRtcpPacketTypeCounterObserver( - RtcpPacketTypeCounterObserver* observer) { - rtp_stream_receiver_->RegisterRtcpPacketTypeCounterObserver(observer); -} - -CallStatsObserver* ViEChannel::GetStatsObserver() { - return stats_observer_.get(); -} - -// Do not acquire the lock of |video_receiver_| in this function. Decode -// callback won't necessarily be called from the decoding thread. The decoding -// thread may have held the lock when calling VideoDecoder::Decode, Reset, or -// Release. Acquiring the same lock in the path of decode callback can deadlock. -int32_t ViEChannel::FrameToRender(VideoFrame& video_frame) { // NOLINT - rtc::CritScope lock(&crit_); - - if (pre_render_callback_) - pre_render_callback_->FrameCallback(&video_frame); - - incoming_video_stream_->OnFrame(video_frame); - return 0; -} - -int32_t ViEChannel::ReceivedDecodedReferenceFrame( - const uint64_t picture_id) { - return rtp_rtcp_->SendRTCPReferencePictureSelection(picture_id); -} - -void ViEChannel::OnIncomingPayloadType(int payload_type) { - rtc::CritScope lock(&crit_); - if (receive_stats_callback_) - receive_stats_callback_->OnIncomingPayloadType(payload_type); -} - -void ViEChannel::OnDecoderImplementationName(const char* implementation_name) { - rtc::CritScope lock(&crit_); - if (receive_stats_callback_) - receive_stats_callback_->OnDecoderImplementationName(implementation_name); -} - -void ViEChannel::OnReceiveRatesUpdated(uint32_t bit_rate, uint32_t frame_rate) { - rtc::CritScope lock(&crit_); - if (receive_stats_callback_) - receive_stats_callback_->OnIncomingRate(frame_rate, bit_rate); -} - -void ViEChannel::OnDiscardedPacketsUpdated(int discarded_packets) { - rtc::CritScope lock(&crit_); - if (receive_stats_callback_) - receive_stats_callback_->OnDiscardedPacketsUpdated(discarded_packets); -} - -void ViEChannel::OnFrameCountsUpdated(const FrameCounts& frame_counts) { - rtc::CritScope lock(&crit_); - receive_frame_counts_ = frame_counts; - if (receive_stats_callback_) - receive_stats_callback_->OnFrameCountsUpdated(frame_counts); -} - -void ViEChannel::OnDecoderTiming(int decode_ms, - int max_decode_ms, - int current_delay_ms, - int target_delay_ms, - int jitter_buffer_ms, - int min_playout_delay_ms, - int render_delay_ms) { - rtc::CritScope lock(&crit_); - if (!receive_stats_callback_) - return; - receive_stats_callback_->OnDecoderTiming( - decode_ms, max_decode_ms, current_delay_ms, target_delay_ms, - jitter_buffer_ms, min_playout_delay_ms, render_delay_ms, last_rtt_ms_); -} - -int32_t ViEChannel::RequestKeyFrame() { - return rtp_rtcp_->RequestKeyFrame(); -} - -int32_t ViEChannel::SliceLossIndicationRequest( - const uint64_t picture_id) { - return rtp_rtcp_->SendRTCPSliceLossIndication( - static_cast(picture_id)); -} - -int32_t ViEChannel::ResendPackets(const uint16_t* sequence_numbers, - uint16_t length) { - return rtp_rtcp_->SendNACK(sequence_numbers, length); -} - -void ViEChannel::OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) { - video_receiver_->SetReceiveChannelParameters(max_rtt_ms); - - rtc::CritScope lock(&crit_); - last_rtt_ms_ = avg_rtt_ms; -} - -void ViEChannel::RegisterPreRenderCallback( - I420FrameCallback* pre_render_callback) { - rtc::CritScope lock(&crit_); - pre_render_callback_ = pre_render_callback; -} - -void ViEChannel::RegisterReceiveStatisticsProxy( - ReceiveStatisticsProxy* receive_statistics_proxy) { - rtc::CritScope lock(&crit_); - receive_stats_callback_ = receive_statistics_proxy; -} - -void ViEChannel::SetIncomingVideoStream( - IncomingVideoStream* incoming_video_stream) { - rtc::CritScope lock(&crit_); - incoming_video_stream_ = incoming_video_stream; -} -} // namespace webrtc diff --git a/webrtc/video/webrtc_video.gypi b/webrtc/video/webrtc_video.gypi index cb63a2e87d..3d6afdee07 100644 --- a/webrtc/video/webrtc_video.gypi +++ b/webrtc/video/webrtc_video.gypi @@ -54,8 +54,8 @@ 'video/video_receive_stream.h', 'video/video_send_stream.cc', 'video/video_send_stream.h', - 'video/vie_channel.cc', - 'video/vie_channel.h', + 'video/video_stream_decoder.cc', + 'video/video_stream_decoder.h', 'video/vie_encoder.cc', 'video/vie_encoder.h', 'video/vie_remb.cc',