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::RtpPayloadType::AUDIO_OPUS; | 60 config.rtp_payload_type = media::cast::RtpPayloadType::AUDIO_OPUS; |
70 payload.max_latency_ms = media::cast::kDefaultRtpMaxDelayMs; | 61 config.sender_ssrc = 1; |
71 payload.ssrc = 1; | 62 config.receiver_ssrc = 2; |
72 payload.feedback_ssrc = 2; | 63 config.rtp_timebase = media::cast::kDefaultAudioSamplingRate; |
73 payload.clock_rate = media::cast::kDefaultAudioSamplingRate; | 64 config.channels = 2; |
74 // The value is 0 which means VBR. | 65 // The value is 0 which means VBR. |
75 payload.min_bitrate = payload.max_bitrate = | 66 config.min_bitrate = config.max_bitrate = config.start_bitrate = |
76 media::cast::kDefaultAudioEncoderBitrate; | 67 media::cast::kDefaultAudioEncoderBitrate; |
77 payload.channels = 2; | 68 config.max_frame_rate = 100; // 10 ms audio frames |
78 payload.max_frame_rate = 100; // 10 ms audio frames | 69 config.codec = media::cast::CODEC_AUDIO_OPUS; |
79 payload.codec_name = kCodecNameOpus; | 70 return config; |
80 return payload; | |
81 } | 71 } |
82 | 72 |
83 CastRtpPayloadParams DefaultVp8Payload() { | 73 FrameSenderConfig DefaultVp8Config() { |
84 CastRtpPayloadParams payload; | 74 FrameSenderConfig config; |
85 payload.payload_type = media::cast::RtpPayloadType::VIDEO_VP8; | 75 config.rtp_payload_type = media::cast::RtpPayloadType::VIDEO_VP8; |
86 payload.max_latency_ms = media::cast::kDefaultRtpMaxDelayMs; | 76 config.sender_ssrc = 11; |
87 payload.ssrc = 11; | 77 config.receiver_ssrc = 12; |
88 payload.feedback_ssrc = 12; | 78 config.rtp_timebase = media::cast::kVideoFrequency; |
89 payload.clock_rate = media::cast::kVideoFrequency; | 79 config.channels = 1; |
90 payload.max_bitrate = media::cast::kDefaultMaxVideoKbps; | 80 config.max_bitrate = media::cast::kDefaultMaxVideoBitrate; |
91 payload.min_bitrate = media::cast::kDefaultMinVideoKbps; | 81 config.min_bitrate = media::cast::kDefaultMinVideoBitrate; |
92 payload.channels = 1; | 82 config.max_frame_rate = media::cast::kDefaultMaxFrameRate; |
93 payload.max_frame_rate = media::cast::kDefaultMaxFrameRate; | 83 config.codec = media::cast::CODEC_VIDEO_VP8; |
94 payload.codec_name = kCodecNameVp8; | 84 return config; |
95 return payload; | |
96 } | 85 } |
97 | 86 |
98 CastRtpPayloadParams DefaultH264Payload() { | 87 FrameSenderConfig DefaultH264Config() { |
99 CastRtpPayloadParams payload; | 88 FrameSenderConfig config; |
100 payload.payload_type = media::cast::RtpPayloadType::VIDEO_H264; | 89 config.rtp_payload_type = media::cast::RtpPayloadType::VIDEO_H264; |
101 payload.max_latency_ms = media::cast::kDefaultRtpMaxDelayMs; | 90 config.sender_ssrc = 11; |
102 payload.ssrc = 11; | 91 config.receiver_ssrc = 12; |
103 payload.feedback_ssrc = 12; | 92 config.rtp_timebase = media::cast::kVideoFrequency; |
104 payload.clock_rate = media::cast::kVideoFrequency; | 93 config.channels = 1; |
105 payload.max_bitrate = media::cast::kDefaultMaxVideoKbps; | 94 config.max_bitrate = media::cast::kDefaultMaxVideoBitrate; |
106 payload.min_bitrate = media::cast::kDefaultMinVideoKbps; | 95 config.min_bitrate = media::cast::kDefaultMinVideoBitrate; |
107 payload.channels = 1; | 96 config.max_frame_rate = media::cast::kDefaultMaxFrameRate; |
108 payload.max_frame_rate = media::cast::kDefaultMaxFrameRate; | 97 config.codec = media::cast::CODEC_VIDEO_H264; |
109 payload.codec_name = kCodecNameH264; | 98 return config; |
110 return payload; | |
111 } | 99 } |
112 | 100 |
113 bool IsHardwareVP8EncodingSupported() { | 101 std::vector<FrameSenderConfig> SupportedAudioConfigs() { |
114 const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); | 102 // TODO(hclam): Fill in more codecs here. |
115 if (cmd_line->HasSwitch(switches::kDisableCastStreamingHWEncoding)) { | 103 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 } | 104 } |
131 | 105 |
132 bool IsHardwareH264EncodingSupported() { | 106 std::vector<FrameSenderConfig> SupportedVideoConfigs() { |
133 const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); | 107 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 | 108 |
171 // Prefer VP8 over H.264 for hardware encoder. | 109 // Prefer VP8 over H.264 for hardware encoder. |
172 if (IsHardwareVP8EncodingSupported()) | 110 if (CastRtpStream::IsHardwareVP8EncodingSupported()) |
173 supported_params.push_back(CastRtpParams(DefaultVp8Payload())); | 111 supported_configs.push_back(DefaultVp8Config()); |
174 if (IsHardwareH264EncodingSupported()) | 112 if (CastRtpStream::IsHardwareH264EncodingSupported()) |
175 supported_params.push_back(CastRtpParams(DefaultH264Payload())); | 113 supported_configs.push_back(DefaultH264Config()); |
176 | 114 |
177 // Propose the default software VP8 encoder, if no hardware encoders are | 115 // Propose the default software VP8 encoder, if no hardware encoders are |
178 // available. | 116 // available. |
179 if (supported_params.empty()) | 117 if (supported_configs.empty()) |
180 supported_params.push_back(CastRtpParams(DefaultVp8Payload())); | 118 supported_configs.push_back(DefaultVp8Config()); |
181 | 119 |
182 return supported_params; | 120 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 } | 121 } |
315 | 122 |
316 } // namespace | 123 } // namespace |
317 | 124 |
318 // This class receives MediaStreamTrack events and video frames from a | 125 // This class receives MediaStreamTrack events and video frames from a |
319 // MediaStreamVideoTrack. It also includes a timer to request refresh frames | 126 // MediaStreamVideoTrack. It also includes a timer to request refresh frames |
320 // when the capturer halts (e.g., a screen capturer stops delivering frames | 127 // 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 | 128 // 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. | 129 // 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 | 130 // 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. | 395 // These members are accessed on the real-time audio time only. |
589 media::AudioParameters input_params_; | 396 media::AudioParameters input_params_; |
590 std::unique_ptr<media::AudioConverter> converter_; | 397 std::unique_ptr<media::AudioConverter> converter_; |
591 const media::AudioBus* current_input_bus_; | 398 const media::AudioBus* current_input_bus_; |
592 int64_t sample_frames_in_; | 399 int64_t sample_frames_in_; |
593 int64_t sample_frames_out_; | 400 int64_t sample_frames_out_; |
594 | 401 |
595 DISALLOW_COPY_AND_ASSIGN(CastAudioSink); | 402 DISALLOW_COPY_AND_ASSIGN(CastAudioSink); |
596 }; | 403 }; |
597 | 404 |
598 CastRtpParams::CastRtpParams(const CastRtpPayloadParams& payload_params) | 405 bool CastRtpStream::IsHardwareVP8EncodingSupported() { |
599 : payload(payload_params) {} | 406 const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); |
| 407 if (cmd_line->HasSwitch(switches::kDisableCastStreamingHWEncoding)) { |
| 408 DVLOG(1) << "Disabled hardware VP8 support for Cast Streaming."; |
| 409 return false; |
| 410 } |
600 | 411 |
601 CastCodecSpecificParams::CastCodecSpecificParams() {} | 412 // Query for hardware VP8 encoder support. |
| 413 const std::vector<media::VideoEncodeAccelerator::SupportedProfile> |
| 414 vea_profiles = content::GetSupportedVideoEncodeAcceleratorProfiles(); |
| 415 for (const auto& vea_profile : vea_profiles) { |
| 416 if (vea_profile.profile >= media::VP8PROFILE_MIN && |
| 417 vea_profile.profile <= media::VP8PROFILE_MAX) { |
| 418 return true; |
| 419 } |
| 420 } |
| 421 return false; |
| 422 } |
602 | 423 |
603 CastCodecSpecificParams::~CastCodecSpecificParams() {} | 424 bool CastRtpStream::IsHardwareH264EncodingSupported() { |
| 425 const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); |
| 426 if (cmd_line->HasSwitch(switches::kDisableCastStreamingHWEncoding)) { |
| 427 DVLOG(1) << "Disabled hardware h264 support for Cast Streaming."; |
| 428 return false; |
| 429 } |
604 | 430 |
605 CastRtpPayloadParams::CastRtpPayloadParams() | 431 // Query for hardware H.264 encoder support. |
606 : payload_type(media::cast::RtpPayloadType::UNKNOWN), | 432 // |
607 max_latency_ms(0), | 433 // TODO(miu): Look into why H.264 hardware encoder on MacOS is broken. |
608 min_latency_ms(0), | 434 // http://crbug.com/596674 |
609 ssrc(0), | 435 #if !defined(OS_MACOSX) |
610 feedback_ssrc(0), | 436 const std::vector<media::VideoEncodeAccelerator::SupportedProfile> |
611 clock_rate(0), | 437 vea_profiles = content::GetSupportedVideoEncodeAcceleratorProfiles(); |
612 max_bitrate(0), | 438 for (const auto& vea_profile : vea_profiles) { |
613 min_bitrate(0), | 439 if (vea_profile.profile >= media::H264PROFILE_MIN && |
614 channels(0), | 440 vea_profile.profile <= media::H264PROFILE_MAX) { |
615 max_frame_rate(0.0) {} | 441 return true; |
616 | 442 } |
617 CastRtpPayloadParams::CastRtpPayloadParams(const CastRtpPayloadParams& other) = | 443 } |
618 default; | 444 #endif // !defined(OS_MACOSX) |
619 | 445 return false; |
620 CastRtpPayloadParams::~CastRtpPayloadParams() {} | 446 } |
621 | |
622 CastRtpParams::CastRtpParams() {} | |
623 | |
624 CastRtpParams::CastRtpParams(const CastRtpParams& other) = default; | |
625 | |
626 CastRtpParams::~CastRtpParams() {} | |
627 | 447 |
628 CastRtpStream::CastRtpStream(const blink::WebMediaStreamTrack& track, | 448 CastRtpStream::CastRtpStream(const blink::WebMediaStreamTrack& track, |
629 const scoped_refptr<CastSession>& session) | 449 const scoped_refptr<CastSession>& session) |
630 : track_(track), cast_session_(session), weak_factory_(this) {} | 450 : track_(track), cast_session_(session), weak_factory_(this) {} |
631 | 451 |
632 CastRtpStream::~CastRtpStream() { | 452 CastRtpStream::~CastRtpStream() { |
633 Stop(); | 453 Stop(); |
634 } | 454 } |
635 | 455 |
636 std::vector<CastRtpParams> CastRtpStream::GetSupportedParams() { | 456 std::vector<FrameSenderConfig> CastRtpStream::GetSupportedConfigs() { |
637 if (IsAudio()) | 457 if (IsAudio()) |
638 return SupportedAudioParams(); | 458 return SupportedAudioConfigs(); |
639 else | 459 else |
640 return SupportedVideoParams(); | 460 return SupportedVideoConfigs(); |
641 } | 461 } |
642 | 462 |
643 CastRtpParams CastRtpStream::GetParams() { return params_; } | 463 void CastRtpStream::Start(const FrameSenderConfig& config, |
644 | |
645 void CastRtpStream::Start(const CastRtpParams& params, | |
646 const base::Closure& start_callback, | 464 const base::Closure& start_callback, |
647 const base::Closure& stop_callback, | 465 const base::Closure& stop_callback, |
648 const ErrorCallback& error_callback) { | 466 const ErrorCallback& error_callback) { |
649 DCHECK(!start_callback.is_null()); | 467 DCHECK(!start_callback.is_null()); |
650 DCHECK(!stop_callback.is_null()); | 468 DCHECK(!stop_callback.is_null()); |
651 DCHECK(!error_callback.is_null()); | 469 DCHECK(!error_callback.is_null()); |
652 | 470 |
653 DVLOG(1) << "CastRtpStream::Start = " << (IsAudio() ? "audio" : "video"); | 471 DVLOG(1) << "CastRtpStream::Start = " << (IsAudio() ? "audio" : "video"); |
654 stop_callback_ = stop_callback; | 472 stop_callback_ = stop_callback; |
655 error_callback_ = error_callback; | 473 error_callback_ = error_callback; |
656 | 474 |
657 if (IsAudio()) { | 475 if (IsAudio()) { |
658 AudioSenderConfig config; | |
659 if (!ToAudioSenderConfig(params, &config)) { | |
660 DidEncounterError("Invalid parameters for audio."); | |
661 return; | |
662 } | |
663 | |
664 // In case of error we have to go through DidEncounterError() to stop | 476 // In case of error we have to go through DidEncounterError() to stop |
665 // the streaming after reporting the error. | 477 // the streaming after reporting the error. |
666 audio_sink_.reset(new CastAudioSink( | 478 audio_sink_.reset( |
667 track_, | 479 new CastAudioSink(track_, config.channels, config.rtp_timebase)); |
668 params.payload.channels, | |
669 params.payload.clock_rate)); | |
670 cast_session_->StartAudio( | 480 cast_session_->StartAudio( |
671 config, | 481 config, |
672 base::Bind(&CastAudioSink::AddToTrack, audio_sink_->AsWeakPtr()), | 482 base::Bind(&CastAudioSink::AddToTrack, audio_sink_->AsWeakPtr()), |
673 base::Bind(&CastRtpStream::DidEncounterError, | 483 base::Bind(&CastRtpStream::DidEncounterError, |
674 weak_factory_.GetWeakPtr())); | 484 weak_factory_.GetWeakPtr())); |
675 start_callback.Run(); | 485 start_callback.Run(); |
676 } else { | 486 } else { |
677 VideoSenderConfig config; | |
678 if (!ToVideoSenderConfig(params, &config)) { | |
679 DidEncounterError("Invalid parameters for video."); | |
680 return; | |
681 } | |
682 // See the code for audio above for explanation of callbacks. | 487 // See the code for audio above for explanation of callbacks. |
683 video_sink_.reset(new CastVideoSink( | 488 video_sink_.reset(new CastVideoSink( |
684 track_, | 489 track_, |
685 media::BindToCurrentLoop(base::Bind(&CastRtpStream::DidEncounterError, | 490 media::BindToCurrentLoop(base::Bind(&CastRtpStream::DidEncounterError, |
686 weak_factory_.GetWeakPtr())))); | 491 weak_factory_.GetWeakPtr())))); |
687 cast_session_->StartVideo( | 492 cast_session_->StartVideo( |
688 config, base::Bind(&CastVideoSink::AddToTrack, video_sink_->AsWeakPtr(), | 493 config, base::Bind(&CastVideoSink::AddToTrack, video_sink_->AsWeakPtr(), |
689 !params.payload.aes_key.empty()), | 494 !config.aes_key.empty()), |
690 base::Bind(&CastRtpStream::DidEncounterError, | 495 base::Bind(&CastRtpStream::DidEncounterError, |
691 weak_factory_.GetWeakPtr())); | 496 weak_factory_.GetWeakPtr())); |
692 start_callback.Run(); | 497 start_callback.Run(); |
693 } | 498 } |
694 } | 499 } |
695 | 500 |
696 void CastRtpStream::Stop() { | 501 void CastRtpStream::Stop() { |
697 DVLOG(1) << "CastRtpStream::Stop = " << (IsAudio() ? "audio" : "video"); | 502 DVLOG(1) << "CastRtpStream::Stop = " << (IsAudio() ? "audio" : "video"); |
698 if (stop_callback_.is_null()) | 503 if (stop_callback_.is_null()) |
699 return; // Already stopped. | 504 return; // Already stopped. |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
734 DCHECK(content::RenderThread::Get()); | 539 DCHECK(content::RenderThread::Get()); |
735 DVLOG(1) << "CastRtpStream::DidEncounterError(" << message << ") = " | 540 DVLOG(1) << "CastRtpStream::DidEncounterError(" << message << ") = " |
736 << (IsAudio() ? "audio" : "video"); | 541 << (IsAudio() ? "audio" : "video"); |
737 // Save the WeakPtr first because the error callback might delete this object. | 542 // Save the WeakPtr first because the error callback might delete this object. |
738 base::WeakPtr<CastRtpStream> ptr = weak_factory_.GetWeakPtr(); | 543 base::WeakPtr<CastRtpStream> ptr = weak_factory_.GetWeakPtr(); |
739 error_callback_.Run(message); | 544 error_callback_.Run(message); |
740 base::ThreadTaskRunnerHandle::Get()->PostTask( | 545 base::ThreadTaskRunnerHandle::Get()->PostTask( |
741 FROM_HERE, | 546 FROM_HERE, |
742 base::Bind(&CastRtpStream::Stop, ptr)); | 547 base::Bind(&CastRtpStream::Stop, ptr)); |
743 } | 548 } |
OLD | NEW |