Commit 0ec3cc16 authored by mcasas's avatar mcasas Committed by Commit bot

MediaRecorder (cleanup): support mime type video/x-matroska and codec=avc1 to the list

Following some recommendations in the spec [1] and [2],
this CL adds "video/x-matroska;codecs=avc1" and
"video/webm;codecs=avc1" to the supported list, reusing
the existing H264 encode path.

[1] https://github.com/w3c/mediacapture-record/issues/93
[2] https://github.com/w3c/mediacapture-record/issues/94

BUG=

Review-Url: https://codereview.chromium.org/2585533002
Cr-Commit-Position: refs/heads/master@{#439002}
parent eb32611e
...@@ -18,10 +18,12 @@ static const char kMediaRecorderHtmlFile[] = "/media/mediarecorder_test.html"; ...@@ -18,10 +18,12 @@ static const char kMediaRecorderHtmlFile[] = "/media/mediarecorder_test.html";
static struct EncodingParameters { static struct EncodingParameters {
bool disable_accelerator; bool disable_accelerator;
std::string video_codec; std::string mime_type;
} const kEncodingParameters[] = { } const kEncodingParameters[] = {
{true, "VP8"}, {true, "VP9"}, {true, "H264"}, {true, "video/webm;codecs=VP8"}, {true, "video/webm;codecs=VP9"},
{false, "VP8"}, {false, "VP9"}, {false, "H264"}, {true, "video/webm;codecs=avc1"}, {true, "video/x-matroska;codecs=AVC1"},
{false, "video/webm;codecs=VP8"}, {false, "video/webm;codecs=VP9"},
{false, "video/webm;codecs=H264"},
}; };
} // namespace } // namespace
...@@ -71,14 +73,14 @@ IN_PROC_BROWSER_TEST_F(WebRtcMediaRecorderTest, StartAndStop) { ...@@ -71,14 +73,14 @@ IN_PROC_BROWSER_TEST_F(WebRtcMediaRecorderTest, StartAndStop) {
IN_PROC_BROWSER_TEST_P(WebRtcMediaRecorderTest, StartAndDataAvailable) { IN_PROC_BROWSER_TEST_P(WebRtcMediaRecorderTest, StartAndDataAvailable) {
MaybeForceDisableEncodeAccelerator(GetParam().disable_accelerator); MaybeForceDisableEncodeAccelerator(GetParam().disable_accelerator);
MakeTypicalCall(base::StringPrintf("testStartAndDataAvailable(\"%s\");", MakeTypicalCall(base::StringPrintf("testStartAndDataAvailable(\"%s\");",
GetParam().video_codec.c_str()), GetParam().mime_type.c_str()),
kMediaRecorderHtmlFile); kMediaRecorderHtmlFile);
} }
IN_PROC_BROWSER_TEST_P(WebRtcMediaRecorderTest, StartWithTimeSlice) { IN_PROC_BROWSER_TEST_P(WebRtcMediaRecorderTest, StartWithTimeSlice) {
MaybeForceDisableEncodeAccelerator(GetParam().disable_accelerator); MaybeForceDisableEncodeAccelerator(GetParam().disable_accelerator);
MakeTypicalCall(base::StringPrintf("testStartWithTimeSlice(\"%s\");", MakeTypicalCall(base::StringPrintf("testStartWithTimeSlice(\"%s\");",
GetParam().video_codec.c_str()), GetParam().mime_type.c_str()),
kMediaRecorderHtmlFile); kMediaRecorderHtmlFile);
} }
...@@ -93,7 +95,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcMediaRecorderTest, NoResumeWhenRecorderInactive) { ...@@ -93,7 +95,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcMediaRecorderTest, NoResumeWhenRecorderInactive) {
IN_PROC_BROWSER_TEST_P(WebRtcMediaRecorderTest, ResumeAndDataAvailable) { IN_PROC_BROWSER_TEST_P(WebRtcMediaRecorderTest, ResumeAndDataAvailable) {
MaybeForceDisableEncodeAccelerator(GetParam().disable_accelerator); MaybeForceDisableEncodeAccelerator(GetParam().disable_accelerator);
MakeTypicalCall(base::StringPrintf("testResumeAndDataAvailable(\"%s\");", MakeTypicalCall(base::StringPrintf("testResumeAndDataAvailable(\"%s\");",
GetParam().video_codec.c_str()), GetParam().mime_type.c_str()),
kMediaRecorderHtmlFile); kMediaRecorderHtmlFile);
} }
...@@ -150,7 +152,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcMediaRecorderTest, ...@@ -150,7 +152,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcMediaRecorderTest,
IN_PROC_BROWSER_TEST_P(WebRtcMediaRecorderTest, MAYBE_PeerConnection) { IN_PROC_BROWSER_TEST_P(WebRtcMediaRecorderTest, MAYBE_PeerConnection) {
MaybeForceDisableEncodeAccelerator(GetParam().disable_accelerator); MaybeForceDisableEncodeAccelerator(GetParam().disable_accelerator);
MakeTypicalCall(base::StringPrintf("testRecordRemotePeerConnection(\"%s\");", MakeTypicalCall(base::StringPrintf("testRecordRemotePeerConnection(\"%s\");",
GetParam().video_codec.c_str()), GetParam().mime_type.c_str()),
kMediaRecorderHtmlFile); kMediaRecorderHtmlFile);
} }
......
...@@ -74,16 +74,18 @@ bool MediaRecorderHandler::canSupportMimeType( ...@@ -74,16 +74,18 @@ bool MediaRecorderHandler::canSupportMimeType(
return true; return true;
const std::string type(web_type.utf8()); const std::string type(web_type.utf8());
const bool video = base::EqualsCaseInsensitiveASCII(type, "video/webm"); const bool video = base::EqualsCaseInsensitiveASCII(type, "video/webm") ||
base::EqualsCaseInsensitiveASCII(type, "video/x-matroska");
const bool audio = const bool audio =
video ? false : base::EqualsCaseInsensitiveASCII(type, "audio/webm"); video ? false : base::EqualsCaseInsensitiveASCII(type, "audio/webm");
if (!video && !audio) if (!video && !audio)
return false; return false;
// Both |video| and |audio| support empty |codecs|; |type| == "video" supports // Both |video| and |audio| support empty |codecs|; |type| == "video" supports
// vp8, vp9 or opus; |type| = "audio", supports only opus. // vp8, vp9, h264 and avc1 or opus; |type| = "audio", supports only opus.
// http://www.webmproject.org/docs/container Sec:"HTML5 Video Type Parameters" // http://www.webmproject.org/docs/container Sec:"HTML5 Video Type Parameters"
static const char* const kVideoCodecs[] = { "vp8", "vp9", "h264", "opus" }; static const char* const kVideoCodecs[] = {"vp8", "vp9", "h264", "avc1",
"opus"};
static const char* const kAudioCodecs[] = { "opus" }; static const char* const kAudioCodecs[] = { "opus" };
const char* const* codecs = video ? &kVideoCodecs[0] : &kAudioCodecs[0]; const char* const* codecs = video ? &kVideoCodecs[0] : &kAudioCodecs[0];
const int codecs_count = const int codecs_count =
...@@ -129,6 +131,8 @@ bool MediaRecorderHandler::initialize( ...@@ -129,6 +131,8 @@ bool MediaRecorderHandler::initialize(
#if BUILDFLAG(RTC_USE_H264) #if BUILDFLAG(RTC_USE_H264)
else if (codecs_str.find("h264") != std::string::npos) else if (codecs_str.find("h264") != std::string::npos)
codec_id_ = VideoTrackRecorder::CodecId::H264; codec_id_ = VideoTrackRecorder::CodecId::H264;
else if (codecs_str.find("avc1") != std::string::npos)
codec_id_ = VideoTrackRecorder::CodecId::H264;
#endif #endif
media_stream_ = media_stream; media_stream_ = media_stream;
......
...@@ -168,11 +168,10 @@ function testStartStopAndRecorderState() { ...@@ -168,11 +168,10 @@ function testStartStopAndRecorderState() {
// Tests that when MediaRecorder's start(0) function is called, some data is // Tests that when MediaRecorder's start(0) function is called, some data is
// made available by media recorder via dataavailable events, containing non // made available by media recorder via dataavailable events, containing non
// empty blob data. // empty blob data.
function testStartAndDataAvailable(codec) { function testStartAndDataAvailable(mimeType) {
var videoSize = 0; var videoSize = 0;
var emptyBlobs = 0; var emptyBlobs = 0;
var timeStamps = []; var timeStamps = [];
const mimeType = codec ? "video/webm;codecs=" + String(codec) : "";
navigator.mediaDevices.getUserMedia(DEFAULT_CONSTRAINTS) navigator.mediaDevices.getUserMedia(DEFAULT_CONSTRAINTS)
.then(function(stream) { .then(function(stream) {
return createAndStartMediaRecorder(stream, mimeType); return createAndStartMediaRecorder(stream, mimeType);
...@@ -207,14 +206,14 @@ function testStartAndDataAvailable(codec) { ...@@ -207,14 +206,14 @@ function testStartAndDataAvailable(codec) {
// Tests that when MediaRecorder's start(timeSlice) is called, some data // Tests that when MediaRecorder's start(timeSlice) is called, some data
// available events are fired containing non empty blob data. // available events are fired containing non empty blob data.
function testStartWithTimeSlice(codec) { function testStartWithTimeSlice(mimeType) {
var videoSize = 0; var videoSize = 0;
var emptyBlobs = 0; var emptyBlobs = 0;
var timeStamps = []; var timeStamps = [];
const mimeType = codec ? "video/webm;codecs=" + String(codec) : "";
navigator.mediaDevices.getUserMedia(DEFAULT_CONSTRAINTS) navigator.mediaDevices.getUserMedia(DEFAULT_CONSTRAINTS)
.then(function(stream) { .then(function(stream) {
return createAndStartMediaRecorder(stream, mimeType, DEFAULT_TIME_SLICE); return createAndStartMediaRecorder(stream, mimeType,
DEFAULT_TIME_SLICE);
}) })
.then(function(recorder) { .then(function(recorder) {
recorder.ondataavailable = function(event) { recorder.ondataavailable = function(event) {
...@@ -287,10 +286,9 @@ function testIllegalResumeThrowsDOMError() { ...@@ -287,10 +286,9 @@ function testIllegalResumeThrowsDOMError() {
} }
// Tests that MediaRecorder sends data blobs when resume() is called. // Tests that MediaRecorder sends data blobs when resume() is called.
function testResumeAndDataAvailable(codec) { function testResumeAndDataAvailable(mimeType) {
var videoSize = 0; var videoSize = 0;
var emptyBlobs = 0; var emptyBlobs = 0;
const mimeType = codec ? "video/webm;codecs=" + String(codec) : "";
navigator.mediaDevices.getUserMedia(DEFAULT_CONSTRAINTS) navigator.mediaDevices.getUserMedia(DEFAULT_CONSTRAINTS)
.then(function(stream) { .then(function(stream) {
return createAndStartMediaRecorder(stream, mimeType); return createAndStartMediaRecorder(stream, mimeType);
...@@ -413,10 +411,9 @@ function testIllegalPauseThrowsDOMError() { ...@@ -413,10 +411,9 @@ function testIllegalPauseThrowsDOMError() {
} }
// Tests that a remote peer connection stream can be successfully recorded. // Tests that a remote peer connection stream can be successfully recorded.
function testRecordRemotePeerConnection(codec) { function testRecordRemotePeerConnection(mimeType) {
var videoSize = 0; var videoSize = 0;
var timeStamps = []; var timeStamps = [];
const mimeType = codec ? "video/webm;codecs=" + String(codec) : "";
navigator.mediaDevices.getUserMedia(DEFAULT_CONSTRAINTS) navigator.mediaDevices.getUserMedia(DEFAULT_CONSTRAINTS)
.then(function(localStream) { .then(function(localStream) {
return setupPeerConnection(localStream); return setupPeerConnection(localStream);
......
...@@ -20,6 +20,7 @@ test(function() { ...@@ -20,6 +20,7 @@ test(function() {
assert_true(MediaRecorder.isTypeSupported("video/webm;codecs=vp9.0")); assert_true(MediaRecorder.isTypeSupported("video/webm;codecs=vp9.0"));
assert_true(MediaRecorder.isTypeSupported("video/webm;codecs=h264")); assert_true(MediaRecorder.isTypeSupported("video/webm;codecs=h264"));
assert_true(MediaRecorder.isTypeSupported("video/webm;codecs=H264")); assert_true(MediaRecorder.isTypeSupported("video/webm;codecs=H264"));
assert_true(MediaRecorder.isTypeSupported("video/webm;codecs=avc1"));
// "video/webm" supports audio codec specification, see // "video/webm" supports audio codec specification, see
// http://www.webmproject.org/docs/container/ // http://www.webmproject.org/docs/container/
assert_true(MediaRecorder.isTypeSupported("video/webm;codecs=vp8,opus")); assert_true(MediaRecorder.isTypeSupported("video/webm;codecs=vp8,opus"));
...@@ -28,6 +29,8 @@ test(function() { ...@@ -28,6 +29,8 @@ test(function() {
assert_true(MediaRecorder.isTypeSupported("video/webm;codecs=vp8,vp9,opus")); assert_true(MediaRecorder.isTypeSupported("video/webm;codecs=vp8,vp9,opus"));
assert_true(MediaRecorder.isTypeSupported("video/webm;codecs=h264,opus")); assert_true(MediaRecorder.isTypeSupported("video/webm;codecs=h264,opus"));
assert_true(MediaRecorder.isTypeSupported("video/webm;codecs=h264,vp9,opus")); assert_true(MediaRecorder.isTypeSupported("video/webm;codecs=h264,vp9,opus"));
// https://matroska.org/technical/specs/notes.html#MIME
assert_true(MediaRecorder.isTypeSupported("video/x-matroska;codecs=avc1"));
}, 'check MediaRecorder.isTypeSupported() with valid video MIME types'); }, 'check MediaRecorder.isTypeSupported() with valid video MIME types');
test(function() { test(function() {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment