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