Skip to content

Commit

Permalink
av1hdr10plus: process isobmff files too
Browse files Browse the repository at this point in the history
  • Loading branch information
rbouqueau committed Jun 7, 2022
1 parent 5f6dbef commit b1ce523
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 70 deletions.
74 changes: 38 additions & 36 deletions src/specs/av1_hdr10plus/av1_hdr10plus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,30 @@
#include <cstring> // strcmp

bool checkRuleSection(const SpecDesc& spec, const char* section, Box const& root);
std::vector<const Box*> findBoxes(const Box& root, uint32_t fourcc);

static const SpecDesc specAv1Hdr10plus =
namespace
{
BitReader getData(Box const& root, IReport* out)
{
if(!isIsobmff(root))
return { root.original, (int)root.size }

;

// FIXME: cw is not an ISOBMFF demuxer so we consider the 'mdat' box
auto mdats = findBoxes(root, FOURCC("mdat"));

if(mdats.size() == 1)
return { mdats[0]->original + 8, (int)mdats[0]->size - 8 }

;

out->error("%d mdat found, expected 1", mdats.size());
return { nullptr, 0 };
}

const SpecDesc specAv1Hdr10plus =
{
"av1hdr10plus",
"HDR10+ AV1 Metadata Handling Specification, 8 December 2021\n"
Expand All @@ -16,18 +38,15 @@ static const SpecDesc specAv1Hdr10plus =
"An AV1 stream shall contain at least one OBU",
[] (Box const& root, IReport* out)
{
if(isIsobmff(root))
return;
BoxReader br;
br.br = getData(root, out);

if(root.size < 2)
if(br.br.size < 2)
{
out->error("Not enough bytes(=%llu) to contain an OBU", root.size);
out->error("Not enough bytes(=%llu) to contain an OBU", br.br.size);
return;
}

BoxReader br;
br.br = BitReader { root.original, (int)root.size };

Av1State stateUnused;
auto obuType = parseAv1Obus(&br, stateUnused, false);

Expand All @@ -43,17 +62,11 @@ static const SpecDesc specAv1Hdr10plus =
" - itu_t_t35_terminal_provider_oriented_code set as 0x0001",
[] (Box const& root, IReport* out)
{
if(isIsobmff(root))
return;
BoxReader br;
br.br = getData(root, out);

if(root.size < 2)
{
out->error("Not enough bytes(=%llu) to contain an OBU", root.size);
if(br.br.size < 2)
return;
}

BoxReader br;
br.br = BitReader { root.original, (int)root.size };

while(!br.empty())
{
Expand Down Expand Up @@ -90,17 +103,11 @@ static const SpecDesc specAv1Hdr10plus =
" - chroma_sample_position should be set to 2",
[] (Box const& root, IReport* out)
{
if(isIsobmff(root))
return;
BoxReader br;
br.br = getData(root, out);

if(root.size < 2)
{
out->error("Not enough bytes(=%llu) to contain an OBU", root.size);
if(br.br.size < 2)
return;
}

BoxReader br;
br.br = BitReader { root.original, (int)root.size };

while(!br.empty())
{
Expand Down Expand Up @@ -153,18 +160,11 @@ static const SpecDesc specAv1Hdr10plus =
"temporal delimiter, for storage formats where temporal delimiters are preserved).",
[] (Box const& root, IReport* out)
{
if(isIsobmff(root))
return;
BoxReader br;
br.br = getData(root, out);

if(root.size < 2)
{
out->error("Not enough bytes(=%llu) to contain an OBU", root.size);
if(br.br.size < 2)
return;
}

Av1State stateUnused;
BoxReader br;
br.br = BitReader { root.original, (int)root.size };

struct OBU
{
Expand All @@ -179,6 +179,7 @@ static const SpecDesc specAv1Hdr10plus =
struct TemporalUnit : std::vector<Frame> {};
struct AV1Stream : std::vector<TemporalUnit> {};
AV1Stream av1Stream;
Av1State stateUnused;

while(!br.empty())
{
Expand Down Expand Up @@ -389,4 +390,5 @@ static const SpecDesc specAv1Hdr10plus =
};

static auto const registered = registerSpec(&specAv1Hdr10plus);
}

22 changes: 22 additions & 0 deletions tests/av1hdr10plus/invalid_isobmff_too_small.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
%define BE(a) ( ((((a)>>24)&0xFF) << 0) + ((((a)>>16)&0xFF) << 8) + ((((a)>>8)&0xFF) << 16) + ((((a)>>0)&0xFF) << 24))

ftyp_start:
dd BE(ftyp_end - ftyp_start)
dd "ftyp"
db 0x69, 0x73, 0x6F, 0x6D ; major_brand(32) ('isom')
db 0x00, 0x00, 0x02, 0x00 ; minor_version(32)
db 0x69, 0x73, 0x6F, 0x6D ; compatible_brand(32) ('isom')
db 0x61, 0x76, 0x30, 0x31 ; compatible_brand(32) ('av01')
db 0x69, 0x73, 0x6F, 0x32 ; compatible_brand(32) ('iso2')
db 0x6D, 0x70, 0x34, 0x31 ; compatible_brand(32) ('mp41')
ftyp_end:
free_start:
dd BE(free_end - free_start)
dd "free"
free_end:
mdat_start:
dd BE(mdat_end - mdat_start)
dd "mdat"
mdat_end:

; vim: syntax=nasm
29 changes: 29 additions & 0 deletions tests/av1hdr10plus/invalid_isobmff_too_small.ref
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
+--------------------------------------+
| av1hdr10plus validation |
+--------------------------------------+

Specification description: HDR10+ AV1 Metadata Handling Specification, 8 December 2021
https://aomediacodec.github.io/av1-hdr10plus/

[av1hdr10plus][Rule #0] Error: Not enough bytes(=0) to contain an OBU

========================================
[av1hdr10plus] 1 error(s), 0 warning(s).
========================================

===== Involved rules descriptions:

[av1hdr10plus][Rule #0] Section 2.1
An AV1 stream shall contain at least one OBU

+--------------------------------------+
| isobmff validation |
+--------------------------------------+

Specification description: ISO Base Media File Format
MPEG-4 part 12 - ISO/IEC 14496-12 - m17277 (6th+FDAM1+FDAM2+COR1-R4)

========================================
[isobmff] No errors.
========================================

29 changes: 1 addition & 28 deletions tests/av1hdr10plus/sparks_byte1_invalid.ref
Original file line number Diff line number Diff line change
Expand Up @@ -6,40 +6,13 @@ Specification description: HDR10+ AV1 Metadata Handling Specification, 8 Decembe
https://aomediacodec.github.io/av1-hdr10plus/

[av1hdr10plus][Rule #0] Error: Not enough bytes(=1) to contain an OBU
[av1hdr10plus][Rule #1] Error: Not enough bytes(=1) to contain an OBU
[av1hdr10plus][Rule #2] Error: Not enough bytes(=1) to contain an OBU
[av1hdr10plus][Rule #3] Error: Not enough bytes(=1) to contain an OBU

========================================
[av1hdr10plus] 4 error(s), 0 warning(s).
[av1hdr10plus] 1 error(s), 0 warning(s).
========================================

===== Involved rules descriptions:

[av1hdr10plus][Rule #0] Section 2.1
An AV1 stream shall contain at least one OBU

[av1hdr10plus][Rule #1] Section 2.1
Each HDR10+ OBU includes an ITU-T T.35 identifier with:
- itu_t_t35_country_code set as 0xB5
- itu_t_t35_terminal_provider_code set as 0x003C
- itu_t_t35_terminal_provider_oriented_code set as 0x0001

[av1hdr10plus][Rule #2] Section 2.2.1
Streams shall use the following values for the AV1 color_config:
- color_primaries = 9 ([BT-2020])
- transfer_characteristics = 16 ([SMPTE-ST-2084] / [BT-2100])
- matrix_coefficients = 9 ([BT-2020])
Additionally, the following recommendations apply:
- VideoFullRangeFlag should be set to 0
- subsampling_x and subsampling_y should be set to 0
- mono_chrome should be 0
- chroma_sample_position should be set to 2

[av1hdr10plus][Rule #3] Section 2.2.2
for each frame with show_frame=1 or show_existing_frame=1, there shall be one
and only one HDR10+ metadata OBU preceding the frame header for this frame and
located after the last OBU of the previous frame (if any) or after the
Sequence Header (if any) or after the start of the temporal unit (e.g. after the
temporal delimiter, for storage formats where temporal delimiters are preserved).

47 changes: 47 additions & 0 deletions tests/av1hdr10plus/valid_isobmff.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
%define BE(a) ( ((((a)>>24)&0xFF) << 0) + ((((a)>>16)&0xFF) << 8) + ((((a)>>8)&0xFF) << 16) + ((((a)>>0)&0xFF) << 24))

ftyp_start:
dd BE(ftyp_end - ftyp_start)
dd "ftyp"
db 0x69, 0x73, 0x6F, 0x6D ; major_brand(32) ('isom')
db 0x00, 0x00, 0x02, 0x00 ; minor_version(32)
db 0x69, 0x73, 0x6F, 0x6D ; compatible_brand(32) ('isom')
db 0x61, 0x76, 0x30, 0x31 ; compatible_brand(32) ('av01')
db 0x69, 0x73, 0x6F, 0x32 ; compatible_brand(32) ('iso2')
db 0x6D, 0x70, 0x34, 0x31 ; compatible_brand(32) ('mp41')
ftyp_end:
free_start:
dd BE(free_end - free_start)
dd "free"
free_end:
mdat_start:
dd BE(mdat_end - mdat_start)
dd "mdat"
; obu(0)
db 0x12 ; forbidden(1) obu_type(4) obu_extension_flag(1) obu_has_size_field(1) obu_reserved_1bit(1)
db 0x00 ; leb128_byte(8)
; obu(0)
db 0x0A ; forbidden(1) obu_type(4) obu_extension_flag(1) obu_has_size_field(1) obu_reserved_1bit(1)
db 0x0F ; leb128_byte(8)
; seqhdr(0)
db 0x00, 0x00, 0x00 ; seq_profile(3) still_picture(1) reduced_still_picture_header(1) timing_info_present_flag(1) initial_display_delay_present_flag(1) operating_points_cnt_minus_1(5) operating_point_idc[i])(12)
db 0x6A, 0xEF, 0xFF, 0xE1, 0xBD ; seq_level_idx[i](5) seq_tier[i](1) frame_width_bits_minus_1(4) frame_height_bits_minus_1(4) max_frame_width_minus_1(12) max_frame_height_minus_1(12) frame_id_numbers_present_flag(1) use_128x128_superblock(1)
db 0xFF ; enable_filter_intra(1) enable_intra_edge_filter(1) enable_interintra_compound(1) enable_masked_compound(1) enable_warped_motion(1) enable_dual_filter(1) enable_order_hint(1) enable_jnt_comp(1)
db 0xF9 ; enable_ref_frame_mvs(1) seq_choose_screen_content_tools(1) seq_choose_integer_mv(1) order_hint_bits_minus_1(3) enable_superres(1) enable_cdef(1)
db 0xD0, 0x91, 0x00, 0x94 ; enable_restoration(1) high_bitdepth(1) mono_chrome(1) color_description_present_flag(1) color_primaries(8) transfer_characteristics(8) matrix_coefficients(8) color_range(1) chroma_sample_position(2) separate_uv_delta_q(1)
db 0x40 ; film_grain_params_present(1) ('@') bits(7) ('@')
; /seqhdr(0)
; obu(0)
db 0x2A ; forbidden(1) ('*') obu_type(4) ('*') obu_extension_flag(1) ('*') obu_has_size_field(1) ('*') obu_reserved_1bit(1) ('*')
db 0x06 ; leb128_byte(8)
db 0x04 ; leb128_byte(8)
db 0xB5 ; itu_t_t35_country_code(8)
db 0x00, 0x3C ; itu_t_t35_terminal_provider_code(16)
db 0x00, 0x01 ; itu_t_t35_terminal_provider_oriented_code(16)
; obu(0)
db 0x32 ; forbidden(1) ('2') obu_type(4) ('2') obu_extension_flag(1) ('2') obu_has_size_field(1) ('2') obu_reserved_1bit(1) ('2')
db 0x01 ; leb128_byte(8)
db 0x80 ; show_existing_frame(1) frame_to_show_map_idx(3) bits(4)
mdat_end:

; vim: syntax=nasm
22 changes: 22 additions & 0 deletions tests/av1hdr10plus/valid_isobmff.ref
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
+--------------------------------------+
| av1hdr10plus validation |
+--------------------------------------+

Specification description: HDR10+ AV1 Metadata Handling Specification, 8 December 2021
https://aomediacodec.github.io/av1-hdr10plus/

========================================
[av1hdr10plus] No errors.
========================================

+--------------------------------------+
| isobmff validation |
+--------------------------------------+

Specification description: ISO Base Media File Format
MPEG-4 part 12 - ISO/IEC 14496-12 - m17277 (6th+FDAM1+FDAM2+COR1-R4)

========================================
[isobmff] No errors.
========================================

14 changes: 8 additions & 6 deletions tests/run
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ function main
run_test real_mp4_avc
run_test real_mp4_heif

run_test check_rules_folder isobmff mp4
run_test check_rules_folder heif mp4
run_test check_rules_folder miaf hif
run_test check_rules_folder avif avif
run_test check_rules_folder av1hdr10plus obu
run_test check_rules_folder isobmff mp4 ""
run_test check_rules_folder heif mp4 ""
run_test check_rules_folder miaf hif ""
run_test check_rules_folder avif avif ""
run_test check_rules_folder av1hdr10plus obu "| grep -v isobmff"
run_test check_rules_folder av1hdr10plus mp4 "| grep isobmff"
run_test miaf_file_extension

echo "OK"
Expand Down Expand Up @@ -81,7 +82,8 @@ function check_rules
function check_rules_folder
{
local folder="$1"
for i in `ls $scriptDir/$folder/*.asm` ; do
local list_rule="ls $scriptDir/$folder/*.asm $3"
for i in $(eval $list_rule) ; do
local name=`basename ${i%.*}`
run_test check_rules $folder "$folder/$name" "$2"
done
Expand Down

0 comments on commit b1ce523

Please sign in to comment.