Commit 61cdd525 authored by Dale Curtis's avatar Dale Curtis Committed by Commit Bot

Add profile parsing from the 'av1C' MP4 atom. Enable fuzzing.

This implements reading of the 'seq_profile' value from the
'av1C' atom per the spec description here:
https://aomediacodec.github.io/av1-isobmff/#av1codecconfigurationbox
https://aomediacodec.github.io/av1-spec/av1-spec.pdf (Section 5.2)

This also re-enables previously disabled tests and adds the various
bits necessary for av1 fuzzer tests.

Bug: 757047, 784993, 784607
Test: Updated unittests and fuzzertests.
Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;luci.chromium.try:linux_optional_gpu_tests_rel;luci.chromium.try:mac_optional_gpu_tests_rel;luci.chromium.try:win_optional_gpu_tests_rel
Change-Id: I05d8d42c8c022b7dc508ab8d212ad846ae1de8b6
Reviewed-on: https://chromium-review.googlesource.com/1107260
Commit-Queue: Dale Curtis <dalecurtis@chromium.org>
Reviewed-by: default avatarChrome Cunningham (In Paris) <chcunningham@chromium.org>
Reviewed-by: default avatarTom Finegan <tomfinegan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#576335}
parent 416d2b05
......@@ -690,6 +690,92 @@ bool VPCodecConfigurationRecord::Parse(BoxReader* reader) {
return true;
}
#if BUILDFLAG(ENABLE_AV1_DECODER)
AV1CodecConfigurationRecord::AV1CodecConfigurationRecord()
: profile(VIDEO_CODEC_PROFILE_UNKNOWN) {}
AV1CodecConfigurationRecord::AV1CodecConfigurationRecord(
const AV1CodecConfigurationRecord& other) = default;
AV1CodecConfigurationRecord::~AV1CodecConfigurationRecord() = default;
FourCC AV1CodecConfigurationRecord::BoxType() const {
return FOURCC_AV1C;
}
bool AV1CodecConfigurationRecord::Parse(BoxReader* reader) {
RCHECK(reader->ReadFullBoxHeader());
// Skip over unused parts of the configuration record.
RCHECK(reader->SkipBytes(1));
// We need to scan through the OBUs to find the profile.
while (profile == VIDEO_CODEC_PROFILE_UNKNOWN) {
// Zero or more OBUs are allowed, when none are present assume main profile.
if (!reader->HasBytes(1)) {
DVLOG(2) << "No OBU_SEQUENCE_HEADER is present, assuming main profile.";
profile = AV1PROFILE_PROFILE_MAIN;
return true;
}
uint8_t obu_header;
RCHECK(reader->Read1(&obu_header));
// Skip over the extension header if needed.
if (obu_header & 0b100 /* obu_extension_flag */)
RCHECK(reader->SkipBytes(1));
// Low overhead bitstream OBUs, when contained within configOBUs, are
// required to have a size field.
DCHECK(obu_header & 0b10 /* obu_has_size_field */);
// Read the size out in LEB128 format. Per spec this must always fit in a
// uint32_t, but since the max shift below is 49 (7*7), use a uint64_t to
// avoid any undefined behavior.
uint64_t obu_size = 0u;
for (int i = 0; i < 8; ++i) {
uint8_t leb128_byte;
RCHECK(reader->Read1(&leb128_byte));
obu_size |= static_cast<uint64_t>(leb128_byte & 0x7f) << (i * 7);
if (!(leb128_byte & 0x80))
break;
}
RCHECK(reader->HasBytes(obu_size));
// Clear out everything except for the obu_type.
const uint8_t obu_type = (obu_header >> 3) & 0b1111;
// We only want to look at OBUs of type OBU_SEQUENCE_HEADER.
if (obu_type != 1 /* OBU_SEQUENCE_HEADER */) {
RCHECK(reader->SkipBytes(obu_size));
continue;
}
// Read enough of the sequence header to parse |seq_profile|.
uint8_t sequence_header;
RCHECK(reader->Read1(&sequence_header));
const uint8_t seq_profile = sequence_header >> 5;
switch (seq_profile) {
case 0:
profile = AV1PROFILE_PROFILE_MAIN;
break;
case 1:
profile = AV1PROFILE_PROFILE_HIGH;
break;
case 2:
profile = AV1PROFILE_PROFILE_PRO;
break;
default:
MEDIA_LOG(ERROR, reader->media_log())
<< "Unsupported AV1 profile: 0x" << std::hex << seq_profile;
return false;
}
}
return true;
}
#endif // BUILDFLAG(ENABLE_AV1_DECODER)
PixelAspectRatioBox::PixelAspectRatioBox() : h_spacing(1), v_spacing(1) {}
PixelAspectRatioBox::PixelAspectRatioBox(const PixelAspectRatioBox& other) =
default;
......@@ -842,11 +928,11 @@ bool VideoSampleEntry::Parse(BoxReader* reader) {
#if BUILDFLAG(ENABLE_AV1_DECODER)
case FOURCC_AV01: {
DVLOG(2) << __func__ << " reading AV1 configuration.";
// TODO(dalecurtis): This needs updating to read the actual profile and
// configuration before enabling for release. http://crbug.com/784993
AV1CodecConfigurationRecord av1_config;
RCHECK(reader->ReadChild(&av1_config));
frame_bitstream_converter = nullptr;
video_codec = kCodecAV1;
video_codec_profile = AV1PROFILE_PROFILE_MAIN;
video_codec_profile = av1_config.profile;
break;
}
#endif
......
......@@ -252,6 +252,14 @@ struct MEDIA_EXPORT VPCodecConfigurationRecord : Box {
VideoCodecProfile profile;
};
#if BUILDFLAG(ENABLE_AV1_DECODER)
struct MEDIA_EXPORT AV1CodecConfigurationRecord : Box {
DECLARE_BOX_METHODS(AV1CodecConfigurationRecord);
VideoCodecProfile profile;
};
#endif
struct MEDIA_EXPORT PixelAspectRatioBox : Box {
DECLARE_BOX_METHODS(PixelAspectRatioBox);
......
......@@ -21,6 +21,7 @@ enum FourCC {
#endif
#if BUILDFLAG(ENABLE_AV1_DECODER)
FOURCC_AV01 = 0x61763031, // "av01"
FOURCC_AV1C = 0x61763143, // "av1C"
#endif
FOURCC_AVC1 = 0x61766331,
FOURCC_AVC3 = 0x61766333,
......
......@@ -4,6 +4,7 @@
import("//media/media_options.gni")
import("//testing/libfuzzer/fuzzer_test.gni")
import("//third_party/libaom/options.gni")
source_set("run_all_unittests") {
testonly = true
......@@ -167,6 +168,10 @@ pipeline_integration_fuzzer_variants = [
# See below for additional variants depending on build configuration.
]
if (enable_av1_decoder) {
pipeline_integration_fuzzer_variants += [ "MP4_AV1" ]
}
if (proprietary_codecs) {
pipeline_integration_fuzzer_variants += [
"ADTS",
......@@ -210,6 +215,7 @@ foreach(variant, pipeline_integration_fuzzer_variants) {
# header for pipeline_integration_test_base.h. This should be
# moved into the .cc file to avoid the extra dependency here.
"//testing/gmock",
"//third_party/libaom:av1_buildflags",
"//ui/gfx:test_support",
]
......
FOURCC_NULL="\x00\x00\x00\x00"
FOURCC_AC3 ="\x61\x63\x2d\x33"
FOURCC_EAC3="\x65\x63\x2d\x33"
FOURCC_AV01="\x61\x76\x30\x31"
FOURCC_AV1C="\x61\x76\x31\x43"
FOURCC_AVC1="\x61\x76\x63\x31"
FOURCC_AVC3="\x61\x76\x63\x33"
FOURCC_AVCC="\x61\x76\x63\x43"
......
......@@ -20,6 +20,7 @@
#include "media/base/pipeline_status.h"
#include "media/test/mock_media_source.h"
#include "media/test/pipeline_integration_test_base.h"
#include "third_party/libaom/av1_buildflags.h"
namespace {
......@@ -31,6 +32,9 @@ enum FuzzerVariant {
WEBM_VP8,
WEBM_VP9,
WEBM_OPUS_VP9,
#if BUILDFLAG(ENABLE_AV1_DECODER)
MP4_AV1,
#endif
MP4_FLAC,
MP3,
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
......@@ -61,6 +65,10 @@ std::string MseFuzzerVariantEnumToMimeTypeString(FuzzerVariant variant) {
return "video/webm; codecs=\"vp9\"";
case WEBM_OPUS_VP9:
return "video/webm; codecs=\"opus,vp9\"";
#if BUILDFLAG(ENABLE_AV1_DECODER)
case MP4_AV1:
return "video/mp4; codecs=\"av01.0.04M.08\"";
#endif // BUILDFLAG(ENABLE_AV1_DECODER)
case MP4_FLAC:
return "audio/mp4; codecs=\"flac\"";
case MP3:
......
......@@ -765,8 +765,7 @@ const MSEPlaybackTestData kMediaSourceVideoFiles[] = {
#if BUILDFLAG(ENABLE_AV1_DECODER)
// AV1 in MP4
// TODO(johannkoenig): re-enable when an av1 mp4 muxer is available.
// {"bear-av1.mp4", kMP4AV1, kAppendWholeFile, kVP9WebMFileDurationMs},
{"bear-av1.mp4", kMP4AV1, kAppendWholeFile, kVP9WebMFileDurationMs},
// AV1 in WebM
{"bear-av1.webm", kWebMAV1, kAppendWholeFile, kVP9WebMFileDurationMs},
......@@ -1760,11 +1759,10 @@ TEST_F(PipelineIntegrationTest, BasicPlaybackHi12PVP9) {
#endif
#if BUILDFLAG(ENABLE_AV1_DECODER)
// TODO(johannkoenig): re-enable when an av1 mp4 muxer is available.
TEST_P(MSEPipelineIntegrationTest, DISABLED_BasicPlayback_AV1_MP4) {
TEST_P(MSEPipelineIntegrationTest, BasicPlayback_AV1_MP4) {
base::test::ScopedFeatureList scoped_feature_list_;
scoped_feature_list_.InitAndEnableFeature(kAv1Decoder);
MockMediaSource source("bear-av1.mp4", kMP4AV1, 80496);
MockMediaSource source("bear-av1.mp4", kMP4AV1, 24723);
EXPECT_EQ(PIPELINE_OK, StartPipelineWithMediaSource(&source));
source.EndOfStream();
......@@ -1817,8 +1815,7 @@ TEST_F(PipelineIntegrationTest, BasicPlaybackHashed_FlacInMp4) {
}
#if BUILDFLAG(ENABLE_AV1_DECODER)
// TODO(johannkoenig): re-enable when an av1 mp4 muxer is available.
TEST_F(PipelineIntegrationTest, DISABLED_BasicPlayback_VideoOnly_AV1_Mp4) {
TEST_F(PipelineIntegrationTest, BasicPlayback_VideoOnly_AV1_Mp4) {
base::test::ScopedFeatureList scoped_feature_list_;
scoped_feature_list_.InitAndEnableFeature(kAv1Decoder);
ASSERT_EQ(PIPELINE_OK, Start("bear-av1.mp4"));
......
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