OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/sender/video_sender.h" | 5 #include "media/cast/sender/video_sender.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <cmath> | 8 #include <cmath> |
9 #include <cstring> | 9 #include <cstring> |
10 | 10 |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
88 const PlayoutDelayChangeCB& playout_delay_change_cb) | 88 const PlayoutDelayChangeCB& playout_delay_change_cb) |
89 : FrameSender( | 89 : FrameSender( |
90 cast_environment, | 90 cast_environment, |
91 false, | 91 false, |
92 transport_sender, | 92 transport_sender, |
93 kVideoFrequency, | 93 kVideoFrequency, |
94 video_config.ssrc, | 94 video_config.ssrc, |
95 video_config.max_frame_rate, | 95 video_config.max_frame_rate, |
96 video_config.min_playout_delay, | 96 video_config.min_playout_delay, |
97 video_config.max_playout_delay, | 97 video_config.max_playout_delay, |
| 98 video_config.animated_playout_delay, |
98 video_config.use_external_encoder | 99 video_config.use_external_encoder |
99 ? NewFixedCongestionControl( | 100 ? NewFixedCongestionControl( |
100 (video_config.min_bitrate + video_config.max_bitrate) / 2) | 101 (video_config.min_bitrate + video_config.max_bitrate) / 2) |
101 : NewAdaptiveCongestionControl(cast_environment->Clock(), | 102 : NewAdaptiveCongestionControl(cast_environment->Clock(), |
102 video_config.max_bitrate, | 103 video_config.max_bitrate, |
103 video_config.min_bitrate, | 104 video_config.min_bitrate, |
104 video_config.max_frame_rate)), | 105 video_config.max_frame_rate)), |
105 frames_in_encoder_(0), | 106 frames_in_encoder_(0), |
106 last_bitrate_(0), | 107 last_bitrate_(0), |
107 playout_delay_change_cb_(playout_delay_change_cb), | 108 playout_delay_change_cb_(playout_delay_change_cb), |
| 109 interactive_mode_(false), |
108 last_reported_deadline_utilization_(-1.0), | 110 last_reported_deadline_utilization_(-1.0), |
109 last_reported_lossy_utilization_(-1.0), | 111 last_reported_lossy_utilization_(-1.0), |
110 weak_factory_(this) { | 112 weak_factory_(this) { |
111 video_encoder_ = VideoEncoder::Create( | 113 video_encoder_ = VideoEncoder::Create( |
112 cast_environment_, | 114 cast_environment_, |
113 video_config, | 115 video_config, |
114 status_change_cb, | 116 status_change_cb, |
115 create_vea_cb, | 117 create_vea_cb, |
116 create_video_encode_mem_cb); | 118 create_video_encode_mem_cb); |
117 if (!video_encoder_) { | 119 if (!video_encoder_) { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
154 LogVideoCaptureTimestamps(cast_environment_.get(), *video_frame, | 156 LogVideoCaptureTimestamps(cast_environment_.get(), *video_frame, |
155 rtp_timestamp); | 157 rtp_timestamp); |
156 | 158 |
157 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc | 159 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc |
158 TRACE_EVENT_INSTANT2( | 160 TRACE_EVENT_INSTANT2( |
159 "cast_perf_test", "InsertRawVideoFrame", | 161 "cast_perf_test", "InsertRawVideoFrame", |
160 TRACE_EVENT_SCOPE_THREAD, | 162 TRACE_EVENT_SCOPE_THREAD, |
161 "timestamp", reference_time.ToInternalValue(), | 163 "timestamp", reference_time.ToInternalValue(), |
162 "rtp_timestamp", rtp_timestamp); | 164 "rtp_timestamp", rtp_timestamp); |
163 | 165 |
| 166 bool interactive_mode; |
| 167 if (video_frame->metadata()->GetBoolean(VideoFrameMetadata::INTERACTIVE_MODE, |
| 168 &interactive_mode)) { |
| 169 if (interactive_mode && !interactive_mode_) { |
| 170 VLOG(1) << "Interactive mode playout time " << min_playout_delay_; |
| 171 playout_delay_change_cb_.Run(min_playout_delay_); |
| 172 } |
| 173 interactive_mode_ = interactive_mode; |
| 174 } |
| 175 |
164 // Drop the frame if either its RTP or reference timestamp is not an increase | 176 // Drop the frame if either its RTP or reference timestamp is not an increase |
165 // over the last frame's. This protects: 1) the duration calculations that | 177 // over the last frame's. This protects: 1) the duration calculations that |
166 // assume timestamps are monotonically non-decreasing, and 2) assumptions made | 178 // assume timestamps are monotonically non-decreasing, and 2) assumptions made |
167 // deeper in the implementation where each frame's RTP timestamp needs to be | 179 // deeper in the implementation where each frame's RTP timestamp needs to be |
168 // unique. | 180 // unique. |
169 if (!last_enqueued_frame_reference_time_.is_null() && | 181 if (!last_enqueued_frame_reference_time_.is_null() && |
170 (!IsNewerRtpTimestamp(rtp_timestamp, | 182 (!IsNewerRtpTimestamp(rtp_timestamp, |
171 last_enqueued_frame_rtp_timestamp_) || | 183 last_enqueued_frame_rtp_timestamp_) || |
172 reference_time <= last_enqueued_frame_reference_time_)) { | 184 reference_time <= last_enqueued_frame_reference_time_)) { |
173 VLOG(1) << "Dropping video frame: RTP or reference time did not increase."; | 185 VLOG(1) << "Dropping video frame: RTP or reference time did not increase."; |
(...skipping 11 matching lines...) Expand all Loading... |
185 // OnEncodedVideoFrame(). | 197 // OnEncodedVideoFrame(). |
186 const base::TimeDelta duration_added_by_next_frame = frames_in_encoder_ > 0 ? | 198 const base::TimeDelta duration_added_by_next_frame = frames_in_encoder_ > 0 ? |
187 reference_time - last_enqueued_frame_reference_time_ : | 199 reference_time - last_enqueued_frame_reference_time_ : |
188 base::TimeDelta::FromSecondsD(1.0 / max_frame_rate_); | 200 base::TimeDelta::FromSecondsD(1.0 / max_frame_rate_); |
189 | 201 |
190 if (ShouldDropNextFrame(duration_added_by_next_frame)) { | 202 if (ShouldDropNextFrame(duration_added_by_next_frame)) { |
191 base::TimeDelta new_target_delay = std::min( | 203 base::TimeDelta new_target_delay = std::min( |
192 current_round_trip_time_ * kRoundTripsNeeded + | 204 current_round_trip_time_ * kRoundTripsNeeded + |
193 base::TimeDelta::FromMilliseconds(kConstantTimeMs), | 205 base::TimeDelta::FromMilliseconds(kConstantTimeMs), |
194 max_playout_delay_); | 206 max_playout_delay_); |
195 if (new_target_delay > target_playout_delay_) { | 207 // In case of interactive mode, we prefer frame drops over increasing |
| 208 // playout time. |
| 209 if (!interactive_mode_ && new_target_delay > target_playout_delay_) { |
| 210 // In case we detect user is no more in an interactive mode and there is |
| 211 // a need to drop a frame, we ensure the playout delay is at-least the |
| 212 // the starting value for playing animated content. |
| 213 // This is intended to minimize freeze when moving from an interactive |
| 214 // session to watching animating content while being limited by end-to-end |
| 215 // delay. |
| 216 VLOG(1) << "Ensure playout time is at least " << animated_playout_delay_; |
| 217 if (new_target_delay < animated_playout_delay_) |
| 218 new_target_delay = animated_playout_delay_; |
196 VLOG(1) << "New target delay: " << new_target_delay.InMilliseconds(); | 219 VLOG(1) << "New target delay: " << new_target_delay.InMilliseconds(); |
197 playout_delay_change_cb_.Run(new_target_delay); | 220 playout_delay_change_cb_.Run(new_target_delay); |
198 } | 221 } |
199 | 222 |
200 // Some encoder implementations have a frame window for analysis. Since we | 223 // Some encoder implementations have a frame window for analysis. Since we |
201 // are dropping this frame, unless we instruct the encoder to flush all the | 224 // are dropping this frame, unless we instruct the encoder to flush all the |
202 // frames that have been enqueued for encoding, frames_in_encoder_ and | 225 // frames that have been enqueued for encoding, frames_in_encoder_ and |
203 // last_enqueued_frame_reference_time_ will never be updated and we will | 226 // last_enqueued_frame_reference_time_ will never be updated and we will |
204 // drop every subsequent frame for the rest of the session. | 227 // drop every subsequent frame for the rest of the session. |
205 video_encoder_->EmitFrames(); | 228 video_encoder_->EmitFrames(); |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
356 media::VideoFrameMetadata::RESOURCE_UTILIZATION, | 379 media::VideoFrameMetadata::RESOURCE_UTILIZATION, |
357 encoded_frame->dependency == EncodedFrame::KEY ? | 380 encoded_frame->dependency == EncodedFrame::KEY ? |
358 std::min(1.0, attenuated_utilization) : attenuated_utilization); | 381 std::min(1.0, attenuated_utilization) : attenuated_utilization); |
359 } | 382 } |
360 | 383 |
361 SendEncodedFrame(encoder_bitrate, encoded_frame.Pass()); | 384 SendEncodedFrame(encoder_bitrate, encoded_frame.Pass()); |
362 } | 385 } |
363 | 386 |
364 } // namespace cast | 387 } // namespace cast |
365 } // namespace media | 388 } // namespace media |
OLD | NEW |