Commit 904b7a6f authored by mcasas's avatar mcasas Committed by Commit bot

MediaRecorder: use VideoTrackRecorder::GetPreferredCodecId() when available

This CL adds a static method to VTR to query which
one, if any, is the preferred video codec.

A new singleton Lazy Leaky class CodecEnumerator is
added to encapsulate poking the VEA to see which
codecs are supported, and to further query
a) the preferred codec id
b) if a given codec is supported
and wraps the previous CodecIdToVEAProfile()
functionality.

BUG=679946

Review-Url: https://codereview.chromium.org/2624053002
Cr-Commit-Position: refs/heads/master@{#443165}
parent 14f22398
...@@ -23,6 +23,7 @@ static struct EncodingParameters { ...@@ -23,6 +23,7 @@ static struct EncodingParameters {
{true, "video/webm;codecs=VP8"}, {true, "video/webm;codecs=VP8"},
{true, "video/webm;codecs=VP9"}, {true, "video/webm;codecs=VP9"},
{true, "video/x-matroska;codecs=AVC1"}, {true, "video/x-matroska;codecs=AVC1"},
{false, ""}, // Instructs the platform to choose any accelerated codec.
{false, "video/webm;codecs=VP8"}, {false, "video/webm;codecs=VP8"},
{false, "video/webm;codecs=VP9"}, {false, "video/webm;codecs=VP9"},
{false, "video/x-matroska;codecs=AVC1"}, {false, "video/x-matroska;codecs=AVC1"},
......
...@@ -42,6 +42,8 @@ media::VideoCodec CodecIdToMediaVideoCodec(VideoTrackRecorder::CodecId id) { ...@@ -42,6 +42,8 @@ media::VideoCodec CodecIdToMediaVideoCodec(VideoTrackRecorder::CodecId id) {
return media::kCodecVP9; return media::kCodecVP9;
case VideoTrackRecorder::CodecId::H264: case VideoTrackRecorder::CodecId::H264:
return media::kCodecH264; return media::kCodecH264;
case VideoTrackRecorder::CodecId::LAST:
return media::kUnknownVideoCodec;
} }
NOTREACHED() << "Unsupported codec"; NOTREACHED() << "Unsupported codec";
return media::kUnknownVideoCodec; return media::kUnknownVideoCodec;
...@@ -119,8 +121,7 @@ bool MediaRecorderHandler::initialize( ...@@ -119,8 +121,7 @@ bool MediaRecorderHandler::initialize(
UpdateWebRTCMethodCount(WEBKIT_MEDIA_STREAM_RECORDER); UpdateWebRTCMethodCount(WEBKIT_MEDIA_STREAM_RECORDER);
if (!canSupportMimeType(type, codecs)) { if (!canSupportMimeType(type, codecs)) {
DLOG(ERROR) << "Can't support " << type.utf8() DLOG(ERROR) << "Unsupported " << type.utf8() << ";codecs=" << codecs.utf8();
<< ";codecs=" << codecs.utf8();
return false; return false;
} }
...@@ -136,6 +137,11 @@ bool MediaRecorderHandler::initialize( ...@@ -136,6 +137,11 @@ bool MediaRecorderHandler::initialize(
else if (codecs_str.find("avc1") != std::string::npos) else if (codecs_str.find("avc1") != std::string::npos)
codec_id_ = VideoTrackRecorder::CodecId::H264; codec_id_ = VideoTrackRecorder::CodecId::H264;
#endif #endif
else
codec_id_ = VideoTrackRecorder::GetPreferredCodecId();
DVLOG_IF(1, codecs_str.empty()) << "Falling back to preferred codec id "
<< static_cast<int>(codec_id_);
media_stream_ = media_stream; media_stream_ = media_stream;
DCHECK(client); DCHECK(client);
......
...@@ -60,60 +60,98 @@ const int kVEADefaultBitratePerPixel = 2; ...@@ -60,60 +60,98 @@ const int kVEADefaultBitratePerPixel = 2;
// encoders. // encoders.
const int kVEAEncoderOutputBufferCount = 4; const int kVEAEncoderOutputBufferCount = 4;
static struct { using CodecId = VideoTrackRecorder::CodecId;
VideoTrackRecorder::CodecId codec_id;
static const struct {
CodecId codec_id;
media::VideoCodecProfile min_profile; media::VideoCodecProfile min_profile;
media::VideoCodecProfile max_profile; media::VideoCodecProfile max_profile;
} const kSupportedVideoCodecIdToProfile[] = { } kPreferredCodecIdAndVEAProfiles[] = {
{VideoTrackRecorder::CodecId::VP8, {CodecId::VP8, media::VP8PROFILE_MIN, media::VP8PROFILE_MAX},
media::VP8PROFILE_MIN, {CodecId::VP9, media::VP9PROFILE_MIN, media::VP9PROFILE_MAX},
media::VP8PROFILE_MAX}, {CodecId::H264, media::H264PROFILE_MIN, media::H264PROFILE_MAX}};
{VideoTrackRecorder::CodecId::VP9,
media::VP9PROFILE_MIN, static_assert(arraysize(kPreferredCodecIdAndVEAProfiles) ==
media::VP9PROFILE_MAX}, static_cast<int>(CodecId::LAST),
{VideoTrackRecorder::CodecId::H264, "|kPreferredCodecIdAndVEAProfiles| should consider all CodecIds");
media::H264PROFILE_MIN,
media::H264PROFILE_MAX}}; // Class to encapsulate the enumeration of CodecIds/VideoCodecProfiles supported
// by the VEA underlying platform. Provides methods to query the preferred
// Returns the corresponding codec profile from VEA supported codecs. If no // CodecId and to check if a given CodecId is supported.
// profile is found, returns VIDEO_CODEC_PROFILE_UNKNOWN. class CodecEnumerator {
media::VideoCodecProfile CodecIdToVEAProfile( public:
content::VideoTrackRecorder::CodecId codec) { CodecEnumerator();
// See https://crbug.com/616659. ~CodecEnumerator() = default;
// Returns the first CodecId that has an associated VEA VideoCodecProfile, or
// VP8 if none available.
CodecId GetPreferredCodecId();
// Returns the VEA VideoCodedProfile for a given CodecId, if supported, or
// VIDEO_CODEC_PROFILE_UNKNOWN otherwise.
media::VideoCodecProfile CodecIdToVEAProfile(CodecId codec);
private:
// A map of VEA-supported CodecId-and-VEA-profile pairs.
std::map<CodecId, media::VideoCodecProfile> codec_id_to_profile_;
DISALLOW_COPY_AND_ASSIGN(CodecEnumerator);
};
static base::LazyInstance<CodecEnumerator>::Leaky g_codec_enumerator =
LAZY_INSTANCE_INITIALIZER;
CodecEnumerator::CodecEnumerator() {
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
return media::VIDEO_CODEC_PROFILE_UNKNOWN; // See https://crbug.com/616659.
#endif // defined(OS_CHROMEOS) return;
#endif
// See https://crbug.com/653864.
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
return media::VIDEO_CODEC_PROFILE_UNKNOWN; // See https://crbug.com/653864.
#endif // defined(OS_ANDROID) return;
#endif
content::RenderThreadImpl* const render_thread_impl = content::RenderThreadImpl* const render_thread_impl =
content::RenderThreadImpl::current(); content::RenderThreadImpl::current();
if (!render_thread_impl) { if (!render_thread_impl) {
DVLOG(3) << "Couldn't access the render thread"; DVLOG(2) << "Couldn't access the render thread";
return media::VIDEO_CODEC_PROFILE_UNKNOWN; return;
} }
media::GpuVideoAcceleratorFactories* const gpu_factories = media::GpuVideoAcceleratorFactories* const gpu_factories =
render_thread_impl->GetGpuFactories(); render_thread_impl->GetGpuFactories();
if (!gpu_factories || !gpu_factories->IsGpuVideoAcceleratorEnabled()) { if (!gpu_factories || !gpu_factories->IsGpuVideoAcceleratorEnabled()) {
DVLOG(3) << "Couldn't initialize GpuVideoAcceleratorFactories"; DVLOG(2) << "Couldn't initialize GpuVideoAcceleratorFactories";
return media::VIDEO_CODEC_PROFILE_UNKNOWN; return;
} }
const media::VideoEncodeAccelerator::SupportedProfiles& vea_profiles = const auto vea_supported_profiles =
gpu_factories->GetVideoEncodeAcceleratorSupportedProfiles(); gpu_factories->GetVideoEncodeAcceleratorSupportedProfiles();
for (const auto& vea_profile : vea_profiles) { for (const auto& supported_profile : vea_supported_profiles) {
for (const auto& supported_profile : kSupportedVideoCodecIdToProfile) { for (auto& codec_id_and_profile : kPreferredCodecIdAndVEAProfiles) {
if (codec == supported_profile.codec_id && if (supported_profile.profile >= codec_id_and_profile.min_profile &&
vea_profile.profile >= supported_profile.min_profile && supported_profile.profile <= codec_id_and_profile.max_profile) {
vea_profile.profile <= supported_profile.max_profile) DVLOG(2) << "Accelerated codec found: "
return vea_profile.profile; << media::GetProfileName(supported_profile.profile);
codec_id_to_profile_.insert(std::make_pair(
codec_id_and_profile.codec_id, supported_profile.profile));
}
} }
} }
return media::VIDEO_CODEC_PROFILE_UNKNOWN; }
CodecId CodecEnumerator::GetPreferredCodecId() {
if (codec_id_to_profile_.empty())
return CodecId::VP8;
return codec_id_to_profile_.begin()->first;
}
media::VideoCodecProfile CodecEnumerator::CodecIdToVEAProfile(CodecId codec) {
const auto profile = codec_id_to_profile_.find(codec);
return profile == codec_id_to_profile_.end()
? media::VIDEO_CODEC_PROFILE_UNKNOWN
: profile->second;
} }
} // anonymous namespace } // anonymous namespace
...@@ -1075,6 +1113,11 @@ void H264Encoder::ConfigureEncoderOnEncodingTaskRunner(const gfx::Size& size) { ...@@ -1075,6 +1113,11 @@ void H264Encoder::ConfigureEncoderOnEncodingTaskRunner(const gfx::Size& size) {
} // anonymous namespace } // anonymous namespace
// static
VideoTrackRecorder::CodecId VideoTrackRecorder::GetPreferredCodecId() {
return g_codec_enumerator.Get().GetPreferredCodecId();
}
VideoTrackRecorder::VideoTrackRecorder( VideoTrackRecorder::VideoTrackRecorder(
CodecId codec, CodecId codec,
const blink::WebMediaStreamTrack& track, const blink::WebMediaStreamTrack& track,
...@@ -1143,7 +1186,8 @@ void VideoTrackRecorder::InitializeEncoder( ...@@ -1143,7 +1186,8 @@ void VideoTrackRecorder::InitializeEncoder(
MediaStreamVideoSink::DisconnectFromTrack(); MediaStreamVideoSink::DisconnectFromTrack();
const gfx::Size& input_size = frame->visible_rect().size(); const gfx::Size& input_size = frame->visible_rect().size();
const auto& vea_supported_profile = CodecIdToVEAProfile(codec); const auto& vea_supported_profile =
g_codec_enumerator.Get().CodecIdToVEAProfile(codec);
if (vea_supported_profile != media::VIDEO_CODEC_PROFILE_UNKNOWN && if (vea_supported_profile != media::VIDEO_CODEC_PROFILE_UNKNOWN &&
input_size.width() >= kVEAEncoderMinResolutionWidth && input_size.width() >= kVEAEncoderMinResolutionWidth &&
input_size.height() >= kVEAEncoderMinResolutionHeight) { input_size.height() >= kVEAEncoderMinResolutionHeight) {
......
...@@ -37,10 +37,12 @@ namespace content { ...@@ -37,10 +37,12 @@ namespace content {
class CONTENT_EXPORT VideoTrackRecorder class CONTENT_EXPORT VideoTrackRecorder
: NON_EXPORTED_BASE(public MediaStreamVideoSink) { : NON_EXPORTED_BASE(public MediaStreamVideoSink) {
public: public:
// Do not change the order of codecs; add new ones right before LAST.
enum class CodecId { enum class CodecId {
VP8, VP8,
VP9, VP9,
H264, H264,
LAST
}; };
class Encoder; class Encoder;
...@@ -50,6 +52,8 @@ class CONTENT_EXPORT VideoTrackRecorder ...@@ -50,6 +52,8 @@ class CONTENT_EXPORT VideoTrackRecorder
base::TimeTicks capture_timestamp, base::TimeTicks capture_timestamp,
bool is_key_frame)>; bool is_key_frame)>;
static CodecId GetPreferredCodecId();
VideoTrackRecorder(CodecId codec, VideoTrackRecorder(CodecId codec,
const blink::WebMediaStreamTrack& track, const blink::WebMediaStreamTrack& track,
const OnEncodedVideoCB& on_encoded_video_cb, const OnEncodedVideoCB& on_encoded_video_cb,
......
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