Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(67)

Side by Side Diff: webrtc/video/video_receive_stream.cc

Issue 2764573002: Deliver video frames on Android, on the decode thread. (Closed)
Patch Set: Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/video/video_receive_stream.h" 11 #include "webrtc/video/video_receive_stream.h"
12 12
13 #include <stdlib.h> 13 #include <stdlib.h>
14 14
15 #include <set> 15 #include <set>
16 #include <string> 16 #include <string>
17 #include <utility> 17 #include <utility>
18 18
19 #include "webrtc/base/checks.h" 19 #include "webrtc/base/checks.h"
20 #include "webrtc/base/location.h" 20 #include "webrtc/base/location.h"
21 #include "webrtc/base/logging.h" 21 #include "webrtc/base/logging.h"
22 #include "webrtc/base/optional.h" 22 #include "webrtc/base/optional.h"
23 #include "webrtc/base/timeutils.h"
23 #include "webrtc/base/trace_event.h" 24 #include "webrtc/base/trace_event.h"
24 #include "webrtc/common_video/h264/profile_level_id.h" 25 #include "webrtc/common_video/h264/profile_level_id.h"
25 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" 26 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
26 #include "webrtc/modules/rtp_rtcp/include/rtp_receiver.h" 27 #include "webrtc/modules/rtp_rtcp/include/rtp_receiver.h"
27 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h" 28 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
28 #include "webrtc/modules/utility/include/process_thread.h" 29 #include "webrtc/modules/utility/include/process_thread.h"
29 #include "webrtc/modules/video_coding/frame_object.h" 30 #include "webrtc/modules/video_coding/frame_object.h"
30 #include "webrtc/modules/video_coding/include/video_coding.h" 31 #include "webrtc/modules/video_coding/include/video_coding.h"
31 #include "webrtc/modules/video_coding/jitter_estimator.h" 32 #include "webrtc/modules/video_coding/jitter_estimator.h"
32 #include "webrtc/modules/video_coding/timing.h" 33 #include "webrtc/modules/video_coding/timing.h"
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 const int kDefaultStartBitrate = 300; 168 const int kDefaultStartBitrate = 300;
168 codec.startBitrate = codec.minBitrate = codec.maxBitrate = 169 codec.startBitrate = codec.minBitrate = codec.maxBitrate =
169 kDefaultStartBitrate; 170 kDefaultStartBitrate;
170 171
171 return codec; 172 return codec;
172 } 173 }
173 } // namespace 174 } // namespace
174 175
175 namespace internal { 176 namespace internal {
176 177
177 VideoReceiveStream::VideoReceiveStream( 178 VideoReceiveStream::VideoReceiveStream(int num_cpu_cores,
178 int num_cpu_cores, 179 PacketRouter* packet_router,
179 PacketRouter* packet_router, 180 VideoReceiveStream::Config config,
180 VideoReceiveStream::Config config, 181 ProcessThread* process_thread,
181 ProcessThread* process_thread, 182 CallStats* call_stats,
182 CallStats* call_stats, 183 VieRemb* remb)
183 VieRemb* remb)
184 : transport_adapter_(config.rtcp_send_transport), 184 : transport_adapter_(config.rtcp_send_transport),
185 config_(std::move(config)), 185 config_(std::move(config)),
186 num_cpu_cores_(num_cpu_cores), 186 num_cpu_cores_(num_cpu_cores),
187 process_thread_(process_thread), 187 process_thread_(process_thread),
188 clock_(Clock::GetRealTimeClock()), 188 clock_(Clock::GetRealTimeClock()),
189 decode_thread_(DecodeThreadFunction, this, "DecodingThread"), 189 decode_thread_(&DecodeThreadFunction,
190 this,
191 "DecodingThread",
192 rtc::kHighestPriority),
190 call_stats_(call_stats), 193 call_stats_(call_stats),
191 timing_(new VCMTiming(clock_)), 194 timing_(new VCMTiming(clock_)),
192 video_receiver_(clock_, nullptr, this, timing_.get(), this, this), 195 video_receiver_(clock_, nullptr, this, timing_.get(), this, this),
193 stats_proxy_(&config_, clock_), 196 stats_proxy_(&config_, clock_),
194 rtp_stream_receiver_(&transport_adapter_, 197 rtp_stream_receiver_(&transport_adapter_,
195 call_stats_->rtcp_rtt_stats(), 198 call_stats_->rtcp_rtt_stats(),
196 packet_router, 199 packet_router,
197 remb, 200 remb,
198 &config_, 201 &config_,
199 &stats_proxy_, 202 &stats_proxy_,
(...skipping 20 matching lines...) Expand all
220 << ") for different decoders."; 223 << ") for different decoders.";
221 decoder_payload_types.insert(decoder.payload_type); 224 decoder_payload_types.insert(decoder.payload_type);
222 } 225 }
223 226
224 video_receiver_.SetRenderDelay(config.render_delay_ms); 227 video_receiver_.SetRenderDelay(config.render_delay_ms);
225 228
226 jitter_estimator_.reset(new VCMJitterEstimator(clock_)); 229 jitter_estimator_.reset(new VCMJitterEstimator(clock_));
227 frame_buffer_.reset(new video_coding::FrameBuffer( 230 frame_buffer_.reset(new video_coding::FrameBuffer(
228 clock_, jitter_estimator_.get(), timing_.get(), &stats_proxy_)); 231 clock_, jitter_estimator_.get(), timing_.get(), &stats_proxy_));
229 232
230 process_thread_->RegisterModule(&video_receiver_, RTC_FROM_HERE);
231 process_thread_->RegisterModule(&rtp_stream_sync_, RTC_FROM_HERE); 233 process_thread_->RegisterModule(&rtp_stream_sync_, RTC_FROM_HERE);
232 } 234 }
233 235
234 VideoReceiveStream::~VideoReceiveStream() { 236 VideoReceiveStream::~VideoReceiveStream() {
235 RTC_DCHECK_RUN_ON(&worker_thread_checker_); 237 RTC_DCHECK_RUN_ON(&worker_thread_checker_);
236 LOG(LS_INFO) << "~VideoReceiveStream: " << config_.ToString(); 238 LOG(LS_INFO) << "~VideoReceiveStream: " << config_.ToString();
237 Stop(); 239 Stop();
238 240
239 process_thread_->DeRegisterModule(&rtp_stream_sync_); 241 process_thread_->DeRegisterModule(&rtp_stream_sync_);
240 process_thread_->DeRegisterModule(&video_receiver_);
241 } 242 }
242 243
243 void VideoReceiveStream::SignalNetworkState(NetworkState state) { 244 void VideoReceiveStream::SignalNetworkState(NetworkState state) {
244 RTC_DCHECK_RUN_ON(&worker_thread_checker_); 245 RTC_DCHECK_RUN_ON(&worker_thread_checker_);
245 rtp_stream_receiver_.SignalNetworkState(state); 246 rtp_stream_receiver_.SignalNetworkState(state);
246 } 247 }
247 248
248
249 bool VideoReceiveStream::DeliverRtcp(const uint8_t* packet, size_t length) { 249 bool VideoReceiveStream::DeliverRtcp(const uint8_t* packet, size_t length) {
250 return rtp_stream_receiver_.DeliverRtcp(packet, length); 250 return rtp_stream_receiver_.DeliverRtcp(packet, length);
251 } 251 }
252 252
253 void VideoReceiveStream::OnRtpPacket(const RtpPacketReceived& packet) { 253 void VideoReceiveStream::OnRtpPacket(const RtpPacketReceived& packet) {
254 rtp_stream_receiver_.OnRtpPacket(packet); 254 rtp_stream_receiver_.OnRtpPacket(packet);
255 } 255 }
256 256
257 bool VideoReceiveStream::OnRecoveredPacket(const uint8_t* packet, 257 bool VideoReceiveStream::OnRecoveredPacket(const uint8_t* packet,
258 size_t length) { 258 size_t length) {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
301 RTC_CHECK_EQ(VCM_OK, video_receiver_.RegisterReceiveCodec( 301 RTC_CHECK_EQ(VCM_OK, video_receiver_.RegisterReceiveCodec(
302 &codec, num_cpu_cores_, false)); 302 &codec, num_cpu_cores_, false));
303 } 303 }
304 304
305 video_stream_decoder_.reset(new VideoStreamDecoder( 305 video_stream_decoder_.reset(new VideoStreamDecoder(
306 &video_receiver_, &rtp_stream_receiver_, &rtp_stream_receiver_, 306 &video_receiver_, &rtp_stream_receiver_, &rtp_stream_receiver_,
307 rtp_stream_receiver_.IsRetransmissionsEnabled(), protected_by_fec, 307 rtp_stream_receiver_.IsRetransmissionsEnabled(), protected_by_fec,
308 &stats_proxy_, renderer)); 308 &stats_proxy_, renderer));
309 // Register the channel to receive stats updates. 309 // Register the channel to receive stats updates.
310 call_stats_->RegisterStatsObserver(video_stream_decoder_.get()); 310 call_stats_->RegisterStatsObserver(video_stream_decoder_.get());
311
312 video_receiver_.DecoderThreadStarting();
313 process_thread_->RegisterModule(&video_receiver_, RTC_FROM_HERE);
314
311 // Start the decode thread 315 // Start the decode thread
312 decode_thread_.Start(); 316 decode_thread_.Start();
313 decode_thread_.SetPriority(rtc::kHighestPriority);
314 rtp_stream_receiver_.StartReceive(); 317 rtp_stream_receiver_.StartReceive();
315 } 318 }
316 319
317 void VideoReceiveStream::Stop() { 320 void VideoReceiveStream::Stop() {
318 RTC_DCHECK_RUN_ON(&worker_thread_checker_); 321 RTC_DCHECK_RUN_ON(&worker_thread_checker_);
319 rtp_stream_receiver_.StopReceive(); 322 rtp_stream_receiver_.StopReceive();
320 // TriggerDecoderShutdown will release any waiting decoder thread and make it
321 // stop immediately, instead of waiting for a timeout. Needs to be called
322 // before joining the decoder thread thread.
323 video_receiver_.TriggerDecoderShutdown();
324 323
325 frame_buffer_->Stop(); 324 frame_buffer_->Stop();
326 call_stats_->DeregisterStatsObserver(&rtp_stream_receiver_); 325 call_stats_->DeregisterStatsObserver(&rtp_stream_receiver_);
326 process_thread_->DeRegisterModule(&video_receiver_);
327 327
328 if (decode_thread_.IsRunning()) { 328 if (decode_thread_.IsRunning()) {
329 // TriggerDecoderShutdown will release any waiting decoder thread and make
330 // it stop immediately, instead of waiting for a timeout. Needs to be called
331 // before joining the decoder thread thread.
332 video_receiver_.TriggerDecoderShutdown();
333
329 decode_thread_.Stop(); 334 decode_thread_.Stop();
335 video_receiver_.DecoderThreadStopped();
330 // Deregister external decoders so they are no longer running during 336 // Deregister external decoders so they are no longer running during
331 // destruction. This effectively stops the VCM since the decoder thread is 337 // destruction. This effectively stops the VCM since the decoder thread is
332 // stopped, the VCM is deregistered and no asynchronous decoder threads are 338 // stopped, the VCM is deregistered and no asynchronous decoder threads are
333 // running. 339 // running.
334 for (const Decoder& decoder : config_.decoders) 340 for (const Decoder& decoder : config_.decoders)
335 video_receiver_.RegisterExternalDecoder(nullptr, decoder.payload_type); 341 video_receiver_.RegisterExternalDecoder(nullptr, decoder.payload_type);
336 } 342 }
337 343
338 call_stats_->DeregisterStatsObserver(video_stream_decoder_.get()); 344 call_stats_->DeregisterStatsObserver(video_stream_decoder_.get());
339 video_stream_decoder_.reset(); 345 video_stream_decoder_.reset();
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
463 uint32_t VideoReceiveStream::GetPlayoutTimestamp() const { 469 uint32_t VideoReceiveStream::GetPlayoutTimestamp() const {
464 RTC_NOTREACHED(); 470 RTC_NOTREACHED();
465 return 0; 471 return 0;
466 } 472 }
467 473
468 void VideoReceiveStream::SetMinimumPlayoutDelay(int delay_ms) { 474 void VideoReceiveStream::SetMinimumPlayoutDelay(int delay_ms) {
469 RTC_DCHECK_RUN_ON(&module_process_thread_checker_); 475 RTC_DCHECK_RUN_ON(&module_process_thread_checker_);
470 video_receiver_.SetMinimumPlayoutDelay(delay_ms); 476 video_receiver_.SetMinimumPlayoutDelay(delay_ms);
471 } 477 }
472 478
473 bool VideoReceiveStream::DecodeThreadFunction(void* ptr) { 479 void VideoReceiveStream::DecodeThreadFunction(void* ptr) {
474 return static_cast<VideoReceiveStream*>(ptr)->Decode(); 480 while (static_cast<VideoReceiveStream*>(ptr)->Decode()) {
481 }
475 } 482 }
476 483
477 bool VideoReceiveStream::Decode() { 484 bool VideoReceiveStream::Decode() {
478 TRACE_EVENT0("webrtc", "VideoReceiveStream::Decode"); 485 TRACE_EVENT0("webrtc", "VideoReceiveStream::Decode");
479 static const int kMaxWaitForFrameMs = 3000; 486 static const int kMaxWaitForFrameMs = 3000;
480 std::unique_ptr<video_coding::FrameObject> frame; 487 std::unique_ptr<video_coding::FrameObject> frame;
481 video_coding::FrameBuffer::ReturnReason res =
482 frame_buffer_->NextFrame(kMaxWaitForFrameMs, &frame);
483 488
484 if (res == video_coding::FrameBuffer::ReturnReason::kStopped) { 489 video_coding::FrameBuffer::ReturnReason res;
485 video_receiver_.DecodingStopped(); 490 #if defined(WEBRTC_ANDROID)
491 // This is a temporary workaround for video capture on Android in order to
492 // deliver asynchronously delivered frames, on the decoder thread.
493 // More details here:
494 // https://bugs.chromium.org/p/webrtc/issues/detail?id=7361
495 static const int kPollIntervalMs = 10;
496 int time_remaining = kMaxWaitForFrameMs;
497 do {
498 res = frame_buffer_->NextFrame(kPollIntervalMs, &frame);
499 if (res != video_coding::FrameBuffer::ReturnReason::kTimeout)
500 break;
501 time_remaining -= kPollIntervalMs;
502 video_receiver_.PollDecodedFrames();
503 } while (time_remaining > 0);
504 #else
505 res = frame_buffer_->NextFrame(kMaxWaitForFrameMs, &frame);
506 #endif
507
508 if (res == video_coding::FrameBuffer::ReturnReason::kStopped)
486 return false; 509 return false;
487 }
488 510
489 if (frame) { 511 if (frame) {
490 if (video_receiver_.Decode(frame.get()) == VCM_OK) 512 if (video_receiver_.Decode(frame.get()) == VCM_OK)
491 rtp_stream_receiver_.FrameDecoded(frame->picture_id); 513 rtp_stream_receiver_.FrameDecoded(frame->picture_id);
492 } else { 514 } else {
515 RTC_DCHECK_EQ(res, video_coding::FrameBuffer::ReturnReason::kTimeout);
493 LOG(LS_WARNING) << "No decodable frame in " << kMaxWaitForFrameMs 516 LOG(LS_WARNING) << "No decodable frame in " << kMaxWaitForFrameMs
494 << " ms, requesting keyframe."; 517 << " ms, requesting keyframe.";
495 RequestKeyFrame(); 518 RequestKeyFrame();
496 } 519 }
520
497 return true; 521 return true;
498 } 522 }
499 } // namespace internal 523 } // namespace internal
500 } // namespace webrtc 524 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698