| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "media/cast/video_sender/video_sender.h" | 5 #include "media/cast/video_sender/video_sender.h" |
| 6 | 6 |
| 7 #include <cstring> | 7 #include <cstring> |
| 8 #include <list> | 8 #include <list> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 namespace cast { | 21 namespace cast { |
| 22 | 22 |
| 23 const int kNumAggressiveReportsSentAtStart = 100; | 23 const int kNumAggressiveReportsSentAtStart = 100; |
| 24 const int kMinSchedulingDelayMs = 1; | 24 const int kMinSchedulingDelayMs = 1; |
| 25 | 25 |
| 26 VideoSender::VideoSender( | 26 VideoSender::VideoSender( |
| 27 scoped_refptr<CastEnvironment> cast_environment, | 27 scoped_refptr<CastEnvironment> cast_environment, |
| 28 const VideoSenderConfig& video_config, | 28 const VideoSenderConfig& video_config, |
| 29 const CreateVideoEncodeAcceleratorCallback& create_vea_cb, | 29 const CreateVideoEncodeAcceleratorCallback& create_vea_cb, |
| 30 const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb, | 30 const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb, |
| 31 const CastInitializationCallback& cast_initialization_cb, | |
| 32 transport::CastTransportSender* const transport_sender) | 31 transport::CastTransportSender* const transport_sender) |
| 33 : rtp_max_delay_(base::TimeDelta::FromMilliseconds( | 32 : rtp_max_delay_(base::TimeDelta::FromMilliseconds( |
| 34 video_config.rtp_config.max_delay_ms)), | 33 video_config.rtp_config.max_delay_ms)), |
| 35 max_frame_rate_(video_config.max_frame_rate), | 34 max_frame_rate_(video_config.max_frame_rate), |
| 36 cast_environment_(cast_environment), | 35 cast_environment_(cast_environment), |
| 37 transport_sender_(transport_sender), | 36 transport_sender_(transport_sender), |
| 38 rtp_timestamp_helper_(kVideoFrequency), | 37 rtp_timestamp_helper_(kVideoFrequency), |
| 39 num_aggressive_rtcp_reports_sent_(0), | 38 num_aggressive_rtcp_reports_sent_(0), |
| 40 last_acked_frame_id_(-1), | 39 last_acked_frame_id_(-1), |
| 41 last_sent_frame_id_(-1), | 40 last_sent_frame_id_(-1), |
| 42 frames_in_encoder_(0), | 41 frames_in_encoder_(0), |
| 43 duplicate_ack_(0), | 42 duplicate_ack_(0), |
| 44 last_skip_count_(0), | 43 last_skip_count_(0), |
| 45 current_requested_bitrate_(video_config.start_bitrate), | 44 current_requested_bitrate_(video_config.start_bitrate), |
| 46 congestion_control_(cast_environment->Clock(), | 45 congestion_control_(cast_environment->Clock(), |
| 47 video_config.congestion_control_back_off, | 46 video_config.congestion_control_back_off, |
| 48 video_config.max_bitrate, | 47 video_config.max_bitrate, |
| 49 video_config.min_bitrate, | 48 video_config.min_bitrate, |
| 50 video_config.start_bitrate), | 49 video_config.start_bitrate), |
| 50 cast_initialization_status_(STATUS_VIDEO_UNINITIALIZED), |
| 51 initialized_(false), | 51 initialized_(false), |
| 52 active_session_(false), | 52 active_session_(false), |
| 53 weak_factory_(this) { | 53 weak_factory_(this) { |
| 54 max_unacked_frames_ = | 54 max_unacked_frames_ = |
| 55 1 + static_cast<uint8>(video_config.rtp_config.max_delay_ms * | 55 1 + static_cast<uint8>(video_config.rtp_config.max_delay_ms * |
| 56 max_frame_rate_ / 1000); | 56 max_frame_rate_ / 1000); |
| 57 VLOG(1) << "max_unacked_frames " << static_cast<int>(max_unacked_frames_); | 57 VLOG(1) << "max_unacked_frames " << static_cast<int>(max_unacked_frames_); |
| 58 DCHECK_GT(max_unacked_frames_, 0) << "Invalid argument"; | 58 DCHECK_GT(max_unacked_frames_, 0) << "Invalid argument"; |
| 59 | |
| 60 if (video_config.use_external_encoder) { | 59 if (video_config.use_external_encoder) { |
| 61 video_encoder_.reset(new ExternalVideoEncoder(cast_environment, | 60 video_encoder_.reset(new ExternalVideoEncoder(cast_environment, |
| 62 video_config, | 61 video_config, |
| 63 create_vea_cb, | 62 create_vea_cb, |
| 64 create_video_encode_mem_cb)); | 63 create_video_encode_mem_cb)); |
| 65 } else { | 64 } else { |
| 66 video_encoder_.reset(new VideoEncoderImpl( | 65 video_encoder_.reset(new VideoEncoderImpl( |
| 67 cast_environment, video_config, max_unacked_frames_)); | 66 cast_environment, video_config, max_unacked_frames_)); |
| 68 } | 67 } |
| 69 | 68 cast_initialization_status_ = STATUS_VIDEO_INITIALIZED; |
| 70 | 69 |
| 71 media::cast::transport::CastTransportVideoConfig transport_config; | 70 media::cast::transport::CastTransportVideoConfig transport_config; |
| 72 transport_config.codec = video_config.codec; | 71 transport_config.codec = video_config.codec; |
| 73 transport_config.rtp.config = video_config.rtp_config; | 72 transport_config.rtp.config = video_config.rtp_config; |
| 74 transport_config.rtp.max_outstanding_frames = max_unacked_frames_ + 1; | 73 transport_config.rtp.max_outstanding_frames = max_unacked_frames_ + 1; |
| 75 transport_sender_->InitializeVideo(transport_config); | 74 transport_sender_->InitializeVideo(transport_config); |
| 76 | 75 |
| 77 rtcp_.reset( | 76 rtcp_.reset( |
| 78 new Rtcp(cast_environment_, | 77 new Rtcp(cast_environment_, |
| 79 this, | 78 this, |
| 80 transport_sender_, | 79 transport_sender_, |
| 81 NULL, // paced sender. | 80 NULL, // paced sender. |
| 82 NULL, | 81 NULL, |
| 83 video_config.rtcp_mode, | 82 video_config.rtcp_mode, |
| 84 base::TimeDelta::FromMilliseconds(video_config.rtcp_interval), | 83 base::TimeDelta::FromMilliseconds(video_config.rtcp_interval), |
| 85 video_config.rtp_config.ssrc, | 84 video_config.rtp_config.ssrc, |
| 86 video_config.incoming_feedback_ssrc, | 85 video_config.incoming_feedback_ssrc, |
| 87 video_config.rtcp_c_name, | 86 video_config.rtcp_c_name, |
| 88 false)); | 87 false)); |
| 89 rtcp_->SetCastReceiverEventHistorySize(kReceiverRtcpEventHistorySize); | 88 rtcp_->SetCastReceiverEventHistorySize(kReceiverRtcpEventHistorySize); |
| 90 | 89 |
| 91 // TODO(pwestin): pass cast_initialization_cb to |video_encoder_| | |
| 92 // and remove this call. | |
| 93 cast_environment_->PostTask( | |
| 94 CastEnvironment::MAIN, | |
| 95 FROM_HERE, | |
| 96 base::Bind(cast_initialization_cb, STATUS_VIDEO_INITIALIZED)); | |
| 97 | |
| 98 memset(frame_id_to_rtp_timestamp_, 0, sizeof(frame_id_to_rtp_timestamp_)); | 90 memset(frame_id_to_rtp_timestamp_, 0, sizeof(frame_id_to_rtp_timestamp_)); |
| 99 } | 91 } |
| 100 | 92 |
| 101 VideoSender::~VideoSender() { | 93 VideoSender::~VideoSender() { |
| 102 } | 94 } |
| 103 | 95 |
| 104 void VideoSender::InitializeTimers() { | 96 void VideoSender::InitializeTimers() { |
| 105 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 97 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 106 if (!initialized_) { | 98 if (!initialized_) { |
| 107 initialized_ = true; | 99 initialized_ = true; |
| 108 ScheduleNextResendCheck(); | 100 ScheduleNextResendCheck(); |
| 109 ScheduleNextSkippedFramesCheck(); | 101 ScheduleNextSkippedFramesCheck(); |
| 110 } | 102 } |
| 111 } | 103 } |
| 112 | 104 |
| 113 void VideoSender::InsertRawVideoFrame( | 105 void VideoSender::InsertRawVideoFrame( |
| 114 const scoped_refptr<media::VideoFrame>& video_frame, | 106 const scoped_refptr<media::VideoFrame>& video_frame, |
| 115 const base::TimeTicks& capture_time) { | 107 const base::TimeTicks& capture_time) { |
| 116 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 108 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 109 if (cast_initialization_status_ != STATUS_VIDEO_INITIALIZED) { |
| 110 NOTREACHED(); |
| 111 return; |
| 112 } |
| 117 DCHECK(video_encoder_.get()) << "Invalid state"; | 113 DCHECK(video_encoder_.get()) << "Invalid state"; |
| 118 | 114 |
| 119 RtpTimestamp rtp_timestamp = GetVideoRtpTimestamp(capture_time); | 115 RtpTimestamp rtp_timestamp = GetVideoRtpTimestamp(capture_time); |
| 120 cast_environment_->Logging()->InsertFrameEvent( | 116 cast_environment_->Logging()->InsertFrameEvent( |
| 121 capture_time, FRAME_CAPTURE_BEGIN, VIDEO_EVENT, | 117 capture_time, FRAME_CAPTURE_BEGIN, VIDEO_EVENT, |
| 122 rtp_timestamp, kFrameIdUnknown); | 118 rtp_timestamp, kFrameIdUnknown); |
| 123 cast_environment_->Logging()->InsertFrameEvent( | 119 cast_environment_->Logging()->InsertFrameEvent( |
| 124 cast_environment_->Clock()->NowTicks(), | 120 cast_environment_->Clock()->NowTicks(), |
| 125 FRAME_CAPTURE_END, VIDEO_EVENT, | 121 FRAME_CAPTURE_END, VIDEO_EVENT, |
| 126 rtp_timestamp, | 122 rtp_timestamp, |
| 127 kFrameIdUnknown); | 123 kFrameIdUnknown); |
| 128 | 124 |
| 129 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc | 125 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc |
| 130 TRACE_EVENT_INSTANT2( | 126 TRACE_EVENT_INSTANT2( |
| 131 "cast_perf_test", "InsertRawVideoFrame", | 127 "cast_perf_test", "InsertRawVideoFrame", |
| 132 TRACE_EVENT_SCOPE_THREAD, | 128 TRACE_EVENT_SCOPE_THREAD, |
| 133 "timestamp", capture_time.ToInternalValue(), | 129 "timestamp", capture_time.ToInternalValue(), |
| 134 "rtp_timestamp", rtp_timestamp); | 130 "rtp_timestamp", rtp_timestamp); |
| 135 | 131 |
| 136 if (video_encoder_->EncodeVideoFrame( | 132 if (video_encoder_->EncodeVideoFrame( |
| 137 video_frame, | 133 video_frame, |
| 138 capture_time, | 134 capture_time, |
| 139 base::Bind(&VideoSender::SendEncodedVideoFrameMainThread, | 135 base::Bind(&VideoSender::SendEncodedVideoFrame, |
| 140 weak_factory_.GetWeakPtr(), | 136 weak_factory_.GetWeakPtr(), |
| 141 current_requested_bitrate_))) { | 137 current_requested_bitrate_))) { |
| 142 frames_in_encoder_++; | 138 frames_in_encoder_++; |
| 143 UpdateFramesInFlight(); | 139 UpdateFramesInFlight(); |
| 144 } | 140 } |
| 145 } | 141 } |
| 146 | 142 |
| 147 void VideoSender::SendEncodedVideoFrameMainThread( | 143 void VideoSender::SendEncodedVideoFrame( |
| 148 int requested_bitrate_before_encode, | 144 int requested_bitrate_before_encode, |
| 149 scoped_ptr<transport::EncodedFrame> encoded_frame) { | 145 scoped_ptr<transport::EncodedFrame> encoded_frame) { |
| 150 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 146 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 151 last_send_time_ = cast_environment_->Clock()->NowTicks(); | 147 last_send_time_ = cast_environment_->Clock()->NowTicks(); |
| 152 VLOG_IF(1, encoded_frame->dependency == transport::EncodedFrame::KEY) | 148 VLOG_IF(1, encoded_frame->dependency == transport::EncodedFrame::KEY) |
| 153 << "Send encoded key frame; frame_id: " << encoded_frame->frame_id; | 149 << "Send encoded key frame; frame_id: " << encoded_frame->frame_id; |
| 154 | 150 |
| 155 DCHECK_GT(frames_in_encoder_, 0); | 151 DCHECK_GT(frames_in_encoder_, 0); |
| 156 frames_in_encoder_--; | 152 frames_in_encoder_--; |
| 157 uint32 frame_id = encoded_frame->frame_id; | 153 uint32 frame_id = encoded_frame->frame_id; |
| 158 cast_environment_->Logging()->InsertEncodedFrameEvent( | 154 cast_environment_->Logging()->InsertEncodedFrameEvent( |
| 159 last_send_time_, FRAME_ENCODED, VIDEO_EVENT, encoded_frame->rtp_timestamp, | 155 last_send_time_, FRAME_ENCODED, VIDEO_EVENT, encoded_frame->rtp_timestamp, |
| 160 frame_id, static_cast<int>(encoded_frame->data.size()), | 156 frame_id, static_cast<int>(encoded_frame->data.size()), |
| 161 encoded_frame->dependency == transport::EncodedFrame::KEY, | 157 encoded_frame->dependency == transport::EncodedFrame::KEY, |
| 162 requested_bitrate_before_encode); | 158 requested_bitrate_before_encode); |
| 163 | 159 |
| 164 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc | 160 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc |
| 165 TRACE_EVENT_INSTANT1( | 161 TRACE_EVENT_INSTANT1( |
| 166 "cast_perf_test", "VideoFrameEncoded", | 162 "cast_perf_test", "VideoFrameEncoded", |
| 167 TRACE_EVENT_SCOPE_THREAD, | 163 TRACE_EVENT_SCOPE_THREAD, |
| 168 "rtp_timestamp", encoded_frame->rtp_timestamp); | 164 "rtp_timestamp", encoded_frame->rtp_timestamp); |
| 169 | 165 |
| 170 // Only use lowest 8 bits as key. | 166 // Only use lowest 8 bits as key. |
| 171 frame_id_to_rtp_timestamp_[frame_id & 0xff] = encoded_frame->rtp_timestamp; | 167 frame_id_to_rtp_timestamp_[frame_id & 0xff] = encoded_frame->rtp_timestamp; |
| 172 | 168 |
| 173 last_sent_frame_id_ = static_cast<int>(encoded_frame->frame_id); | 169 last_sent_frame_id_ = static_cast<int>(encoded_frame->frame_id); |
| 170 |
| 174 DCHECK(!encoded_frame->reference_time.is_null()); | 171 DCHECK(!encoded_frame->reference_time.is_null()); |
| 175 rtp_timestamp_helper_.StoreLatestTime(encoded_frame->reference_time, | 172 rtp_timestamp_helper_.StoreLatestTime(encoded_frame->reference_time, |
| 176 encoded_frame->rtp_timestamp); | 173 encoded_frame->rtp_timestamp); |
| 177 | 174 |
| 178 // At the start of the session, it's important to send reports before each | 175 // At the start of the session, it's important to send reports before each |
| 179 // frame so that the receiver can properly compute playout times. The reason | 176 // frame so that the receiver can properly compute playout times. The reason |
| 180 // more than one report is sent is because transmission is not guaranteed, | 177 // more than one report is sent is because transmission is not guaranteed, |
| 181 // only best effort, so send enough that one should almost certainly get | 178 // only best effort, so send enough that one should almost certainly get |
| 182 // through. | 179 // through. |
| 183 if (num_aggressive_rtcp_reports_sent_ < kNumAggressiveReportsSentAtStart) { | 180 if (num_aggressive_rtcp_reports_sent_ < kNumAggressiveReportsSentAtStart) { |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 435 | 432 |
| 436 void VideoSender::UpdateBitrate(int new_bitrate) { | 433 void VideoSender::UpdateBitrate(int new_bitrate) { |
| 437 // Make sure we don't set the bitrate too insanely low. | 434 // Make sure we don't set the bitrate too insanely low. |
| 438 DCHECK_GT(new_bitrate, 1000); | 435 DCHECK_GT(new_bitrate, 1000); |
| 439 video_encoder_->SetBitRate(new_bitrate); | 436 video_encoder_->SetBitRate(new_bitrate); |
| 440 current_requested_bitrate_ = new_bitrate; | 437 current_requested_bitrate_ = new_bitrate; |
| 441 } | 438 } |
| 442 | 439 |
| 443 } // namespace cast | 440 } // namespace cast |
| 444 } // namespace media | 441 } // namespace media |
| OLD | NEW |