Chromium Code Reviews| Index: chrome/renderer/media/cast_rtp_stream.cc |
| diff --git a/chrome/renderer/media/cast_rtp_stream.cc b/chrome/renderer/media/cast_rtp_stream.cc |
| index 53e46fea9317cf48b27548e929179d6bc0afb74b..81609f7e7abed41fe127559080cf867fdf8f45bc 100644 |
| --- a/chrome/renderer/media/cast_rtp_stream.cc |
| +++ b/chrome/renderer/media/cast_rtp_stream.cc |
| @@ -19,7 +19,6 @@ |
| #include "base/memory/ref_counted.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/strings/stringprintf.h" |
| -#include "base/sys_info.h" |
| #include "base/threading/thread_task_runner_handle.h" |
| #include "base/timer/timer.h" |
| #include "base/trace_event/trace_event.h" |
| @@ -44,18 +43,10 @@ |
| #include "third_party/WebKit/public/platform/WebMediaStreamSource.h" |
| #include "ui/gfx/geometry/size.h" |
| -using media::cast::AudioSenderConfig; |
| -using media::cast::VideoSenderConfig; |
| +using media::cast::FrameSenderConfig; |
| namespace { |
| -const char kCodecNameOpus[] = "OPUS"; |
| -const char kCodecNameVp8[] = "VP8"; |
| -const char kCodecNameH264[] = "H264"; |
| - |
| -// To convert from kilobits per second to bits to per second. |
| -const int kBitrateMultiplier = 1000; |
| - |
| // The maximum number of milliseconds that should elapse since the last video |
| // frame was received from the video source, before requesting refresh frames. |
| const int kRefreshIntervalMilliseconds = 250; |
| @@ -64,253 +55,75 @@ const int kRefreshIntervalMilliseconds = 250; |
| // limit (60 * 250ms = 15 seconds), refresh frame requests will stop being made. |
| const int kMaxConsecutiveRefreshFrames = 60; |
| -CastRtpPayloadParams DefaultOpusPayload() { |
| - CastRtpPayloadParams payload; |
| - payload.payload_type = media::cast::kDefaultRtpAudioPayloadType; |
| - payload.max_latency_ms = media::cast::kDefaultRtpMaxDelayMs; |
| - payload.ssrc = 1; |
| - payload.feedback_ssrc = 2; |
| - payload.clock_rate = media::cast::kDefaultAudioSamplingRate; |
| +FrameSenderConfig DefaultOpusConfig() { |
| + FrameSenderConfig config; |
| + config.rtp_payload_type = media::cast::RtpPayloadType::AUDIO_OPUS; |
| + config.max_playout_delay = |
| + base::TimeDelta::FromMilliseconds(media::cast::kDefaultRtpMaxDelayMs); |
| + config.sender_ssrc = 1; |
| + config.receiver_ssrc = 2; |
| + config.frequency = media::cast::kDefaultAudioSamplingRate; |
| // The value is 0 which means VBR. |
| - payload.min_bitrate = payload.max_bitrate = |
| + 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.
|
| media::cast::kDefaultAudioEncoderBitrate; |
| - payload.channels = 2; |
| - payload.max_frame_rate = 100; // 10 ms audio frames |
| - payload.codec_name = kCodecNameOpus; |
| - return payload; |
| -} |
| - |
| -CastRtpPayloadParams DefaultVp8Payload() { |
| - CastRtpPayloadParams payload; |
| - payload.payload_type = media::cast::kDefaultRtpVideoPayloadType; |
| - payload.max_latency_ms = media::cast::kDefaultRtpMaxDelayMs; |
| - payload.ssrc = 11; |
| - payload.feedback_ssrc = 12; |
| - payload.clock_rate = media::cast::kVideoFrequency; |
| - payload.max_bitrate = media::cast::kDefaultMaxVideoKbps; |
| - payload.min_bitrate = media::cast::kDefaultMinVideoKbps; |
| - payload.channels = 1; |
| - payload.max_frame_rate = media::cast::kDefaultMaxFrameRate; |
| - payload.codec_name = kCodecNameVp8; |
| - return payload; |
| -} |
| - |
| -CastRtpPayloadParams DefaultH264Payload() { |
| - CastRtpPayloadParams payload; |
| - payload.payload_type = 96; |
| - payload.max_latency_ms = media::cast::kDefaultRtpMaxDelayMs; |
| - payload.ssrc = 11; |
| - payload.feedback_ssrc = 12; |
| - payload.clock_rate = media::cast::kVideoFrequency; |
| - payload.max_bitrate = media::cast::kDefaultMaxVideoKbps; |
| - payload.min_bitrate = media::cast::kDefaultMinVideoKbps; |
| - payload.channels = 1; |
| - payload.max_frame_rate = media::cast::kDefaultMaxFrameRate; |
| - payload.codec_name = kCodecNameH264; |
| - return payload; |
| -} |
| - |
| -bool IsHardwareVP8EncodingSupported() { |
| - const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); |
| - if (cmd_line->HasSwitch(switches::kDisableCastStreamingHWEncoding)) { |
| - DVLOG(1) << "Disabled hardware VP8 support for Cast Streaming."; |
| - return false; |
| - } |
| - |
| - // Query for hardware VP8 encoder support. |
| - const std::vector<media::VideoEncodeAccelerator::SupportedProfile> |
| - vea_profiles = content::GetSupportedVideoEncodeAcceleratorProfiles(); |
| - for (const auto& vea_profile : vea_profiles) { |
| - if (vea_profile.profile >= media::VP8PROFILE_MIN && |
| - vea_profile.profile <= media::VP8PROFILE_MAX) { |
| - return true; |
| - } |
| - } |
| - return false; |
| + config.channels = 2; |
| + config.max_frame_rate = 100; // 10 ms audio frames |
| + config.codec = media::cast::CODEC_AUDIO_OPUS; |
| + return config; |
| } |
| -bool IsHardwareH264EncodingSupported() { |
| - const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); |
| - if (cmd_line->HasSwitch(switches::kDisableCastStreamingHWEncoding)) { |
| - DVLOG(1) << "Disabled hardware h264 support for Cast Streaming."; |
| - return false; |
| - } |
| - |
| - // Query for hardware H.264 encoder support. |
| - // |
| - // TODO(miu): Look into why H.264 hardware encoder on MacOS is broken. |
| - // http://crbug.com/596674 |
| -#if !defined(OS_MACOSX) |
| - const std::vector<media::VideoEncodeAccelerator::SupportedProfile> |
| - vea_profiles = content::GetSupportedVideoEncodeAcceleratorProfiles(); |
| - for (const auto& vea_profile : vea_profiles) { |
| - if (vea_profile.profile >= media::H264PROFILE_MIN && |
| - vea_profile.profile <= media::H264PROFILE_MAX) { |
| - return true; |
| - } |
| - } |
| -#endif // !defined(OS_MACOSX) |
| - return false; |
| +FrameSenderConfig DefaultVp8Config() { |
| + FrameSenderConfig config; |
| + config.rtp_payload_type = media::cast::RtpPayloadType::VIDEO_VP8; |
| + 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.
|
| + base::TimeDelta::FromMilliseconds(media::cast::kDefaultRtpMaxDelayMs); |
| + config.sender_ssrc = 11; |
| + config.receiver_ssrc = 12; |
| + config.frequency = media::cast::kVideoFrequency; |
| + config.max_bitrate = media::cast::kDefaultMaxVideoKbps; |
| + config.min_bitrate = media::cast::kDefaultMinVideoKbps; |
| + 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.
|
| + config.max_frame_rate = media::cast::kDefaultMaxFrameRate; |
| + config.codec = media::cast::CODEC_VIDEO_VP8; |
| + return config; |
| } |
| -int NumberOfEncodeThreads() { |
| - // Do not saturate CPU utilization just for encoding. On a lower-end system |
| - // with only 1 or 2 cores, use only one thread for encoding. On systems with |
| - // more cores, allow half of the cores to be used for encoding. |
| - return std::min(8, (base::SysInfo::NumberOfProcessors() + 1) / 2); |
| +FrameSenderConfig DefaultH264Config() { |
| + FrameSenderConfig config; |
| + config.rtp_payload_type = media::cast::RtpPayloadType::VIDEO_H264; |
| + config.max_playout_delay = |
| + base::TimeDelta::FromMilliseconds(media::cast::kDefaultRtpMaxDelayMs); |
| + config.sender_ssrc = 11; |
| + config.receiver_ssrc = 12; |
| + config.frequency = media::cast::kVideoFrequency; |
| + config.max_bitrate = media::cast::kDefaultMaxVideoKbps; |
| + config.min_bitrate = media::cast::kDefaultMinVideoKbps; |
| + config.channels = 1; |
| + config.max_frame_rate = media::cast::kDefaultMaxFrameRate; |
| + config.codec = media::cast::CODEC_VIDEO_H264; |
| + return config; |
| } |
| -std::vector<CastRtpParams> SupportedAudioParams() { |
| +std::vector<FrameSenderConfig> SupportedAudioConfigs() { |
| // TODO(hclam): Fill in more codecs here. |
| - return std::vector<CastRtpParams>(1, CastRtpParams(DefaultOpusPayload())); |
| + return std::vector<FrameSenderConfig>(1, DefaultOpusConfig()); |
| } |
| -std::vector<CastRtpParams> SupportedVideoParams() { |
| - std::vector<CastRtpParams> supported_params; |
| +std::vector<FrameSenderConfig> SupportedVideoConfigs() { |
| + std::vector<FrameSenderConfig> supported_configs; |
| // Prefer VP8 over H.264 for hardware encoder. |
| - if (IsHardwareVP8EncodingSupported()) |
| - supported_params.push_back(CastRtpParams(DefaultVp8Payload())); |
| - if (IsHardwareH264EncodingSupported()) |
| - supported_params.push_back(CastRtpParams(DefaultH264Payload())); |
| + if (CastRtpStream::IsHardwareVP8EncodingSupported()) |
| + supported_configs.push_back(DefaultVp8Config()); |
| + if (CastRtpStream::IsHardwareH264EncodingSupported()) |
| + supported_configs.push_back(DefaultH264Config()); |
| // Propose the default software VP8 encoder, if no hardware encoders are |
| // available. |
| - if (supported_params.empty()) |
| - supported_params.push_back(CastRtpParams(DefaultVp8Payload())); |
| + if (supported_configs.empty()) |
| + supported_configs.push_back(DefaultVp8Config()); |
| - return supported_params; |
| -} |
| - |
| -bool ToAudioSenderConfig(const CastRtpParams& params, |
| - AudioSenderConfig* config) { |
| - config->ssrc = params.payload.ssrc; |
| - config->receiver_ssrc = params.payload.feedback_ssrc; |
| - if (config->ssrc == config->receiver_ssrc) { |
| - DVLOG(1) << "ssrc " << config->ssrc << " cannot be equal to receiver_ssrc"; |
| - return false; |
| - } |
| - config->min_playout_delay = base::TimeDelta::FromMilliseconds( |
| - params.payload.min_latency_ms ? |
| - params.payload.min_latency_ms : |
| - params.payload.max_latency_ms); |
| - config->max_playout_delay = |
| - base::TimeDelta::FromMilliseconds(params.payload.max_latency_ms); |
| - config->animated_playout_delay = base::TimeDelta::FromMilliseconds( |
| - params.payload.animated_latency_ms ? params.payload.animated_latency_ms |
| - : params.payload.max_latency_ms); |
| - if (config->min_playout_delay <= base::TimeDelta()) { |
| - DVLOG(1) << "min_playout_delay " << config->min_playout_delay |
| - << " is too small"; |
| - return false; |
| - } |
| - if (config->min_playout_delay > config->max_playout_delay) { |
| - DVLOG(1) << "min_playout_delay " << config->min_playout_delay |
| - << " is too big"; |
| - return false; |
| - } |
| - if (config->animated_playout_delay < config->min_playout_delay || |
| - config->animated_playout_delay > config->max_playout_delay) { |
| - DVLOG(1) << "animated_playout_delay " << config->animated_playout_delay |
| - << " is out of range"; |
| - return false; |
| - } |
| - config->rtp_payload_type = params.payload.payload_type; |
| - config->use_external_encoder = false; |
| - config->frequency = params.payload.clock_rate; |
| - // Sampling rate must be one of the Opus-supported values. |
| - switch (config->frequency) { |
| - case 48000: |
| - case 24000: |
| - case 16000: |
| - case 12000: |
| - case 8000: |
| - break; |
| - default: |
| - DVLOG(1) << "frequency " << config->frequency << " is invalid"; |
| - return false; |
| - } |
| - config->channels = params.payload.channels; |
| - if (config->channels < 1) { |
| - DVLOG(1) << "channels " << config->channels << " is invalid"; |
| - return false; |
| - } |
| - config->bitrate = params.payload.max_bitrate * kBitrateMultiplier; |
| - if (params.payload.codec_name == kCodecNameOpus) { |
| - config->codec = media::cast::CODEC_AUDIO_OPUS; |
| - } else { |
| - DVLOG(1) << "codec_name " << params.payload.codec_name << " is invalid"; |
| - return false; |
| - } |
| - config->aes_key = params.payload.aes_key; |
| - config->aes_iv_mask = params.payload.aes_iv_mask; |
| - return true; |
| -} |
| - |
| -bool ToVideoSenderConfig(const CastRtpParams& params, |
| - VideoSenderConfig* config) { |
| - config->ssrc = params.payload.ssrc; |
| - config->receiver_ssrc = params.payload.feedback_ssrc; |
| - if (config->ssrc == config->receiver_ssrc) { |
| - DVLOG(1) << "ssrc " << config->ssrc << " cannot be equal to receiver_ssrc"; |
| - return false; |
| - } |
| - config->min_playout_delay = base::TimeDelta::FromMilliseconds( |
| - params.payload.min_latency_ms ? |
| - params.payload.min_latency_ms : |
| - params.payload.max_latency_ms); |
| - config->max_playout_delay = |
| - base::TimeDelta::FromMilliseconds(params.payload.max_latency_ms); |
| - config->animated_playout_delay = base::TimeDelta::FromMilliseconds( |
| - params.payload.animated_latency_ms ? params.payload.animated_latency_ms |
| - : params.payload.max_latency_ms); |
| - if (config->min_playout_delay <= base::TimeDelta()) { |
| - DVLOG(1) << "min_playout_delay " << config->min_playout_delay |
| - << " is too small"; |
| - return false; |
| - } |
| - if (config->min_playout_delay > config->max_playout_delay) { |
| - DVLOG(1) << "min_playout_delay " << config->min_playout_delay |
| - << " is too big"; |
| - return false; |
| - } |
| - if (config->animated_playout_delay < config->min_playout_delay || |
| - config->animated_playout_delay > config->max_playout_delay) { |
| - DVLOG(1) << "animated_playout_delay " << config->animated_playout_delay |
| - << " is out of range"; |
| - return false; |
| - } |
| - config->rtp_payload_type = params.payload.payload_type; |
| - config->min_bitrate = config->start_bitrate = |
| - params.payload.min_bitrate * kBitrateMultiplier; |
| - config->max_bitrate = params.payload.max_bitrate * kBitrateMultiplier; |
| - if (config->min_bitrate > config->max_bitrate) { |
| - DVLOG(1) << "min_bitrate " << config->min_bitrate << " is larger than " |
| - << "max_bitrate " << config->max_bitrate; |
| - return false; |
| - } |
| - config->start_bitrate = config->min_bitrate; |
| - config->max_frame_rate = static_cast<int>( |
| - std::max(1.0, params.payload.max_frame_rate) + 0.5); |
| - if (config->max_frame_rate > media::limits::kMaxFramesPerSecond) { |
| - DVLOG(1) << "max_frame_rate " << config->max_frame_rate << " is invalid"; |
| - return false; |
| - } |
| - if (params.payload.codec_name == kCodecNameVp8) { |
| - config->use_external_encoder = IsHardwareVP8EncodingSupported(); |
| - config->codec = media::cast::CODEC_VIDEO_VP8; |
| - } else if (params.payload.codec_name == kCodecNameH264) { |
| - config->use_external_encoder = IsHardwareH264EncodingSupported(); |
| - config->codec = media::cast::CODEC_VIDEO_H264; |
| - } else { |
| - DVLOG(1) << "codec_name " << params.payload.codec_name << " is invalid"; |
| - return false; |
| - } |
| - if (!config->use_external_encoder) |
| - config->number_of_encode_threads = NumberOfEncodeThreads(); |
| - config->aes_key = params.payload.aes_key; |
| - config->aes_iv_mask = params.payload.aes_iv_mask; |
| - return true; |
| + return supported_configs; |
| } |
| } // namespace |
| @@ -595,36 +408,48 @@ class CastAudioSink : public base::SupportsWeakPtr<CastAudioSink>, |
| DISALLOW_COPY_AND_ASSIGN(CastAudioSink); |
| }; |
| -CastRtpParams::CastRtpParams(const CastRtpPayloadParams& payload_params) |
| - : payload(payload_params) {} |
| - |
| -CastCodecSpecificParams::CastCodecSpecificParams() {} |
| - |
| -CastCodecSpecificParams::~CastCodecSpecificParams() {} |
| +bool CastRtpStream::IsHardwareVP8EncodingSupported() { |
| + const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); |
| + if (cmd_line->HasSwitch(switches::kDisableCastStreamingHWEncoding)) { |
| + DVLOG(1) << "Disabled hardware VP8 support for Cast Streaming."; |
| + return false; |
| + } |
| -CastRtpPayloadParams::CastRtpPayloadParams() |
| - : payload_type(0), |
| - max_latency_ms(0), |
| - min_latency_ms(0), |
| - ssrc(0), |
| - feedback_ssrc(0), |
| - clock_rate(0), |
| - max_bitrate(0), |
| - min_bitrate(0), |
| - channels(0), |
| - max_frame_rate(0.0) { |
| + // Query for hardware VP8 encoder support. |
| + const std::vector<media::VideoEncodeAccelerator::SupportedProfile> |
| + vea_profiles = content::GetSupportedVideoEncodeAcceleratorProfiles(); |
| + for (const auto& vea_profile : vea_profiles) { |
| + if (vea_profile.profile >= media::VP8PROFILE_MIN && |
| + vea_profile.profile <= media::VP8PROFILE_MAX) { |
| + return true; |
| + } |
| + } |
| + return false; |
| } |
| -CastRtpPayloadParams::CastRtpPayloadParams(const CastRtpPayloadParams& other) = |
| - default; |
| - |
| -CastRtpPayloadParams::~CastRtpPayloadParams() {} |
| - |
| -CastRtpParams::CastRtpParams() {} |
| - |
| -CastRtpParams::CastRtpParams(const CastRtpParams& other) = default; |
| +bool CastRtpStream::IsHardwareH264EncodingSupported() { |
| + const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); |
| + if (cmd_line->HasSwitch(switches::kDisableCastStreamingHWEncoding)) { |
| + DVLOG(1) << "Disabled hardware h264 support for Cast Streaming."; |
| + return false; |
| + } |
| -CastRtpParams::~CastRtpParams() {} |
| +// Query for hardware H.264 encoder support. |
| +// |
| +// TODO(miu): Look into why H.264 hardware encoder on MacOS is broken. |
| +// http://crbug.com/596674 |
| +#if !defined(OS_MACOSX) |
| + const std::vector<media::VideoEncodeAccelerator::SupportedProfile> |
| + vea_profiles = content::GetSupportedVideoEncodeAcceleratorProfiles(); |
| + for (const auto& vea_profile : vea_profiles) { |
| + if (vea_profile.profile >= media::H264PROFILE_MIN && |
| + vea_profile.profile <= media::H264PROFILE_MAX) { |
| + return true; |
| + } |
| + } |
| +#endif // !defined(OS_MACOSX) |
| + return false; |
| +} |
| CastRtpStream::CastRtpStream(const blink::WebMediaStreamTrack& track, |
| const scoped_refptr<CastSession>& session) |
| @@ -634,16 +459,14 @@ CastRtpStream::~CastRtpStream() { |
| Stop(); |
| } |
| -std::vector<CastRtpParams> CastRtpStream::GetSupportedParams() { |
| +std::vector<FrameSenderConfig> CastRtpStream::GetSupportedConfigs() { |
| if (IsAudio()) |
| - return SupportedAudioParams(); |
| + return SupportedAudioConfigs(); |
| else |
| - return SupportedVideoParams(); |
| + return SupportedVideoConfigs(); |
| } |
| -CastRtpParams CastRtpStream::GetParams() { return params_; } |
| - |
| -void CastRtpStream::Start(const CastRtpParams& params, |
| +void CastRtpStream::Start(const FrameSenderConfig& config, |
| const base::Closure& start_callback, |
| const base::Closure& stop_callback, |
| const ErrorCallback& error_callback) { |
| @@ -656,18 +479,10 @@ void CastRtpStream::Start(const CastRtpParams& params, |
| error_callback_ = error_callback; |
| if (IsAudio()) { |
| - AudioSenderConfig config; |
| - if (!ToAudioSenderConfig(params, &config)) { |
| - DidEncounterError("Invalid parameters for audio."); |
| - return; |
| - } |
| - |
| // In case of error we have to go through DidEncounterError() to stop |
| // the streaming after reporting the error. |
| - audio_sink_.reset(new CastAudioSink( |
| - track_, |
| - params.payload.channels, |
| - params.payload.clock_rate)); |
| + audio_sink_.reset( |
| + new CastAudioSink(track_, config.channels, config.frequency)); |
| cast_session_->StartAudio( |
| config, |
| base::Bind(&CastAudioSink::AddToTrack, audio_sink_->AsWeakPtr()), |
| @@ -675,11 +490,6 @@ void CastRtpStream::Start(const CastRtpParams& params, |
| weak_factory_.GetWeakPtr())); |
| start_callback.Run(); |
| } else { |
| - VideoSenderConfig config; |
| - if (!ToVideoSenderConfig(params, &config)) { |
| - DidEncounterError("Invalid parameters for video."); |
| - return; |
| - } |
| // See the code for audio above for explanation of callbacks. |
| video_sink_.reset(new CastVideoSink( |
| track_, |
| @@ -687,7 +497,7 @@ void CastRtpStream::Start(const CastRtpParams& params, |
| weak_factory_.GetWeakPtr())))); |
| cast_session_->StartVideo( |
| config, base::Bind(&CastVideoSink::AddToTrack, video_sink_->AsWeakPtr(), |
| - !params.payload.aes_key.empty()), |
| + !config.aes_key.empty()), |
| base::Bind(&CastRtpStream::DidEncounterError, |
| weak_factory_.GetWeakPtr())); |
| start_callback.Run(); |