| Index: content/renderer/media/media_recorder_handler.cc
|
| diff --git a/content/renderer/media/media_recorder_handler.cc b/content/renderer/media/media_recorder_handler.cc
|
| index ce59ce42a4ecf1baf89f21bcf150aa896648dec3..759e4274fa4e922d710d70adfe7efd220ea335cd 100644
|
| --- a/content/renderer/media/media_recorder_handler.cc
|
| +++ b/content/renderer/media/media_recorder_handler.cc
|
| @@ -47,11 +47,30 @@ media::VideoCodec CodecIdToMediaVideoCodec(VideoTrackRecorder::CodecId id) {
|
| return media::kUnknownVideoCodec;
|
| }
|
|
|
| +// Extracts the MIME subtype from an incoming |content_type|, or empty.
|
| +std::string getSubtypeFromContentType(const std::string& content_type) {
|
| + base::StringTokenizer web_type_tokens(content_type, "/");
|
| + if (!web_type_tokens.GetNext() || !web_type_tokens.GetNext())
|
| + return std::string();
|
| + return web_type_tokens.token();
|
| +}
|
| +
|
| +bool findCodecInList(const std::string& codec,
|
| + const char* const* codecs,
|
| + size_t codecs_count) {
|
| + auto* const* found = std::find_if(
|
| + &codecs[0], &codecs[codecs_count], [&codec](const char* name) {
|
| + return base::EqualsCaseInsensitiveASCII(codec, name);
|
| + });
|
| + return found != &codecs[codecs_count];
|
| +}
|
| +
|
| } // anonymous namespace
|
|
|
| MediaRecorderHandler::MediaRecorderHandler()
|
| : video_bits_per_second_(0),
|
| audio_bits_per_second_(0),
|
| + use_container_(true),
|
| codec_id_(VideoTrackRecorder::CodecId::VP8),
|
| recording_(false),
|
| client_(nullptr),
|
| @@ -74,14 +93,16 @@ bool MediaRecorderHandler::canSupportMimeType(
|
| return true;
|
|
|
| const std::string type(web_type.utf8());
|
| - const bool video = base::EqualsCaseInsensitiveASCII(type, "video/webm");
|
| + const bool video =
|
| + base::StartsWith(type, "video/", base::CompareCase::INSENSITIVE_ASCII);
|
| const bool audio =
|
| - video ? false : base::EqualsCaseInsensitiveASCII(type, "audio/webm");
|
| + video ? false : base::StartsWith(type, "audio/",
|
| + base::CompareCase::INSENSITIVE_ASCII);
|
| if (!video && !audio)
|
| return false;
|
|
|
| // Both |video| and |audio| support empty |codecs|; |type| == "video" supports
|
| - // vp8, vp9 or opus; |type| = "audio", supports only opus.
|
| + // vp8, vp9, H264 or opus; |type| = "audio", supports only opus.
|
| // http://www.webmproject.org/docs/container Sec:"HTML5 Video Type Parameters"
|
| static const char* const kVideoCodecs[] = { "vp8", "vp9", "h264", "opus" };
|
| static const char* const kAudioCodecs[] = { "opus" };
|
| @@ -89,14 +110,16 @@ bool MediaRecorderHandler::canSupportMimeType(
|
| const int codecs_count =
|
| video ? arraysize(kVideoCodecs) : arraysize(kAudioCodecs);
|
|
|
| + // Check for the container or the codec following video/ or audio/. "webm"
|
| + // container is supported,; so are any of the |codecs| as non-contained.
|
| + const std::string mime_subtype = getSubtypeFromContentType(type);
|
| + if (!base::EqualsCaseInsensitiveASCII(mime_subtype, "webm"))
|
| + return findCodecInList(mime_subtype, codecs, codecs_count);
|
| +
|
| std::vector<std::string> codecs_list;
|
| media::ParseCodecString(web_codecs.utf8(), &codecs_list, true /* strip */);
|
| for (const auto& codec : codecs_list) {
|
| - auto* const* found = std::find_if(
|
| - &codecs[0], &codecs[codecs_count], [&codec](const char* name) {
|
| - return base::EqualsCaseInsensitiveASCII(codec, name);
|
| - });
|
| - if (found == &codecs[codecs_count])
|
| + if (!findCodecInList(codec, codecs, codecs_count))
|
| return false;
|
| }
|
| return true;
|
| @@ -120,8 +143,14 @@ bool MediaRecorderHandler::initialize(
|
| return false;
|
| }
|
|
|
| + const std::string mime_subtype = getSubtypeFromContentType(type.utf8());
|
| + use_container_ =
|
| + type.isEmpty() || base::EqualsCaseInsensitiveASCII(mime_subtype, "webm");
|
| +
|
| + const std::string& codecs_str =
|
| + use_container_ ? ToLowerASCII(codecs.utf8()) : ToLowerASCII(mime_subtype);
|
| +
|
| // Once established that we support the codec(s), hunt then individually.
|
| - const std::string& codecs_str = ToLowerASCII(codecs.utf8());
|
| if (codecs_str.find("vp8") != std::string::npos)
|
| codec_id_ = VideoTrackRecorder::CodecId::VP8;
|
| else if (codecs_str.find("vp9") != std::string::npos)
|
| @@ -180,10 +209,12 @@ bool MediaRecorderHandler::start(int timeslice) {
|
| return false;
|
| }
|
|
|
| - webm_muxer_.reset(new media::WebmMuxer(
|
| - CodecIdToMediaVideoCodec(codec_id_), use_video_tracks, use_audio_tracks,
|
| - base::Bind(&MediaRecorderHandler::WriteData,
|
| - weak_factory_.GetWeakPtr())));
|
| + if (use_container_) {
|
| + webm_muxer_.reset(new media::WebmMuxer(
|
| + CodecIdToMediaVideoCodec(codec_id_), use_video_tracks, use_audio_tracks,
|
| + base::Bind(&MediaRecorderHandler::WriteData,
|
| + weak_factory_.GetWeakPtr())));
|
| + }
|
|
|
| if (use_video_tracks) {
|
| // TODO(mcasas): The muxer API supports only one video track. Extend it to
|
| @@ -244,7 +275,8 @@ void MediaRecorderHandler::pause() {
|
| video_recorder->Pause();
|
| for (auto* audio_recorder : audio_recorders_)
|
| audio_recorder->Pause();
|
| - webm_muxer_->Pause();
|
| + if (webm_muxer_)
|
| + webm_muxer_->Pause();
|
| }
|
|
|
| void MediaRecorderHandler::resume() {
|
| @@ -255,7 +287,8 @@ void MediaRecorderHandler::resume() {
|
| video_recorder->Resume();
|
| for (auto* audio_recorder : audio_recorders_)
|
| audio_recorder->Resume();
|
| - webm_muxer_->Resume();
|
| + if (webm_muxer_)
|
| + webm_muxer_->Resume();
|
| }
|
|
|
| void MediaRecorderHandler::OnEncodedVideo(
|
| @@ -264,10 +297,12 @@ void MediaRecorderHandler::OnEncodedVideo(
|
| TimeTicks timestamp,
|
| bool is_key_frame) {
|
| DCHECK(main_render_thread_checker_.CalledOnValidThread());
|
| - if (!webm_muxer_)
|
| - return;
|
| - webm_muxer_->OnEncodedVideo(video_frame, std::move(encoded_data), timestamp,
|
| - is_key_frame);
|
| + if (webm_muxer_) {
|
| + return webm_muxer_->OnEncodedVideo(video_frame, std::move(encoded_data),
|
| + timestamp, is_key_frame);
|
| + }
|
| + DCHECK(!use_container_);
|
| + WriteData(base::StringPiece(*encoded_data.get()));
|
| }
|
|
|
| void MediaRecorderHandler::OnEncodedAudio(
|
|
|