Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "content/renderer/media_recorder/media_recorder_handler.h" | 5 #include "content/renderer/media_recorder/media_recorder_handler.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/location.h" | 10 #include "base/location.h" |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/macros.h" | 12 #include "base/macros.h" |
| 13 #include "base/strings/string_tokenizer.h" | 13 #include "base/strings/string_tokenizer.h" |
| 14 #include "base/strings/string_util.h" | 14 #include "base/strings/string_util.h" |
| 15 #include "base/sys_info.h" | |
| 15 #include "content/child/scoped_web_callbacks.h" | 16 #include "content/child/scoped_web_callbacks.h" |
| 16 #include "content/renderer/media/media_stream_audio_track.h" | 17 #include "content/renderer/media/media_stream_audio_track.h" |
| 17 #include "content/renderer/media/media_stream_track.h" | 18 #include "content/renderer/media/media_stream_track.h" |
| 18 #include "content/renderer/media/webrtc_uma_histograms.h" | 19 #include "content/renderer/media/webrtc_uma_histograms.h" |
| 19 #include "content/renderer/media_recorder/audio_track_recorder.h" | 20 #include "content/renderer/media_recorder/audio_track_recorder.h" |
| 20 #include "media/base/audio_bus.h" | 21 #include "media/base/audio_bus.h" |
| 21 #include "media/base/audio_parameters.h" | 22 #include "media/base/audio_parameters.h" |
| 22 #include "media/base/bind_to_current_loop.h" | 23 #include "media/base/bind_to_current_loop.h" |
| 23 #include "media/base/mime_util.h" | 24 #include "media/base/mime_util.h" |
| 24 #include "media/base/video_frame.h" | 25 #include "media/base/video_frame.h" |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 48 case VideoTrackRecorder::CodecId::H264: | 49 case VideoTrackRecorder::CodecId::H264: |
| 49 return media::kCodecH264; | 50 return media::kCodecH264; |
| 50 #endif | 51 #endif |
| 51 case VideoTrackRecorder::CodecId::LAST: | 52 case VideoTrackRecorder::CodecId::LAST: |
| 52 return media::kUnknownVideoCodec; | 53 return media::kUnknownVideoCodec; |
| 53 } | 54 } |
| 54 NOTREACHED() << "Unsupported codec"; | 55 NOTREACHED() << "Unsupported codec"; |
| 55 return media::kUnknownVideoCodec; | 56 return media::kUnknownVideoCodec; |
| 56 } | 57 } |
| 57 | 58 |
| 59 // Extracts the first recognised CodecId of |codecs| or CodecId::LAST if none | |
| 60 // of them is known. | |
| 61 VideoTrackRecorder::CodecId StringToCodecId(const blink::WebString& codecs) { | |
| 62 const std::string& codecs_str = ToLowerASCII(codecs.Utf8()); | |
| 63 | |
| 64 if (codecs_str.find("vp8") != std::string::npos) | |
| 65 return VideoTrackRecorder::CodecId::VP8; | |
| 66 else if (codecs_str.find("vp9") != std::string::npos) | |
| 67 return VideoTrackRecorder::CodecId::VP9; | |
| 68 #if BUILDFLAG(RTC_USE_H264) | |
| 69 else if (codecs_str.find("h264") != std::string::npos || | |
| 70 codecs_str.find("avc1") != std::string::npos) | |
| 71 return VideoTrackRecorder::CodecId::H264; | |
| 72 #endif | |
| 73 return VideoTrackRecorder::CodecId::LAST; | |
| 74 } | |
| 75 | |
| 58 void OnEncodingInfoError( | 76 void OnEncodingInfoError( |
| 59 std::unique_ptr<WebMediaCapabilitiesQueryCallbacks> callbacks) { | 77 std::unique_ptr<WebMediaCapabilitiesQueryCallbacks> callbacks) { |
| 60 callbacks->OnError(); | 78 callbacks->OnError(); |
| 61 } | 79 } |
| 62 | 80 |
| 63 } // anonymous namespace | 81 } // anonymous namespace |
| 64 | 82 |
| 65 MediaRecorderHandler::MediaRecorderHandler() | 83 MediaRecorderHandler::MediaRecorderHandler() |
| 66 : video_bits_per_second_(0), | 84 : video_bits_per_second_(0), |
| 67 audio_bits_per_second_(0), | 85 audio_bits_per_second_(0), |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 130 // Save histogram data so we can see how much MediaStream Recorder is used. | 148 // Save histogram data so we can see how much MediaStream Recorder is used. |
| 131 // The histogram counts the number of calls to the JS API. | 149 // The histogram counts the number of calls to the JS API. |
| 132 UpdateWebRTCMethodCount(WEBKIT_MEDIA_STREAM_RECORDER); | 150 UpdateWebRTCMethodCount(WEBKIT_MEDIA_STREAM_RECORDER); |
| 133 | 151 |
| 134 if (!CanSupportMimeType(type, codecs)) { | 152 if (!CanSupportMimeType(type, codecs)) { |
| 135 DLOG(ERROR) << "Unsupported " << type.Utf8() << ";codecs=" << codecs.Utf8(); | 153 DLOG(ERROR) << "Unsupported " << type.Utf8() << ";codecs=" << codecs.Utf8(); |
| 136 return false; | 154 return false; |
| 137 } | 155 } |
| 138 | 156 |
| 139 // Once established that we support the codec(s), hunt then individually. | 157 // Once established that we support the codec(s), hunt then individually. |
| 140 const std::string& codecs_str = ToLowerASCII(codecs.Utf8()); | 158 const VideoTrackRecorder::CodecId codec_id = StringToCodecId(codecs); |
| 141 if (codecs_str.find("vp8") != std::string::npos) | 159 codec_id_ = (codec_id != VideoTrackRecorder::CodecId::LAST) |
| 142 codec_id_ = VideoTrackRecorder::CodecId::VP8; | 160 ? codec_id |
| 143 else if (codecs_str.find("vp9") != std::string::npos) | 161 : VideoTrackRecorder::GetPreferredCodecId(); |
| 144 codec_id_ = VideoTrackRecorder::CodecId::VP9; | |
| 145 #if BUILDFLAG(RTC_USE_H264) | |
| 146 else if (codecs_str.find("h264") != std::string::npos) | |
| 147 codec_id_ = VideoTrackRecorder::CodecId::H264; | |
| 148 else if (codecs_str.find("avc1") != std::string::npos) | |
| 149 codec_id_ = VideoTrackRecorder::CodecId::H264; | |
| 150 #endif | |
| 151 else | |
| 152 codec_id_ = VideoTrackRecorder::GetPreferredCodecId(); | |
| 153 | 162 |
| 154 DVLOG_IF(1, codecs_str.empty()) << "Falling back to preferred codec id " | 163 DVLOG_IF(1, codec_id == VideoTrackRecorder::CodecId::LAST) |
| 155 << static_cast<int>(codec_id_); | 164 << "Falling back to preferred codec id " << static_cast<int>(codec_id_); |
| 156 | 165 |
| 157 media_stream_ = media_stream; | 166 media_stream_ = media_stream; |
| 158 DCHECK(client); | 167 DCHECK(client); |
| 159 client_ = client; | 168 client_ = client; |
| 160 | 169 |
| 161 audio_bits_per_second_ = audio_bits_per_second; | 170 audio_bits_per_second_ = audio_bits_per_second; |
| 162 video_bits_per_second_ = video_bits_per_second; | 171 video_bits_per_second_ = video_bits_per_second; |
| 163 return true; | 172 return true; |
| 164 } | 173 } |
| 165 | 174 |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 295 blink::WebString mime_type; | 304 blink::WebString mime_type; |
| 296 blink::WebString codec; | 305 blink::WebString codec; |
| 297 if (configuration.video_configuration) { | 306 if (configuration.video_configuration) { |
| 298 mime_type = configuration.video_configuration->mime_type; | 307 mime_type = configuration.video_configuration->mime_type; |
| 299 codec = configuration.video_configuration->codec; | 308 codec = configuration.video_configuration->codec; |
| 300 } else { | 309 } else { |
| 301 mime_type = configuration.audio_configuration->mime_type; | 310 mime_type = configuration.audio_configuration->mime_type; |
| 302 codec = configuration.audio_configuration->codec; | 311 codec = configuration.audio_configuration->codec; |
| 303 } | 312 } |
| 304 | 313 |
| 305 // See RFC 2231. https://tools.ietf.org/html/rfc2231 | |
| 306 info->supported = CanSupportMimeType(mime_type, codec); | 314 info->supported = CanSupportMimeType(mime_type, codec); |
| 307 DVLOG(1) << "type: " << mime_type.Ascii() << ", codec:" << codec.Ascii() | 315 |
| 308 << " is" << (info->supported ? " supported" : " NOT supported"); | 316 if (configuration.video_configuration && info->supported) { |
| 317 const bool is_likely_accelerated = | |
| 318 VideoTrackRecorder::CanUseAcceleratedEncoder( | |
| 319 StringToCodecId(codec), configuration.video_configuration->width, | |
| 320 configuration.video_configuration->height); | |
| 321 | |
| 322 // Encoding smoothness depends on a number of parameters, namely: frame | |
| 323 // rate, resolution, hardware support availability, platform and | |
| 324 // IsLowEndDevice(); to simplify calculations we compare the amount of | |
| 325 // pixels per second (i.e. |resolution| times |framerate|). Software based | |
| 326 // encoding on Desktop can run fine up and until HD resolution at 30fps, | |
| 327 // whereas if IsLowEndDevice() we set the cut at VGA (note that either pixel | |
| 328 // volumes would make use of hardware acceleration if available). | |
| 329 const float kNumPixelsPerSecondSmoothnessThreshold = | |
| 330 base::SysInfo::IsLowEndDevice() ? 640 * 480 * 30.0 : 1280 * 720 * 30.0; | |
|
emircan
2017/05/01 17:12:29
Can we define this as constant at the top of this
mcasas
2017/05/01 20:18:44
Done.
| |
| 331 const float pixels_per_second = | |
| 332 configuration.video_configuration->width * | |
| 333 configuration.video_configuration->height * | |
| 334 configuration.video_configuration->framerate; | |
| 335 info->smooth = is_likely_accelerated || | |
| 336 pixels_per_second <= kNumPixelsPerSecondSmoothnessThreshold; | |
| 337 | |
| 338 // TODO(mcasas): revisit what |power_efficient| means | |
| 339 // https://crbug.com/709181. | |
| 340 info->power_efficient = info->smooth; | |
| 341 } | |
| 342 DVLOG(1) << "type: " << mime_type.Ascii() << ", params:" << codec.Ascii() | |
| 343 << " is" << (info->supported ? " supported" : " NOT supported") | |
| 344 << " and" << (info->smooth ? " smooth" : " NOT smooth"); | |
| 309 | 345 |
| 310 scoped_callbacks.PassCallbacks()->OnSuccess(std::move(info)); | 346 scoped_callbacks.PassCallbacks()->OnSuccess(std::move(info)); |
| 311 } | 347 } |
| 312 | 348 |
| 313 void MediaRecorderHandler::OnEncodedVideo( | 349 void MediaRecorderHandler::OnEncodedVideo( |
| 314 const media::WebmMuxer::VideoParameters& params, | 350 const media::WebmMuxer::VideoParameters& params, |
| 315 std::unique_ptr<std::string> encoded_data, | 351 std::unique_ptr<std::string> encoded_data, |
| 316 std::unique_ptr<std::string> encoded_alpha, | 352 std::unique_ptr<std::string> encoded_alpha, |
| 317 TimeTicks timestamp, | 353 TimeTicks timestamp, |
| 318 bool is_key_frame) { | 354 bool is_key_frame) { |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 418 recorder->OnData(audio_bus, timestamp); | 454 recorder->OnData(audio_bus, timestamp); |
| 419 } | 455 } |
| 420 | 456 |
| 421 void MediaRecorderHandler::SetAudioFormatForTesting( | 457 void MediaRecorderHandler::SetAudioFormatForTesting( |
| 422 const media::AudioParameters& params) { | 458 const media::AudioParameters& params) { |
| 423 for (const auto& recorder : audio_recorders_) | 459 for (const auto& recorder : audio_recorders_) |
| 424 recorder->OnSetFormat(params); | 460 recorder->OnSetFormat(params); |
| 425 } | 461 } |
| 426 | 462 |
| 427 } // namespace content | 463 } // namespace content |
| OLD | NEW |