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 VIDEO_EVENT)); | 87 VIDEO_EVENT)); |
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 |