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 "chrome/renderer/media/cast_rtp_stream.h" | 5 #include "chrome/renderer/media/cast_rtp_stream.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <memory> | 10 #include <memory> |
11 #include <utility> | 11 #include <utility> |
12 | 12 |
13 #include "base/bind.h" | 13 #include "base/bind.h" |
14 #include "base/bind_helpers.h" | 14 #include "base/bind_helpers.h" |
15 #include "base/callback_helpers.h" | 15 #include "base/callback_helpers.h" |
16 #include "base/command_line.h" | 16 #include "base/command_line.h" |
17 #include "base/logging.h" | 17 #include "base/logging.h" |
18 #include "base/macros.h" | 18 #include "base/macros.h" |
19 #include "base/memory/ref_counted.h" | 19 #include "base/memory/ref_counted.h" |
20 #include "base/memory/weak_ptr.h" | 20 #include "base/memory/weak_ptr.h" |
21 #include "base/strings/stringprintf.h" | 21 #include "base/strings/stringprintf.h" |
22 #include "base/sys_info.h" | |
23 #include "base/threading/thread_task_runner_handle.h" | 22 #include "base/threading/thread_task_runner_handle.h" |
24 #include "base/timer/timer.h" | 23 #include "base/timer/timer.h" |
25 #include "base/trace_event/trace_event.h" | 24 #include "base/trace_event/trace_event.h" |
26 #include "chrome/common/chrome_switches.h" | 25 #include "chrome/common/chrome_switches.h" |
27 #include "chrome/renderer/media/cast_session.h" | 26 #include "chrome/renderer/media/cast_session.h" |
28 #include "chrome/renderer/media/cast_udp_transport.h" | 27 #include "chrome/renderer/media/cast_udp_transport.h" |
29 #include "content/public/renderer/media_stream_audio_sink.h" | 28 #include "content/public/renderer/media_stream_audio_sink.h" |
30 #include "content/public/renderer/media_stream_utils.h" | 29 #include "content/public/renderer/media_stream_utils.h" |
31 #include "content/public/renderer/media_stream_video_sink.h" | 30 #include "content/public/renderer/media_stream_video_sink.h" |
32 #include "content/public/renderer/render_thread.h" | 31 #include "content/public/renderer/render_thread.h" |
33 #include "content/public/renderer/video_encode_accelerator.h" | 32 #include "content/public/renderer/video_encode_accelerator.h" |
34 #include "media/base/audio_bus.h" | 33 #include "media/base/audio_bus.h" |
35 #include "media/base/audio_converter.h" | 34 #include "media/base/audio_converter.h" |
36 #include "media/base/audio_parameters.h" | 35 #include "media/base/audio_parameters.h" |
37 #include "media/base/bind_to_current_loop.h" | 36 #include "media/base/bind_to_current_loop.h" |
38 #include "media/base/limits.h" | 37 #include "media/base/limits.h" |
39 #include "media/base/video_frame.h" | 38 #include "media/base/video_frame.h" |
40 #include "media/base/video_util.h" | 39 #include "media/base/video_util.h" |
41 #include "media/cast/cast_config.h" | 40 #include "media/cast/cast_config.h" |
42 #include "media/cast/cast_sender.h" | 41 #include "media/cast/cast_sender.h" |
43 #include "media/cast/net/cast_transport_config.h" | 42 #include "media/cast/net/cast_transport_config.h" |
44 #include "third_party/WebKit/public/platform/WebMediaStreamSource.h" | 43 #include "third_party/WebKit/public/platform/WebMediaStreamSource.h" |
45 #include "ui/gfx/geometry/size.h" | 44 #include "ui/gfx/geometry/size.h" |
46 | 45 |
47 using media::cast::AudioSenderConfig; | 46 using media::cast::FrameSenderConfig; |
48 using media::cast::VideoSenderConfig; | |
49 | 47 |
50 namespace { | 48 namespace { |
51 | 49 |
52 const char kCodecNameOpus[] = "OPUS"; | |
53 const char kCodecNameVp8[] = "VP8"; | |
54 const char kCodecNameH264[] = "H264"; | |
55 | |
56 // To convert from kilobits per second to bits to per second. | |
57 const int kBitrateMultiplier = 1000; | |
58 | |
59 // The maximum number of milliseconds that should elapse since the last video | 50 // The maximum number of milliseconds that should elapse since the last video |
60 // frame was received from the video source, before requesting refresh frames. | 51 // frame was received from the video source, before requesting refresh frames. |
61 const int kRefreshIntervalMilliseconds = 250; | 52 const int kRefreshIntervalMilliseconds = 250; |
62 | 53 |
63 // The maximum number of refresh video frames to request/receive. After this | 54 // The maximum number of refresh video frames to request/receive. After this |
64 // limit (60 * 250ms = 15 seconds), refresh frame requests will stop being made. | 55 // limit (60 * 250ms = 15 seconds), refresh frame requests will stop being made. |
65 const int kMaxConsecutiveRefreshFrames = 60; | 56 const int kMaxConsecutiveRefreshFrames = 60; |
66 | 57 |
67 CastRtpPayloadParams DefaultOpusPayload() { | 58 FrameSenderConfig DefaultOpusConfig() { |
68 CastRtpPayloadParams payload; | 59 FrameSenderConfig config; |
69 payload.payload_type = media::cast::kDefaultRtpAudioPayloadType; | 60 config.rtp_payload_type = media::cast::RtpPayloadType::AUDIO_OPUS; |
70 payload.max_latency_ms = media::cast::kDefaultRtpMaxDelayMs; | 61 config.max_playout_delay = |
71 payload.ssrc = 1; | 62 base::TimeDelta::FromMilliseconds(media::cast::kDefaultRtpMaxDelayMs); |
72 payload.feedback_ssrc = 2; | 63 config.sender_ssrc = 1; |
73 payload.clock_rate = media::cast::kDefaultAudioSamplingRate; | 64 config.receiver_ssrc = 2; |
65 config.frequency = media::cast::kDefaultAudioSamplingRate; | |
74 // The value is 0 which means VBR. | 66 // The value is 0 which means VBR. |
75 payload.min_bitrate = payload.max_bitrate = | 67 config.min_bitrate = config.max_bitrate = |
miu
2016/06/30 21:59:43
and start_bitrate (per comment in cast_config.h)
xjz
2016/07/01 23:52:09
Done.
| |
76 media::cast::kDefaultAudioEncoderBitrate; | 68 media::cast::kDefaultAudioEncoderBitrate; |
77 payload.channels = 2; | 69 config.channels = 2; |
78 payload.max_frame_rate = 100; // 10 ms audio frames | 70 config.max_frame_rate = 100; // 10 ms audio frames |
79 payload.codec_name = kCodecNameOpus; | 71 config.codec = media::cast::CODEC_AUDIO_OPUS; |
80 return payload; | 72 return config; |
81 } | 73 } |
82 | 74 |
83 CastRtpPayloadParams DefaultVp8Payload() { | 75 FrameSenderConfig DefaultVp8Config() { |
84 CastRtpPayloadParams payload; | 76 FrameSenderConfig config; |
85 payload.payload_type = media::cast::kDefaultRtpVideoPayloadType; | 77 config.rtp_payload_type = media::cast::RtpPayloadType::VIDEO_VP8; |
86 payload.max_latency_ms = media::cast::kDefaultRtpMaxDelayMs; | 78 config.max_playout_delay = |
miu
2016/06/30 21:59:42
You could omit this, since we set this default in
xjz
2016/07/01 23:52:09
Done.
| |
87 payload.ssrc = 11; | 79 base::TimeDelta::FromMilliseconds(media::cast::kDefaultRtpMaxDelayMs); |
88 payload.feedback_ssrc = 12; | 80 config.sender_ssrc = 11; |
89 payload.clock_rate = media::cast::kVideoFrequency; | 81 config.receiver_ssrc = 12; |
90 payload.max_bitrate = media::cast::kDefaultMaxVideoKbps; | 82 config.frequency = media::cast::kVideoFrequency; |
91 payload.min_bitrate = media::cast::kDefaultMinVideoKbps; | 83 config.max_bitrate = media::cast::kDefaultMaxVideoKbps; |
92 payload.channels = 1; | 84 config.min_bitrate = media::cast::kDefaultMinVideoKbps; |
93 payload.max_frame_rate = media::cast::kDefaultMaxFrameRate; | 85 config.channels = 1; |
miu
2016/06/30 21:59:43
nit: Can you move this to be just before max_bitra
xjz
2016/07/01 23:52:09
Done.
| |
94 payload.codec_name = kCodecNameVp8; | 86 config.max_frame_rate = media::cast::kDefaultMaxFrameRate; |
95 return payload; | 87 config.codec = media::cast::CODEC_VIDEO_VP8; |
88 return config; | |
96 } | 89 } |
97 | 90 |
98 CastRtpPayloadParams DefaultH264Payload() { | 91 FrameSenderConfig DefaultH264Config() { |
99 CastRtpPayloadParams payload; | 92 FrameSenderConfig config; |
100 payload.payload_type = 96; | 93 config.rtp_payload_type = media::cast::RtpPayloadType::VIDEO_H264; |
101 payload.max_latency_ms = media::cast::kDefaultRtpMaxDelayMs; | 94 config.max_playout_delay = |
102 payload.ssrc = 11; | 95 base::TimeDelta::FromMilliseconds(media::cast::kDefaultRtpMaxDelayMs); |
103 payload.feedback_ssrc = 12; | 96 config.sender_ssrc = 11; |
104 payload.clock_rate = media::cast::kVideoFrequency; | 97 config.receiver_ssrc = 12; |
105 payload.max_bitrate = media::cast::kDefaultMaxVideoKbps; | 98 config.frequency = media::cast::kVideoFrequency; |
106 payload.min_bitrate = media::cast::kDefaultMinVideoKbps; | 99 config.max_bitrate = media::cast::kDefaultMaxVideoKbps; |
107 payload.channels = 1; | 100 config.min_bitrate = media::cast::kDefaultMinVideoKbps; |
108 payload.max_frame_rate = media::cast::kDefaultMaxFrameRate; | 101 config.channels = 1; |
109 payload.codec_name = kCodecNameH264; | 102 config.max_frame_rate = media::cast::kDefaultMaxFrameRate; |
110 return payload; | 103 config.codec = media::cast::CODEC_VIDEO_H264; |
104 return config; | |
111 } | 105 } |
112 | 106 |
113 bool IsHardwareVP8EncodingSupported() { | 107 std::vector<FrameSenderConfig> SupportedAudioConfigs() { |
114 const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); | 108 // TODO(hclam): Fill in more codecs here. |
115 if (cmd_line->HasSwitch(switches::kDisableCastStreamingHWEncoding)) { | 109 return std::vector<FrameSenderConfig>(1, DefaultOpusConfig()); |
116 DVLOG(1) << "Disabled hardware VP8 support for Cast Streaming."; | |
117 return false; | |
118 } | |
119 | |
120 // Query for hardware VP8 encoder support. | |
121 const std::vector<media::VideoEncodeAccelerator::SupportedProfile> | |
122 vea_profiles = content::GetSupportedVideoEncodeAcceleratorProfiles(); | |
123 for (const auto& vea_profile : vea_profiles) { | |
124 if (vea_profile.profile >= media::VP8PROFILE_MIN && | |
125 vea_profile.profile <= media::VP8PROFILE_MAX) { | |
126 return true; | |
127 } | |
128 } | |
129 return false; | |
130 } | 110 } |
131 | 111 |
132 bool IsHardwareH264EncodingSupported() { | 112 std::vector<FrameSenderConfig> SupportedVideoConfigs() { |
133 const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); | 113 std::vector<FrameSenderConfig> supported_configs; |
134 if (cmd_line->HasSwitch(switches::kDisableCastStreamingHWEncoding)) { | |
135 DVLOG(1) << "Disabled hardware h264 support for Cast Streaming."; | |
136 return false; | |
137 } | |
138 | |
139 // Query for hardware H.264 encoder support. | |
140 // | |
141 // TODO(miu): Look into why H.264 hardware encoder on MacOS is broken. | |
142 // http://crbug.com/596674 | |
143 #if !defined(OS_MACOSX) | |
144 const std::vector<media::VideoEncodeAccelerator::SupportedProfile> | |
145 vea_profiles = content::GetSupportedVideoEncodeAcceleratorProfiles(); | |
146 for (const auto& vea_profile : vea_profiles) { | |
147 if (vea_profile.profile >= media::H264PROFILE_MIN && | |
148 vea_profile.profile <= media::H264PROFILE_MAX) { | |
149 return true; | |
150 } | |
151 } | |
152 #endif // !defined(OS_MACOSX) | |
153 return false; | |
154 } | |
155 | |
156 int NumberOfEncodeThreads() { | |
157 // Do not saturate CPU utilization just for encoding. On a lower-end system | |
158 // with only 1 or 2 cores, use only one thread for encoding. On systems with | |
159 // more cores, allow half of the cores to be used for encoding. | |
160 return std::min(8, (base::SysInfo::NumberOfProcessors() + 1) / 2); | |
161 } | |
162 | |
163 std::vector<CastRtpParams> SupportedAudioParams() { | |
164 // TODO(hclam): Fill in more codecs here. | |
165 return std::vector<CastRtpParams>(1, CastRtpParams(DefaultOpusPayload())); | |
166 } | |
167 | |
168 std::vector<CastRtpParams> SupportedVideoParams() { | |
169 std::vector<CastRtpParams> supported_params; | |
170 | 114 |
171 // Prefer VP8 over H.264 for hardware encoder. | 115 // Prefer VP8 over H.264 for hardware encoder. |
172 if (IsHardwareVP8EncodingSupported()) | 116 if (CastRtpStream::IsHardwareVP8EncodingSupported()) |
173 supported_params.push_back(CastRtpParams(DefaultVp8Payload())); | 117 supported_configs.push_back(DefaultVp8Config()); |
174 if (IsHardwareH264EncodingSupported()) | 118 if (CastRtpStream::IsHardwareH264EncodingSupported()) |
175 supported_params.push_back(CastRtpParams(DefaultH264Payload())); | 119 supported_configs.push_back(DefaultH264Config()); |
176 | 120 |
177 // Propose the default software VP8 encoder, if no hardware encoders are | 121 // Propose the default software VP8 encoder, if no hardware encoders are |
178 // available. | 122 // available. |
179 if (supported_params.empty()) | 123 if (supported_configs.empty()) |
180 supported_params.push_back(CastRtpParams(DefaultVp8Payload())); | 124 supported_configs.push_back(DefaultVp8Config()); |
181 | 125 |
182 return supported_params; | 126 return supported_configs; |
183 } | |
184 | |
185 bool ToAudioSenderConfig(const CastRtpParams& params, | |
186 AudioSenderConfig* config) { | |
187 config->ssrc = params.payload.ssrc; | |
188 config->receiver_ssrc = params.payload.feedback_ssrc; | |
189 if (config->ssrc == config->receiver_ssrc) { | |
190 DVLOG(1) << "ssrc " << config->ssrc << " cannot be equal to receiver_ssrc"; | |
191 return false; | |
192 } | |
193 config->min_playout_delay = base::TimeDelta::FromMilliseconds( | |
194 params.payload.min_latency_ms ? | |
195 params.payload.min_latency_ms : | |
196 params.payload.max_latency_ms); | |
197 config->max_playout_delay = | |
198 base::TimeDelta::FromMilliseconds(params.payload.max_latency_ms); | |
199 config->animated_playout_delay = base::TimeDelta::FromMilliseconds( | |
200 params.payload.animated_latency_ms ? params.payload.animated_latency_ms | |
201 : params.payload.max_latency_ms); | |
202 if (config->min_playout_delay <= base::TimeDelta()) { | |
203 DVLOG(1) << "min_playout_delay " << config->min_playout_delay | |
204 << " is too small"; | |
205 return false; | |
206 } | |
207 if (config->min_playout_delay > config->max_playout_delay) { | |
208 DVLOG(1) << "min_playout_delay " << config->min_playout_delay | |
209 << " is too big"; | |
210 return false; | |
211 } | |
212 if (config->animated_playout_delay < config->min_playout_delay || | |
213 config->animated_playout_delay > config->max_playout_delay) { | |
214 DVLOG(1) << "animated_playout_delay " << config->animated_playout_delay | |
215 << " is out of range"; | |
216 return false; | |
217 } | |
218 config->rtp_payload_type = params.payload.payload_type; | |
219 config->use_external_encoder = false; | |
220 config->frequency = params.payload.clock_rate; | |
221 // Sampling rate must be one of the Opus-supported values. | |
222 switch (config->frequency) { | |
223 case 48000: | |
224 case 24000: | |
225 case 16000: | |
226 case 12000: | |
227 case 8000: | |
228 break; | |
229 default: | |
230 DVLOG(1) << "frequency " << config->frequency << " is invalid"; | |
231 return false; | |
232 } | |
233 config->channels = params.payload.channels; | |
234 if (config->channels < 1) { | |
235 DVLOG(1) << "channels " << config->channels << " is invalid"; | |
236 return false; | |
237 } | |
238 config->bitrate = params.payload.max_bitrate * kBitrateMultiplier; | |
239 if (params.payload.codec_name == kCodecNameOpus) { | |
240 config->codec = media::cast::CODEC_AUDIO_OPUS; | |
241 } else { | |
242 DVLOG(1) << "codec_name " << params.payload.codec_name << " is invalid"; | |
243 return false; | |
244 } | |
245 config->aes_key = params.payload.aes_key; | |
246 config->aes_iv_mask = params.payload.aes_iv_mask; | |
247 return true; | |
248 } | |
249 | |
250 bool ToVideoSenderConfig(const CastRtpParams& params, | |
251 VideoSenderConfig* config) { | |
252 config->ssrc = params.payload.ssrc; | |
253 config->receiver_ssrc = params.payload.feedback_ssrc; | |
254 if (config->ssrc == config->receiver_ssrc) { | |
255 DVLOG(1) << "ssrc " << config->ssrc << " cannot be equal to receiver_ssrc"; | |
256 return false; | |
257 } | |
258 config->min_playout_delay = base::TimeDelta::FromMilliseconds( | |
259 params.payload.min_latency_ms ? | |
260 params.payload.min_latency_ms : | |
261 params.payload.max_latency_ms); | |
262 config->max_playout_delay = | |
263 base::TimeDelta::FromMilliseconds(params.payload.max_latency_ms); | |
264 config->animated_playout_delay = base::TimeDelta::FromMilliseconds( | |
265 params.payload.animated_latency_ms ? params.payload.animated_latency_ms | |
266 : params.payload.max_latency_ms); | |
267 if (config->min_playout_delay <= base::TimeDelta()) { | |
268 DVLOG(1) << "min_playout_delay " << config->min_playout_delay | |
269 << " is too small"; | |
270 return false; | |
271 } | |
272 if (config->min_playout_delay > config->max_playout_delay) { | |
273 DVLOG(1) << "min_playout_delay " << config->min_playout_delay | |
274 << " is too big"; | |
275 return false; | |
276 } | |
277 if (config->animated_playout_delay < config->min_playout_delay || | |
278 config->animated_playout_delay > config->max_playout_delay) { | |
279 DVLOG(1) << "animated_playout_delay " << config->animated_playout_delay | |
280 << " is out of range"; | |
281 return false; | |
282 } | |
283 config->rtp_payload_type = params.payload.payload_type; | |
284 config->min_bitrate = config->start_bitrate = | |
285 params.payload.min_bitrate * kBitrateMultiplier; | |
286 config->max_bitrate = params.payload.max_bitrate * kBitrateMultiplier; | |
287 if (config->min_bitrate > config->max_bitrate) { | |
288 DVLOG(1) << "min_bitrate " << config->min_bitrate << " is larger than " | |
289 << "max_bitrate " << config->max_bitrate; | |
290 return false; | |
291 } | |
292 config->start_bitrate = config->min_bitrate; | |
293 config->max_frame_rate = static_cast<int>( | |
294 std::max(1.0, params.payload.max_frame_rate) + 0.5); | |
295 if (config->max_frame_rate > media::limits::kMaxFramesPerSecond) { | |
296 DVLOG(1) << "max_frame_rate " << config->max_frame_rate << " is invalid"; | |
297 return false; | |
298 } | |
299 if (params.payload.codec_name == kCodecNameVp8) { | |
300 config->use_external_encoder = IsHardwareVP8EncodingSupported(); | |
301 config->codec = media::cast::CODEC_VIDEO_VP8; | |
302 } else if (params.payload.codec_name == kCodecNameH264) { | |
303 config->use_external_encoder = IsHardwareH264EncodingSupported(); | |
304 config->codec = media::cast::CODEC_VIDEO_H264; | |
305 } else { | |
306 DVLOG(1) << "codec_name " << params.payload.codec_name << " is invalid"; | |
307 return false; | |
308 } | |
309 if (!config->use_external_encoder) | |
310 config->number_of_encode_threads = NumberOfEncodeThreads(); | |
311 config->aes_key = params.payload.aes_key; | |
312 config->aes_iv_mask = params.payload.aes_iv_mask; | |
313 return true; | |
314 } | 127 } |
315 | 128 |
316 } // namespace | 129 } // namespace |
317 | 130 |
318 // This class receives MediaStreamTrack events and video frames from a | 131 // This class receives MediaStreamTrack events and video frames from a |
319 // MediaStreamVideoTrack. It also includes a timer to request refresh frames | 132 // MediaStreamVideoTrack. It also includes a timer to request refresh frames |
320 // when the capturer halts (e.g., a screen capturer stops delivering frames | 133 // when the capturer halts (e.g., a screen capturer stops delivering frames |
321 // because the screen is not being updated). When a halt is detected, refresh | 134 // because the screen is not being updated). When a halt is detected, refresh |
322 // frames will be requested at regular intervals for a short period of time. | 135 // frames will be requested at regular intervals for a short period of time. |
323 // This provides the video encoder, downstream, several copies of the last frame | 136 // This provides the video encoder, downstream, several copies of the last frame |
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
588 // These members are accessed on the real-time audio time only. | 401 // These members are accessed on the real-time audio time only. |
589 media::AudioParameters input_params_; | 402 media::AudioParameters input_params_; |
590 std::unique_ptr<media::AudioConverter> converter_; | 403 std::unique_ptr<media::AudioConverter> converter_; |
591 const media::AudioBus* current_input_bus_; | 404 const media::AudioBus* current_input_bus_; |
592 int64_t sample_frames_in_; | 405 int64_t sample_frames_in_; |
593 int64_t sample_frames_out_; | 406 int64_t sample_frames_out_; |
594 | 407 |
595 DISALLOW_COPY_AND_ASSIGN(CastAudioSink); | 408 DISALLOW_COPY_AND_ASSIGN(CastAudioSink); |
596 }; | 409 }; |
597 | 410 |
598 CastRtpParams::CastRtpParams(const CastRtpPayloadParams& payload_params) | 411 bool CastRtpStream::IsHardwareVP8EncodingSupported() { |
599 : payload(payload_params) {} | 412 const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); |
413 if (cmd_line->HasSwitch(switches::kDisableCastStreamingHWEncoding)) { | |
414 DVLOG(1) << "Disabled hardware VP8 support for Cast Streaming."; | |
415 return false; | |
416 } | |
600 | 417 |
601 CastCodecSpecificParams::CastCodecSpecificParams() {} | 418 // Query for hardware VP8 encoder support. |
602 | 419 const std::vector<media::VideoEncodeAccelerator::SupportedProfile> |
603 CastCodecSpecificParams::~CastCodecSpecificParams() {} | 420 vea_profiles = content::GetSupportedVideoEncodeAcceleratorProfiles(); |
604 | 421 for (const auto& vea_profile : vea_profiles) { |
605 CastRtpPayloadParams::CastRtpPayloadParams() | 422 if (vea_profile.profile >= media::VP8PROFILE_MIN && |
606 : payload_type(0), | 423 vea_profile.profile <= media::VP8PROFILE_MAX) { |
607 max_latency_ms(0), | 424 return true; |
608 min_latency_ms(0), | 425 } |
609 ssrc(0), | 426 } |
610 feedback_ssrc(0), | 427 return false; |
611 clock_rate(0), | |
612 max_bitrate(0), | |
613 min_bitrate(0), | |
614 channels(0), | |
615 max_frame_rate(0.0) { | |
616 } | 428 } |
617 | 429 |
618 CastRtpPayloadParams::CastRtpPayloadParams(const CastRtpPayloadParams& other) = | 430 bool CastRtpStream::IsHardwareH264EncodingSupported() { |
619 default; | 431 const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); |
432 if (cmd_line->HasSwitch(switches::kDisableCastStreamingHWEncoding)) { | |
433 DVLOG(1) << "Disabled hardware h264 support for Cast Streaming."; | |
434 return false; | |
435 } | |
620 | 436 |
621 CastRtpPayloadParams::~CastRtpPayloadParams() {} | 437 // Query for hardware H.264 encoder support. |
622 | 438 // |
623 CastRtpParams::CastRtpParams() {} | 439 // TODO(miu): Look into why H.264 hardware encoder on MacOS is broken. |
624 | 440 // http://crbug.com/596674 |
625 CastRtpParams::CastRtpParams(const CastRtpParams& other) = default; | 441 #if !defined(OS_MACOSX) |
626 | 442 const std::vector<media::VideoEncodeAccelerator::SupportedProfile> |
627 CastRtpParams::~CastRtpParams() {} | 443 vea_profiles = content::GetSupportedVideoEncodeAcceleratorProfiles(); |
444 for (const auto& vea_profile : vea_profiles) { | |
445 if (vea_profile.profile >= media::H264PROFILE_MIN && | |
446 vea_profile.profile <= media::H264PROFILE_MAX) { | |
447 return true; | |
448 } | |
449 } | |
450 #endif // !defined(OS_MACOSX) | |
451 return false; | |
452 } | |
628 | 453 |
629 CastRtpStream::CastRtpStream(const blink::WebMediaStreamTrack& track, | 454 CastRtpStream::CastRtpStream(const blink::WebMediaStreamTrack& track, |
630 const scoped_refptr<CastSession>& session) | 455 const scoped_refptr<CastSession>& session) |
631 : track_(track), cast_session_(session), weak_factory_(this) {} | 456 : track_(track), cast_session_(session), weak_factory_(this) {} |
632 | 457 |
633 CastRtpStream::~CastRtpStream() { | 458 CastRtpStream::~CastRtpStream() { |
634 Stop(); | 459 Stop(); |
635 } | 460 } |
636 | 461 |
637 std::vector<CastRtpParams> CastRtpStream::GetSupportedParams() { | 462 std::vector<FrameSenderConfig> CastRtpStream::GetSupportedConfigs() { |
638 if (IsAudio()) | 463 if (IsAudio()) |
639 return SupportedAudioParams(); | 464 return SupportedAudioConfigs(); |
640 else | 465 else |
641 return SupportedVideoParams(); | 466 return SupportedVideoConfigs(); |
642 } | 467 } |
643 | 468 |
644 CastRtpParams CastRtpStream::GetParams() { return params_; } | 469 void CastRtpStream::Start(const FrameSenderConfig& config, |
645 | |
646 void CastRtpStream::Start(const CastRtpParams& params, | |
647 const base::Closure& start_callback, | 470 const base::Closure& start_callback, |
648 const base::Closure& stop_callback, | 471 const base::Closure& stop_callback, |
649 const ErrorCallback& error_callback) { | 472 const ErrorCallback& error_callback) { |
650 DCHECK(!start_callback.is_null()); | 473 DCHECK(!start_callback.is_null()); |
651 DCHECK(!stop_callback.is_null()); | 474 DCHECK(!stop_callback.is_null()); |
652 DCHECK(!error_callback.is_null()); | 475 DCHECK(!error_callback.is_null()); |
653 | 476 |
654 DVLOG(1) << "CastRtpStream::Start = " << (IsAudio() ? "audio" : "video"); | 477 DVLOG(1) << "CastRtpStream::Start = " << (IsAudio() ? "audio" : "video"); |
655 stop_callback_ = stop_callback; | 478 stop_callback_ = stop_callback; |
656 error_callback_ = error_callback; | 479 error_callback_ = error_callback; |
657 | 480 |
658 if (IsAudio()) { | 481 if (IsAudio()) { |
659 AudioSenderConfig config; | |
660 if (!ToAudioSenderConfig(params, &config)) { | |
661 DidEncounterError("Invalid parameters for audio."); | |
662 return; | |
663 } | |
664 | |
665 // In case of error we have to go through DidEncounterError() to stop | 482 // In case of error we have to go through DidEncounterError() to stop |
666 // the streaming after reporting the error. | 483 // the streaming after reporting the error. |
667 audio_sink_.reset(new CastAudioSink( | 484 audio_sink_.reset( |
668 track_, | 485 new CastAudioSink(track_, config.channels, config.frequency)); |
669 params.payload.channels, | |
670 params.payload.clock_rate)); | |
671 cast_session_->StartAudio( | 486 cast_session_->StartAudio( |
672 config, | 487 config, |
673 base::Bind(&CastAudioSink::AddToTrack, audio_sink_->AsWeakPtr()), | 488 base::Bind(&CastAudioSink::AddToTrack, audio_sink_->AsWeakPtr()), |
674 base::Bind(&CastRtpStream::DidEncounterError, | 489 base::Bind(&CastRtpStream::DidEncounterError, |
675 weak_factory_.GetWeakPtr())); | 490 weak_factory_.GetWeakPtr())); |
676 start_callback.Run(); | 491 start_callback.Run(); |
677 } else { | 492 } else { |
678 VideoSenderConfig config; | |
679 if (!ToVideoSenderConfig(params, &config)) { | |
680 DidEncounterError("Invalid parameters for video."); | |
681 return; | |
682 } | |
683 // See the code for audio above for explanation of callbacks. | 493 // See the code for audio above for explanation of callbacks. |
684 video_sink_.reset(new CastVideoSink( | 494 video_sink_.reset(new CastVideoSink( |
685 track_, | 495 track_, |
686 media::BindToCurrentLoop(base::Bind(&CastRtpStream::DidEncounterError, | 496 media::BindToCurrentLoop(base::Bind(&CastRtpStream::DidEncounterError, |
687 weak_factory_.GetWeakPtr())))); | 497 weak_factory_.GetWeakPtr())))); |
688 cast_session_->StartVideo( | 498 cast_session_->StartVideo( |
689 config, base::Bind(&CastVideoSink::AddToTrack, video_sink_->AsWeakPtr(), | 499 config, base::Bind(&CastVideoSink::AddToTrack, video_sink_->AsWeakPtr(), |
690 !params.payload.aes_key.empty()), | 500 !config.aes_key.empty()), |
691 base::Bind(&CastRtpStream::DidEncounterError, | 501 base::Bind(&CastRtpStream::DidEncounterError, |
692 weak_factory_.GetWeakPtr())); | 502 weak_factory_.GetWeakPtr())); |
693 start_callback.Run(); | 503 start_callback.Run(); |
694 } | 504 } |
695 } | 505 } |
696 | 506 |
697 void CastRtpStream::Stop() { | 507 void CastRtpStream::Stop() { |
698 DVLOG(1) << "CastRtpStream::Stop = " << (IsAudio() ? "audio" : "video"); | 508 DVLOG(1) << "CastRtpStream::Stop = " << (IsAudio() ? "audio" : "video"); |
699 if (stop_callback_.is_null()) | 509 if (stop_callback_.is_null()) |
700 return; // Already stopped. | 510 return; // Already stopped. |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
735 DCHECK(content::RenderThread::Get()); | 545 DCHECK(content::RenderThread::Get()); |
736 DVLOG(1) << "CastRtpStream::DidEncounterError(" << message << ") = " | 546 DVLOG(1) << "CastRtpStream::DidEncounterError(" << message << ") = " |
737 << (IsAudio() ? "audio" : "video"); | 547 << (IsAudio() ? "audio" : "video"); |
738 // Save the WeakPtr first because the error callback might delete this object. | 548 // Save the WeakPtr first because the error callback might delete this object. |
739 base::WeakPtr<CastRtpStream> ptr = weak_factory_.GetWeakPtr(); | 549 base::WeakPtr<CastRtpStream> ptr = weak_factory_.GetWeakPtr(); |
740 error_callback_.Run(message); | 550 error_callback_.Run(message); |
741 base::ThreadTaskRunnerHandle::Get()->PostTask( | 551 base::ThreadTaskRunnerHandle::Get()->PostTask( |
742 FROM_HERE, | 552 FROM_HERE, |
743 base::Bind(&CastRtpStream::Stop, ptr)); | 553 base::Bind(&CastRtpStream::Stop, ptr)); |
744 } | 554 } |
OLD | NEW |