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 305cd0b38a27e1cbeec7caf9897b15ada516309a..01d0fce19b75e52cb5d9f84a3a671b034cfcb30d 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,69 @@ 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::RtpPayloadType::AUDIO_OPUS; |
- 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.sender_ssrc = 1; |
+ config.receiver_ssrc = 2; |
+ config.rtp_timebase = media::cast::kDefaultAudioSamplingRate; |
+ config.channels = 2; |
// The value is 0 which means VBR. |
- payload.min_bitrate = payload.max_bitrate = |
+ config.min_bitrate = config.max_bitrate = config.start_bitrate = |
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::RtpPayloadType::VIDEO_VP8; |
- 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 = media::cast::RtpPayloadType::VIDEO_H264; |
- 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.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.sender_ssrc = 11; |
+ config.receiver_ssrc = 12; |
+ config.rtp_timebase = media::cast::kVideoFrequency; |
+ config.channels = 1; |
+ config.max_bitrate = media::cast::kDefaultMaxVideoBitrate; |
+ config.min_bitrate = media::cast::kDefaultMinVideoBitrate; |
+ 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.sender_ssrc = 11; |
+ config.receiver_ssrc = 12; |
+ config.rtp_timebase = media::cast::kVideoFrequency; |
+ config.channels = 1; |
+ config.max_bitrate = media::cast::kDefaultMaxVideoBitrate; |
+ config.min_bitrate = media::cast::kDefaultMinVideoBitrate; |
+ 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())); |
- |
- 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; |
-} |
+ if (supported_configs.empty()) |
+ supported_configs.push_back(DefaultVp8Config()); |
-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,35 +402,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() {} |
- |
-CastRtpPayloadParams::CastRtpPayloadParams() |
- : payload_type(media::cast::RtpPayloadType::UNKNOWN), |
- 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) {} |
- |
-CastRtpPayloadParams::CastRtpPayloadParams(const CastRtpPayloadParams& other) = |
- default; |
- |
-CastRtpPayloadParams::~CastRtpPayloadParams() {} |
+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; |
+ } |
-CastRtpParams::CastRtpParams() {} |
+ // 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; |
+} |
-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) |
@@ -633,16 +453,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) { |
@@ -655,18 +473,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.rtp_timebase)); |
cast_session_->StartAudio( |
config, |
base::Bind(&CastAudioSink::AddToTrack, audio_sink_->AsWeakPtr()), |
@@ -674,11 +484,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_, |
@@ -686,7 +491,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(); |