Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(77)

Side by Side Diff: media/cast/sender/video_sender.cc

Issue 560223002: [Cast] Limit frames in flight by duration, and not by number of frames. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Removed auto-eviction from PacketStorage, since that should never happen. Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 <cstring> 8 #include <cstring>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/debug/trace_event.h" 11 #include "base/debug/trace_event.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/message_loop/message_loop.h" 13 #include "base/message_loop/message_loop.h"
14 #include "media/cast/cast_defines.h" 14 #include "media/cast/cast_defines.h"
15 #include "media/cast/net/cast_transport_config.h" 15 #include "media/cast/net/cast_transport_config.h"
16 #include "media/cast/sender/external_video_encoder.h" 16 #include "media/cast/sender/external_video_encoder.h"
17 #include "media/cast/sender/video_encoder_impl.h" 17 #include "media/cast/sender/video_encoder_impl.h"
18 18
19 namespace media { 19 namespace media {
20 namespace cast { 20 namespace cast {
21 21
22 namespace {
23
22 // The following two constants are used to adjust the target 24 // The following two constants are used to adjust the target
23 // playout delay (when allowed). They were calculated using 25 // playout delay (when allowed). They were calculated using
24 // a combination of cast_benchmark runs and manual testing. 26 // a combination of cast_benchmark runs and manual testing.
25 27 //
26 // This is how many round trips we think we need on the network. 28 // This is how many round trips we think we need on the network.
27 const int kRoundTripsNeeded = 4; 29 const int kRoundTripsNeeded = 4;
28 // This is an estimate of all the the constant time needed 30 // This is an estimate of all the the constant time needed independent of
29 // independent of network quality. 31 // network quality (e.g., additional time that accounts for encode and decode
32 // time).
30 const int kConstantTimeMs = 75; 33 const int kConstantTimeMs = 75;
31 34
35 } // namespace
36
32 // Note, we use a fixed bitrate value when external video encoder is used. 37 // Note, we use a fixed bitrate value when external video encoder is used.
33 // Some hardware encoder shows bad behavior if we set the bitrate too 38 // Some hardware encoder shows bad behavior if we set the bitrate too
34 // frequently, e.g. quality drop, not abiding by target bitrate, etc. 39 // frequently, e.g. quality drop, not abiding by target bitrate, etc.
35 // See details: crbug.com/392086. 40 // See details: crbug.com/392086.
36 VideoSender::VideoSender( 41 VideoSender::VideoSender(
37 scoped_refptr<CastEnvironment> cast_environment, 42 scoped_refptr<CastEnvironment> cast_environment,
38 const VideoSenderConfig& video_config, 43 const VideoSenderConfig& video_config,
39 const CastInitializationCallback& initialization_cb, 44 const CastInitializationCallback& initialization_cb,
40 const CreateVideoEncodeAcceleratorCallback& create_vea_cb, 45 const CreateVideoEncodeAcceleratorCallback& create_vea_cb,
41 const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb, 46 const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb,
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
88 cast_environment->PostTask( 93 cast_environment->PostTask(
89 CastEnvironment::MAIN, 94 CastEnvironment::MAIN,
90 FROM_HERE, 95 FROM_HERE,
91 base::Bind(initialization_cb, cast_initialization_status_)); 96 base::Bind(initialization_cb, cast_initialization_status_));
92 } 97 }
93 98
94 media::cast::CastTransportRtpConfig transport_config; 99 media::cast::CastTransportRtpConfig transport_config;
95 transport_config.ssrc = video_config.ssrc; 100 transport_config.ssrc = video_config.ssrc;
96 transport_config.feedback_ssrc = video_config.incoming_feedback_ssrc; 101 transport_config.feedback_ssrc = video_config.incoming_feedback_ssrc;
97 transport_config.rtp_payload_type = video_config.rtp_payload_type; 102 transport_config.rtp_payload_type = video_config.rtp_payload_type;
98 transport_config.stored_frames =
99 std::min(kMaxUnackedFrames,
100 1 + static_cast<int>(max_playout_delay_ *
101 max_frame_rate_ /
102 base::TimeDelta::FromSeconds(1)));
103 transport_config.aes_key = video_config.aes_key; 103 transport_config.aes_key = video_config.aes_key;
104 transport_config.aes_iv_mask = video_config.aes_iv_mask; 104 transport_config.aes_iv_mask = video_config.aes_iv_mask;
105 105
106 transport_sender->InitializeVideo( 106 transport_sender->InitializeVideo(
107 transport_config, 107 transport_config,
108 base::Bind(&VideoSender::OnReceivedCastFeedback, 108 base::Bind(&VideoSender::OnReceivedCastFeedback,
109 weak_factory_.GetWeakPtr()), 109 weak_factory_.GetWeakPtr()),
110 base::Bind(&VideoSender::OnMeasuredRoundTripTime, 110 base::Bind(&VideoSender::OnMeasuredRoundTripTime,
111 weak_factory_.GetWeakPtr())); 111 weak_factory_.GetWeakPtr()));
112 } 112 }
(...skipping 21 matching lines...) Expand all
134 rtp_timestamp, 134 rtp_timestamp,
135 kFrameIdUnknown); 135 kFrameIdUnknown);
136 136
137 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc 137 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc
138 TRACE_EVENT_INSTANT2( 138 TRACE_EVENT_INSTANT2(
139 "cast_perf_test", "InsertRawVideoFrame", 139 "cast_perf_test", "InsertRawVideoFrame",
140 TRACE_EVENT_SCOPE_THREAD, 140 TRACE_EVENT_SCOPE_THREAD,
141 "timestamp", capture_time.ToInternalValue(), 141 "timestamp", capture_time.ToInternalValue(),
142 "rtp_timestamp", rtp_timestamp); 142 "rtp_timestamp", rtp_timestamp);
143 143
144 if (ShouldDropNextFrame(capture_time)) { 144 // Drop frames that are out-of-order since the duration calculations assume
145 VLOG(1) << "Dropping frame due to too many frames currently in-flight."; 145 // frame timestamps are monotonically non-decreasing.
146 if (!last_enqueued_frame_reference_time_.is_null() &&
147 capture_time < last_enqueued_frame_reference_time_) {
hubbe 2014/09/18 17:56:05 We don't want frames where capture time is identic
miu 2014/09/18 21:38:43 Done.
148 VLOG(1) << "Dropping video frame: Reference time is out-of-order.";
149 return;
150 }
151
152 // Two video frames are needed to compute the exact media duration added by
153 // the next frame. If there are no frames in the encoder, compute a guess
154 // based on the configured |max_frame_rate_|. Any error introduced by this
155 // guess will be eliminated when |duration_in_encoder_| is updated in
156 // OnEncodedVideoFrame().
157 const base::TimeDelta duration_added_by_next_frame = frames_in_encoder_ > 0 ?
158 capture_time - last_enqueued_frame_reference_time_ :
159 base::TimeDelta::FromMicroseconds(1000000.0 / max_frame_rate_ + 0.5);
hubbe 2014/09/18 17:56:05 why + 0.5 ?
miu 2014/09/18 21:38:43 Rounding to nearest int. I made this more explici
hubbe 2014/09/18 22:22:59 Why not just use TimeDelta::FromSecondsD(1.0 / max
miu 2014/09/19 19:39:43 Because that would be the right way to do it. ;-)
160
161 if (ShouldDropNextFrame(duration_added_by_next_frame)) {
146 base::TimeDelta new_target_delay = std::min( 162 base::TimeDelta new_target_delay = std::min(
147 current_round_trip_time_ * kRoundTripsNeeded + 163 current_round_trip_time_ * kRoundTripsNeeded +
148 base::TimeDelta::FromMilliseconds(kConstantTimeMs), 164 base::TimeDelta::FromMilliseconds(kConstantTimeMs),
149 max_playout_delay_); 165 max_playout_delay_);
150 if (new_target_delay > target_playout_delay_) { 166 if (new_target_delay > target_playout_delay_) {
151 VLOG(1) << "New target delay: " << new_target_delay.InMilliseconds(); 167 VLOG(1) << "New target delay: " << new_target_delay.InMilliseconds();
152 playout_delay_change_cb_.Run(new_target_delay); 168 playout_delay_change_cb_.Run(new_target_delay);
153 } 169 }
154 return; 170 return;
155 } 171 }
156 172
157 uint32 bitrate = congestion_control_->GetBitrate( 173 uint32 bitrate = congestion_control_->GetBitrate(
158 capture_time + target_playout_delay_, target_playout_delay_); 174 capture_time + target_playout_delay_, target_playout_delay_);
159 if (bitrate != last_bitrate_) { 175 if (bitrate != last_bitrate_) {
160 video_encoder_->SetBitRate(bitrate); 176 video_encoder_->SetBitRate(bitrate);
161 last_bitrate_ = bitrate; 177 last_bitrate_ = bitrate;
162 } 178 }
163 179
164 if (video_encoder_->EncodeVideoFrame( 180 if (video_encoder_->EncodeVideoFrame(
165 video_frame, 181 video_frame,
166 capture_time, 182 capture_time,
167 base::Bind(&VideoSender::OnEncodedVideoFrame, 183 base::Bind(&VideoSender::OnEncodedVideoFrame,
168 weak_factory_.GetWeakPtr(), 184 weak_factory_.GetWeakPtr(),
169 bitrate))) { 185 bitrate))) {
170 frames_in_encoder_++; 186 frames_in_encoder_++;
187 duration_in_encoder_ += duration_added_by_next_frame;
188 last_enqueued_frame_reference_time_ = capture_time;
171 } else { 189 } else {
172 VLOG(1) << "Encoder rejected a frame. Skipping..."; 190 VLOG(1) << "Encoder rejected a frame. Skipping...";
173 } 191 }
174 } 192 }
175 193
176 int VideoSender::GetNumberOfFramesInEncoder() const { 194 int VideoSender::GetNumberOfFramesInEncoder() const {
177 return frames_in_encoder_; 195 return frames_in_encoder_;
178 } 196 }
179 197
198 base::TimeDelta VideoSender::GetInFlightMediaDuration() const {
199 if (GetUnacknowledgedFrameCount() > 0) {
200 const uint32 oldest_unacked_frame_id = latest_acked_frame_id_ + 1;
201 return duration_in_encoder_ +
hubbe 2014/09/18 17:56:05 Isn't this equivalent to: GetRecordedReferenceTim
miu 2014/09/18 21:38:43 Ah, good point. But, I think you meant: last_e
202 (GetRecordedReferenceTime(last_sent_frame_id_) -
203 GetRecordedReferenceTime(oldest_unacked_frame_id));
204 } else {
205 return duration_in_encoder_;
206 }
207 }
208
180 void VideoSender::OnAck(uint32 frame_id) { 209 void VideoSender::OnAck(uint32 frame_id) {
181 video_encoder_->LatestFrameIdToReference(frame_id); 210 video_encoder_->LatestFrameIdToReference(frame_id);
182 } 211 }
183 212
184 void VideoSender::OnEncoderInitialized( 213 void VideoSender::OnEncoderInitialized(
185 const CastInitializationCallback& initialization_cb, 214 const CastInitializationCallback& initialization_cb,
186 CastInitializationStatus status) { 215 CastInitializationStatus status) {
187 cast_initialization_status_ = status; 216 cast_initialization_status_ = status;
188 initialization_cb.Run(status); 217 initialization_cb.Run(status);
189 } 218 }
190 219
191 void VideoSender::OnEncodedVideoFrame( 220 void VideoSender::OnEncodedVideoFrame(
192 int encoder_bitrate, 221 int encoder_bitrate,
193 scoped_ptr<EncodedFrame> encoded_frame) { 222 scoped_ptr<EncodedFrame> encoded_frame) {
194 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 223 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
195 224
196 frames_in_encoder_--; 225 frames_in_encoder_--;
197 DCHECK_GE(frames_in_encoder_, 0); 226 DCHECK_GE(frames_in_encoder_, 0);
198 227
228 duration_in_encoder_ =
229 last_enqueued_frame_reference_time_ - encoded_frame->reference_time;
230
199 SendEncodedFrame(encoder_bitrate, encoded_frame.Pass()); 231 SendEncodedFrame(encoder_bitrate, encoded_frame.Pass());
200 } 232 }
201 233
202 } // namespace cast 234 } // namespace cast
203 } // namespace media 235 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698