| OLD | NEW |
| 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/logging.h" | 20 #include "webrtc/base/logging.h" |
| 21 #include "webrtc/base/optional.h" | 21 #include "webrtc/base/optional.h" |
| 22 #include "webrtc/common_video/h264/profile_level_id.h" | 22 #include "webrtc/common_video/h264/profile_level_id.h" |
| 23 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" | 23 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" |
| 24 #include "webrtc/modules/congestion_controller/include/congestion_controller.h" | 24 #include "webrtc/modules/congestion_controller/include/congestion_controller.h" |
| 25 #include "webrtc/modules/rtp_rtcp/include/rtp_receiver.h" |
| 26 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h" |
| 25 #include "webrtc/modules/utility/include/process_thread.h" | 27 #include "webrtc/modules/utility/include/process_thread.h" |
| 26 #include "webrtc/modules/video_coding/frame_object.h" | 28 #include "webrtc/modules/video_coding/frame_object.h" |
| 27 #include "webrtc/modules/video_coding/include/video_coding.h" | 29 #include "webrtc/modules/video_coding/include/video_coding.h" |
| 28 #include "webrtc/modules/video_coding/jitter_estimator.h" | 30 #include "webrtc/modules/video_coding/jitter_estimator.h" |
| 29 #include "webrtc/modules/video_coding/timing.h" | 31 #include "webrtc/modules/video_coding/timing.h" |
| 30 #include "webrtc/modules/video_coding/utility/ivf_file_writer.h" | 32 #include "webrtc/modules/video_coding/utility/ivf_file_writer.h" |
| 31 #include "webrtc/system_wrappers/include/clock.h" | 33 #include "webrtc/system_wrappers/include/clock.h" |
| 32 #include "webrtc/system_wrappers/include/field_trial.h" | 34 #include "webrtc/system_wrappers/include/field_trial.h" |
| 33 #include "webrtc/video/call_stats.h" | 35 #include "webrtc/video/call_stats.h" |
| 34 #include "webrtc/video/receive_statistics_proxy.h" | 36 #include "webrtc/video/receive_statistics_proxy.h" |
| 35 #include "webrtc/video_receive_stream.h" | 37 #include "webrtc/video_receive_stream.h" |
| 36 #include "webrtc/voice_engine/include/voe_video_sync.h" | |
| 37 | 38 |
| 38 namespace webrtc { | 39 namespace webrtc { |
| 39 | 40 |
| 40 static bool UseSendSideBwe(const VideoReceiveStream::Config& config) { | 41 static bool UseSendSideBwe(const VideoReceiveStream::Config& config) { |
| 41 if (!config.rtp.transport_cc) | 42 if (!config.rtp.transport_cc) |
| 42 return false; | 43 return false; |
| 43 for (const auto& extension : config.rtp.extensions) { | 44 for (const auto& extension : config.rtp.extensions) { |
| 44 if (extension.uri == RtpExtension::kTransportSequenceNumberUri) | 45 if (extension.uri == RtpExtension::kTransportSequenceNumberUri) |
| 45 return true; | 46 return true; |
| 46 } | 47 } |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 183 } // namespace | 184 } // namespace |
| 184 | 185 |
| 185 namespace internal { | 186 namespace internal { |
| 186 | 187 |
| 187 VideoReceiveStream::VideoReceiveStream( | 188 VideoReceiveStream::VideoReceiveStream( |
| 188 int num_cpu_cores, | 189 int num_cpu_cores, |
| 189 bool protected_by_flexfec, | 190 bool protected_by_flexfec, |
| 190 CongestionController* congestion_controller, | 191 CongestionController* congestion_controller, |
| 191 PacketRouter* packet_router, | 192 PacketRouter* packet_router, |
| 192 VideoReceiveStream::Config config, | 193 VideoReceiveStream::Config config, |
| 193 webrtc::VoiceEngine* voice_engine, | |
| 194 ProcessThread* process_thread, | 194 ProcessThread* process_thread, |
| 195 CallStats* call_stats, | 195 CallStats* call_stats, |
| 196 VieRemb* remb) | 196 VieRemb* remb) |
| 197 : transport_adapter_(config.rtcp_send_transport), | 197 : transport_adapter_(config.rtcp_send_transport), |
| 198 config_(std::move(config)), | 198 config_(std::move(config)), |
| 199 num_cpu_cores_(num_cpu_cores), | 199 num_cpu_cores_(num_cpu_cores), |
| 200 protected_by_flexfec_(protected_by_flexfec), | 200 protected_by_flexfec_(protected_by_flexfec), |
| 201 process_thread_(process_thread), | 201 process_thread_(process_thread), |
| 202 clock_(Clock::GetRealTimeClock()), | 202 clock_(Clock::GetRealTimeClock()), |
| 203 decode_thread_(DecodeThreadFunction, this, "DecodingThread"), | 203 decode_thread_(DecodeThreadFunction, this, "DecodingThread"), |
| 204 congestion_controller_(congestion_controller), | 204 congestion_controller_(congestion_controller), |
| 205 call_stats_(call_stats), | 205 call_stats_(call_stats), |
| 206 timing_(new VCMTiming(clock_)), | 206 timing_(new VCMTiming(clock_)), |
| 207 video_receiver_(clock_, nullptr, this, timing_.get(), this, this), | 207 video_receiver_(clock_, nullptr, this, timing_.get(), this, this), |
| 208 stats_proxy_(&config_, clock_), | 208 stats_proxy_(&config_, clock_), |
| 209 rtp_stream_receiver_(&video_receiver_, | 209 rtp_stream_receiver_(&video_receiver_, |
| 210 congestion_controller_->GetRemoteBitrateEstimator( | 210 congestion_controller_->GetRemoteBitrateEstimator( |
| 211 UseSendSideBwe(config_)), | 211 UseSendSideBwe(config_)), |
| 212 &transport_adapter_, | 212 &transport_adapter_, |
| 213 call_stats_->rtcp_rtt_stats(), | 213 call_stats_->rtcp_rtt_stats(), |
| 214 packet_router, | 214 packet_router, |
| 215 remb, | 215 remb, |
| 216 &config_, | 216 &config_, |
| 217 &stats_proxy_, | 217 &stats_proxy_, |
| 218 process_thread_, | 218 process_thread_, |
| 219 this, // NackSender | 219 this, // NackSender |
| 220 this, // KeyFrameRequestSender | 220 this, // KeyFrameRequestSender |
| 221 this, // OnCompleteFrameCallback | 221 this, // OnCompleteFrameCallback |
| 222 timing_.get()), | 222 timing_.get()), |
| 223 rtp_stream_sync_(&video_receiver_, &rtp_stream_receiver_), | 223 rtp_stream_sync_(this), |
| 224 jitter_buffer_experiment_( | 224 jitter_buffer_experiment_( |
| 225 field_trial::FindFullName("WebRTC-NewVideoJitterBuffer") == | 225 field_trial::FindFullName("WebRTC-NewVideoJitterBuffer") == |
| 226 "Enabled") { | 226 "Enabled") { |
| 227 LOG(LS_INFO) << "VideoReceiveStream: " << config_.ToString(); | 227 LOG(LS_INFO) << "VideoReceiveStream: " << config_.ToString(); |
| 228 | 228 |
| 229 RTC_DCHECK(process_thread_); | 229 RTC_DCHECK(process_thread_); |
| 230 RTC_DCHECK(congestion_controller_); | 230 RTC_DCHECK(congestion_controller_); |
| 231 RTC_DCHECK(call_stats_); | 231 RTC_DCHECK(call_stats_); |
| 232 | 232 |
| 233 module_process_thread_checker_.DetachFromThread(); |
| 234 |
| 233 RTC_DCHECK(!config_.decoders.empty()); | 235 RTC_DCHECK(!config_.decoders.empty()); |
| 234 std::set<int> decoder_payload_types; | 236 std::set<int> decoder_payload_types; |
| 235 for (const Decoder& decoder : config_.decoders) { | 237 for (const Decoder& decoder : config_.decoders) { |
| 236 RTC_CHECK(decoder.decoder); | 238 RTC_CHECK(decoder.decoder); |
| 237 RTC_CHECK(decoder_payload_types.find(decoder.payload_type) == | 239 RTC_CHECK(decoder_payload_types.find(decoder.payload_type) == |
| 238 decoder_payload_types.end()) | 240 decoder_payload_types.end()) |
| 239 << "Duplicate payload type (" << decoder.payload_type | 241 << "Duplicate payload type (" << decoder.payload_type |
| 240 << ") for different decoders."; | 242 << ") for different decoders."; |
| 241 decoder_payload_types.insert(decoder.payload_type); | 243 decoder_payload_types.insert(decoder.payload_type); |
| 242 } | 244 } |
| 243 | 245 |
| 244 video_receiver_.SetRenderDelay(config.render_delay_ms); | 246 video_receiver_.SetRenderDelay(config.render_delay_ms); |
| 245 | 247 |
| 246 if (jitter_buffer_experiment_) { | 248 if (jitter_buffer_experiment_) { |
| 247 jitter_estimator_.reset(new VCMJitterEstimator(clock_)); | 249 jitter_estimator_.reset(new VCMJitterEstimator(clock_)); |
| 248 frame_buffer_.reset(new video_coding::FrameBuffer( | 250 frame_buffer_.reset(new video_coding::FrameBuffer( |
| 249 clock_, jitter_estimator_.get(), timing_.get())); | 251 clock_, jitter_estimator_.get(), timing_.get())); |
| 250 } | 252 } |
| 251 | 253 |
| 252 process_thread_->RegisterModule(&video_receiver_); | 254 process_thread_->RegisterModule(&video_receiver_); |
| 253 process_thread_->RegisterModule(&rtp_stream_sync_); | 255 process_thread_->RegisterModule(&rtp_stream_sync_); |
| 254 } | 256 } |
| 255 | 257 |
| 256 VideoReceiveStream::~VideoReceiveStream() { | 258 VideoReceiveStream::~VideoReceiveStream() { |
| 259 RTC_DCHECK_RUN_ON(&worker_thread_checker_); |
| 257 LOG(LS_INFO) << "~VideoReceiveStream: " << config_.ToString(); | 260 LOG(LS_INFO) << "~VideoReceiveStream: " << config_.ToString(); |
| 258 Stop(); | 261 Stop(); |
| 259 | 262 |
| 260 process_thread_->DeRegisterModule(&rtp_stream_sync_); | 263 process_thread_->DeRegisterModule(&rtp_stream_sync_); |
| 261 process_thread_->DeRegisterModule(&video_receiver_); | 264 process_thread_->DeRegisterModule(&video_receiver_); |
| 262 | 265 |
| 263 congestion_controller_->GetRemoteBitrateEstimator(UseSendSideBwe(config_)) | 266 congestion_controller_->GetRemoteBitrateEstimator(UseSendSideBwe(config_)) |
| 264 ->RemoveStream(rtp_stream_receiver_.GetRemoteSsrc()); | 267 ->RemoveStream(rtp_stream_receiver_.GetRemoteSsrc()); |
| 265 } | 268 } |
| 266 | 269 |
| 267 void VideoReceiveStream::SignalNetworkState(NetworkState state) { | 270 void VideoReceiveStream::SignalNetworkState(NetworkState state) { |
| 271 RTC_DCHECK_RUN_ON(&worker_thread_checker_); |
| 268 rtp_stream_receiver_.SignalNetworkState(state); | 272 rtp_stream_receiver_.SignalNetworkState(state); |
| 269 } | 273 } |
| 270 | 274 |
| 271 | 275 |
| 272 bool VideoReceiveStream::DeliverRtcp(const uint8_t* packet, size_t length) { | 276 bool VideoReceiveStream::DeliverRtcp(const uint8_t* packet, size_t length) { |
| 273 return rtp_stream_receiver_.DeliverRtcp(packet, length); | 277 return rtp_stream_receiver_.DeliverRtcp(packet, length); |
| 274 } | 278 } |
| 275 | 279 |
| 276 bool VideoReceiveStream::DeliverRtp(const uint8_t* packet, | 280 bool VideoReceiveStream::DeliverRtp(const uint8_t* packet, |
| 277 size_t length, | 281 size_t length, |
| 278 const PacketTime& packet_time) { | 282 const PacketTime& packet_time) { |
| 279 return rtp_stream_receiver_.DeliverRtp(packet, length, packet_time); | 283 return rtp_stream_receiver_.DeliverRtp(packet, length, packet_time); |
| 280 } | 284 } |
| 281 | 285 |
| 282 bool VideoReceiveStream::OnRecoveredPacket(const uint8_t* packet, | 286 bool VideoReceiveStream::OnRecoveredPacket(const uint8_t* packet, |
| 283 size_t length) { | 287 size_t length) { |
| 288 RTC_DCHECK_RUN_ON(&worker_thread_checker_); |
| 284 return rtp_stream_receiver_.OnRecoveredPacket(packet, length); | 289 return rtp_stream_receiver_.OnRecoveredPacket(packet, length); |
| 285 } | 290 } |
| 286 | 291 |
| 287 void VideoReceiveStream::SetSyncChannel(VoiceEngine* voice_engine, | 292 void VideoReceiveStream::SetSync(Syncable* audio_syncable) { |
| 288 int audio_channel_id) { | 293 RTC_DCHECK_RUN_ON(&worker_thread_checker_); |
| 289 if (voice_engine && audio_channel_id != -1) { | 294 rtp_stream_sync_.ConfigureSync(audio_syncable); |
| 290 VoEVideoSync* voe_sync_interface = VoEVideoSync::GetInterface(voice_engine); | |
| 291 rtp_stream_sync_.ConfigureSync(audio_channel_id, voe_sync_interface); | |
| 292 voe_sync_interface->Release(); | |
| 293 } else { | |
| 294 rtp_stream_sync_.ConfigureSync(-1, nullptr); | |
| 295 } | |
| 296 } | 295 } |
| 297 | 296 |
| 298 void VideoReceiveStream::Start() { | 297 void VideoReceiveStream::Start() { |
| 298 RTC_DCHECK_RUN_ON(&worker_thread_checker_); |
| 299 if (decode_thread_.IsRunning()) | 299 if (decode_thread_.IsRunning()) |
| 300 return; | 300 return; |
| 301 | 301 |
| 302 bool protected_by_fec = | 302 bool protected_by_fec = |
| 303 protected_by_flexfec_ || rtp_stream_receiver_.IsUlpfecEnabled(); | 303 protected_by_flexfec_ || rtp_stream_receiver_.IsUlpfecEnabled(); |
| 304 | 304 |
| 305 if (jitter_buffer_experiment_) { | 305 if (jitter_buffer_experiment_) { |
| 306 frame_buffer_->Start(); | 306 frame_buffer_->Start(); |
| 307 call_stats_->RegisterStatsObserver(&rtp_stream_receiver_); | 307 call_stats_->RegisterStatsObserver(&rtp_stream_receiver_); |
| 308 | 308 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 339 &stats_proxy_, renderer, config_.pre_render_callback)); | 339 &stats_proxy_, renderer, config_.pre_render_callback)); |
| 340 // Register the channel to receive stats updates. | 340 // Register the channel to receive stats updates. |
| 341 call_stats_->RegisterStatsObserver(video_stream_decoder_.get()); | 341 call_stats_->RegisterStatsObserver(video_stream_decoder_.get()); |
| 342 // Start the decode thread | 342 // Start the decode thread |
| 343 decode_thread_.Start(); | 343 decode_thread_.Start(); |
| 344 decode_thread_.SetPriority(rtc::kHighestPriority); | 344 decode_thread_.SetPriority(rtc::kHighestPriority); |
| 345 rtp_stream_receiver_.StartReceive(); | 345 rtp_stream_receiver_.StartReceive(); |
| 346 } | 346 } |
| 347 | 347 |
| 348 void VideoReceiveStream::Stop() { | 348 void VideoReceiveStream::Stop() { |
| 349 RTC_DCHECK_RUN_ON(&worker_thread_checker_); |
| 349 rtp_stream_receiver_.StopReceive(); | 350 rtp_stream_receiver_.StopReceive(); |
| 350 // TriggerDecoderShutdown will release any waiting decoder thread and make it | 351 // TriggerDecoderShutdown will release any waiting decoder thread and make it |
| 351 // stop immediately, instead of waiting for a timeout. Needs to be called | 352 // stop immediately, instead of waiting for a timeout. Needs to be called |
| 352 // before joining the decoder thread thread. | 353 // before joining the decoder thread thread. |
| 353 video_receiver_.TriggerDecoderShutdown(); | 354 video_receiver_.TriggerDecoderShutdown(); |
| 354 | 355 |
| 355 if (jitter_buffer_experiment_) { | 356 if (jitter_buffer_experiment_) { |
| 356 frame_buffer_->Stop(); | 357 frame_buffer_->Stop(); |
| 357 call_stats_->DeregisterStatsObserver(&rtp_stream_receiver_); | 358 call_stats_->DeregisterStatsObserver(&rtp_stream_receiver_); |
| 358 } | 359 } |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 400 // TODO(tommi): OnDecodedFrame grabs a lock, incidentally the same lock | 401 // TODO(tommi): OnDecodedFrame grabs a lock, incidentally the same lock |
| 401 // that OnSyncOffsetUpdated() and OnRenderedFrame() below grab. | 402 // that OnSyncOffsetUpdated() and OnRenderedFrame() below grab. |
| 402 stats_proxy_.OnDecodedFrame(); | 403 stats_proxy_.OnDecodedFrame(); |
| 403 | 404 |
| 404 int64_t sync_offset_ms; | 405 int64_t sync_offset_ms; |
| 405 double estimated_freq_khz; | 406 double estimated_freq_khz; |
| 406 // TODO(tommi): GetStreamSyncOffsetInMs grabs three locks. One inside the | 407 // TODO(tommi): GetStreamSyncOffsetInMs grabs three locks. One inside the |
| 407 // function itself, another in GetChannel() and a third in | 408 // function itself, another in GetChannel() and a third in |
| 408 // GetPlayoutTimestamp. Seems excessive. Anyhow, I'm assuming the function | 409 // GetPlayoutTimestamp. Seems excessive. Anyhow, I'm assuming the function |
| 409 // succeeds most of the time, which leads to grabbing a fourth lock. | 410 // succeeds most of the time, which leads to grabbing a fourth lock. |
| 410 if (rtp_stream_sync_.GetStreamSyncOffsetInMs(video_frame, &sync_offset_ms, | 411 if (rtp_stream_sync_.GetStreamSyncOffsetInMs(video_frame.timestamp(), |
| 412 video_frame.render_time_ms(), |
| 413 &sync_offset_ms, |
| 411 &estimated_freq_khz)) { | 414 &estimated_freq_khz)) { |
| 412 // TODO(tommi): OnSyncOffsetUpdated grabs a lock. | 415 // TODO(tommi): OnSyncOffsetUpdated grabs a lock. |
| 413 stats_proxy_.OnSyncOffsetUpdated(sync_offset_ms, estimated_freq_khz); | 416 stats_proxy_.OnSyncOffsetUpdated(sync_offset_ms, estimated_freq_khz); |
| 414 } | 417 } |
| 415 | 418 |
| 416 // config_.renderer must never be null if we're getting this callback. | 419 // config_.renderer must never be null if we're getting this callback. |
| 417 config_.renderer->OnFrame(video_frame); | 420 config_.renderer->OnFrame(video_frame); |
| 418 | 421 |
| 419 // TODO(tommi): OnRenderFrame grabs a lock too. | 422 // TODO(tommi): OnRenderFrame grabs a lock too. |
| 420 stats_proxy_.OnRenderedFrame(video_frame); | 423 stats_proxy_.OnRenderedFrame(video_frame); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 454 rtp_stream_receiver_.RequestKeyFrame(); | 457 rtp_stream_receiver_.RequestKeyFrame(); |
| 455 } | 458 } |
| 456 | 459 |
| 457 void VideoReceiveStream::OnCompleteFrame( | 460 void VideoReceiveStream::OnCompleteFrame( |
| 458 std::unique_ptr<video_coding::FrameObject> frame) { | 461 std::unique_ptr<video_coding::FrameObject> frame) { |
| 459 int last_continuous_pid = frame_buffer_->InsertFrame(std::move(frame)); | 462 int last_continuous_pid = frame_buffer_->InsertFrame(std::move(frame)); |
| 460 if (last_continuous_pid != -1) | 463 if (last_continuous_pid != -1) |
| 461 rtp_stream_receiver_.FrameContinuous(last_continuous_pid); | 464 rtp_stream_receiver_.FrameContinuous(last_continuous_pid); |
| 462 } | 465 } |
| 463 | 466 |
| 467 int VideoReceiveStream::id() const { |
| 468 RTC_DCHECK_RUN_ON(&worker_thread_checker_); |
| 469 return config_.rtp.remote_ssrc; |
| 470 } |
| 471 |
| 472 rtc::Optional<Syncable::Info> VideoReceiveStream::GetInfo() const { |
| 473 RTC_DCHECK_RUN_ON(&module_process_thread_checker_); |
| 474 Syncable::Info info; |
| 475 |
| 476 RtpReceiver* rtp_receiver = rtp_stream_receiver_.GetRtpReceiver(); |
| 477 RTC_DCHECK(rtp_receiver); |
| 478 if (!rtp_receiver->Timestamp(&info.latest_received_capture_timestamp)) |
| 479 return rtc::Optional<Syncable::Info>(); |
| 480 if (!rtp_receiver->LastReceivedTimeMs(&info.latest_receive_time_ms)) |
| 481 return rtc::Optional<Syncable::Info>(); |
| 482 |
| 483 RtpRtcp* rtp_rtcp = rtp_stream_receiver_.rtp_rtcp(); |
| 484 RTC_DCHECK(rtp_rtcp); |
| 485 if (rtp_rtcp->RemoteNTP(&info.capture_time_ntp_secs, |
| 486 &info.capture_time_ntp_frac, |
| 487 nullptr, |
| 488 nullptr, |
| 489 &info.capture_time_source_clock) != 0) { |
| 490 return rtc::Optional<Syncable::Info>(); |
| 491 } |
| 492 |
| 493 info.current_delay_ms = video_receiver_.Delay(); |
| 494 return rtc::Optional<Syncable::Info>(info); |
| 495 } |
| 496 |
| 497 uint32_t VideoReceiveStream::GetPlayoutTimestamp() const { |
| 498 RTC_NOTREACHED(); |
| 499 return 0; |
| 500 } |
| 501 |
| 502 void VideoReceiveStream::SetMinimumPlayoutDelay(int delay_ms) { |
| 503 RTC_DCHECK_RUN_ON(&module_process_thread_checker_); |
| 504 video_receiver_.SetMinimumPlayoutDelay(delay_ms); |
| 505 } |
| 506 |
| 464 bool VideoReceiveStream::DecodeThreadFunction(void* ptr) { | 507 bool VideoReceiveStream::DecodeThreadFunction(void* ptr) { |
| 465 static_cast<VideoReceiveStream*>(ptr)->Decode(); | 508 static_cast<VideoReceiveStream*>(ptr)->Decode(); |
| 466 return true; | 509 return true; |
| 467 } | 510 } |
| 468 | 511 |
| 469 void VideoReceiveStream::Decode() { | 512 void VideoReceiveStream::Decode() { |
| 470 static const int kMaxDecodeWaitTimeMs = 50; | 513 static const int kMaxDecodeWaitTimeMs = 50; |
| 471 if (jitter_buffer_experiment_) { | 514 if (jitter_buffer_experiment_) { |
| 472 static const int kMaxWaitForFrameMs = 3000; | 515 static const int kMaxWaitForFrameMs = 3000; |
| 473 std::unique_ptr<video_coding::FrameObject> frame; | 516 std::unique_ptr<video_coding::FrameObject> frame; |
| 474 video_coding::FrameBuffer::ReturnReason res = | 517 video_coding::FrameBuffer::ReturnReason res = |
| 475 frame_buffer_->NextFrame(kMaxWaitForFrameMs, &frame); | 518 frame_buffer_->NextFrame(kMaxWaitForFrameMs, &frame); |
| 476 | 519 |
| 477 if (res == video_coding::FrameBuffer::ReturnReason::kStopped) | 520 if (res == video_coding::FrameBuffer::ReturnReason::kStopped) |
| 478 return; | 521 return; |
| 479 | 522 |
| 480 if (frame) { | 523 if (frame) { |
| 481 if (video_receiver_.Decode(frame.get()) == VCM_OK) | 524 if (video_receiver_.Decode(frame.get()) == VCM_OK) |
| 482 rtp_stream_receiver_.FrameDecoded(frame->picture_id); | 525 rtp_stream_receiver_.FrameDecoded(frame->picture_id); |
| 483 } else { | 526 } else { |
| 484 LOG(LS_WARNING) << "No decodable frame in " << kMaxWaitForFrameMs | 527 LOG(LS_WARNING) << "No decodable frame in " << kMaxWaitForFrameMs |
| 485 << " ms, requesting keyframe."; | 528 << " ms, requesting keyframe."; |
| 486 RequestKeyFrame(); | 529 RequestKeyFrame(); |
| 487 } | 530 } |
| 488 } else { | 531 } else { |
| 489 video_receiver_.Decode(kMaxDecodeWaitTimeMs); | 532 video_receiver_.Decode(kMaxDecodeWaitTimeMs); |
| 490 } | 533 } |
| 491 } | 534 } |
| 492 | |
| 493 } // namespace internal | 535 } // namespace internal |
| 494 } // namespace webrtc | 536 } // namespace webrtc |
| OLD | NEW |