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 <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 // The following two constants are used to adjust the target | |
23 // playout delay (when allowed). They were calculated using | |
24 // a combination of cast_benchmark runs and manual testing. | |
25 | |
26 // This is how many round trips we think we need on the network. | |
27 const int kRoundTripsNeeded = 4; | |
28 // This is an estimate of all the the constant time needed | |
Alpha Left Google
2014/09/11 20:33:44
There's an extra "needed" here. Please remove.
hubbe
2014/09/11 20:47:13
Done.
| |
29 // needed independent of network quality. | |
30 const int kConstantTimeMs = 75; | |
31 | |
22 // Note, we use a fixed bitrate value when external video encoder is used. | 32 // Note, we use a fixed bitrate value when external video encoder is used. |
23 // Some hardware encoder shows bad behavior if we set the bitrate too | 33 // Some hardware encoder shows bad behavior if we set the bitrate too |
24 // frequently, e.g. quality drop, not abiding by target bitrate, etc. | 34 // frequently, e.g. quality drop, not abiding by target bitrate, etc. |
25 // See details: crbug.com/392086. | 35 // See details: crbug.com/392086. |
26 VideoSender::VideoSender( | 36 VideoSender::VideoSender( |
27 scoped_refptr<CastEnvironment> cast_environment, | 37 scoped_refptr<CastEnvironment> cast_environment, |
28 const VideoSenderConfig& video_config, | 38 const VideoSenderConfig& video_config, |
29 const CastInitializationCallback& initialization_cb, | 39 const CastInitializationCallback& initialization_cb, |
30 const CreateVideoEncodeAcceleratorCallback& create_vea_cb, | 40 const CreateVideoEncodeAcceleratorCallback& create_vea_cb, |
31 const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb, | 41 const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb, |
32 CastTransportSender* const transport_sender) | 42 CastTransportSender* const transport_sender, |
43 const PlayoutDelayChangeCB& playout_delay_change_cb) | |
33 : FrameSender( | 44 : FrameSender( |
34 cast_environment, | 45 cast_environment, |
35 false, | 46 false, |
36 transport_sender, | 47 transport_sender, |
37 base::TimeDelta::FromMilliseconds(video_config.rtcp_interval), | 48 base::TimeDelta::FromMilliseconds(video_config.rtcp_interval), |
38 kVideoFrequency, | 49 kVideoFrequency, |
39 video_config.ssrc, | 50 video_config.ssrc, |
40 video_config.max_frame_rate, | 51 video_config.max_frame_rate, |
41 video_config.target_playout_delay, | 52 video_config.min_playout_delay, |
53 video_config.max_playout_delay, | |
42 NewFixedCongestionControl( | 54 NewFixedCongestionControl( |
43 (video_config.min_bitrate + video_config.max_bitrate) / 2)), | 55 (video_config.min_bitrate + video_config.max_bitrate) / 2)), |
44 frames_in_encoder_(0), | 56 frames_in_encoder_(0), |
45 last_bitrate_(0), | 57 last_bitrate_(0), |
58 playout_delay_change_cb_(playout_delay_change_cb), | |
46 weak_factory_(this) { | 59 weak_factory_(this) { |
47 cast_initialization_status_ = STATUS_VIDEO_UNINITIALIZED; | 60 cast_initialization_status_ = STATUS_VIDEO_UNINITIALIZED; |
48 VLOG(1) << "max_unacked_frames is " << max_unacked_frames_ | 61 VLOG(1) << "max_unacked_frames is " << max_unacked_frames_ |
49 << " for target_playout_delay=" | 62 << " for target_playout_delay=" |
50 << target_playout_delay_.InMilliseconds() << " ms" | 63 << target_playout_delay_.InMilliseconds() << " ms" |
51 << " and max_frame_rate=" << video_config.max_frame_rate; | 64 << " and max_frame_rate=" << video_config.max_frame_rate; |
52 DCHECK_GT(max_unacked_frames_, 0); | 65 DCHECK_GT(max_unacked_frames_, 0); |
53 | 66 |
54 if (video_config.use_external_encoder) { | 67 if (video_config.use_external_encoder) { |
55 video_encoder_.reset(new ExternalVideoEncoder( | 68 video_encoder_.reset(new ExternalVideoEncoder( |
(...skipping 19 matching lines...) Expand all Loading... | |
75 cast_environment->PostTask( | 88 cast_environment->PostTask( |
76 CastEnvironment::MAIN, | 89 CastEnvironment::MAIN, |
77 FROM_HERE, | 90 FROM_HERE, |
78 base::Bind(initialization_cb, cast_initialization_status_)); | 91 base::Bind(initialization_cb, cast_initialization_status_)); |
79 } | 92 } |
80 | 93 |
81 media::cast::CastTransportRtpConfig transport_config; | 94 media::cast::CastTransportRtpConfig transport_config; |
82 transport_config.ssrc = video_config.ssrc; | 95 transport_config.ssrc = video_config.ssrc; |
83 transport_config.feedback_ssrc = video_config.incoming_feedback_ssrc; | 96 transport_config.feedback_ssrc = video_config.incoming_feedback_ssrc; |
84 transport_config.rtp_payload_type = video_config.rtp_payload_type; | 97 transport_config.rtp_payload_type = video_config.rtp_payload_type; |
85 transport_config.stored_frames = max_unacked_frames_; | 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))); | |
86 transport_config.aes_key = video_config.aes_key; | 103 transport_config.aes_key = video_config.aes_key; |
87 transport_config.aes_iv_mask = video_config.aes_iv_mask; | 104 transport_config.aes_iv_mask = video_config.aes_iv_mask; |
88 | 105 |
89 transport_sender->InitializeVideo( | 106 transport_sender->InitializeVideo( |
90 transport_config, | 107 transport_config, |
91 base::Bind(&VideoSender::OnReceivedCastFeedback, | 108 base::Bind(&VideoSender::OnReceivedCastFeedback, |
92 weak_factory_.GetWeakPtr()), | 109 weak_factory_.GetWeakPtr()), |
93 base::Bind(&VideoSender::OnMeasuredRoundTripTime, | 110 base::Bind(&VideoSender::OnMeasuredRoundTripTime, |
94 weak_factory_.GetWeakPtr())); | 111 weak_factory_.GetWeakPtr())); |
95 } | 112 } |
(...skipping 23 matching lines...) Expand all Loading... | |
119 | 136 |
120 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc | 137 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc |
121 TRACE_EVENT_INSTANT2( | 138 TRACE_EVENT_INSTANT2( |
122 "cast_perf_test", "InsertRawVideoFrame", | 139 "cast_perf_test", "InsertRawVideoFrame", |
123 TRACE_EVENT_SCOPE_THREAD, | 140 TRACE_EVENT_SCOPE_THREAD, |
124 "timestamp", capture_time.ToInternalValue(), | 141 "timestamp", capture_time.ToInternalValue(), |
125 "rtp_timestamp", rtp_timestamp); | 142 "rtp_timestamp", rtp_timestamp); |
126 | 143 |
127 if (ShouldDropNextFrame(capture_time)) { | 144 if (ShouldDropNextFrame(capture_time)) { |
128 VLOG(1) << "Dropping frame due to too many frames currently in-flight."; | 145 VLOG(1) << "Dropping frame due to too many frames currently in-flight."; |
146 base::TimeDelta new_target_delay = std::min( | |
147 current_round_trip_time_ * kRoundTripsNeeded + | |
148 base::TimeDelta::FromMilliseconds(kConstantTimeMs), | |
149 max_playout_delay_); | |
150 if (new_target_delay > target_playout_delay_) { | |
151 VLOG(1) << "New target delay: " << new_target_delay.InMilliseconds(); | |
152 playout_delay_change_cb_.Run(new_target_delay); | |
153 } | |
129 return; | 154 return; |
130 } | 155 } |
131 | 156 |
132 uint32 bitrate = congestion_control_->GetBitrate( | 157 uint32 bitrate = congestion_control_->GetBitrate( |
133 capture_time + target_playout_delay_, target_playout_delay_); | 158 capture_time + target_playout_delay_, target_playout_delay_); |
134 if (bitrate != last_bitrate_) { | 159 if (bitrate != last_bitrate_) { |
135 video_encoder_->SetBitRate(bitrate); | 160 video_encoder_->SetBitRate(bitrate); |
136 last_bitrate_ = bitrate; | 161 last_bitrate_ = bitrate; |
137 } | 162 } |
138 | 163 |
(...skipping 30 matching lines...) Expand all Loading... | |
169 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 194 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
170 | 195 |
171 frames_in_encoder_--; | 196 frames_in_encoder_--; |
172 DCHECK_GE(frames_in_encoder_, 0); | 197 DCHECK_GE(frames_in_encoder_, 0); |
173 | 198 |
174 SendEncodedFrame(encoder_bitrate, encoded_frame.Pass()); | 199 SendEncodedFrame(encoder_bitrate, encoded_frame.Pass()); |
175 } | 200 } |
176 | 201 |
177 } // namespace cast | 202 } // namespace cast |
178 } // namespace media | 203 } // namespace media |
OLD | NEW |