Commit 806e82b0 authored by Chris Cunningham's avatar Chris Cunningham Committed by Commit Bot

[RELAND] media: Add H264 profile extraction support

Originally reviewed-on: https://chromium-review.googlesource.com/c/1292605

No change to the files in the reland. Added new web test. The issue that
caused the revert is addressed in dependent CLs (crbug/911823).

-- begin original commit msg --

Without the ffmpeg decoder configured, libavformat is unable to get the
codec profile and chromium ffmpeg wrapper code choose some defaults.
This will mess up the decode scenarios where non-ffmpeg decoders like vaapi
are in use. Fortunately, we can still get hold of the ffmpeg's
AVStream extradata param which should contain the
H264 AVCDecoderConfigurationRecord (ISO/IEC 14496-15).
So we use internal parser for extracting profile information
from this AVCDecoderConfigurationRecord.

BUG=784610,911823
TEST=media_unittests:FFmpegCommonTest.VerifyH264Profile
TBR=tguilbert@chromium.org

Change-Id: I021fb2c92e56846824a9e362d8f3ec8665724fb5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1362468Reviewed-by: default avatarChrome Cunningham <chcunningham@chromium.org>
Reviewed-by: default avatarThomas Guilbert <tguilbert@chromium.org>
Commit-Queue: Chrome Cunningham <chcunningham@chromium.org>
Cr-Commit-Position: refs/heads/master@{#637915}
parent 374813d9
...@@ -30,6 +30,7 @@ source_set("ffmpeg") { ...@@ -30,6 +30,7 @@ source_set("ffmpeg") {
deps = [ deps = [
"//base", "//base",
"//media/base", "//media/base",
"//media/formats",
"//third_party/ffmpeg", "//third_party/ffmpeg",
"//third_party/ffmpeg:ffmpeg_features", "//third_party/ffmpeg:ffmpeg_features",
] ]
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "media/base/media_util.h" #include "media/base/media_util.h"
#include "media/base/video_decoder_config.h" #include "media/base/video_decoder_config.h"
#include "media/base/video_util.h" #include "media/base/video_util.h"
#include "media/formats/mp4/box_definitions.h"
#include "media/media_buildflags.h" #include "media/media_buildflags.h"
namespace media { namespace media {
...@@ -479,11 +480,26 @@ bool AVStreamToVideoDecoderConfig(const AVStream* stream, ...@@ -479,11 +480,26 @@ bool AVStreamToVideoDecoderConfig(const AVStream* stream,
// actually handle capabilities requests correctly. http://crbug.com/784610 // actually handle capabilities requests correctly. http://crbug.com/784610
VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN; VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN;
switch (codec) { switch (codec) {
#if !BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS) #if BUILDFLAG(USE_PROPRIETARY_CODECS)
case kCodecH264: case kCodecH264: {
profile = ProfileIDToVideoCodecProfile(codec_context->profile);
// if the profile is still unknown, try to extract it from
// the extradata using the internal parser
if (profile == VIDEO_CODEC_PROFILE_UNKNOWN && codec_context->extradata &&
codec_context->extradata_size) {
mp4::AVCDecoderConfigurationRecord avc_config;
if (avc_config.Parse(codec_context->extradata,
codec_context->extradata_size)) {
profile = ProfileIDToVideoCodecProfile(avc_config.profile_indication);
}
}
// All the heuristics failed, let's assign a default profile
if (profile == VIDEO_CODEC_PROFILE_UNKNOWN)
profile = H264PROFILE_BASELINE;
format = PIXEL_FORMAT_I420; format = PIXEL_FORMAT_I420;
profile = H264PROFILE_BASELINE;
break; break;
}
#endif #endif
case kCodecVP8: case kCodecVP8:
#if !BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS) #if !BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS)
......
...@@ -296,5 +296,31 @@ TEST_F(FFmpegCommonTest, VerifyUmaCodecHashes) { ...@@ -296,5 +296,31 @@ TEST_F(FFmpegCommonTest, VerifyUmaCodecHashes) {
printf("</enum>\n"); printf("</enum>\n");
#endif #endif
} }
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
TEST_F(FFmpegCommonTest, VerifyH264Profile) {
// Open a file to get a real AVStreams from FFmpeg.
base::MemoryMappedFile file;
ASSERT_TRUE(file.Initialize(GetTestDataFilePath("bear-1280x720.mp4")));
InMemoryUrlProtocol protocol(file.data(), file.length(), false);
FFmpegGlue glue(&protocol);
ASSERT_TRUE(glue.OpenContext());
AVFormatContext* format_context = glue.format_context();
for (size_t i = 0; i < format_context->nb_streams; ++i) {
AVStream* stream = format_context->streams[i];
AVCodecParameters* codec_parameters = stream->codecpar;
AVMediaType codec_type = codec_parameters->codec_type;
if (codec_type == AVMEDIA_TYPE_VIDEO) {
VideoDecoderConfig video_config;
EXPECT_TRUE(AVStreamToVideoDecoderConfig(stream, &video_config));
EXPECT_EQ(H264PROFILE_HIGH, video_config.profile());
} else {
// Only process video.
continue;
}
}
}
#endif
} // namespace media } // namespace media
...@@ -14,6 +14,7 @@ source_set("formats") { ...@@ -14,6 +14,7 @@ source_set("formats") {
"//media/cdm", "//media/cdm",
"//media/filters", "//media/filters",
"//media/muxers", "//media/muxers",
"//media/ffmpeg",
] ]
sources = [ sources = [
......
...@@ -26,7 +26,9 @@ var testInfo = [ ...@@ -26,7 +26,9 @@ var testInfo = [
{ element: "audio", typeArray: ["audio/wav", "audio/ogg"], srcArray: ["content/test.wav", "content/test.oga"], description: "Test audio with ['audio/wav', 'audio/ogg']" }, { element: "audio", typeArray: ["audio/wav", "audio/ogg"], srcArray: ["content/test.wav", "content/test.oga"], description: "Test audio with ['audio/wav', 'audio/ogg']" },
{ element: "audio", typeArray: ["audio/ogg", "audio/wav"], srcArray: ["content/test.oga", "content/test.wav"], description: "Test audio with ['audio/ogg', 'audio/wav']" }, { element: "audio", typeArray: ["audio/ogg", "audio/wav"], srcArray: ["content/test.oga", "content/test.wav"], description: "Test audio with ['audio/ogg', 'audio/wav']" },
{ element: "video", srcArray: [mp4DataSrc, ogvDataSrc], description: "Test video with ['data:video/mp4;base64', 'data:video/ogg;base64']" }, { element: "video", srcArray: [mp4DataSrc, ogvDataSrc], description: "Test video with ['data:video/mp4;base64', 'data:video/ogg;base64']" },
{ element: "video", srcArray: [ogvDataSrc, mp4DataSrc], description: "Test video with ['data:video/ogg;base64', 'data:video/mp4;base64']" } { element: "video", srcArray: [ogvDataSrc, mp4DataSrc], description: "Test video with ['data:video/ogg;base64', 'data:video/mp4;base64']" },
{ element: "audio", typeArray: ["audio/mp4", "audio/ogg"], srcArray: ["content/test.m4a", "content/test.oga"], description: "Test audio with ['audio/mp4', \"audio/ogg\"]" },
{ element: "audio", typeArray: ["audio/ogg", "audio/mp4"], srcArray: ["content/test.oga", "content/test.m4a"], description: "Test audio with ['audio/ogg', \"audio/mp4\"]" },
]; ];
testInfo.forEach(function(test) { testInfo.forEach(function(test) {
......
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