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( |