| 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 |
| (...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 278 size_t length, | 278 size_t length, |
| 279 const PacketTime& packet_time) { | 279 const PacketTime& packet_time) { |
| 280 return rtp_stream_receiver_.DeliverRtp(packet, length, packet_time); | 280 return rtp_stream_receiver_.DeliverRtp(packet, length, packet_time); |
| 281 } | 281 } |
| 282 | 282 |
| 283 bool VideoReceiveStream::OnRecoveredPacket(const uint8_t* packet, | 283 bool VideoReceiveStream::OnRecoveredPacket(const uint8_t* packet, |
| 284 size_t length) { | 284 size_t length) { |
| 285 return rtp_stream_receiver_.OnRecoveredPacket(packet, length); | 285 return rtp_stream_receiver_.OnRecoveredPacket(packet, length); |
| 286 } | 286 } |
| 287 | 287 |
| 288 void VideoReceiveStream::SetSyncChannel(VoiceEngine* voice_engine, |
| 289 int audio_channel_id) { |
| 290 if (voice_engine && audio_channel_id != -1) { |
| 291 VoEVideoSync* voe_sync_interface = VoEVideoSync::GetInterface(voice_engine); |
| 292 rtp_stream_sync_.ConfigureSync(audio_channel_id, voe_sync_interface); |
| 293 voe_sync_interface->Release(); |
| 294 } else { |
| 295 rtp_stream_sync_.ConfigureSync(-1, nullptr); |
| 296 } |
| 297 } |
| 298 |
| 288 void VideoReceiveStream::Start() { | 299 void VideoReceiveStream::Start() { |
| 289 if (decode_thread_.IsRunning()) | 300 if (decode_thread_.IsRunning()) |
| 290 return; | 301 return; |
| 291 if (jitter_buffer_experiment_) { | 302 if (jitter_buffer_experiment_) { |
| 292 frame_buffer_->Start(); | 303 frame_buffer_->Start(); |
| 293 call_stats_->RegisterStatsObserver(&rtp_stream_receiver_); | 304 call_stats_->RegisterStatsObserver(&rtp_stream_receiver_); |
| 294 | 305 |
| 295 if (rtp_stream_receiver_.IsRetransmissionsEnabled() && | 306 if (rtp_stream_receiver_.IsRetransmissionsEnabled() && |
| 296 rtp_stream_receiver_.IsUlpfecEnabled()) { | 307 rtp_stream_receiver_.IsUlpfecEnabled()) { |
| 297 frame_buffer_->SetProtectionMode(kProtectionNackFEC); | 308 frame_buffer_->SetProtectionMode(kProtectionNackFEC); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 355 for (const Decoder& decoder : config_.decoders) | 366 for (const Decoder& decoder : config_.decoders) |
| 356 video_receiver_.RegisterExternalDecoder(nullptr, decoder.payload_type); | 367 video_receiver_.RegisterExternalDecoder(nullptr, decoder.payload_type); |
| 357 } | 368 } |
| 358 | 369 |
| 359 call_stats_->DeregisterStatsObserver(video_stream_decoder_.get()); | 370 call_stats_->DeregisterStatsObserver(video_stream_decoder_.get()); |
| 360 video_stream_decoder_.reset(); | 371 video_stream_decoder_.reset(); |
| 361 incoming_video_stream_.reset(); | 372 incoming_video_stream_.reset(); |
| 362 transport_adapter_.Disable(); | 373 transport_adapter_.Disable(); |
| 363 } | 374 } |
| 364 | 375 |
| 365 void VideoReceiveStream::SetSyncChannel(VoiceEngine* voice_engine, | |
| 366 int audio_channel_id) { | |
| 367 if (voice_engine && audio_channel_id != -1) { | |
| 368 VoEVideoSync* voe_sync_interface = VoEVideoSync::GetInterface(voice_engine); | |
| 369 rtp_stream_sync_.ConfigureSync(audio_channel_id, voe_sync_interface); | |
| 370 voe_sync_interface->Release(); | |
| 371 } else { | |
| 372 rtp_stream_sync_.ConfigureSync(-1, nullptr); | |
| 373 } | |
| 374 } | |
| 375 | |
| 376 VideoReceiveStream::Stats VideoReceiveStream::GetStats() const { | 376 VideoReceiveStream::Stats VideoReceiveStream::GetStats() const { |
| 377 return stats_proxy_.GetStats(); | 377 return stats_proxy_.GetStats(); |
| 378 } | 378 } |
| 379 | 379 |
| 380 void VideoReceiveStream::EnableEncodedFrameRecording(rtc::PlatformFile file, |
| 381 size_t byte_limit) { |
| 382 { |
| 383 rtc::CritScope lock(&ivf_writer_lock_); |
| 384 if (file == rtc::kInvalidPlatformFileValue) { |
| 385 ivf_writer_.reset(); |
| 386 } else { |
| 387 ivf_writer_ = IvfFileWriter::Wrap(rtc::File(file), byte_limit); |
| 388 } |
| 389 } |
| 390 |
| 391 if (file != rtc::kInvalidPlatformFileValue) { |
| 392 // Make a keyframe appear as early as possible in the logs, to give actually |
| 393 // decodable output. |
| 394 RequestKeyFrame(); |
| 395 } |
| 396 } |
| 397 |
| 380 // TODO(tommi): This method grabs a lock 6 times. | 398 // TODO(tommi): This method grabs a lock 6 times. |
| 381 void VideoReceiveStream::OnFrame(const VideoFrame& video_frame) { | 399 void VideoReceiveStream::OnFrame(const VideoFrame& video_frame) { |
| 382 // TODO(tommi): OnDecodedFrame grabs a lock, incidentally the same lock | 400 // TODO(tommi): OnDecodedFrame grabs a lock, incidentally the same lock |
| 383 // that OnSyncOffsetUpdated() and OnRenderedFrame() below grab. | 401 // that OnSyncOffsetUpdated() and OnRenderedFrame() below grab. |
| 384 stats_proxy_.OnDecodedFrame(); | 402 stats_proxy_.OnDecodedFrame(); |
| 385 | 403 |
| 386 int64_t sync_offset_ms; | 404 int64_t sync_offset_ms; |
| 387 double estimated_freq_khz; | 405 double estimated_freq_khz; |
| 388 // TODO(tommi): GetStreamSyncOffsetInMs grabs three locks. One inside the | 406 // TODO(tommi): GetStreamSyncOffsetInMs grabs three locks. One inside the |
| 389 // function itself, another in GetChannel() and a third in | 407 // function itself, another in GetChannel() and a third in |
| 390 // GetPlayoutTimestamp. Seems excessive. Anyhow, I'm assuming the function | 408 // GetPlayoutTimestamp. Seems excessive. Anyhow, I'm assuming the function |
| 391 // succeeds most of the time, which leads to grabbing a fourth lock. | 409 // succeeds most of the time, which leads to grabbing a fourth lock. |
| 392 if (rtp_stream_sync_.GetStreamSyncOffsetInMs(video_frame, &sync_offset_ms, | 410 if (rtp_stream_sync_.GetStreamSyncOffsetInMs(video_frame, &sync_offset_ms, |
| 393 &estimated_freq_khz)) { | 411 &estimated_freq_khz)) { |
| 394 // TODO(tommi): OnSyncOffsetUpdated grabs a lock. | 412 // TODO(tommi): OnSyncOffsetUpdated grabs a lock. |
| 395 stats_proxy_.OnSyncOffsetUpdated(sync_offset_ms, estimated_freq_khz); | 413 stats_proxy_.OnSyncOffsetUpdated(sync_offset_ms, estimated_freq_khz); |
| 396 } | 414 } |
| 397 | 415 |
| 398 // config_.renderer must never be null if we're getting this callback. | 416 // config_.renderer must never be null if we're getting this callback. |
| 399 config_.renderer->OnFrame(video_frame); | 417 config_.renderer->OnFrame(video_frame); |
| 400 | 418 |
| 401 // TODO(tommi): OnRenderFrame grabs a lock too. | 419 // TODO(tommi): OnRenderFrame grabs a lock too. |
| 402 stats_proxy_.OnRenderedFrame(video_frame); | 420 stats_proxy_.OnRenderedFrame(video_frame); |
| 403 } | 421 } |
| 404 | 422 |
| 405 void VideoReceiveStream::OnCompleteFrame( | |
| 406 std::unique_ptr<video_coding::FrameObject> frame) { | |
| 407 int last_continuous_pid = frame_buffer_->InsertFrame(std::move(frame)); | |
| 408 if (last_continuous_pid != -1) | |
| 409 rtp_stream_receiver_.FrameContinuous(last_continuous_pid); | |
| 410 } | |
| 411 | |
| 412 // TODO(asapersson): Consider moving callback from video_encoder.h or | 423 // TODO(asapersson): Consider moving callback from video_encoder.h or |
| 413 // creating a different callback. | 424 // creating a different callback. |
| 414 EncodedImageCallback::Result VideoReceiveStream::OnEncodedImage( | 425 EncodedImageCallback::Result VideoReceiveStream::OnEncodedImage( |
| 415 const EncodedImage& encoded_image, | 426 const EncodedImage& encoded_image, |
| 416 const CodecSpecificInfo* codec_specific_info, | 427 const CodecSpecificInfo* codec_specific_info, |
| 417 const RTPFragmentationHeader* fragmentation) { | 428 const RTPFragmentationHeader* fragmentation) { |
| 418 stats_proxy_.OnPreDecode(encoded_image, codec_specific_info); | 429 stats_proxy_.OnPreDecode(encoded_image, codec_specific_info); |
| 419 if (config_.pre_decode_callback) { | 430 if (config_.pre_decode_callback) { |
| 420 config_.pre_decode_callback->EncodedFrameCallback( | 431 config_.pre_decode_callback->EncodedFrameCallback( |
| 421 EncodedFrame(encoded_image._buffer, encoded_image._length, | 432 EncodedFrame(encoded_image._buffer, encoded_image._length, |
| 422 encoded_image._frameType)); | 433 encoded_image._frameType)); |
| 423 } | 434 } |
| 424 { | 435 { |
| 425 rtc::CritScope lock(&ivf_writer_lock_); | 436 rtc::CritScope lock(&ivf_writer_lock_); |
| 426 if (ivf_writer_.get()) { | 437 if (ivf_writer_.get()) { |
| 427 RTC_DCHECK(codec_specific_info); | 438 RTC_DCHECK(codec_specific_info); |
| 428 bool ok = ivf_writer_->WriteFrame(encoded_image, | 439 bool ok = ivf_writer_->WriteFrame(encoded_image, |
| 429 codec_specific_info->codecType); | 440 codec_specific_info->codecType); |
| 430 RTC_DCHECK(ok); | 441 RTC_DCHECK(ok); |
| 431 } | 442 } |
| 432 } | 443 } |
| 433 | 444 |
| 434 return Result(Result::OK, encoded_image._timeStamp); | 445 return Result(Result::OK, encoded_image._timeStamp); |
| 435 } | 446 } |
| 436 | 447 |
| 448 void VideoReceiveStream::SendNack( |
| 449 const std::vector<uint16_t>& sequence_numbers) { |
| 450 rtp_stream_receiver_.RequestPacketRetransmit(sequence_numbers); |
| 451 } |
| 452 |
| 453 void VideoReceiveStream::RequestKeyFrame() { |
| 454 rtp_stream_receiver_.RequestKeyFrame(); |
| 455 } |
| 456 |
| 457 void VideoReceiveStream::OnCompleteFrame( |
| 458 std::unique_ptr<video_coding::FrameObject> frame) { |
| 459 int last_continuous_pid = frame_buffer_->InsertFrame(std::move(frame)); |
| 460 if (last_continuous_pid != -1) |
| 461 rtp_stream_receiver_.FrameContinuous(last_continuous_pid); |
| 462 } |
| 463 |
| 437 bool VideoReceiveStream::DecodeThreadFunction(void* ptr) { | 464 bool VideoReceiveStream::DecodeThreadFunction(void* ptr) { |
| 438 static_cast<VideoReceiveStream*>(ptr)->Decode(); | 465 static_cast<VideoReceiveStream*>(ptr)->Decode(); |
| 439 return true; | 466 return true; |
| 440 } | 467 } |
| 441 | 468 |
| 442 void VideoReceiveStream::Decode() { | 469 void VideoReceiveStream::Decode() { |
| 443 static const int kMaxDecodeWaitTimeMs = 50; | 470 static const int kMaxDecodeWaitTimeMs = 50; |
| 444 if (jitter_buffer_experiment_) { | 471 if (jitter_buffer_experiment_) { |
| 445 static const int kMaxWaitForFrameMs = 3000; | 472 static const int kMaxWaitForFrameMs = 3000; |
| 446 std::unique_ptr<video_coding::FrameObject> frame; | 473 std::unique_ptr<video_coding::FrameObject> frame; |
| 447 video_coding::FrameBuffer::ReturnReason res = | 474 video_coding::FrameBuffer::ReturnReason res = |
| 448 frame_buffer_->NextFrame(kMaxWaitForFrameMs, &frame); | 475 frame_buffer_->NextFrame(kMaxWaitForFrameMs, &frame); |
| 449 | 476 |
| 450 if (res == video_coding::FrameBuffer::ReturnReason::kStopped) | 477 if (res == video_coding::FrameBuffer::ReturnReason::kStopped) |
| 451 return; | 478 return; |
| 452 | 479 |
| 453 if (frame) { | 480 if (frame) { |
| 454 if (video_receiver_.Decode(frame.get()) == VCM_OK) | 481 if (video_receiver_.Decode(frame.get()) == VCM_OK) |
| 455 rtp_stream_receiver_.FrameDecoded(frame->picture_id); | 482 rtp_stream_receiver_.FrameDecoded(frame->picture_id); |
| 456 } else { | 483 } else { |
| 457 LOG(LS_WARNING) << "No decodable frame in " << kMaxWaitForFrameMs | 484 LOG(LS_WARNING) << "No decodable frame in " << kMaxWaitForFrameMs |
| 458 << " ms, requesting keyframe."; | 485 << " ms, requesting keyframe."; |
| 459 RequestKeyFrame(); | 486 RequestKeyFrame(); |
| 460 } | 487 } |
| 461 } else { | 488 } else { |
| 462 video_receiver_.Decode(kMaxDecodeWaitTimeMs); | 489 video_receiver_.Decode(kMaxDecodeWaitTimeMs); |
| 463 } | 490 } |
| 464 } | 491 } |
| 465 | 492 |
| 466 void VideoReceiveStream::SendNack( | |
| 467 const std::vector<uint16_t>& sequence_numbers) { | |
| 468 rtp_stream_receiver_.RequestPacketRetransmit(sequence_numbers); | |
| 469 } | |
| 470 | |
| 471 void VideoReceiveStream::EnableEncodedFrameRecording(rtc::PlatformFile file, | |
| 472 size_t byte_limit) { | |
| 473 { | |
| 474 rtc::CritScope lock(&ivf_writer_lock_); | |
| 475 if (file == rtc::kInvalidPlatformFileValue) { | |
| 476 ivf_writer_.reset(); | |
| 477 } else { | |
| 478 ivf_writer_ = IvfFileWriter::Wrap(rtc::File(file), byte_limit); | |
| 479 } | |
| 480 } | |
| 481 | |
| 482 if (file != rtc::kInvalidPlatformFileValue) { | |
| 483 // Make a keyframe appear as early as possible in the logs, to give actually | |
| 484 // decodable output. | |
| 485 RequestKeyFrame(); | |
| 486 } | |
| 487 } | |
| 488 | |
| 489 void VideoReceiveStream::RequestKeyFrame() { | |
| 490 rtp_stream_receiver_.RequestKeyFrame(); | |
| 491 } | |
| 492 | |
| 493 } // namespace internal | 493 } // namespace internal |
| 494 } // namespace webrtc | 494 } // namespace webrtc |
| OLD | NEW |