Index: webrtc/video/video_receive_stream.cc |
diff --git a/webrtc/video/video_receive_stream.cc b/webrtc/video/video_receive_stream.cc |
index 9909e29c433b394da8ed2b9ca18b51442e4ddb5e..92f84a0cb8e0d82eede9df651d927a383ccc0a70 100644 |
--- a/webrtc/video/video_receive_stream.cc |
+++ b/webrtc/video/video_receive_stream.cc |
@@ -144,6 +144,32 @@ VideoCodec CreateDecoderVideoCodec(const VideoReceiveStream::Decoder& decoder) { |
} // namespace |
namespace internal { |
+ |
+// Since an IncomingVideoStream instance will create a thread/queue, we don't |
+// instantiate one unless we know we're going to be delivering the frames |
+// to a renderer. |
+// |
+// TODO(tommi): Consider making the functionality provided by the |
+// IncomingVideoStream classes, tied to the Config class instead or even higher |
+// level. That will make it an optional feature that will be up to the |
+// application to use or not use. Right now, we have two classes available, |
+// they both have threads involved which uses WebRTC's threading classes and |
+// that might not suit what the application wants to do. If one of them or |
+// neither, suits, the app can get some code size back as well as more control. |
+std::unique_ptr<rtc::VideoSinkInterface<VideoFrame>> |
+MaybeCreateIncomingVideoStream(const VideoReceiveStream::Config& config, |
+ rtc::VideoSinkInterface<VideoFrame>* callback) { |
+ std::unique_ptr<rtc::VideoSinkInterface<VideoFrame>> ret; |
+ if (config.renderer) { |
+ if (config.disable_prerenderer_smoothing) { |
+ ret.reset(new IncomingVideoStreamNoSmoothing(callback)); |
+ } else { |
+ ret.reset(new IncomingVideoStream(config.render_delay_ms, callback)); |
+ } |
+ } |
+ return ret; |
+} |
+ |
VideoReceiveStream::VideoReceiveStream( |
int num_cpu_cores, |
CongestionController* congestion_controller, |
@@ -160,7 +186,6 @@ VideoReceiveStream::VideoReceiveStream( |
congestion_controller_(congestion_controller), |
call_stats_(call_stats), |
video_receiver_(clock_, nullptr, this, this, this), |
- incoming_video_stream_(config_.disable_prerenderer_smoothing), |
stats_proxy_(&config_, clock_), |
rtp_stream_receiver_(&video_receiver_, |
congestion_controller_->GetRemoteBitrateEstimator( |
@@ -173,14 +198,6 @@ VideoReceiveStream::VideoReceiveStream( |
&config_, |
&stats_proxy_, |
process_thread_), |
- video_stream_decoder_(&video_receiver_, |
- &rtp_stream_receiver_, |
- &rtp_stream_receiver_, |
- rtp_stream_receiver_.IsRetransmissionsEnabled(), |
- rtp_stream_receiver_.IsFecEnabled(), |
- &stats_proxy_, |
- &incoming_video_stream_, |
- config.pre_render_callback), |
vie_sync_(&video_receiver_) { |
LOG(LS_INFO) << "VideoReceiveStream: " << config_.ToString(); |
@@ -188,9 +205,6 @@ VideoReceiveStream::VideoReceiveStream( |
RTC_DCHECK(congestion_controller_); |
RTC_DCHECK(call_stats_); |
- // Register the channel to receive stats updates. |
- call_stats_->RegisterStatsObserver(&video_stream_decoder_); |
- |
RTC_DCHECK(!config_.decoders.empty()); |
std::set<int> decoder_payload_types; |
for (const Decoder& decoder : config_.decoders) { |
@@ -210,8 +224,6 @@ VideoReceiveStream::VideoReceiveStream( |
} |
video_receiver_.SetRenderDelay(config.render_delay_ms); |
- incoming_video_stream_.SetExpectedRenderDelay(config.render_delay_ms); |
- incoming_video_stream_.SetExternalCallback(this); |
process_thread_->RegisterModule(&video_receiver_); |
process_thread_->RegisterModule(&vie_sync_); |
@@ -231,8 +243,6 @@ VideoReceiveStream::~VideoReceiveStream() { |
for (const Decoder& decoder : config_.decoders) |
video_receiver_.RegisterExternalDecoder(nullptr, decoder.payload_type); |
- call_stats_->DeregisterStatsObserver(&video_stream_decoder_); |
- |
congestion_controller_->GetRemoteBitrateEstimator(UseSendSideBwe(config_)) |
->RemoveStream(rtp_stream_receiver_.GetRemoteSsrc()); |
} |
@@ -256,7 +266,14 @@ void VideoReceiveStream::Start() { |
if (decode_thread_.IsRunning()) |
return; |
transport_adapter_.Enable(); |
- incoming_video_stream_.Start(); |
+ incoming_video_stream_ = MaybeCreateIncomingVideoStream(config_, this); |
+ video_stream_decoder_.reset(new VideoStreamDecoder( |
+ &video_receiver_, &rtp_stream_receiver_, &rtp_stream_receiver_, |
+ rtp_stream_receiver_.IsRetransmissionsEnabled(), |
+ rtp_stream_receiver_.IsFecEnabled(), &stats_proxy_, |
+ incoming_video_stream_.get(), config_.pre_render_callback)); |
+ // Register the channel to receive stats updates. |
+ call_stats_->RegisterStatsObserver(video_stream_decoder_.get()); |
// Start the decode thread |
decode_thread_.Start(); |
decode_thread_.SetPriority(rtc::kHighestPriority); |
@@ -264,10 +281,12 @@ void VideoReceiveStream::Start() { |
} |
void VideoReceiveStream::Stop() { |
- incoming_video_stream_.Stop(); |
rtp_stream_receiver_.StopReceive(); |
video_receiver_.TriggerDecoderShutdown(); |
decode_thread_.Stop(); |
+ call_stats_->DeregisterStatsObserver(video_stream_decoder_.get()); |
+ video_stream_decoder_.reset(); |
+ incoming_video_stream_.reset(); |
transport_adapter_.Disable(); |
} |
@@ -289,16 +308,26 @@ VideoReceiveStream::Stats VideoReceiveStream::GetStats() const { |
return stats_proxy_.GetStats(); |
} |
+// TODO(tommi): This method grabs a lock 6 times. |
void VideoReceiveStream::OnFrame(const VideoFrame& video_frame) { |
+ // TODO(tommi): OnDecodedFrame grabs a lock, incidentally the same lock |
+ // that OnSyncOffsetUpdated() and OnRenderedFrame() below grab. |
stats_proxy_.OnDecodedFrame(); |
int64_t sync_offset_ms; |
- if (vie_sync_.GetStreamSyncOffsetInMs(video_frame, &sync_offset_ms)) |
+ // TODO(tommi): GetStreamSyncOffsetInMs grabs three locks. One inside the |
+ // function itself, another in GetChannel() and a third in |
+ // GetPlayoutTimestamp. Seems excessive. Anyhow, I'm assuming the function |
+ // succeeds most of the time, which leads to grabbing a fourth lock. |
+ if (vie_sync_.GetStreamSyncOffsetInMs(video_frame, &sync_offset_ms)) { |
+ // TODO(tommi): OnSyncOffsetUpdated grabs a lock. |
stats_proxy_.OnSyncOffsetUpdated(sync_offset_ms); |
+ } |
- if (config_.renderer) |
- config_.renderer->OnFrame(video_frame); |
+ // config_.renderer must never be null if we're getting this callback. |
+ config_.renderer->OnFrame(video_frame); |
+ // TODO(tommi): OnRenderFrame grabs a lock too. |
stats_proxy_.OnRenderedFrame(video_frame.width(), video_frame.height()); |
} |