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 |