Commit 59f0d053 authored by Miguel Casas's avatar Miguel Casas Committed by Commit Bot

MediaRecorder: Retrieve actual recording mime type if not user-specified

This CL introduces a new  MediaRecorderHandler::ActualMimeType() method
that produces the mimeType used for recording by MRHandler. This method
is then called from Blink's MediaRecorder when the user has specified
no mime type for recording, so the output Blobs can have the correct
type.

Bug: 859199
Change-Id: I941f46a2ef495f5ac68995f79319fe6f07836a89
Reviewed-on: https://chromium-review.googlesource.com/1121141Reviewed-by: default avatarKent Tamura <tkent@chromium.org>
Reviewed-by: default avatarEmircan Uysaler <emircan@chromium.org>
Commit-Queue: Miguel Casas <mcasas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#572207}
parent cc396e0d
......@@ -123,8 +123,8 @@ MediaRecorderHandler::MediaRecorderHandler(
scoped_refptr<base::SingleThreadTaskRunner> task_runner)
: video_bits_per_second_(0),
audio_bits_per_second_(0),
video_codec_id_(VideoTrackRecorder::CodecId::VP8),
audio_codec_id_(AudioTrackRecorder::CodecId::OPUS),
video_codec_id_(VideoTrackRecorder::CodecId::LAST),
audio_codec_id_(AudioTrackRecorder::CodecId::LAST),
recording_(false),
client_(nullptr),
task_runner_(std::move(task_runner)),
......@@ -399,6 +399,72 @@ void MediaRecorderHandler::EncodingInfo(
scoped_callbacks.PassCallbacks()->OnSuccess(std::move(info));
}
blink::WebString MediaRecorderHandler::ActualMimeType() {
DCHECK(main_render_thread_checker_.CalledOnValidThread());
DCHECK(client_) << __func__ << " should be called after Initialize()";
const bool has_video_tracks = !media_stream_.VideoTracks().empty();
const bool has_audio_tracks = !media_stream_.AudioTracks().empty();
if (!has_video_tracks && !has_audio_tracks)
return blink::WebString();
std::string mime_type;
if (!has_video_tracks && has_audio_tracks) {
mime_type.append("audio/webm;codecs=");
} else {
switch (video_codec_id_) {
case VideoTrackRecorder::CodecId::VP8:
case VideoTrackRecorder::CodecId::VP9:
mime_type.append("video/webm;codecs=");
break;
#if BUILDFLAG(RTC_USE_H264)
case VideoTrackRecorder::CodecId::H264:
mime_type.append("video/x-matroska;codecs=");
break;
#endif
case VideoTrackRecorder::CodecId::LAST:
// Do nothing.
break;
}
}
if (has_video_tracks) {
switch (video_codec_id_) {
case VideoTrackRecorder::CodecId::VP8:
mime_type.append("vp8");
break;
case VideoTrackRecorder::CodecId::VP9:
mime_type.append("vp9");
break;
#if BUILDFLAG(RTC_USE_H264)
case VideoTrackRecorder::CodecId::H264:
mime_type.append("avc1");
break;
#endif
case VideoTrackRecorder::CodecId::LAST:
DCHECK_NE(audio_codec_id_, AudioTrackRecorder::CodecId::LAST);
}
}
if (has_video_tracks && has_audio_tracks) {
if (video_codec_id_ != VideoTrackRecorder::CodecId::LAST &&
audio_codec_id_ != AudioTrackRecorder::CodecId::LAST) {
mime_type.append(",");
}
}
if (has_audio_tracks) {
switch (audio_codec_id_) {
case AudioTrackRecorder::CodecId::OPUS:
mime_type.append("opus");
break;
case AudioTrackRecorder::CodecId::PCM:
mime_type.append("pcm");
break;
case AudioTrackRecorder::CodecId::LAST:
DCHECK_NE(video_codec_id_, VideoTrackRecorder::CodecId::LAST);
}
}
return blink::WebString::FromUTF8(mime_type);
}
void MediaRecorderHandler::OnEncodedVideo(
const media::WebmMuxer::VideoParameters& params,
std::unique_ptr<std::string> encoded_data,
......
......@@ -67,6 +67,7 @@ class CONTENT_EXPORT MediaRecorderHandler final
void EncodingInfo(
const blink::WebMediaConfiguration& configuration,
std::unique_ptr<blink::WebMediaCapabilitiesQueryCallbacks> cb) override;
blink::WebString ActualMimeType() override;
private:
friend class MediaRecorderHandlerTest;
......
......@@ -65,11 +65,12 @@ static const MediaRecorderTestParams kMediaRecorderTestParams[] = {
{true, false, "video/webm", "vp8", true},
{true, false, "video/webm", "vp9", true},
#if BUILDFLAG(RTC_USE_H264)
{true, false, "video/webm", "h264", false},
{true, false, "video/x-matroska", "avc1", false},
#endif
{false, true, "audio/webm", "opus", true},
{false, true, "audio/webm", "", true}, // Should default to opus.
{false, true, "audio/webm", "pcm", true},
{true, true, "video/webm", "vp9,opus", true},
};
class MediaRecorderHandlerTest : public TestWithParam<MediaRecorderTestParams>,
......@@ -429,6 +430,29 @@ TEST_P(MediaRecorderHandlerTest, WebmMuxerErrorWhileEncoding) {
run_loop.Run();
}
// Expect a last call on destruction, with size 0 and |lastInSlice| true.
EXPECT_CALL(*this, WriteData(nullptr, 0, true, _)).Times(1);
media_recorder_handler_.reset();
}
// Checks the ActualMimeType() versus the expected.
TEST_P(MediaRecorderHandlerTest, ActualMimeType) {
AddTracks();
const WebString mime_type(WebString::FromASCII(GetParam().mime_type));
const WebString codecs(WebString::FromASCII(GetParam().codecs));
EXPECT_TRUE(media_recorder_handler_->Initialize(this, registry_.test_stream(),
mime_type, codecs, 0, 0));
std::string actual_mime_type(GetParam().mime_type);
actual_mime_type.append(";codecs=");
if (strlen(GetParam().codecs) != 0u)
actual_mime_type.append(GetParam().codecs);
else if (GetParam().has_video)
actual_mime_type.append("vp8");
else if (GetParam().has_audio)
actual_mime_type.append("opus");
EXPECT_EQ(media_recorder_handler_->ActualMimeType().Utf8(), actual_mime_type);
// Expect a last call on destruction, with size 0 and |lastInSlice| true.
EXPECT_CALL(*this, WriteData(nullptr, 0, true, _)).Times(1);
......
......@@ -26,7 +26,7 @@ var makeAsyncTest = function(value, expected) {
async_test(function(test) {
const recorderOnDataAvailable = test.step_func_done(function(event) {
assert_equals(event.data.size, 0, 'Recorded data size should be == 0');
assert_equals(event.data.type, "video/webm");
assert_equals(event.data.type, value['mimeType']);
assert_not_equals(event.timecode, NaN, 'timecode');
});
......@@ -60,8 +60,11 @@ var makeAsyncTest = function(value, expected) {
};
generate_tests(makeAsyncTest,
[["video-only", {video: true, audio: false}],
["audio-only", {video: false, audio: true}],
["audio-video", {video: true, audio: true}]]);
[["video-only",
{video: true, audio: false, mimeType: "video/webm;codecs=vp8"}],
["audio-only",
{video: false, audio: true, mimeType: "audio/webm;codecs=opus"}],
["audio-video",
{video: true, audio: true, mimeType: "video/webm;codecs=vp8,opus"}]]);
</script>
......@@ -10,13 +10,13 @@
#include "third_party/blink/public/platform/web_common.h"
#include "third_party/blink/public/platform/modules/media_capabilities/web_media_capabilities_info.h"
#include "third_party/blink/public/platform/web_string.h"
namespace blink {
class WebMediaRecorderHandlerClient;
struct WebMediaConfiguration;
class WebMediaStream;
class WebString;
// Platform interface of a MediaRecorder.
class BLINK_PLATFORM_EXPORT WebMediaRecorderHandler {
......@@ -47,6 +47,9 @@ class BLINK_PLATFORM_EXPORT WebMediaRecorderHandler {
return false;
}
// What is really being encoded???
virtual WebString ActualMimeType() { return WebString(); }
// Implements WICG Media Capabilities encodingInfo() call for local encoding.
// https://wicg.github.io/media-capabilities/#media-capabilities-interface
virtual void EncodingInfo(
......
......@@ -202,6 +202,12 @@ MediaRecorder::MediaRecorder(ExecutionContext* context,
mime_type_ + ") is not supported.");
return;
}
// If the user requested no mimeType, query |recorder_handler_|.
if (options.mimeType().IsEmpty()) {
const String actual_mime_type = recorder_handler_->ActualMimeType();
if (!actual_mime_type.IsEmpty())
mime_type_ = actual_mime_type;
}
stopped_ = false;
}
......
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