From ce1174e282a253ce9a8757fd964bf4249b620786 Mon Sep 17 00:00:00 2001
From: Yannis Guyon
Date: Wed, 26 Jun 2024 14:21:40 +0000
Subject: [PATCH 01/65] Begin new Working Group Draft version
---
index.bs | 35 ++++++++++-------------------------
latest-approved.html | 1 +
latest-draft.html | 1 +
3 files changed, 12 insertions(+), 25 deletions(-)
create mode 120000 latest-approved.html
create mode 120000 latest-draft.html
diff --git a/index.bs b/index.bs
index 496e165..fa75ffd 100755
--- a/index.bs
+++ b/index.bs
@@ -1,19 +1,21 @@
Group: AOM
-Status: FD
-Text Macro: SPECVERSION v1.1.0
+Status: WGD
+Text Macro: SPECVERSION v1.2.0
Title: AV1 Image File Format (AVIF)
-URL: https://AOMediaCodec.github.io/av1-avif/v1.1.0.html
-!Latest version: https://AOMediaCodec.github.io/av1-avif
-!Previously approved version: v1.0.0
+URL: https://AOMediaCodec.github.io/av1-avif
Shortname: av1-avif
-Editor: Cyril Concolato, Netflix, cconcolato@netflix.com
+Editor: Yannis Guyon, Google, yguyon@google.com
+Former Editor: Cyril Concolato, Netflix, cconcolato@netflix.com
Former Editor: Paul Kerr, Netflix, pkerr@netflix.com
Former Editor: Anders Klemets, Microsoft, Anders.Klemets@microsoft.com
Abstract: This document specifies syntax and semantics for the storage of [[!AV1]] images in the generic image file format [[!HEIF]], which is based on [[!ISOBMFF]]. While [[!HEIF]] defines general requirements, this document also specifies additional constraints to ensure higher interoperability between writers and readers when [[!HEIF]] is used with [[!AV1]] images. These constraints are based on constraints defined in the Multi-Image Application Format [[!MIAF]] and are grouped into profiles inspired by the profiles defined in [[!MIAF]].
-Date: 2022-04-15
+Date: 2024-06-25
Repository: AOMediaCodec/av1-avif
Text Macro: ADDITIONALLOGO https://aomedia.org/assets/images/avif-logo-rgb.svg
+!Previously approved version: https://aomediacodec.github.io/av1-avif/v1.1.0.html
+!Latest approved version: https://aomediacodec.github.io/av1-avif/latest-approved.html
+!Latest draft version: https://aomediacodec.github.io/av1-avif/latest-draft.html
Metadata Order: This version, !*, *
@@ -434,21 +436,4 @@ A file containing a 'pict' track compliant with this profile is expected to list
The media type "image/avif"
is officially registered with IANA and available at: https://www.iana.org/assignments/media-types/image/avif.
- Changes since v1.0.0 release
-- Constrain image sequence to one sample description entry and constant sequence header.
-- Clarify ispe semantics.
-- Update use of essential field for av1C.
-- Clarify that constraints on still picture flags apply to non-layered images.
-- Clarify in-profile and out-of-profile restrictions.
-- Replace Media Type section with link to IANA official registration.
-- Define properties for layered images to allow selective or progressive decoding of layers.
-- Add restriction on transformative properties in derivation chains.
-- Extend semantics of avio brand to image items and clarify brand usage.
-- Clarify image sequence constraints in profile definitions.
-- add support for the ContentColourVolumeBox property.
-- Remove wrong recommendations regarding still picture flags in image sequences.
-- constrain auxiliary images to be full range, and ignore colr for alpha planes.
-- Rephrase statement about auxiliary images and profiles. (Editorial change)
-- Remove the definition of the image/avif-sequence MIME type.
-- Adding bitdepth constraint for alpha and master images.
-
+ Changes since v1.1.0 release
diff --git a/latest-approved.html b/latest-approved.html
new file mode 120000
index 0000000..8bcda4a
--- /dev/null
+++ b/latest-approved.html
@@ -0,0 +1 @@
+v1.1.0.html
\ No newline at end of file
diff --git a/latest-draft.html b/latest-draft.html
new file mode 120000
index 0000000..64233a9
--- /dev/null
+++ b/latest-draft.html
@@ -0,0 +1 @@
+index.html
\ No newline at end of file
From 8ebeb5ffbd21cc46c4de9d87f799c9971786e8c3 Mon Sep 17 00:00:00 2001
From: Yannis Guyon
Date: Wed, 14 Aug 2024 16:12:34 +0000
Subject: [PATCH 02/65] Make indent and formatting consistent (#204)
Fix white spaces, indentation, newlines, missing closing HTML elements
and mismatched opening/closing HTML elements.
---
index.bs | 114 +++++++++++++++++++++++++++----------------------------
1 file changed, 56 insertions(+), 58 deletions(-)
diff --git a/index.bs b/index.bs
index fa75ffd..2e56c4c 100755
--- a/index.bs
+++ b/index.bs
@@ -66,7 +66,6 @@ Metadata Order: This version, !*, *
}
-
url: https://www.iso.org/standard/66067.html; spec: HEIF; type: property;
text: colr
@@ -163,12 +162,12 @@ When an item is of type av01,
- The [=AV1 Image Item Data=] shall be identical to the content of an [=AV1 Sample=] marked as 'sync', as defined in [[!AV1-ISOBMFF]].
- The [=AV1 Image Item Data=] shall have exactly one [=Sequence Header OBU=].
- If the [=AV1 Image Item Data=] consists of a single frame (i.e. when using a single layer),
- - It should have its [=still_picture=]
flag set to 1.
- - It should have its [=reduced_still_picture_header=]
flag set to 1.
+ - It should have its [=still_picture=]
flag set to 1.
+ - It should have its [=reduced_still_picture_header=]
flag set to 1.
Image Item Properties
-AV1 Item Configuration Property
+AV1 Item Configuration Property
Box Type: av1C
@@ -187,24 +186,24 @@ The syntax and semantics of the AV1 Item Configuration Property are i
This property should be marked as essential.
-Image Spatial Extents Property
+Image Spatial Extents Property
The semantics of the 'ispe' property as defined in [[!HEIF]] apply. More specifically, for AV1 images, the values of 'image_width' and 'image_height' shall respectively equal the values of [=FrameWidth=] and [=FrameHeight=] as defined in [[!AV1]] but for a specific frame in the item payload. The exact frame depends on the presence and content of the 'lsel' and [=OperatingPointSelectorProperty=] properties as follows:
-- In the absence of a 'lsel' property associated with the item, or if it is present and its 'layer_id' value is set to 0xFFFF:
+ - In the absence of a 'lsel' property associated with the item, or if it is present and its 'layer_id' value is set to 0xFFFF:
- If no [=OperatingPointSelectorProperty=] is associated with the item, the 'ispe' shall document the dimensions of the last frame decoded when processing the operating point whose index is 0.
- If an [=OperatingPointSelectorProperty=] is associated with the item, the 'ispe' property shall document the dimensions of the last frame decoded when processing the corresponding operating point.
NOTE: The dimensions of possible intermediate output images might not match the ones given in the 'ispe' property. If they display these intermediate images, renderers are expected to scale the output image to match the 'ispe' property.
-- If a 'lsel' property is associated with an item and its 'layer_id' is different from 0xFFFF, the 'ispe' property documents the dimensions of the output frame produced by decoding the corresponding layer.
+ - If a 'lsel' property is associated with an item and its 'layer_id' is different from 0xFFFF, the 'ispe' property documents the dimensions of the output frame produced by decoding the corresponding layer.
NOTE: The dimensions indicated in the 'ispe' property might not match the values [=max_frame_width_minus1=]+1 and [=max_frame_height_minus1=]+1 indicated in the AV1 bitstream.
NOTE: The values of [=render_width_minus1=] and [=render_height_minus1=] possibly present in the AV1 bistream are not exposed in the AVIF container level.
-Other Item Properties
+Other Item Properties
In addition to the Image Properties defined in [[!HEIF]], such as 'colr', 'pixi' or 'pasp', [=AV1 image items=] MAY also be associated with 'clli', 'cclv' and 'mdcv' introduced in [[!MIAF]].
@@ -212,9 +211,9 @@ In general, it is recommended to use properties instead of [=Metadata OBUs=] in
NOTE: Although the clean aperture property ('clap') defined in [[!HEIF]] is applicable to AVIF, implementers of authoring tools should be aware of the possibility of unintended consequences since users may not realize image data outside the clap region is still in the file. A future revision of this specification may place normative restrictions on how clap can be used.
-AV1 Layered Image Items
+AV1 Layered Image Items
-Overview
+Overview
[[!AV1]] supports encoding a frame using multiple spatial layers. A spatial layer may improve the resolution or quality of the image decoded based on one or more of the previous layers. A layer may also provide an image that does not depend on the previous layers. Additionally, not all layers are expected to produce an image meant to be rendered. Some decoded images may be used only as intermediate decodes. Finally, layers are grouped into one or more [=Operating Points=]. The [=Sequence Header OBU=] defines the list of [=Operating Points=], provides required decoding capabilities, and indicates which layers form each [=Operating Point=].
@@ -226,10 +225,10 @@ NOTE: When an author wants to offer the ability to render multiple [=Operating P
NOTE: When such a progressive decoding of the layers within an [=Operating Point=] is not desired or when an author wants to expose each layer as a specific item, multiple [=AV1 Image Items=] sharing the same [=AV1 Image Item Data=] can be created and associated with different 'lsel' properties, each with a different value of 'layer_id'.
-Properties
-Operating Point Selector Property
+Properties
+Operating Point Selector Property
-Definition
+Definition
Box Type: a1op
@@ -243,7 +242,7 @@ NOTE: When such a progressive decoding of the layers within an [=Operating Point
An OperatingPointSelectorProperty may be associated with an [=AV1 Image Item=] to provide the index of the operating point to be processed for this item. If associated, it shall be marked as essential.
-Syntax
+Syntax
```
class OperatingPointSelectorProperty extends ItemProperty('a1op') {
@@ -251,16 +250,16 @@ class OperatingPointSelectorProperty extends ItemProperty('a1op') {
}
```
-Semantics
+Semantics
op_index indicates the index of the operating point to be processed for this item. Its value shall be between 0 and [=operating_points_cnt_minus_1=].
-Layer Selector Property
+Layer Selector Property
The 'lsel' property defined in [[!HEIF]] may be associated with an [=AV1 Image Item=]. The 'layer_id' indicates the value of the [=spatial_id=] to render. The value shall be between 0 and 3, or the special value 0xFFFF. When a value between 0 and 3 is used, the corresponding spatial layer shall be present in the bitstream and shall produce an output frame. Other layers may be needed to decode the indicated layer. When the special value 0xFFFF is used, progressive decoding is allowed as described in [[#layered-items-overview]].
-Layered Image Indexing Property
+Layered Image Indexing Property
-Definition
+Definition
Box Type: a1lx
@@ -270,13 +269,13 @@ The 'lsel' property defined in [[!HEIF]] may be associated with an [=AV1 Image I
Quantity: Zero or one
-Description
+Description
The AV1LayeredImageIndexingProperty property may be associated with an [=AV1 Image Item=]. It should not be associated with [=AV1 Image Items=] consisting of only one layer.
The [=AV1LayeredImageIndexingProperty=] documents the size in bytes of each layer (except the last one) in the [=AV1 Image Item Data=], and enables determining the byte ranges required to process one or more layers of an [=Operating Point=]. If associated, it shall not be marked as essential.
-Syntax
+Syntax
```
class AV1LayeredImageIndexingProperty extends ItemProperty('a1lx') {
@@ -287,7 +286,7 @@ class AV1LayeredImageIndexingProperty extends ItemProperty('a1lx') {
}
```
-Semantics
+Semantics
layer_size indicates the number of bytes corresponding to each layer in the item payload, except for the last layer. Values are provided in increasing order of [=spatial_id=]. A value of zero means that all the layers except the last one have been documented and following values shall be 0. The number of non-zero values shall match the number of layers in the image minus one.
@@ -297,19 +296,19 @@ NOTE: The size of the last layer can be determined by subtracting the sum of the
Image Sequences
-
- An AV1 Image Sequence is defined as a set of AV1 [=Temporal Units=] stored in an [=AV1 track=] as defined in [[!AV1-ISOBMFF]] with the following constraints:
+
An AV1 Image Sequence is defined as a set of AV1 [=Temporal Units=] stored in an [=AV1 track=] as defined in [[!AV1-ISOBMFF]] with the following constraints:
+
+ - The track shall be a valid [=MIAF image sequence=].
+ - The track handler for an [=AV1 Image Sequence=] shall be pict
.
+ - The track shall have only one sample description entry.
+ - If multiple [=Sequence Header OBUs=] are present in the track payload, they shall be identical.
- - The track shall be a valid [=MIAF image sequence=].
- - The track handler for an [=AV1 Image Sequence=] shall be pict
.
- - The track shall have only one sample description entry.
- - If multiple [=Sequence Header OBUs=] are present in the track payload, they shall be identical.
+Auxiliary Image Items and Sequences
- Auxiliary Image Items and Sequences
-An AV1 Auxiliary Image Item (respectively an AV1 Auxiliary Image Sequence) is an [=AV1 Image Item=] (respectively [=AV1 Image Sequence=]) with the following additional constraints:
- - It shall be a compliant [=MIAF Auxiliary Image Item=] (respectively [=MIAF Auxiliary Image Sequence=]).
- - The [=mono_chrome=]
field in the [=Sequence Header OBU=] shall be set to 1.
- - The [=color_range=]
field in the [=Sequence Header OBU=] shall be set to 1.
+
An AV1 Auxiliary Image Item (respectively an AV1 Auxiliary Image Sequence) is an [=AV1 Image Item=] (respectively [=AV1 Image Sequence=]) with the following additional constraints:
+ - It shall be a compliant [=MIAF Auxiliary Image Item=] (respectively [=MIAF Auxiliary Image Sequence=]).
+ - The [=mono_chrome=]
field in the [=Sequence Header OBU=] shall be set to 1.
+ - The [=color_range=]
field in the [=Sequence Header OBU=] shall be set to 1.
An AV1 Alpha Image Item (respectively an AV1 Alpha Image Sequence) is an [=AV1 Auxiliary Image Item=] (respectively an [=AV1 Auxiliary Image Sequence=]), and as defined in [[!MIAF]], with the aux_type
field of the AuxiliaryTypeProperty
(respectively AuxiliaryTypeInfoBox
) set to urn:mpeg:mpegB:cicp:systems:auxiliary:alpha
. An AV1 Alpha Image Item (respectively an AV1 Alpha Image Sequence) shall be encoded with the same bit depth as the associated master AV1 Image Item (respectively AV1 Image Sequence).
@@ -319,7 +318,7 @@ NOTE: The size of the last layer can be determined by subtracting the sum of the
NOTE: [[!AV1]] supports encoding either 3-component images (whose semantics are given by the matrix_coefficients
element), or 1-component images (monochrome). When an image requires a different number of components, multiple auxiliary images may be used, each providing additional component(s), according to the semantics of their aux_type
field. In such case, the maximum number of components is restricted by number of possible items in a file, coded on 16 or 32 bits.
- Brands, Internet media types and file extensions
+Brands, Internet media types and file extensions
Brands overview
@@ -333,8 +332,8 @@ NOTE: [[!AV1]] supports encoding either 3-component images (whose semantics are
The brand to identify [=AV1 image items=] is avif.
Files that indicate this brand in the [=compatible_brands=] field of the [=FileTypeBox=] shall comply with the following:
-- The primary item shall be an [=AV1 Image Item=] or be a derived image that references directly or indirectly one or more items that all are [=AV1 Image Items=].
-- [=AV1 auxiliary image items=] may be present in the file.
+ - The primary item shall be an [=AV1 Image Item=] or be a derived image that references directly or indirectly one or more items that all are [=AV1 Image Items=].
+ - [=AV1 auxiliary image items=] may be present in the file.
Files that conform with these constraints should include the brand [=avif=]
in the [=compatible_brands=] field of the [=FileTypeBox=].
@@ -344,8 +343,8 @@ Additionally, the brand
The brand to identify AVIF image sequences is avis.
Files that indicate this brand in the [=compatible_brands=] field of the [=FileTypeBox=] shall comply with the following:
-- they shall contain one or more [=AV1 image sequences=].
-- they may contain [=AV1 auxiliary image sequences=].
+ - they shall contain one or more [=AV1 image sequences=].
+ - they may contain [=AV1 auxiliary image sequences=].
Files that conform with these constraints should include the brand [=avis=]
in the [=compatible_brands=] field of the [=FileTypeBox=].
@@ -353,38 +352,38 @@ Additionally, if a file contains [=AV1 image sequences=] and the brand [=a
NOTE: As defined in [[!MIAF]], a file that is primarily an image sequence still has at least an image item. Hence, it can also declare brands for signaling the image item.
- General constraints
+General constraints
- The following constraints are common to files compliant with this specification:
+The following constraints are common to files compliant with this specification:
- The file shall be compliant with the [[!MIAF]] specification and list 'miaf' in the [=compatible_brands=] field of the [=FileTypeBox=].
- The file shall list '[=avif=]'
or '[=avis=]'
in the [=compatible_brands=] field of the [=FileTypeBox=].
- If transformative properties are used in derivation chains (as defined in [[MIAF]]), they shall only be associated with items that are not referenced by another derived item. For example, if a file contains a grid item and its referenced coded image items, cropping, mirroring or rotation transformations are only permitted on the grid item itself.
- NOTE: This constraint further restricts files compared to [[MIAF]].
+NOTE: This constraint further restricts files compared to [[MIAF]].
- Profiles
+Profiles
- Overview
+Overview
- The profiles defined in this section are for enabling interoperability between [=AV1 Image File Format=] files and [=AV1 Image File Format=] readers/parsers. A profile imposes a set of specific restrictions and is signaled by brands defined in this specification.
+The profiles defined in this section are for enabling interoperability between [=AV1 Image File Format=] files and [=AV1 Image File Format=] readers/parsers. A profile imposes a set of specific restrictions and is signaled by brands defined in this specification.
- The [=FileTypeBox=] should declare at least one profile that enables decoding of the primary image item. It is not an error for the encoder to include an auxiliary image that is not allowed by the specified profile(s).
+The [=FileTypeBox=] should declare at least one profile that enables decoding of the primary image item. It is not an error for the encoder to include an auxiliary image that is not allowed by the specified profile(s).
- If '[=avis=]'
is declared in the [=FileTypeBox=] and a profile is declared in the [=FileTypeBox=], the profile shall also enable decoding of at least one image sequence track. The profile should allow decoding of any associated auxiliary image sequence tracks, unless it is acceptable to decode the image sequence without its auxiliary image sequence tracks.
+If '[=avis=]'
is declared in the [=FileTypeBox=] and a profile is declared in the [=FileTypeBox=], the profile shall also enable decoding of at least one image sequence track. The profile should allow decoding of any associated auxiliary image sequence tracks, unless it is acceptable to decode the image sequence without its auxiliary image sequence tracks.
- It is possible for a file compliant to this [=AV1 Image File Format=] to not be able to declare an AVIF profile, if the corresponding AV1 encoding characteristics do not match any of the defined profiles.
+It is possible for a file compliant to this [=AV1 Image File Format=] to not be able to declare an AVIF profile, if the corresponding AV1 encoding characteristics do not match any of the defined profiles.
- NOTE: [[!AV1]] supports 3 bit depths: 8, 10 and 12 bits, and the maximum dimensions of a coded image is 65536x65536, when [=seq_level_idx=] is set to 31 (maximum parameters level).
+NOTE: [[!AV1]] supports 3 bit depths: 8, 10 and 12 bits, and the maximum dimensions of a coded image is 65536x65536, when [=seq_level_idx=] is set to 31 (maximum parameters level).
-
If an image is encoded with dimensions (respectively a bit depth) that exceed the maximum dimensions (respectively bit depth) required by the AV1 profile and level of the AVIF profiles defined in this specification, the file will only signal general AVIF brands.
+If an image is encoded with dimensions (respectively a bit depth) that exceed the maximum dimensions (respectively bit depth) required by the AV1 profile and level of the AVIF profiles defined in this specification, the file will only signal general AVIF brands.
- AVIF Baseline Profile
+AVIF Baseline Profile
This section defines the MIAF AV1 Baseline profile of [[!HEIF]], specifically for [[!AV1]] bitstreams, based on the constraints specified in [[!MIAF]] and identified by the brand MA1B.
If the brand MA1B
is in the list of [=compatible_brands=] of the [=FileTypeBox=], the common constraints in the section [[#brands]] shall apply.
- The following additional constraints apply to all [=AV1 Image Items=] and all [=AV1 Image Sequences=]:
+The following additional constraints apply to all [=AV1 Image Items=] and all [=AV1 Image Sequences=]:
- The AV1 profile shall be the Main Profile and the level shall be 5.1 or lower.
NOTE: AV1 tiers are not constrained because timing is optional in image sequences and are not relevant in image items or collections.
@@ -403,24 +402,23 @@ A file containing a 'pict' track compliant with this profile is expected to list
A file containing a 'pict' track compliant with this profile and made only of samples marked 'sync' is expected to list the following brands, in any order, in the [=compatible_brands=] of the [=FileTypeBox=]:
avis, avio, msf1, miaf, MA1B
-
- AVIF Advanced Profile
+AVIF Advanced Profile
This section defines the MIAF AV1 Advanced profile of [[!HEIF]], specifically for [[!AV1]] bitstreams, based on the constraints specified in [[!MIAF]] and identified by the brand MA1A.
If the brand MA1A
is in the list of [=compatible_brands=] of the [=FileTypeBox=], the common constraints in the section [[#brands]] shall apply.
The following additional constraints apply to all [=AV1 Image Items=]:
-- The AV1 profile shall be the High Profile and the level shall be 6.0 or lower.
+ - The AV1 profile shall be the High Profile and the level shall be 6.0 or lower.
NOTE: Following [[!AV1]] level definitions, coded image items compliant to the AVIF Advanced profile may not have a number of pixels greater than 35651584, a width greater than 16384 or a height greater than 8704. It is still possible to use the Advanced profile to create larger images using grid derivation.
The following additional constraints apply only to [=AV1 Image Sequences=]:
-- The AV1 profile shall be either Main Profile or High Profile.
-- The AV1 level for Main Profile shall be 5.1 or lower.
-- The AV1 level for High Profile shall be 5.1 or lower.
+ - The AV1 profile shall be either Main Profile or High Profile.
+ - The AV1 level for Main Profile shall be 5.1 or lower.
+ - The AV1 level for High Profile shall be 5.1 or lower.
A file containing items compliant with this profile is expected to list the following brands, in any order, in the [=compatible_brands=] of the [=FileTypeBox=]:
@@ -432,8 +430,8 @@ A file containing a 'pict' track compliant with this profile is expected to list
avis, msf1, miaf, MA1A
- AVIF Media Type Registration
+AVIF Media Type Registration
The media type "image/avif"
is officially registered with IANA and available at: https://www.iana.org/assignments/media-types/image/avif.
- Changes since v1.1.0 release
+Changes since v1.1.0 release
From fa97d56de46f33f8d6e937277172cf0ebea0eeed Mon Sep 17 00:00:00 2001
From: Leo Barnes
Date: Tue, 13 Aug 2024 10:04:42 +0200
Subject: [PATCH 03/65] Fix use of and some indenting.
---
index.bs | 239 ++++++++++++++++++++++++++++---------------------------
1 file changed, 120 insertions(+), 119 deletions(-)
diff --git a/index.bs b/index.bs
index 2e56c4c..8bc73a3 100755
--- a/index.bs
+++ b/index.bs
@@ -6,6 +6,7 @@ Title: AV1 Image File Format (AVIF)
URL: https://AOMediaCodec.github.io/av1-avif
Shortname: av1-avif
Editor: Yannis Guyon, Google, yguyon@google.com
+Editor: Leo Barnes, Apple, lbarnes@apple.com
Former Editor: Cyril Concolato, Netflix, cconcolato@netflix.com
Former Editor: Paul Kerr, Netflix, pkerr@netflix.com
Former Editor: Anders Klemets, Microsoft, Anders.Klemets@microsoft.com
@@ -21,123 +22,123 @@ Metadata Order: This version, !*, *
{
- "AV1": {
- "href": "https://aomediacodec.github.io/av1-spec/av1-spec.pdf",
- "id": "AV1",
- "title": "AV1 Bitstream & Decoding Process Specification",
- "status": "LS",
- "publisher": "AOM"
- },
-
- "AV1-ISOBMFF": {
- "href": "https://aomediacodec.github.io/av1-isobmff/",
- "id": "AV1-ISOBMFF",
- "title": "AV1 Codec ISO Media File Format Binding",
- "status": "LS",
- "publisher": "AOM"
- },
-
- "HEIF": {
- "id": "HEIF",
- "href": "https://www.iso.org/standard/66067.html",
- "title": "Information technology — High efficiency coding and media delivery in heterogeneous environments — Part 12: Image File Format",
- "status": "International Standard",
- "publisher": "ISO/IEC",
- "isoNumber":"ISO/IEC 23008-12:2017"
- },
-
- "ISOBMFF": {
- "id": "ISOBMFF",
- "href": "https://www.iso.org/standard/68960.html",
- "title": "Information technology — Coding of audio-visual objects — Part 12: ISO base media file format",
- "status": "International Standard",
- "publisher": "ISO/IEC",
- "isoNumber":"ISO/IEC 14496-12:2015"
- },
-
- "MIAF": {
- "href": "https://www.iso.org/standard/74417.html",
- "id": "MIAF",
- "title": "Information technology -- Multimedia application format (MPEG-A) -- Part 22: Multi-Image Application Format (MiAF)",
- "status": "Enquiry",
- "publisher": "ISO/IEC",
- "isoNumber": "ISO/IEC DIS 23000-22"
- }
+ "AV1": {
+ "href": "https://aomediacodec.github.io/av1-spec/av1-spec.pdf",
+ "id": "AV1",
+ "title": "AV1 Bitstream & Decoding Process Specification",
+ "status": "LS",
+ "publisher": "AOM"
+ },
+
+ "AV1-ISOBMFF": {
+ "href": "https://aomediacodec.github.io/av1-isobmff/",
+ "id": "AV1-ISOBMFF",
+ "title": "AV1 Codec ISO Media File Format Binding",
+ "status": "LS",
+ "publisher": "AOM"
+ },
+
+ "HEIF": {
+ "id": "HEIF",
+ "href": "https://www.iso.org/standard/66067.html",
+ "title": "Information technology — High efficiency coding and media delivery in heterogeneous environments — Part 12: Image File Format",
+ "status": "International Standard",
+ "publisher": "ISO/IEC",
+ "isoNumber":"ISO/IEC 23008-12:2017"
+ },
+
+ "ISOBMFF": {
+ "id": "ISOBMFF",
+ "href": "https://www.iso.org/standard/68960.html",
+ "title": "Information technology — Coding of audio-visual objects — Part 12: ISO base media file format",
+ "status": "International Standard",
+ "publisher": "ISO/IEC",
+ "isoNumber":"ISO/IEC 14496-12:2015"
+ },
+
+ "MIAF": {
+ "href": "https://www.iso.org/standard/74417.html",
+ "id": "MIAF",
+ "title": "Information technology -- Multimedia application format (MPEG-A) -- Part 22: Multi-Image Application Format (MiAF)",
+ "status": "Enquiry",
+ "publisher": "ISO/IEC",
+ "isoNumber": "ISO/IEC DIS 23000-22"
+ }
}
url: https://www.iso.org/standard/66067.html; spec: HEIF; type: property;
- text: colr
- text: mif1
- text: msf1
- text: pasp
- text: pict
- text: pixi
- text: ispe
- text: lsel
- text: layer_id
- text: image_width
- text: image_height
+ text: colr
+ text: mif1
+ text: msf1
+ text: pasp
+ text: pict
+ text: pixi
+ text: ispe
+ text: lsel
+ text: layer_id
+ text: image_width
+ text: image_height
url: https://www.iso.org/standard/68960.html; spec: ISOBMFF; type: dfn;
- text: compatible_brands
- text: FileTypeBox
- text: major_brand
+ text: compatible_brands
+ text: FileTypeBox
+ text: major_brand
url: https://www.iso.org/standard/68960.html; spec: ISOBMFF; type: property;
- text: sync
- text: cclv
- text: clli
- text: mdcv
- text: clap
- text: iloc
+ text: sync
+ text: cclv
+ text: clli
+ text: mdcv
+ text: clap
+ text: iloc
url: https://www.iso.org/standard/74417.html; spec: MIAF; type: property;
- text: miaf
+ text: miaf
url: https://www.iso.org/standard/74417.html; spec: MIAF; type: dfn;
- text: primary image
- text: MIAF image item
- text: MIAF image sequence
- text: MIAF auxiliary image item
- text: MIAF auxiliary image sequence
- text: MIAF file
+ text: primary image
+ text: MIAF image item
+ text: MIAF image sequence
+ text: MIAF auxiliary image item
+ text: MIAF auxiliary image sequence
+ text: MIAF file
url: https://aomediacodec.github.io/av1-isobmff/; spec: AV1-ISOBMFF; type: dfn;
- text: av1codecconfigurationbox
- text: AV1 Sample
- text: AV1 Track
+ text: AV1CodecConfigurationBox
+ text: AV1 Sample
+ text: AV1 Track
url: https://aomediacodec.github.io/av1-spec/av1-spec.pdf; spec: AV1; type: dfn;
- text: AV1 bitstream
- text: AV1 Frame
- text: Sequence Header OBU
- text: Metadata OBU
- text: Temporal Unit
- text: Operating Point
- text: Intra Frame
+ text: AV1 bitstream
+ text: AV1 Frame
+ text: Sequence Header OBU
+ text: Metadata OBU
+ text: Temporal Unit
+ text: Operating Point
+ text: Intra Frame
url: https://aomediacodec.github.io/av1-spec/av1-spec.pdf; spec: AV1; type: dfn;
- text: mono_chrome
- text: color_range
- text: still_picture
- text: reduced_still_picture_header
- text: operating_points_cnt_minus_1
- text: choose_operating_point
- text: spatial_id
- text: seq_level_idx
- text: render_width_minus1
- text: render_height_minus1
- text: FrameWidth
- text: FrameHeight
- text: max_frame_width_minus1
- text: max_frame_height_minus1
+ text: mono_chrome
+ text: color_range
+ text: still_picture
+ text: reduced_still_picture_header
+ text: operating_points_cnt_minus_1
+ text: choose_operating_point
+ text: spatial_id
+ text: seq_level_idx
+ text: render_width_minus1
+ text: render_height_minus1
+ text: FrameWidth
+ text: FrameHeight
+ text: max_frame_width_minus1
+ text: max_frame_height_minus1
Scope
-[[!AV1]] defines the syntax and semantics of an [=AV1 bitstream=]. The AV1 Image File Format (AVIF) defined in this document supports the storage of a subset of the syntax and semantics of an [=AV1 bitstream=] in a [[!HEIF]] file.
+[[!AV1]] defines the syntax and semantics of an [=AV1 bitstream=]. The AV1 Image File Format (AVIF) defined in this document supports the storage of a subset of the syntax and semantics of an [=AV1 bitstream=] in a [[!HEIF]] file.
The [=AV1 Image File Format=] defines multiple profiles, which restrict the allowed syntax and semantics of the [=AV1 bitstream=] with the goal to improve interoperability, especially for hardware implementations.
The profiles defined in this specification follow the conventions of the [[!MIAF]] specification.
Images encoded with AV1 and not meeting the restrictions of the defined profiles may still be compliant to this [=AV1 Image File Format=] if they adhere to the general AVIF requirements.
@@ -155,10 +156,10 @@ This specification reuses syntax and semantics used in [[!AV1-ISOBMFF]].
AV1 Image Item
-When an item is of type av01, it is called an AV1 Image Item, and shall obey the following constraints:
+When an item is of type av01, it is called an AV1 Image Item, and shall obey the following constraints:
- The [=AV1 Image Item=] shall be a conformant [=MIAF image item=].
- - The [=AV1 Image Item=] shall be associated with an [=AV1 Item Configuration Property=].
- - The content of an [=AV1 Image Item=] is called the AV1 Image Item Data and shall obey the following constraints:
+ - The [=AV1 Image Item=] shall be associated with an [=AV1ItemConfigurationProperty=].
+ - The content of an [=AV1 Image Item=] is called the AV1 Image Item Data and shall obey the following constraints:
- The [=AV1 Image Item Data=] shall be identical to the content of an [=AV1 Sample=] marked as 'sync', as defined in [[!AV1-ISOBMFF]].
- The [=AV1 Image Item Data=] shall have exactly one [=Sequence Header OBU=].
- If the [=AV1 Image Item Data=] consists of a single frame (i.e. when using a single layer),
@@ -167,17 +168,17 @@ When an item is of type av01,
Image Item Properties
-AV1 Item Configuration Property
+AV1 Item Configuration Property
- Box Type: av1C
+ Box Type: av1C
Property type: Descriptive item property
Container: ItemPropertyContainerBox
Mandatory (per item): Yes, for an image item of type 'av01'
Quantity: One for an image item of type 'av01'
-The syntax and semantics of the AV1 Item Configuration Property are identical to those of the [=AV1CodecConfigurationBox=] defined in [[!AV1-ISOBMFF]], with the following constraints:
+The syntax and semantics of the AV1ItemConfigurationProperty are identical to those of the [=AV1CodecConfigurationBox=] defined in [[!AV1-ISOBMFF]], with the following constraints:
- [=Sequence Header OBUs=] should not be present in the [=AV1CodecConfigurationBox=].
- If a [=Sequence Header OBU=] is present in the [=AV1CodecConfigurationBox=], it shall match the [=Sequence Header OBU=] in the [=AV1 Image Item Data=].
@@ -207,7 +208,7 @@ NOTE: The values of [=render_width_minus1=] and [=render_height_minus1=] possibl
In addition to the Image Properties defined in [[!HEIF]], such as 'colr', 'pixi' or 'pasp', [=AV1 image items=] MAY also be associated with 'clli', 'cclv' and 'mdcv' introduced in [[!MIAF]].
-In general, it is recommended to use properties instead of [=Metadata OBUs=] in the [=AV1 Item Configuration Property=].
+In general, it is recommended to use properties instead of [=Metadata OBUs=] in the [=AV1ItemConfigurationProperty=].
NOTE: Although the clean aperture property ('clap') defined in [[!HEIF]] is applicable to AVIF, implementers of authoring tools should be aware of the possibility of unintended consequences since users may not realize image data outside the clap region is still in the file. A future revision of this specification may place normative restrictions on how clap can be used.
@@ -231,7 +232,7 @@ NOTE: When such a progressive decoding of the layers within an [=Operating Point
Definition
- Box Type: a1op
+ Box Type: a1op
Property type: Descriptive item property
Container: ItemPropertyContainerBox
Mandatory: No
@@ -240,7 +241,7 @@ NOTE: When such a progressive decoding of the layers within an [=Operating Point
Description
-An OperatingPointSelectorProperty may be associated with an [=AV1 Image Item=] to provide the index of the operating point to be processed for this item. If associated, it shall be marked as essential.
+An OperatingPointSelectorProperty may be associated with an [=AV1 Image Item=] to provide the index of the operating point to be processed for this item. If associated, it shall be marked as essential.
Syntax
@@ -262,7 +263,7 @@ The 'lsel' property defined in [[!HEIF]] may be associated with an [=AV1 Image I
Definition
- Box Type: a1lx
+ Box Type: a1lx
Property type: Descriptive item property
Container: ItemPropertyContainerBox
Mandatory: No
@@ -295,8 +296,7 @@ NOTE: The size of the last layer can be determined by subtracting the sum of the
A property indicating [X,0,0] is used for an image item composed of 2 layers. The size of the first layer is X and the size of the second layer is ItemSize - X. Note that the [=spatial_id=] for the first layer does not necessarily match the index in the array that provides the size. In other words, in this case the index giving value X is 0, but the corresponding [=spatial_id=] could be 0, 1 or 2. Similarly, a property indicating [X,Y,0] is used for an image made of 3 layers.
Image Sequences
-
-An AV1 Image Sequence is defined as a set of AV1 [=Temporal Units=] stored in an [=AV1 track=] as defined in [[!AV1-ISOBMFF]] with the following constraints:
+
An AV1 Image Sequence is defined as a set of AV1 [=Temporal Units=] stored in an [=AV1 track=] as defined in [[!AV1-ISOBMFF]] with the following constraints:
- The track shall be a valid [=MIAF image sequence=].
- The track handler for an [=AV1 Image Sequence=] shall be pict
.
@@ -305,16 +305,16 @@ NOTE: The size of the last layer can be determined by subtracting the sum of the
Auxiliary Image Items and Sequences
-An AV1 Auxiliary Image Item (respectively an AV1 Auxiliary Image Sequence) is an [=AV1 Image Item=] (respectively [=AV1 Image Sequence=]) with the following additional constraints:
+
An AV1 Auxiliary Image Item (respectively an AV1 Auxiliary Image Sequence) is an [=AV1 Image Item=] (respectively [=AV1 Image Sequence=]
) with the following additional constraints:
- It shall be a compliant [=MIAF Auxiliary Image Item=] (respectively [=MIAF Auxiliary Image Sequence=]).
- The [=mono_chrome=]
field in the [=Sequence Header OBU=] shall be set to 1.
- The [=color_range=]
field in the [=Sequence Header OBU=] shall be set to 1.
-An AV1 Alpha Image Item (respectively an AV1 Alpha Image Sequence) is an [=AV1 Auxiliary Image Item=] (respectively an [=AV1 Auxiliary Image Sequence=]), and as defined in [[!MIAF]], with the aux_type
field of the AuxiliaryTypeProperty
(respectively AuxiliaryTypeInfoBox
) set to urn:mpeg:mpegB:cicp:systems:auxiliary:alpha
. An AV1 Alpha Image Item (respectively an AV1 Alpha Image Sequence) shall be encoded with the same bit depth as the associated master AV1 Image Item (respectively AV1 Image Sequence).
+An AV1 Alpha Image Item (respectively an AV1 Alpha Image Sequence) is an [=AV1 Auxiliary Image Item=] (respectively an [=AV1 Auxiliary Image Sequence=]), and as defined in [[!MIAF]], with the aux_type
field of the AuxiliaryTypeProperty
(respectively AuxiliaryTypeInfoBox
) set to urn:mpeg:mpegB:cicp:systems:auxiliary:alpha
. An [=AV1 Alpha Image Item=] (respectively an [=AV1 Alpha Image Sequence=]) shall be encoded with the same bit depth as the associated master [=AV1 Image Item=] (respectively [=AV1 Image Sequence=]).
For [=AV1 Alpha Image Item=] and [=AV1 Alpha Image Sequence=], the ColourInformationBox should be omitted. If present, readers shall ignore it.
-An AV1 Depth Image Item (respectively an AV1 Depth Image Sequence) is an [=AV1 Auxiliary Image Item=] (respectively an [=AV1 Auxiliary Image Sequence=]), and as defined in [[!MIAF]], with the aux_type
field of the AuxiliaryTypeProperty
(respectively AuxiliaryTypeInfoBox
) set to urn:mpeg:mpegB:cicp:systems:auxiliary:depth
.
+An AV1 Depth Image Item (respectively an AV1 Depth Image Sequence) is an [=AV1 Auxiliary Image Item=] (respectively an [=AV1 Auxiliary Image Sequence=]), and as defined in [[!MIAF]], with the aux_type
field of the AuxiliaryTypeProperty
(respectively AuxiliaryTypeInfoBox
) set to urn:mpeg:mpegB:cicp:systems:auxiliary:depth
.
NOTE: [[!AV1]] supports encoding either 3-component images (whose semantics are given by the matrix_coefficients
element), or 1-component images (monochrome). When an image requires a different number of components, multiple auxiliary images may be used, each providing additional component(s), according to the semantics of their aux_type
field. In such case, the maximum number of components is restricted by number of possible items in a file, coded on 16 or 32 bits.
@@ -329,7 +329,7 @@ NOTE: [[!AV1]] supports encoding either 3-component images (whose semantics are
If any of the brands defined in this document is specified in the [=major_brand=]
field of the [=FileTypeBox=], the file extension and Internet Media Type should respectively be ".avif
" and "image/avif
" as defined in [[#mime-registration]].
AVIF image and image collection brand
-The brand to identify [=AV1 image items=] is avif.
+The brand to identify [=AV1 image items=] is avif.
Files that indicate this brand in the [=compatible_brands=] field of the [=FileTypeBox=] shall comply with the following:
- The primary item shall be an [=AV1 Image Item=] or be a derived image that references directly or indirectly one or more items that all are [=AV1 Image Items=].
@@ -337,10 +337,10 @@ Files that indicate this brand in the [=compatible_brands=] field of the [=FileT
Files that conform with these constraints should include the brand [=avif=]
in the [=compatible_brands=] field of the [=FileTypeBox=].
-Additionally, the brand avio is defined. If the file indicates the brand [=avio=]
in the [=compatible_brands=] field of the [=FileTypeBox=], then the primary item or all the items referenced by the primary item shall be [=AV1 image items=] made only of [=Intra Frames=]. Conversely, if the previous constraint applies, the brand [=avio=]
should be used in the [=compatible_brands=] field of the [=FileTypeBox=].
+Additionally, the brand avio is defined. If the file indicates the brand [=avio=]
in the [=compatible_brands=] field of the [=FileTypeBox=], then the primary item or all the items referenced by the primary item shall be [=AV1 image items=] made only of [=Intra Frames=]. Conversely, if the previous constraint applies, the brand [=avio=]
should be used in the [=compatible_brands=] field of the [=FileTypeBox=].
AVIF image sequence brands
-The brand to identify AVIF image sequences is avis.
+The brand to identify AVIF image sequences is avis.
Files that indicate this brand in the [=compatible_brands=] field of the [=FileTypeBox=] shall comply with the following:
- they shall contain one or more [=AV1 image sequences=].
@@ -379,7 +379,7 @@ NOTE: [[!AV1]] supports 3 bit depths: 8, 10 and 12 bits, and the maximum dimensi
AVIF Baseline Profile
-This section defines the MIAF AV1 Baseline profile of [[!HEIF]], specifically for [[!AV1]] bitstreams, based on the constraints specified in [[!MIAF]] and identified by the brand MA1B.
+This section defines the MIAF AV1 Baseline profile of [[!HEIF]], specifically for [[!AV1]] bitstreams, based on the constraints specified in [[!MIAF]] and identified by the brand MA1B.
If the brand MA1B
is in the list of [=compatible_brands=] of the [=FileTypeBox=], the common constraints in the section [[#brands]] shall apply.
@@ -391,22 +391,22 @@ NOTE: AV1 tiers are not constrained because timing is optional in image sequenc
NOTE: Level 5.1 is chosen for the Baseline profile to ensure that no single coded image exceeds 4k resolution, as some decoder may not be able to handle larger images. More precisely, following [[!AV1]] level definitions, coded image items compliant to the AVIF Baseline profile may not have a number of pixels greater than 8912896, a width greater than 8192 or a height greater than 4352. It is still possible to use the Baseline profile to create larger images using grid derivation.
-A file containing items compliant with this profile is expected to list the following brands, in any order, in the [=compatible_brands=] of the [=FileTypeBox=]:
+ A file containing items compliant with this profile is expected to list the following brands, in any order, in the [=compatible_brands=] of the [=FileTypeBox=]:
avif, mif1, miaf, MA1B
-A file containing a 'pict' track compliant with this profile is expected to list the following brands, in any order, in the [=compatible_brands=] of the [=FileTypeBox=]:
+ A file containing a 'pict' track compliant with this profile is expected to list the following brands, in any order, in the [=compatible_brands=] of the [=FileTypeBox=]:
avis, msf1, miaf, MA1B
-A file containing a 'pict' track compliant with this profile and made only of samples marked 'sync' is expected to list the following brands, in any order, in the [=compatible_brands=] of the [=FileTypeBox=]:
+ A file containing a 'pict' track compliant with this profile and made only of samples marked 'sync' is expected to list the following brands, in any order, in the [=compatible_brands=] of the [=FileTypeBox=]:
avis, avio, msf1, miaf, MA1B
AVIF Advanced Profile
-This section defines the MIAF AV1 Advanced profile of [[!HEIF]], specifically for [[!AV1]] bitstreams, based on the constraints specified in [[!MIAF]] and identified by the brand MA1A.
+This section defines the MIAF AV1 Advanced profile of [[!HEIF]], specifically for [[!AV1]] bitstreams, based on the constraints specified in [[!MIAF]] and identified by the brand MA1A.
If the brand MA1A
is in the list of [=compatible_brands=] of the [=FileTypeBox=], the common constraints in the section [[#brands]] shall apply.
@@ -421,11 +421,11 @@ The following additional constraints apply only to [=AV1 Image Sequences=]:
- The AV1 level for High Profile shall be 5.1 or lower.
-A file containing items compliant with this profile is expected to list the following brands, in any order, in the [=compatible_brands=] of the [=FileTypeBox=]:
+ A file containing items compliant with this profile is expected to list the following brands, in any order, in the [=compatible_brands=] of the [=FileTypeBox=]:
avif, mif1, miaf, MA1A
-A file containing a 'pict' track compliant with this profile is expected to list the following brands, in any order, in the [=compatible_brands=] of the [=FileTypeBox=]:
+ A file containing a 'pict' track compliant with this profile is expected to list the following brands, in any order, in the [=compatible_brands=] of the [=FileTypeBox=]:
avis, msf1, miaf, MA1A
@@ -435,3 +435,4 @@ A file containing a 'pict' track compliant with this profile is expected to list
The media type "image/avif"
is officially registered with IANA and available at: https://www.iana.org/assignments/media-types/image/avif.
Changes since v1.1.0 release
+
From d32b750943f17cdc21e59e69a23ae5b4ba667a85 Mon Sep 17 00:00:00 2001
From: Leo Barnes
Date: Tue, 13 Aug 2024 10:07:48 +0200
Subject: [PATCH 04/65] Add changes since v1.1.0 entry
---
index.bs | 1 +
1 file changed, 1 insertion(+)
diff --git a/index.bs b/index.bs
index 8bc73a3..26e5c93 100755
--- a/index.bs
+++ b/index.bs
@@ -435,4 +435,5 @@ The following additional constraints apply only to [=AV1 Image Sequences=]:
The media type "image/avif"
is officially registered with IANA and available at: https://www.iana.org/assignments/media-types/image/avif.
Changes since v1.1.0 release
+ - Stop using `dfn value` for definitions.
From b0b1c4d0fe687360acab6b1e61ebfe3e4ecf3524 Mon Sep 17 00:00:00 2001
From: Leo Barnes
Date: Thu, 5 Sep 2024 09:43:58 +0200
Subject: [PATCH 05/65] Mark change as editorial
---
index.bs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/index.bs b/index.bs
index 26e5c93..bd085fd 100755
--- a/index.bs
+++ b/index.bs
@@ -435,5 +435,5 @@ The following additional constraints apply only to [=AV1 Image Sequences=]:
The media type "image/avif"
is officially registered with IANA and available at: https://www.iana.org/assignments/media-types/image/avif.
Changes since v1.1.0 release
- - Stop using `dfn value` for definitions.
+ - EDITORIAL: Stop using `dfn value` for definitions.
From 2bd17c231f40975a5e5e3d6e2391043f1335f39e Mon Sep 17 00:00:00 2001
From: Leo Barnes
Date: Thu, 5 Sep 2024 10:11:36 +0200
Subject: [PATCH 06/65] Rebase fixes
---
index.bs | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/index.bs b/index.bs
index bd085fd..2fee788 100755
--- a/index.bs
+++ b/index.bs
@@ -296,6 +296,7 @@ NOTE: The size of the last layer can be determined by subtracting the sum of the
A property indicating [X,0,0] is used for an image item composed of 2 layers. The size of the first layer is X and the size of the second layer is ItemSize - X. Note that the [=spatial_id=] for the first layer does not necessarily match the index in the array that provides the size. In other words, in this case the index giving value X is 0, but the corresponding [=spatial_id=] could be 0, 1 or 2. Similarly, a property indicating [X,Y,0] is used for an image made of 3 layers.
Image Sequences
+
An AV1 Image Sequence is defined as a set of AV1 [=Temporal Units=] stored in an [=AV1 track=] as defined in [[!AV1-ISOBMFF]] with the following constraints:
- The track shall be a valid [=MIAF image sequence=].
@@ -305,7 +306,7 @@ NOTE: The size of the last layer can be determined by subtracting the sum of the
Auxiliary Image Items and Sequences
-An AV1 Auxiliary Image Item (respectively an AV1 Auxiliary Image Sequence) is an [=AV1 Image Item=] (respectively [=AV1 Image Sequence=]) with the following additional constraints:
+
An AV1 Auxiliary Image Item (respectively an AV1 Auxiliary Image Sequence) is an [=AV1 Image Item=] (respectively [=AV1 Image Sequence=]) with the following additional constraints:
- It shall be a compliant [=MIAF Auxiliary Image Item=] (respectively [=MIAF Auxiliary Image Sequence=]).
- The [=mono_chrome=]
field in the [=Sequence Header OBU=] shall be set to 1.
- The [=color_range=]
field in the [=Sequence Header OBU=] shall be set to 1.
@@ -391,15 +392,15 @@ NOTE: AV1 tiers are not constrained because timing is optional in image sequenc
NOTE: Level 5.1 is chosen for the Baseline profile to ensure that no single coded image exceeds 4k resolution, as some decoder may not be able to handle larger images. More precisely, following [[!AV1]] level definitions, coded image items compliant to the AVIF Baseline profile may not have a number of pixels greater than 8912896, a width greater than 8192 or a height greater than 4352. It is still possible to use the Baseline profile to create larger images using grid derivation.
- A file containing items compliant with this profile is expected to list the following brands, in any order, in the [=compatible_brands=] of the [=FileTypeBox=]:
+A file containing items compliant with this profile is expected to list the following brands, in any order, in the [=compatible_brands=] of the [=FileTypeBox=]:
avif, mif1, miaf, MA1B
- A file containing a 'pict' track compliant with this profile is expected to list the following brands, in any order, in the [=compatible_brands=] of the [=FileTypeBox=]:
+A file containing a 'pict' track compliant with this profile is expected to list the following brands, in any order, in the [=compatible_brands=] of the [=FileTypeBox=]:
avis, msf1, miaf, MA1B
- A file containing a 'pict' track compliant with this profile and made only of samples marked 'sync' is expected to list the following brands, in any order, in the [=compatible_brands=] of the [=FileTypeBox=]:
+A file containing a 'pict' track compliant with this profile and made only of samples marked 'sync' is expected to list the following brands, in any order, in the [=compatible_brands=] of the [=FileTypeBox=]:
avis, avio, msf1, miaf, MA1B
@@ -421,11 +422,11 @@ The following additional constraints apply only to [=AV1 Image Sequences=]:
- The AV1 level for High Profile shall be 5.1 or lower.
- A file containing items compliant with this profile is expected to list the following brands, in any order, in the [=compatible_brands=] of the [=FileTypeBox=]:
+A file containing items compliant with this profile is expected to list the following brands, in any order, in the [=compatible_brands=] of the [=FileTypeBox=]:
avif, mif1, miaf, MA1A
- A file containing a 'pict' track compliant with this profile is expected to list the following brands, in any order, in the [=compatible_brands=] of the [=FileTypeBox=]:
+A file containing a 'pict' track compliant with this profile is expected to list the following brands, in any order, in the [=compatible_brands=] of the [=FileTypeBox=]:
avis, msf1, miaf, MA1A
From 79bd06fd127da18ba4137eac5b4658a07012513a Mon Sep 17 00:00:00 2001
From: Leo Barnes
Date: Thu, 5 Sep 2024 10:25:12 +0200
Subject: [PATCH 07/65] Switch indentation to 4 spaces
---
index.bs | 296 +++++++++++++++++++++++++++----------------------------
1 file changed, 148 insertions(+), 148 deletions(-)
diff --git a/index.bs b/index.bs
index 2fee788..a55cce2 100755
--- a/index.bs
+++ b/index.bs
@@ -22,118 +22,118 @@ Metadata Order: This version, !*, *
{
- "AV1": {
- "href": "https://aomediacodec.github.io/av1-spec/av1-spec.pdf",
- "id": "AV1",
- "title": "AV1 Bitstream & Decoding Process Specification",
- "status": "LS",
- "publisher": "AOM"
+ "AV1": {
+ "href": "https://aomediacodec.github.io/av1-spec/av1-spec.pdf",
+ "id": "AV1",
+ "title": "AV1 Bitstream & Decoding Process Specification",
+ "status": "LS",
+ "publisher": "AOM"
},
- "AV1-ISOBMFF": {
- "href": "https://aomediacodec.github.io/av1-isobmff/",
- "id": "AV1-ISOBMFF",
- "title": "AV1 Codec ISO Media File Format Binding",
- "status": "LS",
- "publisher": "AOM"
- },
-
- "HEIF": {
- "id": "HEIF",
- "href": "https://www.iso.org/standard/66067.html",
- "title": "Information technology — High efficiency coding and media delivery in heterogeneous environments — Part 12: Image File Format",
- "status": "International Standard",
- "publisher": "ISO/IEC",
- "isoNumber":"ISO/IEC 23008-12:2017"
- },
-
- "ISOBMFF": {
- "id": "ISOBMFF",
- "href": "https://www.iso.org/standard/68960.html",
- "title": "Information technology — Coding of audio-visual objects — Part 12: ISO base media file format",
- "status": "International Standard",
- "publisher": "ISO/IEC",
- "isoNumber":"ISO/IEC 14496-12:2015"
- },
-
- "MIAF": {
- "href": "https://www.iso.org/standard/74417.html",
- "id": "MIAF",
- "title": "Information technology -- Multimedia application format (MPEG-A) -- Part 22: Multi-Image Application Format (MiAF)",
- "status": "Enquiry",
- "publisher": "ISO/IEC",
- "isoNumber": "ISO/IEC DIS 23000-22"
- }
+ "AV1-ISOBMFF": {
+ "href": "https://aomediacodec.github.io/av1-isobmff/",
+ "id": "AV1-ISOBMFF",
+ "title": "AV1 Codec ISO Media File Format Binding",
+ "status": "LS",
+ "publisher": "AOM"
+ },
+
+ "HEIF": {
+ "id": "HEIF",
+ "href": "https://www.iso.org/standard/66067.html",
+ "title": "Information technology — High efficiency coding and media delivery in heterogeneous environments — Part 12: Image File Format",
+ "status": "International Standard",
+ "publisher": "ISO/IEC",
+ "isoNumber":"ISO/IEC 23008-12:2017"
+ },
+
+ "ISOBMFF": {
+ "id": "ISOBMFF",
+ "href": "https://www.iso.org/standard/68960.html",
+ "title": "Information technology — Coding of audio-visual objects — Part 12: ISO base media file format",
+ "status": "International Standard",
+ "publisher": "ISO/IEC",
+ "isoNumber":"ISO/IEC 14496-12:2015"
+ },
+
+ "MIAF": {
+ "href": "https://www.iso.org/standard/74417.html",
+ "id": "MIAF",
+ "title": "Information technology -- Multimedia application format (MPEG-A) -- Part 22: Multi-Image Application Format (MiAF)",
+ "status": "Enquiry",
+ "publisher": "ISO/IEC",
+ "isoNumber": "ISO/IEC DIS 23000-22"
+ }
}
url: https://www.iso.org/standard/66067.html; spec: HEIF; type: property;
- text: colr
- text: mif1
- text: msf1
- text: pasp
- text: pict
- text: pixi
- text: ispe
- text: lsel
- text: layer_id
- text: image_width
- text: image_height
+ text: colr
+ text: mif1
+ text: msf1
+ text: pasp
+ text: pict
+ text: pixi
+ text: ispe
+ text: lsel
+ text: layer_id
+ text: image_width
+ text: image_height
url: https://www.iso.org/standard/68960.html; spec: ISOBMFF; type: dfn;
- text: compatible_brands
- text: FileTypeBox
- text: major_brand
+ text: compatible_brands
+ text: FileTypeBox
+ text: major_brand
url: https://www.iso.org/standard/68960.html; spec: ISOBMFF; type: property;
- text: sync
- text: cclv
- text: clli
- text: mdcv
- text: clap
- text: iloc
+ text: sync
+ text: cclv
+ text: clli
+ text: mdcv
+ text: clap
+ text: iloc
url: https://www.iso.org/standard/74417.html; spec: MIAF; type: property;
- text: miaf
+ text: miaf
url: https://www.iso.org/standard/74417.html; spec: MIAF; type: dfn;
- text: primary image
- text: MIAF image item
- text: MIAF image sequence
- text: MIAF auxiliary image item
- text: MIAF auxiliary image sequence
- text: MIAF file
+ text: primary image
+ text: MIAF image item
+ text: MIAF image sequence
+ text: MIAF auxiliary image item
+ text: MIAF auxiliary image sequence
+ text: MIAF file
url: https://aomediacodec.github.io/av1-isobmff/; spec: AV1-ISOBMFF; type: dfn;
- text: AV1CodecConfigurationBox
- text: AV1 Sample
- text: AV1 Track
+ text: AV1CodecConfigurationBox
+ text: AV1 Sample
+ text: AV1 Track
url: https://aomediacodec.github.io/av1-spec/av1-spec.pdf; spec: AV1; type: dfn;
- text: AV1 bitstream
- text: AV1 Frame
- text: Sequence Header OBU
- text: Metadata OBU
- text: Temporal Unit
- text: Operating Point
- text: Intra Frame
+ text: AV1 bitstream
+ text: AV1 Frame
+ text: Sequence Header OBU
+ text: Metadata OBU
+ text: Temporal Unit
+ text: Operating Point
+ text: Intra Frame
url: https://aomediacodec.github.io/av1-spec/av1-spec.pdf; spec: AV1; type: dfn;
- text: mono_chrome
- text: color_range
- text: still_picture
- text: reduced_still_picture_header
- text: operating_points_cnt_minus_1
- text: choose_operating_point
- text: spatial_id
- text: seq_level_idx
- text: render_width_minus1
- text: render_height_minus1
- text: FrameWidth
- text: FrameHeight
- text: max_frame_width_minus1
- text: max_frame_height_minus1
+ text: mono_chrome
+ text: color_range
+ text: still_picture
+ text: reduced_still_picture_header
+ text: operating_points_cnt_minus_1
+ text: choose_operating_point
+ text: spatial_id
+ text: seq_level_idx
+ text: render_width_minus1
+ text: render_height_minus1
+ text: FrameWidth
+ text: FrameHeight
+ text: max_frame_width_minus1
+ text: max_frame_height_minus1
Scope
@@ -157,33 +157,33 @@ This specification reuses syntax and semantics used in [[!AV1-ISOBMFF]].
AV1 Image Item
When an item is of type av01, it is called an AV1 Image Item, and shall obey the following constraints:
- - The [=AV1 Image Item=] shall be a conformant [=MIAF image item=].
- - The [=AV1 Image Item=] shall be associated with an [=AV1ItemConfigurationProperty=].
- - The content of an [=AV1 Image Item=] is called the AV1 Image Item Data and shall obey the following constraints:
- - The [=AV1 Image Item Data=] shall be identical to the content of an [=AV1 Sample=] marked as 'sync', as defined in [[!AV1-ISOBMFF]].
- - The [=AV1 Image Item Data=] shall have exactly one [=Sequence Header OBU=].
- - If the [=AV1 Image Item Data=] consists of a single frame (i.e. when using a single layer),
- - It should have its [=still_picture=]
flag set to 1.
- - It should have its [=reduced_still_picture_header=]
flag set to 1.
+ - The [=AV1 Image Item=] shall be a conformant [=MIAF image item=].
+ - The [=AV1 Image Item=] shall be associated with an [=AV1ItemConfigurationProperty=].
+ - The content of an [=AV1 Image Item=] is called the AV1 Image Item Data and shall obey the following constraints:
+ - The [=AV1 Image Item Data=] shall be identical to the content of an [=AV1 Sample=] marked as 'sync', as defined in [[!AV1-ISOBMFF]].
+ - The [=AV1 Image Item Data=] shall have exactly one [=Sequence Header OBU=].
+ - If the [=AV1 Image Item Data=] consists of a single frame (i.e. when using a single layer),
+ - It should have its [=still_picture=]
flag set to 1.
+ - It should have its [=reduced_still_picture_header=]
flag set to 1.
Image Item Properties
AV1 Item Configuration Property
- Box Type: av1C
- Property type: Descriptive item property
- Container: ItemPropertyContainerBox
- Mandatory (per item): Yes, for an image item of type 'av01'
- Quantity: One for an image item of type 'av01'
+ Box Type: av1C
+ Property type: Descriptive item property
+ Container: ItemPropertyContainerBox
+ Mandatory (per item): Yes, for an image item of type 'av01'
+ Quantity: One for an image item of type 'av01'
The syntax and semantics of the AV1ItemConfigurationProperty are identical to those of the [=AV1CodecConfigurationBox=] defined in [[!AV1-ISOBMFF]], with the following constraints:
- - [=Sequence Header OBUs=] should not be present in the [=AV1CodecConfigurationBox=].
- - If a [=Sequence Header OBU=] is present in the [=AV1CodecConfigurationBox=], it shall match the [=Sequence Header OBU=] in the [=AV1 Image Item Data=].
- - The values of the fields in the [=AV1CodecConfigurationBox=] shall match those of the [=Sequence Header OBU=] in the [=AV1 Image Item Data=].
- - [=Metadata OBUs=], if present, shall match the values given in other item properties, such as the PixelInformationProperty or ColourInformationBox.
+ - [=Sequence Header OBUs=] should not be present in the [=AV1CodecConfigurationBox=].
+ - If a [=Sequence Header OBU=] is present in the [=AV1CodecConfigurationBox=], it shall match the [=Sequence Header OBU=] in the [=AV1 Image Item Data=].
+ - The values of the fields in the [=AV1CodecConfigurationBox=] shall match those of the [=Sequence Header OBU=] in the [=AV1 Image Item Data=].
+ - [=Metadata OBUs=], if present, shall match the values given in other item properties, such as the PixelInformationProperty or ColourInformationBox.
This property should be marked as essential.
@@ -191,14 +191,14 @@ This property should be marked as essential.
The semantics of the 'ispe' property as defined in [[!HEIF]] apply. More specifically, for AV1 images, the values of 'image_width' and 'image_height' shall respectively equal the values of [=FrameWidth=] and [=FrameHeight=] as defined in [[!AV1]] but for a specific frame in the item payload. The exact frame depends on the presence and content of the 'lsel' and [=OperatingPointSelectorProperty=] properties as follows:
- - In the absence of a 'lsel' property associated with the item, or if it is present and its 'layer_id' value is set to 0xFFFF:
- - If no [=OperatingPointSelectorProperty=] is associated with the item, the 'ispe' shall document the dimensions of the last frame decoded when processing the operating point whose index is 0.
+ - In the absence of a 'lsel' property associated with the item, or if it is present and its 'layer_id' value is set to 0xFFFF:
+ - If no [=OperatingPointSelectorProperty=] is associated with the item, the 'ispe' shall document the dimensions of the last frame decoded when processing the operating point whose index is 0.
- - If an [=OperatingPointSelectorProperty=] is associated with the item, the 'ispe' property shall document the dimensions of the last frame decoded when processing the corresponding operating point.
+ - If an [=OperatingPointSelectorProperty=] is associated with the item, the 'ispe' property shall document the dimensions of the last frame decoded when processing the corresponding operating point.
- NOTE: The dimensions of possible intermediate output images might not match the ones given in the 'ispe' property. If they display these intermediate images, renderers are expected to scale the output image to match the 'ispe' property.
+ NOTE: The dimensions of possible intermediate output images might not match the ones given in the 'ispe' property. If they display these intermediate images, renderers are expected to scale the output image to match the 'ispe' property.
- - If a 'lsel' property is associated with an item and its 'layer_id' is different from 0xFFFF, the 'ispe' property documents the dimensions of the output frame produced by decoding the corresponding layer.
+ - If a 'lsel' property is associated with an item and its 'layer_id' is different from 0xFFFF, the 'ispe' property documents the dimensions of the output frame produced by decoding the corresponding layer.
NOTE: The dimensions indicated in the 'ispe' property might not match the values [=max_frame_width_minus1=]+1 and [=max_frame_height_minus1=]+1 indicated in the AV1 bitstream.
@@ -232,11 +232,11 @@ NOTE: When such a progressive decoding of the layers within an [=Operating Point
Definition
- Box Type: a1op
- Property type: Descriptive item property
- Container: ItemPropertyContainerBox
- Mandatory: No
- Quantity: Zero or one
+ Box Type: a1op
+ Property type: Descriptive item property
+ Container: ItemPropertyContainerBox
+ Mandatory: No
+ Quantity: Zero or one
Description
@@ -263,11 +263,11 @@ The 'lsel' property defined in [[!HEIF]] may be associated with an [=AV1 Image I
Definition
- Box Type: a1lx
- Property type: Descriptive item property
- Container: ItemPropertyContainerBox
- Mandatory: No
- Quantity: Zero or one
+ Box Type: a1lx
+ Property type: Descriptive item property
+ Container: ItemPropertyContainerBox
+ Mandatory: No
+ Quantity: Zero or one
Description
@@ -299,17 +299,17 @@ NOTE: The size of the last layer can be determined by subtracting the sum of the
An AV1 Image Sequence is defined as a set of AV1 [=Temporal Units=] stored in an [=AV1 track=] as defined in [[!AV1-ISOBMFF]] with the following constraints:
- - The track shall be a valid [=MIAF image sequence=].
- - The track handler for an [=AV1 Image Sequence=] shall be pict
.
- - The track shall have only one sample description entry.
- - If multiple [=Sequence Header OBUs=] are present in the track payload, they shall be identical.
+ - The track shall be a valid [=MIAF image sequence=].
+ - The track handler for an [=AV1 Image Sequence=] shall be pict
.
+ - The track shall have only one sample description entry.
+ - If multiple [=Sequence Header OBUs=] are present in the track payload, they shall be identical.
Auxiliary Image Items and Sequences
An AV1 Auxiliary Image Item (respectively an AV1 Auxiliary Image Sequence) is an [=AV1 Image Item=] (respectively [=AV1 Image Sequence=]) with the following additional constraints:
- - It shall be a compliant [=MIAF Auxiliary Image Item=] (respectively [=MIAF Auxiliary Image Sequence=]).
- - The [=mono_chrome=]
field in the [=Sequence Header OBU=] shall be set to 1.
- - The [=color_range=]
field in the [=Sequence Header OBU=] shall be set to 1.
+ - It shall be a compliant [=MIAF Auxiliary Image Item=] (respectively [=MIAF Auxiliary Image Sequence=]).
+ - The [=mono_chrome=]
field in the [=Sequence Header OBU=] shall be set to 1.
+ - The [=color_range=]
field in the [=Sequence Header OBU=] shall be set to 1.
An AV1 Alpha Image Item (respectively an AV1 Alpha Image Sequence) is an [=AV1 Auxiliary Image Item=] (respectively an [=AV1 Auxiliary Image Sequence=]), and as defined in [[!MIAF]], with the aux_type
field of the AuxiliaryTypeProperty
(respectively AuxiliaryTypeInfoBox
) set to urn:mpeg:mpegB:cicp:systems:auxiliary:alpha
. An [=AV1 Alpha Image Item=] (respectively an [=AV1 Alpha Image Sequence=]) shall be encoded with the same bit depth as the associated master [=AV1 Image Item=] (respectively [=AV1 Image Sequence=]).
@@ -333,8 +333,8 @@ NOTE: [[!AV1]] supports encoding either 3-component images (whose semantics are
The brand to identify [=AV1 image items=] is avif.
Files that indicate this brand in the [=compatible_brands=] field of the [=FileTypeBox=] shall comply with the following:
- - The primary item shall be an [=AV1 Image Item=] or be a derived image that references directly or indirectly one or more items that all are [=AV1 Image Items=].
- - [=AV1 auxiliary image items=] may be present in the file.
+ - The primary item shall be an [=AV1 Image Item=] or be a derived image that references directly or indirectly one or more items that all are [=AV1 Image Items=].
+ - [=AV1 auxiliary image items=] may be present in the file.
Files that conform with these constraints should include the brand [=avif=]
in the [=compatible_brands=] field of the [=FileTypeBox=].
@@ -344,8 +344,8 @@ Additionally, the brand avio is de
The brand to identify AVIF image sequences is avis.
Files that indicate this brand in the [=compatible_brands=] field of the [=FileTypeBox=] shall comply with the following:
- - they shall contain one or more [=AV1 image sequences=].
- - they may contain [=AV1 auxiliary image sequences=].
+ - they shall contain one or more [=AV1 image sequences=].
+ - they may contain [=AV1 auxiliary image sequences=].
Files that conform with these constraints should include the brand [=avis=]
in the [=compatible_brands=] field of the [=FileTypeBox=].
@@ -356,9 +356,9 @@ NOTE: As defined in [[!MIAF]], a file that is primarily an image sequence still
General constraints
The following constraints are common to files compliant with this specification:
- - The file shall be compliant with the [[!MIAF]] specification and list 'miaf' in the [=compatible_brands=] field of the [=FileTypeBox=].
- - The file shall list '[=avif=]'
or '[=avis=]'
in the [=compatible_brands=] field of the [=FileTypeBox=].
- - If transformative properties are used in derivation chains (as defined in [[MIAF]]), they shall only be associated with items that are not referenced by another derived item. For example, if a file contains a grid item and its referenced coded image items, cropping, mirroring or rotation transformations are only permitted on the grid item itself.
+ - The file shall be compliant with the [[!MIAF]] specification and list 'miaf' in the [=compatible_brands=] field of the [=FileTypeBox=].
+ - The file shall list '[=avif=]'
or '[=avis=]'
in the [=compatible_brands=] field of the [=FileTypeBox=].
+ - If transformative properties are used in derivation chains (as defined in [[MIAF]]), they shall only be associated with items that are not referenced by another derived item. For example, if a file contains a grid item and its referenced coded image items, cropping, mirroring or rotation transformations are only permitted on the grid item itself.
NOTE: This constraint further restricts files compared to [[MIAF]].
@@ -385,7 +385,7 @@ This section defines the MIAF AV1 Baseline profile of [[!HEIF]], specifically fo
If the brand MA1B
is in the list of [=compatible_brands=] of the [=FileTypeBox=], the common constraints in the section [[#brands]] shall apply.
The following additional constraints apply to all [=AV1 Image Items=] and all [=AV1 Image Sequences=]:
- - The AV1 profile shall be the Main Profile and the level shall be 5.1 or lower.
+ - The AV1 profile shall be the Main Profile and the level shall be 5.1 or lower.
NOTE: AV1 tiers are not constrained because timing is optional in image sequences and are not relevant in image items or collections.
@@ -394,15 +394,15 @@ NOTE: Level 5.1 is chosen for the Baseline profile to ensure that no single cod
A file containing items compliant with this profile is expected to list the following brands, in any order, in the [=compatible_brands=] of the [=FileTypeBox=]:
- avif, mif1, miaf, MA1B
+ avif, mif1, miaf, MA1B
A file containing a 'pict' track compliant with this profile is expected to list the following brands, in any order, in the [=compatible_brands=] of the [=FileTypeBox=]:
- avis, msf1, miaf, MA1B
+ avis, msf1, miaf, MA1B
A file containing a 'pict' track compliant with this profile and made only of samples marked 'sync' is expected to list the following brands, in any order, in the [=compatible_brands=] of the [=FileTypeBox=]:
- avis, avio, msf1, miaf, MA1B
+ avis, avio, msf1, miaf, MA1B
AVIF Advanced Profile
@@ -412,23 +412,23 @@ This section defines the MIAF AV1 Advanced profile of [[!HEIF]], specifically fo
If the brand MA1A
is in the list of [=compatible_brands=] of the [=FileTypeBox=], the common constraints in the section [[#brands]] shall apply.
The following additional constraints apply to all [=AV1 Image Items=]:
- - The AV1 profile shall be the High Profile and the level shall be 6.0 or lower.
+ - The AV1 profile shall be the High Profile and the level shall be 6.0 or lower.
NOTE: Following [[!AV1]] level definitions, coded image items compliant to the AVIF Advanced profile may not have a number of pixels greater than 35651584, a width greater than 16384 or a height greater than 8704. It is still possible to use the Advanced profile to create larger images using grid derivation.
The following additional constraints apply only to [=AV1 Image Sequences=]:
- - The AV1 profile shall be either Main Profile or High Profile.
- - The AV1 level for Main Profile shall be 5.1 or lower.
- - The AV1 level for High Profile shall be 5.1 or lower.
+ - The AV1 profile shall be either Main Profile or High Profile.
+ - The AV1 level for Main Profile shall be 5.1 or lower.
+ - The AV1 level for High Profile shall be 5.1 or lower.
A file containing items compliant with this profile is expected to list the following brands, in any order, in the [=compatible_brands=] of the [=FileTypeBox=]:
- avif, mif1, miaf, MA1A
+ avif, mif1, miaf, MA1A
A file containing a 'pict' track compliant with this profile is expected to list the following brands, in any order, in the [=compatible_brands=] of the [=FileTypeBox=]:
- avis, msf1, miaf, MA1A
+ avis, msf1, miaf, MA1A
AVIF Media Type Registration
@@ -436,5 +436,5 @@ A file containing a 'pict' track compliant with this profile is expected to list
The media type "image/avif"
is officially registered with IANA and available at: https://www.iana.org/assignments/media-types/image/avif.
Changes since v1.1.0 release
- - EDITORIAL: Stop using `dfn value` for definitions.
+ - EDITORIAL: Stop using `dfn value` for definitions.
From 58098656320984773bf8f4517259f66b79c57b9d Mon Sep 17 00:00:00 2001
From: Leo Barnes
Date: Mon, 12 Aug 2024 13:19:23 +0200
Subject: [PATCH 08/65] Add asserts for shoulds and shalls
---
index.bs | 95 ++++++++++++++++++++++++++++----------------------------
1 file changed, 48 insertions(+), 47 deletions(-)
diff --git a/index.bs b/index.bs
index a55cce2..a62172a 100755
--- a/index.bs
+++ b/index.bs
@@ -157,14 +157,14 @@ This specification reuses syntax and semantics used in [[!AV1-ISOBMFF]].
AV1 Image Item
When an item is of type av01, it is called an AV1 Image Item, and shall obey the following constraints:
- - The [=AV1 Image Item=] shall be a conformant [=MIAF image item=].
- - The [=AV1 Image Item=] shall be associated with an [=AV1ItemConfigurationProperty=].
+ - The [=AV1 Image Item=] shall be a conformant [=MIAF image item=].
+ - The [=AV1 Image Item=] shall be associated with an [=AV1ItemConfigurationProperty=].
- The content of an [=AV1 Image Item=] is called the AV1 Image Item Data and shall obey the following constraints:
- - The [=AV1 Image Item Data=] shall be identical to the content of an [=AV1 Sample=] marked as 'sync', as defined in [[!AV1-ISOBMFF]].
- - The [=AV1 Image Item Data=] shall have exactly one [=Sequence Header OBU=].
+ - The [=AV1 Image Item Data=] shall be identical to the content of an [=AV1 Sample=] marked as 'sync', as defined in [[!AV1-ISOBMFF]].
+ - The [=AV1 Image Item Data=] shall have exactly one [=Sequence Header OBU=].
- If the [=AV1 Image Item Data=] consists of a single frame (i.e. when using a single layer),
- - It should have its [=still_picture=]
flag set to 1.
- - It should have its [=reduced_still_picture_header=]
flag set to 1.
+ - It should have its [=still_picture=]
flag set to 1.
+ - It should have its [=reduced_still_picture_header=]
flag set to 1.
Image Item Properties
@@ -180,21 +180,21 @@ When an item is of type av01, it is
The syntax and semantics of the AV1ItemConfigurationProperty are identical to those of the [=AV1CodecConfigurationBox=] defined in [[!AV1-ISOBMFF]], with the following constraints:
- - [=Sequence Header OBUs=] should not be present in the [=AV1CodecConfigurationBox=].
- - If a [=Sequence Header OBU=] is present in the [=AV1CodecConfigurationBox=], it shall match the [=Sequence Header OBU=] in the [=AV1 Image Item Data=].
- - The values of the fields in the [=AV1CodecConfigurationBox=] shall match those of the [=Sequence Header OBU=] in the [=AV1 Image Item Data=].
- - [=Metadata OBUs=], if present, shall match the values given in other item properties, such as the PixelInformationProperty or ColourInformationBox.
+ - [=Sequence Header OBUs=] should not be present in the [=AV1CodecConfigurationBox=].
+ - If a [=Sequence Header OBU=] is present in the [=AV1CodecConfigurationBox=], it shall match the [=Sequence Header OBU=] in the [=AV1 Image Item Data=].
+ - The values of the fields in the [=AV1CodecConfigurationBox=] shall match those of the [=Sequence Header OBU=] in the [=AV1 Image Item Data=].
+ - [=Metadata OBUs=], if present, shall match the values given in other item properties, such as the PixelInformationProperty or ColourInformationBox.
-This property should be marked as essential.
+This property should be marked as essential.
Image Spatial Extents Property
-The semantics of the 'ispe' property as defined in [[!HEIF]] apply. More specifically, for AV1 images, the values of 'image_width' and 'image_height' shall respectively equal the values of [=FrameWidth=] and [=FrameHeight=] as defined in [[!AV1]] but for a specific frame in the item payload. The exact frame depends on the presence and content of the 'lsel' and [=OperatingPointSelectorProperty=] properties as follows:
+The semantics of the 'ispe' property as defined in [[!HEIF]] apply. More specifically, for AV1 images, the values of 'image_width' and 'image_height' shall respectively equal the values of [=FrameWidth=] and [=FrameHeight=] as defined in [[!AV1]] but for a specific frame in the item payload. The exact frame depends on the presence and content of the 'lsel' and [=OperatingPointSelectorProperty=] properties as follows:
- In the absence of a 'lsel' property associated with the item, or if it is present and its 'layer_id' value is set to 0xFFFF:
- - If no [=OperatingPointSelectorProperty=] is associated with the item, the 'ispe' shall document the dimensions of the last frame decoded when processing the operating point whose index is 0.
+ - If no [=OperatingPointSelectorProperty=] is associated with the item, the 'ispe' shall document the dimensions of the last frame decoded when processing the operating point whose index is 0.
- - If an [=OperatingPointSelectorProperty=] is associated with the item, the 'ispe' property shall document the dimensions of the last frame decoded when processing the corresponding operating point.
+ - If an [=OperatingPointSelectorProperty=] is associated with the item, the 'ispe' property shall document the dimensions of the last frame decoded when processing the corresponding operating point.
NOTE: The dimensions of possible intermediate output images might not match the ones given in the 'ispe' property. If they display these intermediate images, renderers are expected to scale the output image to match the 'ispe' property.
@@ -218,7 +218,7 @@ NOTE: Although the clean aperture property ('clap') defined in [[!HEIF]] is appl
[[!AV1]] supports encoding a frame using multiple spatial layers. A spatial layer may improve the resolution or quality of the image decoded based on one or more of the previous layers. A layer may also provide an image that does not depend on the previous layers. Additionally, not all layers are expected to produce an image meant to be rendered. Some decoded images may be used only as intermediate decodes. Finally, layers are grouped into one or more [=Operating Points=]. The [=Sequence Header OBU=] defines the list of [=Operating Points=], provides required decoding capabilities, and indicates which layers form each [=Operating Point=].
-[[!AV1]] delegates the selection of which [=Operating Point=] to process to the application, by means of a function called choose_operating_point()
. AVIF defines the [=OperatingPointSelectorProperty=] to control this selection. In the absence of an [=OperatingPointSelectorProperty=] associated with an [=AV1 Image Item=], the AVIF renderer is free to process any [=Operating Point=] present in the [=AV1 Image Item Data=]. In particular, when the [=AV1 Image Item=] is composed of a unique [=Operating Point=], the [=OperatingPointSelectorProperty=] should not be present. If an [=OperatingPointSelectorProperty=] is associated with an [=AV1 Image Item=], the op_index
field indicates which [=Operating Point=] is expected to be processed for this item.
+[[!AV1]] delegates the selection of which [=Operating Point=] to process to the application, by means of a function called choose_operating_point()
. AVIF defines the [=OperatingPointSelectorProperty=] to control this selection. In the absence of an [=OperatingPointSelectorProperty=] associated with an [=AV1 Image Item=], the AVIF renderer is free to process any [=Operating Point=] present in the [=AV1 Image Item Data=]. In particular, when the [=AV1 Image Item=] is composed of a unique [=Operating Point=], the [=OperatingPointSelectorProperty=] should not be present. If an [=OperatingPointSelectorProperty=] is associated with an [=AV1 Image Item=], the op_index
field indicates which [=Operating Point=] is expected to be processed for this item.
NOTE: When an author wants to offer the ability to render multiple [=Operating Points=] from the same AV1 image (e.g. in the case of multi-view images), multiple [=AV1 Image Items=] can be created that share the same [=AV1 Image Item Data=] but have different [=OperatingPointSelectorProperty=]s.
@@ -241,7 +241,7 @@ NOTE: When such a progressive decoding of the layers within an [=Operating Point
Description
-An OperatingPointSelectorProperty may be associated with an [=AV1 Image Item=] to provide the index of the operating point to be processed for this item. If associated, it shall be marked as essential.
+An OperatingPointSelectorProperty may be associated with an [=AV1 Image Item=] to provide the index of the operating point to be processed for this item. If associated, it shall be marked as essential.
Syntax
@@ -253,10 +253,10 @@ class OperatingPointSelectorProperty extends ItemProperty('a1op') {
Semantics
-op_index indicates the index of the operating point to be processed for this item. Its value shall be between 0 and [=operating_points_cnt_minus_1=].
+op_index indicates the index of the operating point to be processed for this item. Its value shall be between 0 and [=operating_points_cnt_minus_1=].
Layer Selector Property
-The 'lsel' property defined in [[!HEIF]] may be associated with an [=AV1 Image Item=]. The 'layer_id' indicates the value of the [=spatial_id=] to render. The value shall be between 0 and 3, or the special value 0xFFFF. When a value between 0 and 3 is used, the corresponding spatial layer shall be present in the bitstream and shall produce an output frame. Other layers may be needed to decode the indicated layer. When the special value 0xFFFF is used, progressive decoding is allowed as described in [[#layered-items-overview]].
+The 'lsel' property defined in [[!HEIF]] may be associated with an [=AV1 Image Item=]. The 'layer_id' indicates the value of the [=spatial_id=] to render. The value shall be between 0 and 3, or the special value 0xFFFF. When a value between 0 and 3 is used, the corresponding spatial layer shall be present in the bitstream and shall produce an output frame. Other layers may be needed to decode the indicated layer. When the special value 0xFFFF is used, progressive decoding is allowed as described in [[#layered-items-overview]].
Layered Image Indexing Property
@@ -272,9 +272,9 @@ The 'lsel' property defined in [[!HEIF]] may be associated with an [=AV1 Image I
Description
-The AV1LayeredImageIndexingProperty property may be associated with an [=AV1 Image Item=]. It should not be associated with [=AV1 Image Items=] consisting of only one layer.
+The AV1LayeredImageIndexingProperty property may be associated with an [=AV1 Image Item=]. It should not be associated with [=AV1 Image Items=] consisting of only one layer.
-The [=AV1LayeredImageIndexingProperty=] documents the size in bytes of each layer (except the last one) in the [=AV1 Image Item Data=], and enables determining the byte ranges required to process one or more layers of an [=Operating Point=]. If associated, it shall not be marked as essential.
+The [=AV1LayeredImageIndexingProperty=] documents the size in bytes of each layer (except the last one) in the [=AV1 Image Item Data=], and enables determining the byte ranges required to process one or more layers of an [=Operating Point=]. If associated, it shall not be marked as essential.
Syntax
@@ -289,7 +289,7 @@ class AV1LayeredImageIndexingProperty extends ItemProperty('a1lx') {
Semantics
-layer_size indicates the number of bytes corresponding to each layer in the item payload, except for the last layer. Values are provided in increasing order of [=spatial_id=]. A value of zero means that all the layers except the last one have been documented and following values shall be 0. The number of non-zero values shall match the number of layers in the image minus one.
+layer_size indicates the number of bytes corresponding to each layer in the item payload, except for the last layer. Values are provided in increasing order of [=spatial_id=]. A value of zero means that all the layers except the last one have been documented and following values shall be 0. The number of non-zero values shall match the number of layers in the image minus one..
NOTE: The size of the last layer can be determined by subtracting the sum of the sizes of all layers indicated in this property from the entire item size.
@@ -299,21 +299,21 @@ NOTE: The size of the last layer can be determined by subtracting the sum of the
An AV1 Image Sequence is defined as a set of AV1 [=Temporal Units=] stored in an [=AV1 track=] as defined in [[!AV1-ISOBMFF]] with the following constraints:
- - The track shall be a valid [=MIAF image sequence=].
- - The track handler for an [=AV1 Image Sequence=] shall be pict
.
- - The track shall have only one sample description entry.
- - If multiple [=Sequence Header OBUs=] are present in the track payload, they shall be identical.
+ - The track shall be a valid [=MIAF image sequence=].
+ - The track handler for an [=AV1 Image Sequence=] shall be pict
.
+ - The track shall have only one sample description entry.
+ - If multiple [=Sequence Header OBUs=] are present in the track payload, they shall be identical.
Auxiliary Image Items and Sequences
An AV1 Auxiliary Image Item (respectively an AV1 Auxiliary Image Sequence) is an [=AV1 Image Item=] (respectively [=AV1 Image Sequence=]) with the following additional constraints:
- - It shall be a compliant [=MIAF Auxiliary Image Item=] (respectively [=MIAF Auxiliary Image Sequence=]).
- - The [=mono_chrome=]
field in the [=Sequence Header OBU=] shall be set to 1.
- - The [=color_range=]
field in the [=Sequence Header OBU=] shall be set to 1.
+ - It shall be a compliant [=MIAF Auxiliary Image Item=] (respectively [=MIAF Auxiliary Image Sequence=]).
+ - The [=mono_chrome=]
field in the [=Sequence Header OBU=] shall be set to 1.
+ - The [=color_range=]
field in the [=Sequence Header OBU=] shall be set to 1.
-An AV1 Alpha Image Item (respectively an AV1 Alpha Image Sequence) is an [=AV1 Auxiliary Image Item=] (respectively an [=AV1 Auxiliary Image Sequence=]), and as defined in [[!MIAF]], with the aux_type
field of the AuxiliaryTypeProperty
(respectively AuxiliaryTypeInfoBox
) set to urn:mpeg:mpegB:cicp:systems:auxiliary:alpha
. An [=AV1 Alpha Image Item=] (respectively an [=AV1 Alpha Image Sequence=]) shall be encoded with the same bit depth as the associated master [=AV1 Image Item=] (respectively [=AV1 Image Sequence=]).
+An AV1 Alpha Image Item (respectively an AV1 Alpha Image Sequence) is an [=AV1 Auxiliary Image Item=] (respectively an [=AV1 Auxiliary Image Sequence=]), and as defined in [[!MIAF]], with the aux_type
field of the AuxiliaryTypeProperty
(respectively AuxiliaryTypeInfoBox
) set to urn:mpeg:mpegB:cicp:systems:auxiliary:alpha
. An [=AV1 Alpha Image Item=] (respectively an [=AV1 Alpha Image Sequence=]) shall be encoded with the same bit depth as the associated master [=AV1 Image Item=] (respectively [=AV1 Image Sequence=]).
-For [=AV1 Alpha Image Item=] and [=AV1 Alpha Image Sequence=], the ColourInformationBox should be omitted. If present, readers shall ignore it.
+For [=AV1 Alpha Image Item=] and [=AV1 Alpha Image Sequence=], the ColourInformationBox should be omitted. If present, readers shall ignore it.
An AV1 Depth Image Item (respectively an AV1 Depth Image Sequence) is an [=AV1 Auxiliary Image Item=] (respectively an [=AV1 Auxiliary Image Sequence=]), and as defined in [[!MIAF]], with the aux_type
field of the AuxiliaryTypeProperty
(respectively AuxiliaryTypeInfoBox
) set to urn:mpeg:mpegB:cicp:systems:auxiliary:depth
.
@@ -327,38 +327,38 @@ NOTE: [[!AV1]] supports encoding either 3-component images (whose semantics are
An [=AV1 Image File Format=] file may conform to multiple brands. Similarly, an [=AV1 Image File Format=] reader/parser or [=AV1 Image File Format=] renderer may be capable of processing the features associated with one or more brands.
-If any of the brands defined in this document is specified in the [=major_brand=]
field of the [=FileTypeBox=], the file extension and Internet Media Type should respectively be ".avif
" and "image/avif
" as defined in [[#mime-registration]].
+If any of the brands defined in this document is specified in the [=major_brand=]
field of the [=FileTypeBox=], the file extension and Internet Media Type should respectively be ".avif
" and "image/avif
" as defined in [[#mime-registration]].
AVIF image and image collection brand
The brand to identify [=AV1 image items=] is avif.
Files that indicate this brand in the [=compatible_brands=] field of the [=FileTypeBox=] shall comply with the following:
- - The primary item shall be an [=AV1 Image Item=] or be a derived image that references directly or indirectly one or more items that all are [=AV1 Image Items=].
+ - The primary item shall be an [=AV1 Image Item=] or be a derived image that references directly or indirectly one or more items that all are [=AV1 Image Items=].
- [=AV1 auxiliary image items=] may be present in the file.
-Files that conform with these constraints should include the brand [=avif=]
in the [=compatible_brands=] field of the [=FileTypeBox=].
+Files that conform with these constraints should include the brand [=avif=]
in the [=compatible_brands=] field of the [=FileTypeBox=].
-Additionally, the brand avio is defined. If the file indicates the brand [=avio=]
in the [=compatible_brands=] field of the [=FileTypeBox=], then the primary item or all the items referenced by the primary item shall be [=AV1 image items=] made only of [=Intra Frames=]. Conversely, if the previous constraint applies, the brand [=avio=]
should be used in the [=compatible_brands=] field of the [=FileTypeBox=].
+Additionally, the brand avio is defined. If the file indicates the brand [=avio=]
in the [=compatible_brands=] field of the [=FileTypeBox=], then the primary item or all the items referenced by the primary item shall be [=AV1 image items=] made only of [=Intra Frames=]. Conversely, if the previous constraint applies, the brand [=avio=]
should be used in the [=compatible_brands=] field of the [=FileTypeBox=].
AVIF image sequence brands
The brand to identify AVIF image sequences is avis.
Files that indicate this brand in the [=compatible_brands=] field of the [=FileTypeBox=] shall comply with the following:
- - they shall contain one or more [=AV1 image sequences=].
+ - they shall contain one or more [=AV1 image sequences=].
- they may contain [=AV1 auxiliary image sequences=].
-Files that conform with these constraints should include the brand [=avis=]
in the [=compatible_brands=] field of the [=FileTypeBox=].
+Files that conform with these constraints should include the brand [=avis=]
in the [=compatible_brands=] field of the [=FileTypeBox=].
-Additionally, if a file contains [=AV1 image sequences=] and the brand [=avio=]
is used in the [=compatible_brands=] field of the [=FileTypeBox=], the item constraints for this brand shall be met and at least one of the [=AV1 image sequences=] shall be made only of [=AV1 Samples=] marked as 'sync'. Conversely, if such a track exists and the constraints of the brand [=avio=]
on [=AV1 image items=] are met, the brand should be used.
+Additionally, if a file contains [=AV1 image sequences=] and the brand [=avio=]
is used in the [=compatible_brands=] field of the [=FileTypeBox=], the item constraints for this brand shall be met and at least one of the [=AV1 image sequences=] shall be made only of [=AV1 Samples=] marked as 'sync'. Conversely, if such a track exists and the constraints of the brand [=avio=]
on [=AV1 image items=] are met, the brand should be used.
NOTE: As defined in [[!MIAF]], a file that is primarily an image sequence still has at least an image item. Hence, it can also declare brands for signaling the image item.
General constraints
The following constraints are common to files compliant with this specification:
- - The file shall be compliant with the [[!MIAF]] specification and list 'miaf' in the [=compatible_brands=] field of the [=FileTypeBox=].
- - The file shall list '[=avif=]'
or '[=avis=]'
in the [=compatible_brands=] field of the [=FileTypeBox=].
- - If transformative properties are used in derivation chains (as defined in [[MIAF]]), they shall only be associated with items that are not referenced by another derived item. For example, if a file contains a grid item and its referenced coded image items, cropping, mirroring or rotation transformations are only permitted on the grid item itself.
+ - The file shall be compliant with the [[!MIAF]] specification and list 'miaf' in the [=compatible_brands=] field of the [=FileTypeBox=].
+ - The file shall list '[=avif=]'
or '[=avis=]'
in the [=compatible_brands=] field of the [=FileTypeBox=].
+ - If transformative properties are used in derivation chains (as defined in [[MIAF]]), they shall only be associated with items that are not referenced by another derived item. For example, if a file contains a grid item and its referenced coded image items, cropping, mirroring or rotation transformations are only permitted on the grid item itself.
NOTE: This constraint further restricts files compared to [[MIAF]].
@@ -368,9 +368,9 @@ NOTE: This constraint further restricts files compared to [[MIAF]].
The profiles defined in this section are for enabling interoperability between [=AV1 Image File Format=] files and [=AV1 Image File Format=] readers/parsers. A profile imposes a set of specific restrictions and is signaled by brands defined in this specification.
-The [=FileTypeBox=] should declare at least one profile that enables decoding of the primary image item. It is not an error for the encoder to include an auxiliary image that is not allowed by the specified profile(s).
+The [=FileTypeBox=] should declare at least one profile that enables decoding of the primary image item. It is not an error for the encoder to include an auxiliary image that is not allowed by the specified profile(s).
-If '[=avis=]'
is declared in the [=FileTypeBox=] and a profile is declared in the [=FileTypeBox=], the profile shall also enable decoding of at least one image sequence track. The profile should allow decoding of any associated auxiliary image sequence tracks, unless it is acceptable to decode the image sequence without its auxiliary image sequence tracks.
+If '[=avis=]'
is declared in the [=FileTypeBox=] and a profile is declared in the [=FileTypeBox=], the profile shall also enable decoding of at least one image sequence track. The profile should allow decoding of any associated auxiliary image sequence tracks, unless it is acceptable to decode the image sequence without its auxiliary image sequence tracks.
It is possible for a file compliant to this [=AV1 Image File Format=] to not be able to declare an AVIF profile, if the corresponding AV1 encoding characteristics do not match any of the defined profiles.
@@ -385,7 +385,7 @@ This section defines the MIAF AV1 Baseline profile of [[!HEIF]], specifically fo
If the brand MA1B
is in the list of [=compatible_brands=] of the [=FileTypeBox=], the common constraints in the section [[#brands]] shall apply.
The following additional constraints apply to all [=AV1 Image Items=] and all [=AV1 Image Sequences=]:
- - The AV1 profile shall be the Main Profile and the level shall be 5.1 or lower.
+ - The AV1 profile shall be the Main Profile and the level shall be 5.1 or lower.
NOTE: AV1 tiers are not constrained because timing is optional in image sequences and are not relevant in image items or collections.
@@ -412,14 +412,14 @@ This section defines the MIAF AV1 Advanced profile of [[!HEIF]], specifically fo
If the brand MA1A
is in the list of [=compatible_brands=] of the [=FileTypeBox=], the common constraints in the section [[#brands]] shall apply.
The following additional constraints apply to all [=AV1 Image Items=]:
- - The AV1 profile shall be the High Profile and the level shall be 6.0 or lower.
+ - The AV1 profile shall be the High Profile and the level shall be 6.0 or lower.
NOTE: Following [[!AV1]] level definitions, coded image items compliant to the AVIF Advanced profile may not have a number of pixels greater than 35651584, a width greater than 16384 or a height greater than 8704. It is still possible to use the Advanced profile to create larger images using grid derivation.
The following additional constraints apply only to [=AV1 Image Sequences=]:
- - The AV1 profile shall be either Main Profile or High Profile.
- - The AV1 level for Main Profile shall be 5.1 or lower.
- - The AV1 level for High Profile shall be 5.1 or lower.
+ - The AV1 profile shall be either Main Profile or High Profile.
+ - The AV1 level for Main Profile shall be 5.1 or lower.
+ - The AV1 level for High Profile shall be 5.1 or lower.
A file containing items compliant with this profile is expected to list the following brands, in any order, in the [=compatible_brands=] of the [=FileTypeBox=]:
@@ -437,4 +437,5 @@ A file containing a 'pict' track compliant with this profile is expected to list
Changes since v1.1.0 release
- EDITORIAL:
Stop using `dfn value` for definitions.
+ - EDITORIAL:
Add assert-ids in the spec for conformance file testing and ComplianceWarden
From b510e72c0d56c8c98b2d9c4da09d3c4af04f0d2d Mon Sep 17 00:00:00 2001
From: Leo Barnes
Date: Mon, 14 Nov 2022 11:10:15 +0100
Subject: [PATCH 09/65] Fix issue #177
Changed alpha_video.avif:
- Applied Jon's fix to set the correct iref
- Stripped out optional config OBUs from av1C
- Added explicit NCLX with 1,13,1,0
- Set track_in_movie to true in track
---
testFiles/Netflix/avis/alpha_video.avif | Bin 10755 -> 10743 bytes
1 file changed, 0 insertions(+), 0 deletions(-)
diff --git a/testFiles/Netflix/avis/alpha_video.avif b/testFiles/Netflix/avis/alpha_video.avif
index d88c9aeec0f8acd158ccd09510c5ddc88608fd44..e552624ebfa5f2438535993298954317041e50c9 100644
GIT binary patch
delta 202
zcmZn;`5rvMm~rJqlX(7h42%p63{DIzK$3yu!^B02yddV)%z~lzyhRO+dC#dWt_vvyt#?#1{3d71_u5u3=9&s3=E38o6}kCm_^q!FbMu(
cV366!z@Xv=6lTaxNi3PXo7ZXc9}ad!0D2QFV*mgE
delta 167
zcmew!+#E8&m~rbwlX(7J42%p63{DIzK$3yu&%{NEydc)Y%z~li6A}@FflN*GBP!{v@)=;Ffz5ZPrk`GXL24Z
z&*ny^vrN1n85sBvFfd4XGB7AwZjNTPV;0@bz#s%PL}o7ogGvxkm?1YMv1IakUZ>3;
HIM@{dQ*I}e
From 0a4930333ed60c578340fe89438d66e2d983e8e8 Mon Sep 17 00:00:00 2001
From: Leo Barnes
Date: Thu, 10 Nov 2022 10:54:04 +0100
Subject: [PATCH 10/65] Changed Xiph multilayer test content with the following
changes: 1. Add lsel property with value 0xFFFF 2. Add NCLX colr box with
value 1,13,1,0 (since this matches what the PNGs look like)
---
testFiles/Xiph/abandoned_filmgrain.avif | Bin 141518 -> 141549 bytes
testFiles/Xiph/fruits_2layer_thumbsize.avif | Bin 35496 -> 35527 bytes
testFiles/Xiph/quebec_3layer_op2.avif | Bin 86622 -> 86653 bytes
testFiles/Xiph/tiger_3layer_1res.avif | Bin 70944 -> 70975 bytes
testFiles/Xiph/tiger_3layer_3res.avif | Bin 64981 -> 65012 bytes
5 files changed, 0 insertions(+), 0 deletions(-)
diff --git a/testFiles/Xiph/abandoned_filmgrain.avif b/testFiles/Xiph/abandoned_filmgrain.avif
index f3a6abb3578e549a1f81242010c188ab70403e31..ef17a8522a2b7e8818c1538e66e9d43900a20a08 100644
GIT binary patch
delta 97
zcmX?ik>l+}jtTONdJ`4m8G|M^7;?_ZEGQ~qU|^`4xGTm)I5|J3C@(puf`O5N7l?s?
uE2lU$=l_2oODeMlJ&jtTON{1X-88I3147;@HT78DgQFfhbU+!Z4#ky((N2;_hOBLgEVBU5t=
SYqJ+)yB8zlb}vSz#p(c}FcDDz
diff --git a/testFiles/Xiph/fruits_2layer_thumbsize.avif b/testFiles/Xiph/fruits_2layer_thumbsize.avif
index cf5b9b855b1cfa541d6fea5df31ed0761d8d2f9f..16a8d0951a76b6aa198fb3e3f1602a21f697c269 100644
GIT binary patch
delta 89
zcmZ26mFf6YrU~+ldJ`4m8G|M^7;?_ZEGQ~qU|^`4xGTm)I5|J3C@(puf`O5N7l?s?
lE2lU$=l_2oODeM;m1)IPrU~+l{1X-88I3147;@HT78DgQFfhbU+!Z4#ky((N2;_hOBLgEVBU5t=
K>t-*;+D-uSnhzEL
diff --git a/testFiles/Xiph/quebec_3layer_op2.avif b/testFiles/Xiph/quebec_3layer_op2.avif
index c1da468a142892d12327f11ed16751b4f7adfa74..952960391abb9a7502142bab64fd7f3fd939c6f8 100644
GIT binary patch
delta 93
zcmcb&g!S(d)(P^AN)r|08Qmr}7;;X?EGQ~qU|`6bxGTU!I5|J3C@(puf`O5N7l?s?
pE2lU$=l_2oODeM*QmI?BV8WR=b8GR-;7;;X_EGQ~qU|=YjxGT&=I5|J3C@(puf`O5N7l?s?
qE2lU$=l_2oODeMt-*;Reu08`Vig#
From 27cce807c80c2dab72aa02e973523109d6122dae Mon Sep 17 00:00:00 2001
From: Leo Barnes
Date: Mon, 14 Nov 2022 12:31:47 +0100
Subject: [PATCH 11/65] Fix issue 150
Microsoft/Chimera_*_cropped_*.avif:
- Truncated crop to integers
- Stripped optional config OBUs
Link-U/kimono*.crop.avif:
- Reordered property associations so 'ispe' comes before transform properties
- Rounded up crop to integers (that matches the PNGs)
- Added NCLX with values 1,13,9,0
- Stripped optional config OBUs
---
testFiles/Link-U/kimono.crop.avif | Bin 85486 -> 85494 bytes
...kimono.mirror-vertical.rotate270.crop.avif | Bin 85570 -> 85578 bytes
.../Chimera_10bit_cropped_to_1920x1008.avif | Bin 95966 -> 95953 bytes
...ropped_to_1920x1008_with_HDR_metadata.avif | Bin 96012 -> 95999 bytes
.../Chimera_8bit_cropped_480x256.avif | Bin 38547 -> 38534 bytes
5 files changed, 0 insertions(+), 0 deletions(-)
diff --git a/testFiles/Link-U/kimono.crop.avif b/testFiles/Link-U/kimono.crop.avif
index 777813e690c8f086fecd5028450e053800440490..58905363815ce379bc918d5183c636c165bc719e 100644
GIT binary patch
delta 128
zcmaDioAujl)(OgteiK#F8OtX2I7%+bEGQ~qU|?v@EJ)4=(gFpE#UMW8WIjf18J@&4
zL+3_T9-sh&aB_Z5QC@OR1p^}kF9RpT#8=X4=Yir(|NsA;0iuCeGP58z5lDjoBLgE_
T6Jv8rYg=;~!hxODP)(OgtNfTAl8M`L-I7;rwEGQ~qU|^V#hxO1L)(OgtQ4>|t8Ji~dILdCwEGQ~qU|{IWEJ)4=(gFpE#UMT-2v4?Wl;Zk#
z2FgvJ_{>&UBC*WSxsjEJfs0Ert^T)r6O)t>2T*}jW%9vA=s
diff --git a/testFiles/Microsoft/Chimera_10bit_cropped_to_1920x1008.avif b/testFiles/Microsoft/Chimera_10bit_cropped_to_1920x1008.avif
index 4f2da5369644c4ca80e5809f52383a6982afc575..e27cdb02350cb086f09f78426d03ae6d254831f2 100644
GIT binary patch
delta 147
zcmccjmi6LW)(OgtJ`+_sQlKES
zA`{4AVCLfD0#ZDQWrog;96lf+jpUp}phETrAe#}W;sb;Rk_=!&VYEbML2e>g6l@VI
SBNKB=YjZr~_IO6d`ceRE6&qOq
delta 185
zcmcckmi69S)(OgtkrP!qhw`Vglrj-H!
Dqmv{c
diff --git a/testFiles/Microsoft/Chimera_10bit_cropped_to_1920x1008_with_HDR_metadata.avif b/testFiles/Microsoft/Chimera_10bit_cropped_to_1920x1008_with_HDR_metadata.avif
index 442e2bb5a8982b9f6e9f813122ce48ae3503fa6e..c611f3a4c603b6b947ca320bbc17914aa6a52139 100644
GIT binary patch
delta 137
zcmeBq$NK**>jY)Ss);Hc@{br8OY|9-7#J8B85qk1f%H2dKA2fhQ~;#sPdu$R*^1G|
zn{>jY)S_K7MT^6wcKOY|9-7#J8B85qmtfb=^cK9^ZgQ~;#cOgybO*^yB~
zjS1pwto9tr>e
diff --git a/testFiles/Microsoft/Chimera_8bit_cropped_480x256.avif b/testFiles/Microsoft/Chimera_8bit_cropped_480x256.avif
index fc9cc29af8b73212808750dca33440506bb8414e..1f32640f8ec70a0b22713eb540c4290eb045d77a 100644
GIT binary patch
delta 143
zcmbQdmZ@zm(*$KkpNT3R@>>`fCO=_dVqjokWMG&&14zFE;>no>MFl{*c;acjNP&XP
zicBDfftiDY14!{CmKi!XGVp+eG?H@?feINP0NFqTfCx$eX^^2H0HP%_3vv^|Jdivi
PD^044oSpco?|2fif)abyENT98dr<1qw1NGJ!M$GY1C;
wkdnwO$V~+Cfq;>Lk(H6DxrG(TmdY$jO#_QEFz_X(6ek0XWn|c#%_uz;01Yi5l>h($
From a0c026c24beb33940d59003ed33f5e74f996a18d Mon Sep 17 00:00:00 2001
From: Leo Barnes
Date: Mon, 14 Nov 2022 11:01:59 +0100
Subject: [PATCH 12/65] Update Summer_in_Tomsk_720p_5x4_grid.avif and
Chimera-AV1-10bit-480x270.avif to fix issue 151
Summer_in_Tomsk_720p_5x4_grid.avif:
- Added NCLX 1,13,6,0 for all items
- Added pixi for grid item
- Strip optional config OBUs from av1C
Chimera-AV1-10bit-480x270.avif:
- Added NCLX 1,13,6,0
- Added pixi
- Strip optional config OBUs from av1C
- Set track_in_movie to true for track
---
.../Summer_in_Tomsk_720p_5x4_grid.avif | Bin 1964776 -> 1964802 bytes
.../avis/Chimera-AV1-10bit-480x270.avif | Bin 164509 -> 164533 bytes
2 files changed, 0 insertions(+), 0 deletions(-)
diff --git a/testFiles/Microsoft/Summer_in_Tomsk_720p_5x4_grid.avif b/testFiles/Microsoft/Summer_in_Tomsk_720p_5x4_grid.avif
index 64255bd7315139803584c562b2f18a9e68c3fb77..1db64d83bf91ba5ef7efcd1b82f22f7a85e21b23 100644
GIT binary patch
delta 715
zcmXYuKWNlY9LK-!CAquYC6`?O+%?rgwN6C}hlAjvP*5CPR73(M-ZK&XN>e1Tb
zAc`Q|=AeUC3n6^)Buy;{0UFmk&A5b-2yYLtK$8)}M
z{3tZCCs233!!_*<)|a4e-$dO^_}|{M|Da(yIP(fBeF4vOc=-}k`y_nRt%V$_GeXmJ
z)Sre*b`hA4AANzkwU5wr^6Mj1HjS3)L3;EP%6*NFjhJ
zsyUC;^yIlKT)&65>8Zna99`sL-Mm;UI9|w$-YT8s_ll)*Re62-GsoexJ!@v*E#B|W
zZ#v}}+TGsrI&aIDdwrP~D~qy`pH;Tf+x%mewWDF#n_CQ99rFm!xglv`N#Xx!hUsA2`Sf$4!cZa3F|+AP%Ca9O}?P4Bl~dE7wCD
zyg_hraZm>rhf0Uy=A?s*!^ye1i8`o@H@MVaKHm?X=gsr+B_SE@4Zi&uJUS#huMZzH
z!ye4|J`4n~aG(aK9A$eaVS*jF+9r-*!i(^<-2*q-6I8S-OBwqus@kdV
zH1c)GwO#ny!SLQ$$kj`z>qhg_3-)(3w8Q0XNcs$cc64SD(mjZ#cKiByNH#@FJ04UZ
z$poQx=iwX3<)4VOldmr!`F^yuhw1D+#D9fYH!^<>623!6doDi?iKj@k^P|5Ztreu&
z^Cy;h{s+3+y}!?Sb(;L@7k3NJEB)fe9nPe`R@~y`Du18(NG)Wm8%ryjUcmR)%Wqyh
zH=BH!J#im@aE=VO`^D{5Zk8*BI5Kiz#D(K*j<(=hd)5`}s&&oUx2{_^tOM(&b;~-m
zj;!0(v318f`G0d-#@5(dHUpE$3!l_4Ag
From e624c3715d4fce97ecc6d9a80da919def38d5302 Mon Sep 17 00:00:00 2001
From: Leo Barnes
Date: Tue, 10 Sep 2024 10:33:31 +0200
Subject: [PATCH 13/65] Add primary item to Chimera-AV1-10bit-480x270.avif
---
.../avis/Chimera-AV1-10bit-480x270.avif | Bin 164533 -> 164547 bytes
1 file changed, 0 insertions(+), 0 deletions(-)
diff --git a/testFiles/Netflix/avis/Chimera-AV1-10bit-480x270.avif b/testFiles/Netflix/avis/Chimera-AV1-10bit-480x270.avif
index c4dfcfa3ccb6e4950fb007d145978e6d21819a3e..56288b363d3fc06a170d67d09a6a6c5482f0d792 100644
GIT binary patch
delta 84
zcmdnm%5}JvYl0FJBkx3&K*pAdWvh7@_zE&hav4B?akD(59*g2)28Q=;42*`c42iy%qqdq7~Qx
delta 71
zcmV-N0J#6dg$lKW3XmcK0RNFBQ2}<5cB`{50W1U|l>h+mH~;}LPXGaTTL1x$Gynn6
dLjVF4umA!uxBvof;e&hyhkOMAw|oTxM|}_36rcbA
From 30a2f4c4175feb7ee8feefe349cbf1d7621e952b Mon Sep 17 00:00:00 2001
From: Leo Barnes
Date: Thu, 10 Nov 2022 12:19:31 +0100
Subject: [PATCH 14/65] Update testFiles/Link-U/kimono*.avif files to make them
spec compliant
Changes done:
1. Change order of item property associations to place ispe first
2. Add colr-nclx box with values 1,13,9,0 since this is what Sequence Header says
3. Strip out optional config OBUs from av1C
---
testFiles/Link-U/kimono.avif | Bin 85445 -> 85453 bytes
.../Link-U/kimono.mirror-horizontal.avif | Bin 84996 -> 85004 bytes
testFiles/Link-U/kimono.mirror-vertical.avif | Bin 84632 -> 84640 bytes
.../kimono.mirror-vertical.rotate270.avif | Bin 85529 -> 85537 bytes
testFiles/Link-U/kimono.rotate270.avif | Bin 84886 -> 84894 bytes
testFiles/Link-U/kimono.rotate90.avif | Bin 84837 -> 84845 bytes
6 files changed, 0 insertions(+), 0 deletions(-)
diff --git a/testFiles/Link-U/kimono.avif b/testFiles/Link-U/kimono.avif
index e91fe56e724b4b7e2fbfab4412bcf3c7bbcfc972..7fa0d691cc50f8f2e032afa57aaff18101fedd90 100644
GIT binary patch
delta 93
zcmX>)oAvB$)(OgtsuNYx8GR@AIC55J78DgQFfc?2}lUQcx+{nrUZWME`vWNL0{ZMJ3HZp+Bn;R67%y%szG
delta 85
zcmX>*oAu~y)(OgtvJ+L(8C@s#IC2(e78DgQFffEnyk@N-
r$vG7aj10UCoFE~|%!1rR5CaGp85r4`8Jk*K+nU`Ox4Sbk?)3ryuwoZ9
delta 86
zcmeB~!P+u|b%HXZ`b3ps8N(;`IC8dT78DgQFfgP{yyjxclUQcx+{nrUZWME`#W^8I{ZEJRC-0sfE80ZNAyVw@#
delta 86
zcmZ25m378c)(Ogt>JwGc8T}{rIC9oz78DgQFfhbUyyl`SkyvKv+{ntqz{Mq*mMj0i
liAhR`11KqxS&*9uq(Oj@fsvK5iMge<*`IN{KOZWME`(VQgw{ZEJ51WZWLe$aumB0PB7jK>z>%
delta 87
zcmZ2Dhjr#0)(Ogth7(oN86zk5IC8dU78DgQFfgP|yymMXkyvKv+{ntqz{Mq*R{z_*
miAhR`11Kq(S&*9uq(Oj@fsu`|shOpops)H)(Ogt`V&>s8N(;`IC8dT78DgQFfgP{yyjxclUQcx+{nrUZWME`#W^8I{ZEJRC-0sfE=JwGc8T}{rIC9oz78DgQFfhbUyyl`SkyvKv+{ntqz{Mq*R{z_*
liAhR`11KqxS&*9uq(Oj@fsvK5iMge<*`IN{KO>{R7XTQ26;c2I
diff --git a/testFiles/Link-U/kimono.rotate90.avif b/testFiles/Link-U/kimono.rotate90.avif
index ee7c5246e13054a81f70f4affea1571381a88474..76b479d5e9293770c6aeade6fb1181daf482401d 100644
GIT binary patch
delta 94
zcmaDljrHv`)(Ogt`V&>s8N(;`IC8dT78DgQFfgP{yyjxclUQcx+{nrUZWME`#W^8I{ZEJRC-0sfEDCY$L^UoJk
delta 86
zcmaDmjrHj?)(Ogt>JwGc8T}{rIC9oz78DgQFfhbUyyl`SkyvKv+{ntqz{Mq*R{z_*
liAhR`11KqxS&*9uq(Oj@fsvK5iMge<*`IN{KO>`@7XV9}6}
Date: Tue, 6 Dec 2022 14:45:21 +0100
Subject: [PATCH 15/65] Added sanitizer tool that can fix some commonly
identified issues in AVIF files
---
Tools/sanitize_avif.py | 2818 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 2818 insertions(+)
create mode 100644 Tools/sanitize_avif.py
diff --git a/Tools/sanitize_avif.py b/Tools/sanitize_avif.py
new file mode 100644
index 0000000..c7eaff9
--- /dev/null
+++ b/Tools/sanitize_avif.py
@@ -0,0 +1,2818 @@
+#!/usr/bin/env python3
+"""
+Tool to fix commonly identified container level issues in AVIF files.
+
+----------------------
+https://aomedia.org/license/software-license/bsd-3-c-c/
+
+The Clear BSD License
+
+Copyright (c) 2022, Alliance for Open Media
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted (subject to the limitations in the disclaimer below) provided that
+the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+Neither the name of the Alliance for Open Media nor the names of its contributors
+may be used to endorse or promote products derived from this software without
+specific prior written permission.
+
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS
+LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+----------------------
+
+Kept "nice" by running:
+isort sanitize_avif.py --interactive
+black -l 100 sanitize_avif.py
+pylint sanitize_avif.py
+mypy --strict sanitize_avif.py
+"""
+
+# pylint: disable=too-many-lines, too-many-lines, too-many-arguments
+# pylint: disable=too-many-locals, too-many-branches, too-many-statements
+
+import argparse
+import os
+import struct
+import sys
+import typing
+from functools import reduce
+from itertools import accumulate
+from typing import Any, BinaryIO, Callable, NewType, NoReturn, Optional, Union
+
+# ===========================================
+# Types
+# ===========================================
+
+BoxType = NewType("BoxType", str)
+BoxHeader = dict[str, int]
+BoxBody = dict[str, Any]
+BoxSequenceMap = dict[str, "BoxRecipe"]
+BoxBodyParser = Callable[["FileReader", "Box", int], BoxBody]
+OBUParser = Callable[..., dict[str, Any]]
+
+NCLXBodyType = dict[str, Union[str, int]]
+
+BoxWriterReturn = tuple[bytes, list["PlaceholderFileOffset"]]
+BoxWriter = Callable[["Box", int], BoxWriterReturn]
+
+IssueFixer = Callable[[], None]
+
+
+# ===========================================
+# Printing utilities
+# ===========================================
+NONVERBOSE_PRINT_LEVEL = -1000000
+
+
+def print_indent(lvl: int, string: str) -> None:
+ """Print a message with the specified indentation level if lvl is positive."""
+ if lvl >= 0:
+ print(" " * lvl + string)
+
+
+def decode_data_to_string(data: bytes) -> str:
+ """Handles potential unicode decoding errors (typically happens for corrupt files)."""
+ try:
+ string = data.decode()
+ except UnicodeDecodeError:
+ string = "CORRUPT"
+ # Strip out NULL terminated strings (typically only for corrupt files)
+ return string.rstrip("\x00")
+
+
+def bold(string: str) -> str:
+ """Returns the string with bold terminal color escape symbols"""
+ return f"\033[1m{string}\033[0m"
+
+
+def red(string: str) -> str:
+ """Returns the string with red terminal color escape symbols"""
+ return f"\033[1;31m{string}\033[0m"
+
+
+def float_from_rational(arr: list[int]) -> float:
+ """Returns a float value given a rational."""
+ assert len(arr) == 2
+ if arr[1] == 0:
+ return float("inf")
+ return arr[0] / arr[1]
+
+
+# ===========================================
+# Reading utilities
+# ===========================================
+def get_struct_type(nbytes: int, unsigned: bool = True) -> str:
+ """Returns the appropriate struct type string for an element size."""
+ if unsigned:
+ nbytes_to_format_map = {1: "B", 2: "H", 4: "I", 8: "Q"}
+ else:
+ nbytes_to_format_map = {1: "b", 2: "h", 4: "i", 8: "q"}
+ assert nbytes in nbytes_to_format_map
+ return ">" + nbytes_to_format_map[nbytes]
+
+
+def write_integer_of_size(value: int, nbytes: int, unsigned: bool = True) -> bytes:
+ """Writes a value as an integer of nbytes size."""
+ return struct.pack(get_struct_type(nbytes, unsigned=unsigned), value)
+
+
+def write_integer_array_of_size(values: list[int], nbytes: int, unsigned: bool = True) -> bytes:
+ """Writes values as integers each of nbytes size."""
+ return struct.pack(">" + get_struct_type(nbytes, unsigned=unsigned)[1] * len(values), *values)
+
+
+class FileReader:
+ """Utility class for handling file reading operations."""
+
+ def __init__(self, input_file: BinaryIO) -> None:
+ self.file = input_file
+ self.file.seek(0, os.SEEK_END)
+ self.size = self.file.tell()
+ self.file.seek(0, os.SEEK_SET)
+
+ class BitReader:
+ """Utility class for handling bit reading operations."""
+
+ def __init__(self, data: bytes) -> None:
+ self.data = data
+ self.pos = 0
+ self.bit_pos = 0
+
+ def get_next_bit(self) -> int:
+ """Returns the next bit from the stream."""
+ byte = self.data[self.pos]
+ bit = (byte >> (7 - self.bit_pos)) & 1
+ self.bit_pos += 1
+ if self.bit_pos >= 8:
+ self.bit_pos -= 8
+ self.pos += 1
+ return bit
+
+ # pylint: disable=invalid-name
+ def f(self, num_bits: int) -> int:
+ """Returns the next 'num_bits' bits from the stream."""
+ value = 0
+ for _ in range(num_bits):
+ value <<= 1
+ value |= self.get_next_bit()
+ return value
+
+ # pylint: enable=invalid-name
+
+ def get_byte(self) -> int:
+ """Returns the next byte from the stream."""
+ assert self.bit_pos == 0
+ byte = self.data[self.pos]
+ self.pos += 1
+ return byte
+
+ def skip_bytes(self, num: int) -> None:
+ """Skips forward 'num' bytes in the stream."""
+ assert self.bit_pos == 0
+ self.pos += num
+
+ def eof(self) -> bool:
+ """Returns true when the end of the stream has been reached."""
+ return len(self.data) == self.pos
+
+ def get_bytes(self, num_bytes: int = 0) -> bytes:
+ """Returns the next num_bytes bytes, with 'num_bytes == 0' meaning until end."""
+ assert self.bit_pos == 0
+ pos = self.pos
+ if num_bytes == 0:
+ num_bytes = len(self.data) - pos
+ else:
+ assert self.pos + num_bytes <= len(self.data)
+ self.pos += num_bytes
+ return self.data[pos : pos + num_bytes]
+
+ def bit_reader_for_bytes(self, num_bytes: int) -> "FileReader.BitReader":
+ """Returns a new BitReader for the next 'num_bytes'."""
+ return FileReader.BitReader(self.get_bytes(num_bytes))
+
+ def read_leb128_value(self) -> int:
+ """Returns a leb128 value from the stream."""
+ value = 0
+ for i in range(8):
+ byte = self.get_byte()
+ value |= (byte & 0x7F) << (i * 7)
+ if (byte & 0x80) == 0:
+ break
+ return value
+
+ def position(self) -> int:
+ """Returns the current position in the file."""
+ return self.file.tell()
+
+ # -----------------------------------
+ # Methods that move the file position
+ # -----------------------------------
+
+ def rewind(self) -> None:
+ """Rewinds the position to the start of the file."""
+ self.file.seek(0, os.SEEK_SET)
+
+ def read_data(self, nbytes: int, end: Optional[int] = None) -> bytes:
+ """Reads nbytes of data from the file."""
+ if end is None:
+ assert self.position() + nbytes <= self.size, "File ended prematurely"
+ else:
+ assert self.position() + nbytes <= end, "Box/data ended prematurely"
+ return self.file.read(nbytes)
+
+ def bit_reader_for_bytes(
+ self, nbytes: int, end: Optional[int] = None
+ ) -> "FileReader.BitReader":
+ """Returns a BitReader for the next nbytes of data."""
+ data = self.read_data(nbytes, end)
+ return FileReader.BitReader(data)
+
+ def skip_to(self, position: int) -> None:
+ """Moves the position to the indicated position."""
+ self.file.seek(position)
+
+ def read_integer_of_size(self, end: int, nbytes: int, unsigned: bool = True) -> int:
+ """Reads a big-endian integer of size nbytes from file."""
+ data = self.read_data(nbytes, end)
+ unpacked = struct.unpack(get_struct_type(nbytes, unsigned=unsigned), data)
+ return typing.cast(int, unpacked[0])
+
+ def read_integer_array_of_size(
+ self, end: int, nbytes: int, count: int, unsigned: bool = True
+ ) -> list[int]:
+ """Reads an array of size count of integers of size nbytes from file."""
+ return [self.read_integer_of_size(end, nbytes, unsigned) for _ in range(count)]
+
+ def read_string(self, end: int, size: int = 0) -> Optional[str]:
+ """Reads a NULL-terminated or fixed-length string from file."""
+ if size == 0:
+ max_length = end - self.file.tell()
+ buf = bytearray()
+ read = 0
+ while read < max_length:
+ byte = self.file.read(1)
+ read += 1
+ if byte is None or int(byte[0]) == 0:
+ return decode_data_to_string(buf) if len(buf) > 0 else None
+ buf.append(byte[0])
+ return decode_data_to_string(buf) if len(buf) > 0 else None
+ return decode_data_to_string(self.read_data(size, end))
+
+ # ---------------------------------------
+ # Methods that maintain the file position
+ # ---------------------------------------
+
+ def read_data_from_offset(self, offset: int, nbytes: int) -> bytes:
+ """Read nbytes bytes from offset in file without moving position."""
+ pos = self.file.tell()
+ self.file.seek(offset, os.SEEK_SET)
+ data = self.file.read(nbytes)
+ assert len(data) == nbytes
+ self.file.seek(pos, os.SEEK_SET)
+ return data
+
+ def copy_data_to_destination(self, output_file: BinaryIO, offset: int, count: int) -> None:
+ """Copy data from source file to destination file without holding all in memory."""
+ pos = self.file.tell()
+ self.file.seek(offset, os.SEEK_SET)
+ while count > 0:
+ data = self.file.read(min(32768, count))
+ output_file.write(data)
+ count -= len(data)
+ self.file.seek(pos, os.SEEK_SET)
+
+
+# ===========================================
+# Utility classes
+# ===========================================
+class Box:
+ """Class representing a parsed ISOBMFF box."""
+
+ def __init__(self, box_type: BoxType, parent: Optional["Box"], size: int, start: int):
+ self.type = box_type
+ self.size = size
+ self.start = start
+ self.end = start + size
+ self.sub_boxes: Optional[list[Box]] = None
+ self.header: BoxHeader = {}
+ self.body: BoxBody = {}
+ self.needs_rewrite = False
+ self.parent = parent
+
+ @classmethod
+ def from_reader(cls, reader: FileReader, end: int, parent: Optional["Box"] = None) -> "Box":
+ """Read a box header from file and return as a Box."""
+ start = reader.position()
+ size = reader.read_integer_of_size(end, 4)
+ box_type = reader.read_string(end, 4)
+ assert box_type is not None, "Could not get box type"
+ if size == 1:
+ size = reader.read_integer_of_size(end, 8)
+ elif size == 0:
+ size = end - size
+ assert (
+ size >= 8
+ ), f"Encountered box of type {box_type} with invalid size {size}. Cannot continue."
+ return cls(BoxType(box_type), parent, size, start)
+
+ def print_start(self, lvl: int, name: Optional[str] = None) -> None:
+ """For verbose output, prints start of box."""
+ string = f"('{red(self.type)}'"
+ if name:
+ string += f' "{name}",'
+ string += f" size = {self.size}, offset = {self.start}) {{"
+ print_indent(lvl, string)
+
+ def print_end(self, lvl: int) -> None:
+ """For verbose output, prints end of box."""
+ print_indent(lvl, "}")
+
+ def __repr__(self) -> str:
+ sub_boxes = [] if self.sub_boxes is None else self.sub_boxes
+ types_string = ",".join([box.type for box in sub_boxes])
+ sub_box_str = f"[{types_string}]"
+ return (
+ f"Box(type={self.type}, start={self.start}, size={self.size}, "
+ + f"header={self.header}, sub_boxes={sub_box_str}, clean={not self.needs_rewrite})"
+ )
+
+ def mark_for_rewrite(self) -> None:
+ """Marks box and all parent boxes as needing rewriting."""
+ box: Optional[Box] = self
+ while box is not None:
+ box.needs_rewrite = True
+ box = box.parent
+
+ def write_box_header(self, body_size: int) -> bytes:
+ """Writes the Box/Full-Box header."""
+ data = bytes()
+ box_type_data = self.type.encode()
+ assert len(box_type_data) == 4
+ total_size = 4 # size bytes
+ total_size += len(box_type_data)
+ total_size += 0 if len(self.header) == 0 else 4
+ total_size += body_size
+ assert total_size <= 0xFFFFFFFF, "8-byte box size not implemented"
+ data += struct.pack(">I", total_size)
+ data += box_type_data
+ if len(self.header) > 0:
+ version = self.header["version"]
+ data += struct.pack(">B", version)
+ flags = self.header["flags"]
+ data += struct.pack(">I", flags)[1:]
+ return data
+
+
+class BoxRecipe:
+ """Class representing how to parse a specific box."""
+
+ def __init__(
+ self,
+ name: str,
+ full_box: bool = False,
+ sequence_map: Optional[BoxSequenceMap] = None,
+ body_parser: Optional[BoxBodyParser] = None,
+ ) -> None:
+ assert sequence_map is None or body_parser is None
+ self.name = name
+ self.full_box = full_box
+ self.sequence_map = sequence_map
+ self.body_parser = body_parser
+
+ def parse(self, reader: FileReader, dst_box: Box, lvl: int) -> None:
+ """Parses box."""
+
+ # Header
+ if self.full_box:
+ (version, flags1, flags2, flags3) = reader.read_integer_array_of_size(dst_box.end, 1, 4)
+ flags = (flags1 << 16) | (flags2 << 8) | flags3
+ print_indent(lvl, f"Version: {version}, Flags: 0x{flags:06X}")
+ dst_box.header = {"version": version, "flags": flags}
+
+ # Body
+ if self.sequence_map is not None:
+ dst_box.sub_boxes = parse_box_sequence(
+ reader, dst_box.end, lvl, parent=dst_box, box_map=self.sequence_map
+ )
+ elif self.body_parser:
+ dst_box.body = self.body_parser(reader, dst_box, lvl)
+ else:
+ reader.skip_to(dst_box.end)
+
+ def __repr__(self) -> str:
+ return f"BoxRecipe(name: {self.name}, full: {self.full_box}, map: {self.sequence_map})"
+
+
+class BoxIssue:
+ """Class representing found issues for a specific box."""
+
+ def __init__(self, box_id: int, box_type: str, is_track: bool = False) -> None:
+ self.box_id = box_id
+ self.box_type = box_type
+ self.issues: dict[str, list[str]] = {}
+ self.fix: Optional[IssueFixer] = None
+ self.fix_description: Optional[str] = None
+ self.info_url: Optional[str] = None
+ self.is_track = is_track
+ self.base_url = (
+ "https://github.com/AOMediaCodec/av1-avif/wiki/Identified-issues-in-existing-AVIF-files"
+ )
+
+ def add_issue(self, severity: str, description: str) -> None:
+ """Adds an issue for the box."""
+ if severity not in self.issues:
+ self.issues[severity] = []
+ self.issues[severity].append(description)
+
+ def add_info_url(self, url_section: str) -> None:
+ """Adds an info url section in the AVIF Wiki that gives more information."""
+ self.info_url = url_section
+
+ def add_fix(self, fix: IssueFixer, fix_description: str) -> None:
+ """Adds a fix for the identified issues."""
+ self.fix = fix
+ self.fix_description = fix_description
+
+ def apply_fix(self) -> None:
+ """Applies the fix for the identified issues."""
+ assert self.fix, f"No possible fix for issue:\n{self.issues}"
+ self.fix()
+
+ def print(self, lvl: int, others: Optional[list["BoxIssue"]] = None) -> None:
+ """Prints the identified issues."""
+ type_str = "Track " if self.is_track else "Item "
+ if others is None or len(others) == 0:
+ print_indent(lvl, f"{type_str} {self.box_id}")
+ else:
+ other_ids_int = sorted([issue.box_id for issue in others])
+ other_ids: list[str] = list(map(str, other_ids_int))
+ print_indent(lvl, f'{type_str} {self.box_id} (also applies to [{",".join(other_ids)}])')
+ print_indent(lvl + 1, f"Box {self.box_type}")
+ for severity, values in self.issues.items():
+ print_indent(lvl + 2, f"{severity}")
+ for description in values:
+ print_indent(lvl + 3, f"{description}")
+ if self.info_url:
+ print_indent(lvl + 1, f"See {self.base_url}#{self.info_url}")
+ if self.fix_description:
+ print_indent(lvl + 1, f"FIX: {self.fix_description}")
+
+ def issue_hash(self) -> int:
+ """Creates a hash of the issues in this object for aggregating items with the same issue."""
+
+ def _freeze(val: Any) -> Any:
+ if isinstance(val, dict):
+ return frozenset((key, _freeze(value)) for key, value in val.items())
+ if isinstance(val, list):
+ return tuple(_freeze(value) for value in val)
+ return val
+
+ return hash((self.is_track, self.fix_description, _freeze(self.issues)))
+
+
+class PlaceholderFileOffset:
+ """Class representing a placeholder file offset."""
+
+ def __init__(
+ self,
+ box: Box,
+ file_pos: int,
+ size: int,
+ value: int,
+ base: Optional["PlaceholderFileOffset"] = None,
+ ) -> None:
+ self.box = box
+ self.file_pos = file_pos
+ self.size = size
+ self.value = value
+ self.base = base
+ self.dependents: list["PlaceholderFileOffset"] = []
+ if base is not None:
+ base.add_dependent(self)
+
+ def add_dependent(self, dependent: "PlaceholderFileOffset") -> None:
+ """Adds a new file sub-offset that depends on this file offset."""
+ self.dependents.append(dependent)
+
+ def get_offset_list(self) -> list[int]:
+ """Returns this offset and dependents as a list of values."""
+ if len(self.dependents) > 0:
+ return [self.value + dep.value for dep in self.dependents]
+ return [self.value]
+
+ def write_delta(self, file: BinaryIO, delta: int) -> None:
+ """Applies a delta to this placeholder and writes to file."""
+ new_value = self.value + delta
+ assert new_value >= 0, "Base offset too small, can't apply delta"
+ max_val = (1 << self.size * 8) - 1
+ assert new_value <= max_val, "Offset size is too small to contain moved offset"
+ data = write_integer_of_size(new_value, self.size)
+ current_pos = file.tell()
+ file.seek(self.file_pos, os.SEEK_SET)
+ file.write(data)
+ file.seek(current_pos, os.SEEK_SET)
+
+
+# ===========================================
+# Box parsing
+# ===========================================
+def parse_unsupported_box(_reader: FileReader, box: Box, _lvl: int) -> NoReturn:
+ """Function that generates an assertion error when a critical unsupported box is encountered"""
+ assert False, f"'{box.type}' box is currently unsupported"
+
+
+def parse_ftyp_box(reader: FileReader, box: Box, lvl: int) -> BoxBody:
+ """Parse File Type Box."""
+ body: dict[str, Any] = {}
+ body["major"] = reader.read_string(box.end, size=4)
+ body["version"] = reader.read_integer_of_size(box.end, 4)
+ num_brands = int((box.end - reader.position()) / 4)
+ body["compatible"] = []
+ for _ in range(num_brands):
+ body["compatible"].append(reader.read_string(box.end, size=4))
+ print_indent(lvl, f"Major brand: {body['major']}")
+ print_indent(lvl, f"Version: {body['version']}")
+ print_indent(lvl, f"Compatible brands: [{','.join(body['compatible'])}]")
+ return body
+
+
+def parse_tkhd_box(reader: FileReader, box: Box, lvl: int) -> BoxBody:
+ """Parse Track Header Box."""
+ time_size = 8 if box.header["version"] == 1 else 4
+ body: dict[str, Any] = {}
+ body["creation_time"] = reader.read_integer_of_size(box.end, time_size)
+ body["modification_time"] = reader.read_integer_of_size(box.end, time_size)
+ body["track_id"] = reader.read_integer_of_size(box.end, 4)
+ reader.read_data(4, box.end) # Reserved
+ body["duration"] = reader.read_integer_of_size(box.end, time_size)
+
+ print_indent(lvl, f"Creation time: {body['creation_time']}")
+ print_indent(lvl, f"Modification time: {body['modification_time']}")
+ print_indent(lvl, f"Track ID: {body['track_id']}")
+ print_indent(lvl, f"Duration: {body['duration']}")
+
+ reader.read_data(8, box.end) # Reserved
+ body["layer"] = reader.read_integer_of_size(box.end, 2)
+ body["alternate_group"] = reader.read_integer_of_size(box.end, 2)
+ body["volume"] = reader.read_integer_of_size(box.end, 2)
+ reader.read_data(2, box.end) # Reserved
+ print_indent(lvl, f"Layer: {body['layer']}")
+ print_indent(lvl, f"Alternate Group: {body['alternate_group']}")
+ print_indent(lvl, f"Volume: {body['volume']}")
+
+ body["matrix"] = reader.read_integer_array_of_size(box.end, 4, 9)
+ print_indent(lvl, "Matrix: {")
+ for index in range(3):
+ vals = [f"{val:7.1f}" for val in body["matrix"][index : index + 3]]
+ print_indent(lvl + 1, ",".join(vals))
+ print_indent(lvl, "}")
+ body["width"] = reader.read_integer_of_size(box.end, 4)
+ body["height"] = reader.read_integer_of_size(box.end, 4)
+ print_indent(lvl, f"Width: {body['width'] / (1 << 16)}")
+ print_indent(lvl, f"Height: {body['height'] / (1 << 16)}")
+ return body
+
+
+def parse_stsd_box(reader: FileReader, box: Box, lvl: int) -> BoxBody:
+ """Parse Sample Description Box."""
+ entry_count = reader.read_integer_of_size(box.end, 4)
+
+ def _parse_av01_box(sub_reader: FileReader, sub_box: Box, sub_lvl: int) -> BoxBody:
+ body = {}
+ body["sampleentry"] = sub_reader.read_data(8, sub_box.end)
+ body["visualsampleentry"] = sub_reader.read_data(70, sub_box.end)
+ sub_box.sub_boxes = parse_box_sequence(
+ sub_reader, sub_box.end, sub_lvl + 1, parent=sub_box, box_map={}
+ )
+ return body
+
+ box_map = {
+ "av01": BoxRecipe("AV1 Sample Entry", body_parser=_parse_av01_box),
+ }
+ box.sub_boxes = parse_box_sequence(
+ reader, box.end, lvl + 1, parent=box, box_map=box_map, expected_box_count=entry_count
+ )
+ return {}
+
+
+def parse_dref_box(reader: FileReader, box: Box, lvl: int) -> BoxBody:
+ """Parse Data Reference Box."""
+ entry_count = reader.read_integer_of_size(box.end, 4)
+
+ def _parse_dref_url(sub_reader: FileReader, sub_box: Box, sub_lvl: int) -> BoxBody:
+ url = sub_reader.read_string(sub_box.end)
+ print_indent(sub_lvl, f"URL: {url}")
+ assert (
+ sub_box.header["flags"] == 1 and url is None
+ ), "Non-local data references not supported"
+ return {"url": url}
+
+ box_map = {
+ "url ": BoxRecipe("Data Entry URL", full_box=True, body_parser=_parse_dref_url),
+ "default": BoxRecipe("Data Entry", full_box=True, body_parser=parse_unsupported_box),
+ }
+ box.sub_boxes = parse_box_sequence(
+ reader, box.end, lvl + 1, parent=box, box_map=box_map, expected_box_count=entry_count
+ )
+ return {}
+
+
+def parse_stco_box(reader: FileReader, box: Box, lvl: int) -> BoxBody:
+ """Parse Sample Chunk Offset Box."""
+ entry_count = reader.read_integer_of_size(box.end, 4)
+ print_indent(lvl, f"Entry count: {entry_count}")
+ entries = []
+ for chunk in range(entry_count):
+ offset = reader.read_integer_of_size(box.end, 4)
+ print_indent(lvl + 1, f"Chunk #{chunk}: {offset}")
+ entries.append(offset)
+ return {"entries": entries}
+
+
+def parse_hdlr_box(reader: FileReader, box: Box, lvl: int) -> BoxBody:
+ """Parse Handler Reference Box."""
+ predef = reader.read_integer_of_size(box.end, 4)
+ hdlr_type = reader.read_string(box.end, size=4)
+ reader.read_integer_array_of_size(box.end, 4, 3) # Reserved
+
+ print_indent(lvl, f"Pre defined: {predef}")
+ print_indent(lvl, f"Handler type: {hdlr_type}")
+ name = reader.read_string(box.end)
+ print_indent(lvl, f"Name: {name}")
+ return {
+ "pre_defined": predef,
+ "hdlr_type": hdlr_type,
+ "name": name,
+ }
+
+
+def parse_pitm_box(reader: FileReader, box: Box, lvl: int) -> BoxBody:
+ """Parse Primary Item Box."""
+ body: dict[str, Any] = {}
+ id_size = 2 if box.header["version"] == 0 else 4
+ body["item_id"] = reader.read_integer_of_size(box.end, id_size)
+ print_indent(lvl, f"Primary item id: {body['item_id']}")
+ return body
+
+
+def parse_av1c_box(reader: FileReader, box: Box, lvl: int) -> BoxBody:
+ """Parse AV1 Codec Configuration Box."""
+
+ # https://aomediacodec.github.io/av1-isobmff/ section 2.3.3
+ bit_reader = reader.bit_reader_for_bytes(4, box.end)
+ body: dict[str, Any] = {}
+ body["marker"] = bit_reader.f(1)
+ body["version"] = bit_reader.f(7)
+ body["seq_profile"] = bit_reader.f(3)
+ body["seq_level_idx_0"] = bit_reader.f(5)
+ body["seq_tier_0"] = bit_reader.f(1)
+ body["high_bitdepth"] = bit_reader.f(1)
+ body["twelve_bit"] = bit_reader.f(1)
+ body["monochrome"] = bit_reader.f(1)
+ body["chroma_subsampling_x"] = bit_reader.f(1)
+ body["chroma_subsampling_y"] = bit_reader.f(1)
+ body["chroma_sample_position"] = bit_reader.f(2)
+ bit_reader.f(3) # Reserved
+ body["initial_presentation_delay_present"] = bit_reader.f(1)
+ if body["initial_presentation_delay_present"] == 1:
+ body["initial_presentation_delay_minus_one"] = bit_reader.f(4)
+ else:
+ bit_reader.f(4) # Reserved
+
+ if reader.position() < box.end:
+ body["configOBUs"] = reader.read_data(box.end - reader.position())
+
+ print_indent(lvl, f"marker: {body['marker']}")
+ print_indent(lvl, f"version: {body['version']}")
+ print_indent(lvl, f"seq_profile: {body['seq_profile']}")
+ print_indent(lvl, f"seq_level_idx_0: {body['seq_level_idx_0']}")
+ print_indent(lvl, f"seq_tier_0: {body['seq_tier_0']}")
+ print_indent(lvl, f"high_bitdepth: {body['high_bitdepth']}")
+ print_indent(lvl, f"twelve_bit: {body['twelve_bit']}")
+ print_indent(lvl, f"monochrome: {body['monochrome']}")
+ print_indent(lvl, f"chroma_subsampling_x: {body['chroma_subsampling_x']}")
+ print_indent(lvl, f"chroma_subsampling_y: {body['chroma_subsampling_y']}")
+ print_indent(lvl, f"chroma_sample_position: {body['chroma_sample_position']}")
+ print_indent(
+ lvl,
+ f"initial_presentation_delay_present: {body['initial_presentation_delay_present']}",
+ )
+ if body["initial_presentation_delay_present"] == 1:
+ print_indent(
+ lvl,
+ "initial_presentation_delay_minus_one: "
+ + f"{body['initial_presentation_delay_minus_one']}",
+ )
+ if "configOBUs" in body:
+ print_indent(lvl, f"configOBUs: {len(body['configOBUs'])} bytes")
+ return body
+
+
+def parse_iref_box(reader: FileReader, box: Box, lvl: int) -> BoxBody:
+ """Parse Item Reference Box."""
+ id_size = 2 if box.header["version"] == 0 else 4
+
+ def _parse_sitref(sub_reader: FileReader, sub_box: Box, sub_lvl: int) -> BoxBody:
+ body: BoxBody = {}
+ body["from_item_ID"] = sub_reader.read_integer_of_size(sub_box.end, id_size)
+ reference_count = sub_reader.read_integer_of_size(sub_box.end, 2)
+ print_indent(sub_lvl, f"Reference count: {reference_count}")
+ references = []
+ print_indent(sub_lvl, f"From item {body['from_item_ID']}; To items: {{")
+ for _ in range(reference_count):
+ reference = sub_reader.read_integer_of_size(sub_box.end, id_size)
+ print_indent(sub_lvl + 1, f"{reference}")
+ references.append(reference)
+ print_indent(sub_lvl, "}")
+ body["to_item_ID"] = references
+ return body
+
+ box_map = {"default": BoxRecipe("Single Item Reference Box", body_parser=_parse_sitref)}
+ box.sub_boxes = parse_box_sequence(reader, box.end, lvl + 1, parent=box, box_map=box_map)
+
+ return {}
+
+
+def parse_ipma_box(reader: FileReader, box: Box, lvl: int) -> BoxBody:
+ """Parse Item Property Association Box."""
+ item_id_size = 2 if box.header["version"] < 1 else 4
+
+ body: dict[str, Any] = {}
+ body["entry_count"] = reader.read_integer_of_size(box.end, 4)
+ body["associations"] = {}
+
+ for _ in range(body["entry_count"]):
+ item_id = reader.read_integer_of_size(box.end, item_id_size)
+ association_count = reader.read_integer_of_size(box.end, 1)
+ print_indent(lvl, f"Item ID {item_id}:")
+
+ properties = []
+ for _ in range(association_count):
+ tmp = reader.read_integer_of_size(box.end, 1)
+ essential = tmp >> 7 != 0
+ prop_index = tmp & 0x7F
+ if (box.header["flags"] & 1) == 1:
+ prop_index = (prop_index << 8) | reader.read_integer_of_size(box.end, 1)
+ print_indent(
+ lvl + 1,
+ f"Property Index: {prop_index}; " + f'Essential: {"Yes" if essential else "No"}',
+ )
+
+ properties.append((prop_index, essential))
+ body["associations"][item_id] = properties
+ return body
+
+
+def print_iloc_box(body: BoxBody, lvl: int, version: int) -> None:
+ """Print Item Location Box."""
+ print_indent(lvl, f"Offset size: {body['offset_size']}")
+ print_indent(lvl, f"Length size: {body['length_size']}")
+ print_indent(lvl, f"Base offset size: {body['base_offset_size']}")
+ if version in [1, 2]:
+ print_indent(lvl, f"Index size: {body['index_size']}")
+
+ for item in body["items"]:
+ print_indent(
+ lvl,
+ f"Item {item['item_ID']}: construction_method = "
+ + f"{item['construction_method']}; base_offset = {item['base_offset']}",
+ )
+ for extent_index, extent in enumerate(item["extents"]):
+ reference_index_string = ""
+ if "item_reference_index" in extent:
+ reference_index_string = (
+ f"; item_reference_index = {extent['item_reference_index']}"
+ )
+ print_indent(
+ lvl + 1,
+ f"Extent {extent_index}: offset = {extent['offset']} "
+ + f"(total = {extent['calculated_total_offset']}); length = "
+ + f"{extent['length']}{reference_index_string}",
+ )
+
+
+def parse_iloc_box(reader: FileReader, box: Box, lvl: int) -> BoxBody:
+ """Parse Item Location Box."""
+ version = box.header["version"]
+ assert 0 <= version <= 2
+
+ body: dict[str, Any] = {}
+ byte = reader.read_integer_of_size(box.end, 1)
+ body["offset_size"] = byte >> 4
+ body["length_size"] = byte & 0xF
+ byte = reader.read_integer_of_size(box.end, 1)
+ body["base_offset_size"] = byte >> 4
+ body["index_size" if version > 0 else "reserved1"] = byte & 0xF
+
+ items = []
+ if version < 2:
+ item_count = reader.read_integer_of_size(box.end, 2)
+ elif version == 2:
+ item_count = reader.read_integer_of_size(box.end, 4)
+
+ for _ in range(item_count):
+ item: dict[str, Any] = {}
+ if version < 2:
+ item["item_ID"] = reader.read_integer_of_size(box.end, 2)
+ elif version == 2:
+ item["item_ID"] = reader.read_integer_of_size(box.end, 4)
+
+ if version in [1, 2]:
+ item["reserved0"], item["construction_method"] = reader.read_integer_array_of_size(
+ box.end, 1, 2
+ )
+ else:
+ item["construction_method"] = 0
+ item["data_reference_index"] = reader.read_integer_of_size(box.end, 2)
+ assert item["data_reference_index"] == 0, "Non-zero data_reference_index not supported"
+ item["base_offset"] = 0
+ if body["base_offset_size"] > 0:
+ item["base_offset"] = reader.read_integer_of_size(box.end, body["base_offset_size"])
+
+ extent_count = reader.read_integer_of_size(box.end, 2)
+ extents = []
+ for _ in range(extent_count):
+ extent = {}
+ if (version in [1, 2]) and body["index_size"] > 0:
+ extent["item_reference_index"] = reader.read_integer_of_size(
+ box.end, body["index_size"]
+ )
+ extent["offset"] = 0
+ if body["offset_size"] > 0:
+ extent["offset"] = reader.read_integer_of_size(box.end, body["offset_size"])
+ extent["length"] = reader.read_integer_of_size(box.end, body["length_size"])
+ extent["calculated_total_offset"] = item["base_offset"] + extent["offset"]
+ extents += [extent]
+ item["extents"] = extents
+ items += [item]
+ body["items"] = items
+
+ print_iloc_box(body, lvl, version)
+ return body
+
+
+def parse_infe_box(reader: FileReader, box: Box, lvl: int) -> BoxBody:
+ """Parse Item Information Entry Box."""
+ version = box.header["version"]
+ assert 2 <= version <= 3, "Only version 2 and 3 of 'infe' box supported"
+ hidden = box.header["flags"] == 1
+
+ body: dict[str, Any] = {}
+ item_id_size = 2 if version == 2 else 4
+ body["item_id"] = reader.read_integer_of_size(box.end, item_id_size)
+ body["item_protection_index"] = reader.read_integer_of_size(box.end, 2)
+ body["item_type"] = reader.read_string(box.end, size=4)
+ body["name"] = reader.read_string(box.end)
+
+ print_indent(lvl, f"Item ID: {body['item_id']}{' (Hidden)' if hidden else ''}")
+ print_indent(lvl, f"Item protection index: {body['item_protection_index']}")
+ print_indent(lvl, f"Item type: {body['item_type']}")
+
+ if body["item_type"] == "mime":
+ body["content_type"] = reader.read_string(box.end)
+ body["content_encoding"] = reader.read_string(box.end)
+ print_indent(lvl, f"Content type: {body['content_type']}")
+ print_indent(lvl, f"Content encoding: {body['content_encoding']}")
+ elif body["item_type"] == "uri ":
+ body["uri_type"] = reader.read_string(box.end)
+ print_indent(lvl, f"URI type: {body['uri_type']}")
+ return body
+
+
+def parse_iinf_box(reader: FileReader, box: Box, lvl: int) -> BoxBody:
+ """Parse Item Information Box."""
+ version = box.header["version"]
+ assert 0 <= version <= 1, "MIAF requires version 0 or 1 for 'iinf' box"
+
+ entry_count_size = 4 if version != 0 else 2
+ entry_count = reader.read_integer_of_size(box.end, entry_count_size)
+ print_indent(lvl, f"Entry count: {entry_count}")
+
+ box_map = {
+ "infe": BoxRecipe("Item Information Entry Box", full_box=True, body_parser=parse_infe_box)
+ }
+ box.sub_boxes = parse_box_sequence(
+ reader, box.end, lvl + 1, parent=box, box_map=box_map, expected_box_count=entry_count
+ )
+ return {}
+
+
+def parse_colr_box(reader: FileReader, box: Box, lvl: int) -> NCLXBodyType:
+ """Parse Color Information Box."""
+ body: dict[str, Any] = {}
+ body["type"] = reader.read_string(box.end, size=4)
+ if body["type"] == "nclx":
+ body["color_primaries"] = reader.read_integer_of_size(box.end, 2)
+ body["transfer_characteristics"] = reader.read_integer_of_size(box.end, 2)
+ body["matrix_coefficients"] = reader.read_integer_of_size(box.end, 2)
+ body["full_range_flag"] = reader.read_integer_of_size(box.end, 1) >> 7
+ print_indent(
+ lvl,
+ f"NCLX: ({body['color_primaries']},{body['transfer_characteristics']},"
+ + f"{body['matrix_coefficients']},{body['full_range_flag']})",
+ )
+ elif body["type"] in ["rICC", "prof"]:
+ body["icc_data"] = reader.read_data(box.end - reader.position(), box.end)
+ print_indent(lvl, f"{body['type']} of size {len(body['icc_data'])}")
+ else:
+ assert False, f'Unsupported colr type {body["type"]}'
+ return body
+
+
+def parse_pixi_box(reader: FileReader, box: Box, lvl: int) -> BoxBody:
+ """Parse Pixel Information Box."""
+ num_channels = reader.read_integer_of_size(box.end, 1)
+ bpp = reader.read_integer_array_of_size(box.end, 1, num_channels)
+ print_indent(lvl, f"bits_per_channel: {bpp}")
+ return {"bits_per_channel": bpp}
+
+
+def parse_ispe_box(reader: FileReader, box: Box, lvl: int) -> BoxBody:
+ """Parse Image Spatial Extents Box."""
+ body = {}
+ body["width"] = reader.read_integer_of_size(box.end, 4)
+ body["height"] = reader.read_integer_of_size(box.end, 4)
+ print_indent(lvl, f"Dimensions: {body['width']}x{body['height']}")
+ return body
+
+
+def parse_clap_box(reader: FileReader, box: Box, lvl: int) -> BoxBody:
+ """Parse Clean Aperture Box."""
+ body = {}
+ body["width"] = reader.read_integer_array_of_size(box.end, 4, 2, unsigned=False)
+ body["height"] = reader.read_integer_array_of_size(box.end, 4, 2, unsigned=False)
+ body["h_offset"] = reader.read_integer_array_of_size(box.end, 4, 2, unsigned=False)
+ body["v_offset"] = reader.read_integer_array_of_size(box.end, 4, 2, unsigned=False)
+
+ def _print_field(descr: str, key: str) -> None:
+ print_indent(
+ lvl, f"{descr}: {body[key][0]} / {body[key][1]} ({float_from_rational(body[key])})"
+ )
+
+ _print_field("Width", "width")
+ _print_field("Height", "height")
+ _print_field("Horizontal offset", "h_offset")
+ _print_field("Vertical offset", "v_offset")
+ return body
+
+
+def parse_box_sequence(
+ reader: FileReader,
+ end: int,
+ lvl: int,
+ parent: Optional[Box] = None,
+ box_map: Optional[BoxSequenceMap] = None,
+ expected_box_count: Optional[int] = None,
+) -> list[Box]:
+ """Reads the file as a sequence of ISOBMFF boxes."""
+
+ if box_map is None:
+ box_map = {}
+
+ mdat_box_count = 0
+ boxes = []
+ while reader.position() <= (end - 8):
+ # Process Box
+ box = Box.from_reader(reader, end, parent=parent)
+ if box.type == "mdat":
+ mdat_box_count += 1
+ if mdat_box_count > 1:
+ print(
+ "WARNING: Files with multiple mdat boxes should be supported but have "
+ + "not been tested."
+ )
+
+ recipe: Optional[BoxRecipe] = box_map.get(box.type, None)
+ if recipe is None:
+ recipe = box_map.get("default", BoxRecipe("Unknown"))
+ assert recipe is not None
+ box.print_start(lvl, name=recipe.name)
+ recipe.parse(reader, box, lvl + 1)
+
+ # End bounds check
+ assert (
+ reader.position() <= box.end
+ ), f"Error: Read past the box with {reader.position() - box.end} bytes"
+ if reader.position() < box.end:
+ print(
+ "Warning: Did not read all data in the box. "
+ + f"({box.end - reader.position()}) byte(s) more)"
+ )
+
+ box.print_end(lvl)
+ boxes.append(box)
+ reader.skip_to(box.end)
+
+ # If specified, check if the expected number of boxes was read
+ if expected_box_count is not None and expected_box_count != len(boxes):
+ assert expected_box_count != len(
+ boxes
+ ), f"Error: Expected {expected_box_count} boxes but read {len(boxes)}"
+ return boxes
+
+
+# Recipes for how to parse various boxes.
+# Any box not listed here will be copied as-is from source to destination.
+MAP_IPCO_BOX: BoxSequenceMap = {
+ "av1C": BoxRecipe("AV1 Decoder Configuration Record", body_parser=parse_av1c_box),
+ "colr": BoxRecipe("Color Information Box", body_parser=parse_colr_box),
+ "pixi": BoxRecipe("Pixel Information Box", full_box=True, body_parser=parse_pixi_box),
+ "ispe": BoxRecipe("Image Spatial Extents Box", full_box=True, body_parser=parse_ispe_box),
+ "clap": BoxRecipe("Clean Aperture Box", body_parser=parse_clap_box),
+}
+
+MAP_IPRP_BOX: BoxSequenceMap = {
+ "ipco": BoxRecipe("Item Property Container Box", sequence_map=MAP_IPCO_BOX),
+ "ipma": BoxRecipe("Item Property Association Box", full_box=True, body_parser=parse_ipma_box),
+}
+
+MAP_META_BOX: BoxSequenceMap = {
+ "iprp": BoxRecipe("Item Properties Box", sequence_map=MAP_IPRP_BOX),
+ "iloc": BoxRecipe("Item Location Box", full_box=True, body_parser=parse_iloc_box),
+ "iinf": BoxRecipe("Item Information Box", full_box=True, body_parser=parse_iinf_box),
+ "iref": BoxRecipe("Item Reference Box", full_box=True, body_parser=parse_iref_box),
+ "pitm": BoxRecipe("Primary Item Box", full_box=True, body_parser=parse_pitm_box),
+}
+
+MAP_STBL_BOX: BoxSequenceMap = {
+ "stco": BoxRecipe("Sample Chunk Offset Box", full_box=True, body_parser=parse_stco_box),
+ "stsd": BoxRecipe("Sample Description Box", full_box=True, body_parser=parse_stsd_box),
+}
+
+MAP_DINF_BOX: BoxSequenceMap = {
+ "dref": BoxRecipe("Data Reference Box", full_box=True, body_parser=parse_dref_box),
+}
+
+MAP_MINF_BOX: BoxSequenceMap = {
+ "dinf": BoxRecipe("Data Information Box", sequence_map=MAP_DINF_BOX),
+ "stbl": BoxRecipe("Sample Table Box", sequence_map=MAP_STBL_BOX),
+}
+
+MAP_MDIA_BOX: BoxSequenceMap = {
+ "hdlr": BoxRecipe("Handler Reference Box", full_box=True, body_parser=parse_hdlr_box),
+ "minf": BoxRecipe("Media Information Box", sequence_map=MAP_MINF_BOX),
+}
+
+MAP_TRAK_BOX: BoxSequenceMap = {
+ "mdia": BoxRecipe("Media Box", sequence_map=MAP_MDIA_BOX),
+ "tref": BoxRecipe("Track Reference Box", sequence_map={}),
+ "tkhd": BoxRecipe("Track Header Box", full_box=True, body_parser=parse_tkhd_box),
+}
+
+MAP_MOOV_BOX: BoxSequenceMap = {
+ "trak": BoxRecipe("Track Box", sequence_map=MAP_TRAK_BOX),
+}
+
+MAP_TOP_LEVEL: BoxSequenceMap = {
+ "ftyp": BoxRecipe("File Type Box", body_parser=parse_ftyp_box),
+ "meta": BoxRecipe("Meta Box", full_box=True, sequence_map=MAP_META_BOX),
+ "moov": BoxRecipe("Movie Box", sequence_map=MAP_MOOV_BOX),
+ "moof": BoxRecipe("Unsupported box", body_parser=parse_unsupported_box),
+}
+
+
+# ===========================================
+# AV1 OBU parsing
+# ===========================================
+class AV1ElementaryStream:
+ """Class representing an AV1 elementary stream."""
+
+ def __init__(self, data: bytes) -> None:
+ self.data = data
+ self.obu_list: Optional[list[dict[str, Any]]] = None
+
+ def get_sequence_header_obu(self) -> Optional[dict[str, Any]]:
+ """Returns the parsed Sequence Header OBU."""
+ if self.obu_list is None:
+ self._parse_obus()
+ if self.obu_list is not None:
+ for obu in self.obu_list:
+ if obu["description"] == "OBU_SEQUENCE_HEADER":
+ return obu
+ return None
+
+ def generate_av1c_from_sequence_header(self) -> BoxBody:
+ """Generate av1C body from Sequence Header OBU."""
+
+ sequence_header_obu = self.get_sequence_header_obu()
+ assert sequence_header_obu is not None
+ sh_body = sequence_header_obu["body"]
+ body = {}
+ body["marker"] = 1
+ body["version"] = 1
+ body["seq_profile"] = sh_body["seq_profile"]
+ body["seq_level_idx_0"] = sh_body["seq_level_idx[0]"]
+ body["seq_tier_0"] = sh_body["seq_tier[0]"]
+ body["high_bitdepth"] = sh_body["high_bitdepth"]
+ body["twelve_bit"] = sh_body.get("twelve_bit", 0)
+ body["monochrome"] = sh_body["mono_chrome"]
+ body["chroma_subsampling_x"] = sh_body["subsampling_x"]
+ body["chroma_subsampling_y"] = sh_body["subsampling_y"]
+ body["chroma_sample_position"] = sh_body.get("chroma_sample_position", 0)
+ assert (
+ sh_body["initial_display_delay_present_flag"] == 0
+ ), "initial_display_delay_present_flag not implemented"
+ body["initial_presentation_delay_present"] = 0
+ return body
+
+ def generate_nclx_from_sequence_header(self) -> BoxBody:
+ """Generate nclx-colr box body from Sequence Header OBU."""
+ sequence_header_obu = self.get_sequence_header_obu()
+ assert sequence_header_obu is not None
+ sh_body = sequence_header_obu["body"]
+ return {
+ "type": "nclx",
+ "color_primaries": sh_body["color_primaries"],
+ "transfer_characteristics": sh_body["transfer_characteristics"],
+ "matrix_coefficients": sh_body["matrix_coefficients"],
+ "full_range_flag": sh_body["color_range"],
+ }
+
+ def generate_ispe_from_sequence_header(self) -> dict[str, int]:
+ """Generate ispe box body from Sequence Header OBU."""
+ sequence_header_obu = self.get_sequence_header_obu()
+ assert sequence_header_obu is not None
+ sh_body = sequence_header_obu["body"]
+ return {
+ "width": sh_body["max_frame_width_minus_1"] + 1,
+ "height": sh_body["max_frame_height_minus_1"] + 1,
+ }
+
+ def generate_pixi_from_sequence_header(self) -> BoxBody:
+ """Generate pixi box body from Sequence Header OBU."""
+ sequence_header_obu = self.get_sequence_header_obu()
+ assert sequence_header_obu is not None
+ sh_body = sequence_header_obu["body"]
+ return {
+ "bits_per_channel": [sh_body["calculated_bitdepth"]] * sh_body["calculated_numplanes"]
+ }
+
+ def _parse_av1_sequence_header_obu(self, reader: FileReader.BitReader) -> dict[str, int]:
+ """Parse AV1 Sequence Header OBU and return as a dictionary of properties."""
+ parsed = {}
+ parsed["seq_profile"] = reader.f(3)
+ parsed["still_picture"] = reader.f(1)
+ parsed["reduced_still_picture_header"] = reader.f(1)
+ if parsed["reduced_still_picture_header"]:
+ parsed["timing_info_present_flag"] = 0
+ parsed["decoder_model_info_present_flag"] = 0
+ parsed["initial_display_delay_present_flag"] = 0
+ parsed["operating_points_cnt_minus_1"] = 0
+ parsed["operating_point_idc[0]"] = 0
+ parsed["seq_level_idx[0]"] = reader.f(5)
+ parsed["seq_tier[0]"] = 0
+ parsed["decoder_model_present_for_this_op[0]"] = 0
+ parsed["initial_display_delay_present_for_this_op[0]"] = 0
+ else:
+ parsed["timing_info_present_flag"] = reader.f(1)
+ assert parsed["timing_info_present_flag"] == 0, "Not yet implemented"
+ parsed["decoder_model_info_present_flag"] = 0
+
+ parsed["initial_display_delay_present_flag"] = reader.f(1)
+ parsed["operating_points_cnt_minus_1"] = reader.f(5)
+ for i in range(parsed["operating_points_cnt_minus_1"] + 1):
+ parsed[f"operating_point_idc[{i}]"] = reader.f(12)
+ parsed[f"seq_level_idx[{i}]"] = reader.f(5)
+ if parsed[f"seq_level_idx[{i}]"] > 7:
+ parsed[f"seq_tier[{i}]"] = reader.f(1)
+ else:
+ parsed[f"seq_tier[{i}]"] = 0
+ parsed[f"decoder_model_present_for_this_op[{i}]"] = 0
+ if parsed["initial_display_delay_present_flag"]:
+ parsed[f"initial_display_delay_present_for_this_op[{i}]"] = reader.f(1)
+ if parsed[f"initial_display_delay_present_for_this_op[{i}]"]:
+ parsed[f"initial_display_delay_minus_1[{i}]"] = reader.f(4)
+ parsed["frame_width_bits_minus_1"] = reader.f(4)
+ parsed["frame_height_bits_minus_1"] = reader.f(4)
+ parsed["max_frame_width_minus_1"] = reader.f(parsed["frame_width_bits_minus_1"] + 1)
+ parsed["max_frame_height_minus_1"] = reader.f(parsed["frame_height_bits_minus_1"] + 1)
+ if parsed["reduced_still_picture_header"]:
+ parsed["frame_id_numbers_present_flag"] = 0
+ else:
+ parsed["frame_id_numbers_present_flag"] = reader.f(1)
+ if parsed["frame_id_numbers_present_flag"]:
+ parsed["delta_frame_id_length_minus_2"] = reader.f(4)
+ parsed["additional_frame_id_length_minus_1"] = reader.f(3)
+ parsed["use_128x128_superblock"] = reader.f(1)
+ parsed["enable_filter_intra"] = reader.f(1)
+ parsed["enable_intra_edge_filter"] = reader.f(1)
+ if parsed["reduced_still_picture_header"]:
+ parsed["enable_interintra_compound"] = 0
+ parsed["enable_masked_compound"] = 0
+ parsed["enable_warped_motion"] = 0
+ parsed["enable_dual_filter"] = 0
+ parsed["enable_order_hint"] = 0
+ parsed["enable_jnt_comp"] = 0
+ parsed["enable_ref_frame_mvs"] = 0
+ parsed["seq_force_screen_content_tools"] = 2 # SELECT_SCREEN_CONTENT_TOOLS
+ parsed["seq_choose_integer_mv"] = 2 # SELECT_INTEGER_MV
+ else:
+ parsed["enable_interintra_compound"] = reader.f(1)
+ parsed["enable_masked_compound"] = reader.f(1)
+ parsed["enable_warped_motion"] = reader.f(1)
+ parsed["enable_dual_filter"] = reader.f(1)
+ parsed["enable_order_hint"] = reader.f(1)
+ if parsed["enable_order_hint"]:
+ parsed["enable_jnt_comp"] = reader.f(1)
+ parsed["enable_ref_frame_mvs"] = reader.f(1)
+ else:
+ parsed["enable_jnt_comp"] = 0
+ parsed["enable_ref_frame_mvs"] = 0
+ parsed["seq_choose_screen_content_tools"] = reader.f(1)
+ if parsed["seq_choose_screen_content_tools"]:
+ parsed["seq_force_screen_content_tools"] = 2 # SELECT_SCREEN_CONTENT_TOOLS
+ else:
+ parsed["seq_force_screen_content_tools"] = reader.f(1)
+
+ if parsed["seq_force_screen_content_tools"] > 0:
+ parsed["seq_choose_integer_mv"] = reader.f(1)
+ if parsed["seq_choose_integer_mv"]:
+ parsed["seq_force_integer_mv"] = 2 # SELECT_INTEGER_MV
+ else:
+ parsed["seq_force_integer_mv"] = reader.f(1)
+ else:
+ parsed["seq_force_integer_mv"] = 2 # SELECT_INTEGER_MV
+ if parsed["enable_order_hint"]:
+ parsed["order_hint_bits_minus_1"] = reader.f(3)
+ parsed["enable_superres"] = reader.f(1)
+ parsed["enable_cdef"] = reader.f(1)
+ parsed["enable_restoration"] = reader.f(1)
+
+ # color_config()
+ parsed["high_bitdepth"] = reader.f(1)
+ if parsed["seq_profile"] == 2 and parsed["high_bitdepth"]:
+ parsed["twelve_bit"] = reader.f(1)
+ bitdepth = 12 if parsed["twelve_bit"] else 10
+ elif parsed["seq_profile"] <= 2:
+ bitdepth = 10 if parsed["high_bitdepth"] else 8
+ parsed["calculated_bitdepth"] = bitdepth
+
+ if parsed["seq_profile"] != 1:
+ parsed["mono_chrome"] = reader.f(1)
+ else:
+ parsed["mono_chrome"] = 0
+ numplanes = 1 if parsed["mono_chrome"] else 3
+ parsed["calculated_numplanes"] = numplanes
+ parsed["color_description_present_flag"] = reader.f(1)
+ if parsed["color_description_present_flag"]:
+ parsed["color_primaries"] = reader.f(8)
+ parsed["transfer_characteristics"] = reader.f(8)
+ parsed["matrix_coefficients"] = reader.f(8)
+ else:
+ parsed["color_primaries"] = 2
+ parsed["transfer_characteristics"] = 2
+ parsed["matrix_coefficients"] = 2
+ if parsed["mono_chrome"]:
+ parsed["color_range"] = reader.f(1)
+ parsed["subsampling_x"] = 1
+ parsed["subsampling_y"] = 1
+ parsed["chroma_sample_position"] = 0
+ elif (
+ parsed["color_primaries"] == 1
+ and parsed["transfer_characteristics"] == 13
+ and parsed["matrix_coefficients"] == 0
+ ):
+ parsed["color_range"] = 1
+ parsed["subsampling_x"] = 0
+ parsed["subsampling_y"] = 0
+ else:
+ parsed["color_range"] = reader.f(1)
+ if parsed["seq_profile"] == 0:
+ parsed["subsampling_x"] = parsed["subsampling_y"] = 1
+ elif parsed["seq_profile"] == 1:
+ parsed["subsampling_x"] = parsed["subsampling_y"] = 0
+ else:
+ if parsed["twelve_bit"]:
+ parsed["subsampling_x"] = reader.f(1)
+ if parsed["subsampling_x"]:
+ parsed["subsampling_y"] = reader.f(1)
+ else:
+ parsed["subsampling_y"] = 0
+ else:
+ parsed["subsampling_x"] = 1
+ parsed["subsampling_y"] = 0
+ if parsed["subsampling_x"] and parsed["subsampling_y"]:
+ parsed["chroma_sample_position"] = reader.f(2)
+ parsed["separate_uv_delta_q"] = reader.f(1)
+ # end color_config()
+
+ parsed["film_grain_params_present"] = reader.f(1)
+ return parsed
+
+ def _parse_obus(self) -> None:
+ """Parse data as sequence of AV1 OBUs."""
+ reader = FileReader.BitReader(self.data)
+ obu_map: dict[int, tuple[Optional[OBUParser], str]] = {
+ 1: (self._parse_av1_sequence_header_obu, "OBU_SEQUENCE_HEADER"),
+ 2: (None, "OBU_TEMPORAL_DELIMITER"),
+ 3: (None, "OBU_FRAME_HEADER"),
+ 4: (None, "OBU_TILE_GROUP"),
+ 5: (None, "OBU_METADATA"),
+ 6: (None, "OBU_FRAME"),
+ 7: (None, "OBU_REDUNDANT_FRAME_HEADER"),
+ 8: (None, "OBU_TILE_LIST"),
+ 15: (None, "OBU_PADDING"),
+ }
+
+ def _read_obu_header(bit_reader: FileReader.BitReader) -> dict[str, int]:
+ header = {}
+ header["forbidden_bit"] = bit_reader.f(1)
+ header["type"] = bit_reader.f(4)
+ header["extension_flag"] = bit_reader.f(1)
+ header["has_size_field"] = bit_reader.f(1)
+ header["reserved_1bit"] = bit_reader.f(1)
+ if header["extension_flag"] != 0:
+ header["temporal_id"] = bit_reader.f(3)
+ header["spatial_id"] = bit_reader.f(2)
+ header["extension_reserved_3bits"] = bit_reader.f(3)
+ return header
+
+ obu_list = []
+
+ while not reader.eof():
+ obu_header = _read_obu_header(reader)
+ assert obu_header["has_size_field"] != 0
+ obu_size = reader.read_leb128_value()
+ parse_function = None
+ description = "Unknown OBU"
+ if obu_header["type"] in obu_map:
+ parse_function, description = obu_map[obu_header["type"]]
+
+ body = {}
+ if parse_function is not None:
+ body = parse_function(reader.bit_reader_for_bytes(obu_size))
+ else:
+ reader.skip_bytes(obu_size)
+
+ obu = {
+ "description": description,
+ "header": obu_header,
+ "body": body,
+ }
+ obu_list.append(obu)
+ self.obu_list = obu_list
+
+
+# ===========================================
+# Box validation
+# ===========================================
+class ParsedFile:
+ """Class describing a parsed AVIF file."""
+
+ def __init__(self, file: BinaryIO, verbose: bool) -> None:
+ self.reader = FileReader(file)
+
+ assert self.reader.size > 8, "Size of file is too small to be AVIF"
+
+ # Check if file seems to be HEIF
+ box_size = self.reader.read_integer_of_size(self.reader.size, 4)
+ assert box_size > 8, "Size of ftyp box is too small to be AVIF"
+
+ box_type = self.reader.read_string(self.reader.size, 4)
+ if box_type != "ftyp":
+ print('File does not start with "ftyp" box. Cannot proceed.')
+ sys.exit(1)
+ self.reader.rewind()
+
+ # Parse the boxes
+ self.lvl = 0 if verbose else NONVERBOSE_PRINT_LEVEL
+ self.boxes = parse_box_sequence(
+ self.reader, self.reader.size, self.lvl, box_map=MAP_TOP_LEVEL
+ )
+
+ self.ipma = self.get_box_from_hierarchy(["meta", "iprp", "ipma"])
+ self.ipco = self.get_box_from_hierarchy(["meta", "iprp", "ipco"])
+
+ def get_box_from_hierarchy(
+ self, box_hierarchy: list[str], box_array: Optional[list[Box]] = None
+ ) -> Optional[Box]:
+ """Extracts the first box matching a given hierarchy."""
+ box_array = self.boxes if box_array is None else box_array
+ for box in box_array:
+ if box.type == box_hierarchy[0]:
+ if len(box_hierarchy) == 1:
+ return box
+ return self.get_box_from_hierarchy(box_hierarchy[1:], box_array=box.sub_boxes)
+ return None
+
+ def get_iloc_entry_for_item(self, item_id: int) -> Optional[dict[str, Any]]:
+ """Extracts the iloc entry for the given item_id."""
+ iloc_box = self.get_box_from_hierarchy(["meta", "iloc"])
+ if iloc_box is not None:
+ body = iloc_box.body
+ for item in body["items"]:
+ if item["item_ID"] == item_id:
+ return typing.cast(dict[str, Any], item)
+ return None
+
+ def get_item_properties_for_item(self, item_id: int) -> list[tuple[Box, bool]]:
+ """Extracts the item properties associated with a given item_id."""
+ if self.ipma is None or self.ipco is None or self.ipco.sub_boxes is None:
+ return []
+ associations = self.ipma.body["associations"].get(item_id, [])
+ properties = []
+ for property_index, essential in associations:
+ assert 1 <= property_index <= len(self.ipco.sub_boxes) + 1
+ property_box = self.ipco.sub_boxes[property_index - 1]
+ properties.append((property_box, essential))
+ return properties
+
+ def get_items(self) -> dict[int, dict[str, Any]]:
+ """Creates a list of items from parsed boxes."""
+ items: dict[int, dict[str, Any]] = {}
+ iinf_box = self.get_box_from_hierarchy(["meta", "iinf"])
+ if iinf_box is None or iinf_box.sub_boxes is None:
+ return items
+
+ for infe_box in iinf_box.sub_boxes:
+ item_id = infe_box.body["item_id"]
+ items[item_id] = {}
+
+ iloc = self.get_iloc_entry_for_item(item_id)
+ items[item_id]["item_id"] = item_id
+ items[item_id]["infe"] = infe_box
+ items[item_id]["iloc"] = iloc
+ items[item_id]["item_properties"] = self.get_item_properties_for_item(item_id)
+ if infe_box.body["item_type"] == "av01" and iloc is not None:
+ items[item_id]["av01_stream"] = self.get_av1_elementary_stream_for_item(iloc)
+ return items
+
+ def get_av1_elementary_stream_for_item(self, iloc_entry: dict[str, Any]) -> AV1ElementaryStream:
+ """Extract and parse AV1 elementary stream for a given item iloc."""
+ assert iloc_entry["construction_method"] == 0, "Only construction_method 0 implemented"
+ base = iloc_entry["base_offset"]
+ data = bytes()
+ for extent in iloc_entry["extents"]:
+ total_offset = base + extent["offset"]
+ length = extent["length"]
+ data += self.reader.read_data_from_offset(total_offset, length)
+ return AV1ElementaryStream(data)
+
+ def get_existing_property_if_present(
+ self,
+ property_type: BoxType,
+ property_header: Optional[BoxHeader],
+ property_body: Optional[BoxBody],
+ ) -> int:
+ """Gets the index in the 'ipco' for an existing property, or -1 if none exists."""
+ existing_box_index = -1
+ if self.ipco is None or self.ipco.sub_boxes is None:
+ return existing_box_index
+ for box_index, box in enumerate(self.ipco.sub_boxes):
+ if (
+ box.type == property_type
+ and box.header == property_header
+ and box.body == property_body
+ ):
+ existing_box_index = box_index
+ break
+ return existing_box_index
+
+ def add_property_association(
+ self, item_id: int, ipco_index: int, essential: bool, position: Optional[int] = None
+ ) -> None:
+ """Add an association from an item to a property in the ipco box if not already present."""
+ if self.ipma is None or self.ipco is None or self.ipco.sub_boxes is None:
+ return
+ associations = self.ipma.body["associations"].get(item_id, [])
+ association_index = -1
+ existing_association_essential = False
+ for cur_index, (property_index, cur_essential) in enumerate(associations):
+ assert 1 <= property_index <= len(self.ipco.sub_boxes)
+ if ipco_index == property_index - 1:
+ association_index = cur_index
+ existing_association_essential = cur_essential
+ break
+
+ # If association is not present, we need to add it
+ if association_index == -1:
+ if item_id not in self.ipma.body["associations"]:
+ self.ipma.body["associations"][item_id] = []
+ val = (ipco_index + 1, essential)
+ if position is None:
+ position = len(self.ipma.body["associations"][item_id])
+ self.ipma.body["associations"][item_id].insert(position, val)
+ self.ipma.mark_for_rewrite()
+ elif essential and not existing_association_essential:
+ self.ipma.body["associations"][item_id][association_index] = (ipco_index + 1, essential)
+ self.ipma.mark_for_rewrite()
+
+ def remove_property_associations(
+ self,
+ item_id: int,
+ property_type: BoxType,
+ header: Optional[BoxHeader] = None,
+ body: Optional[BoxBody] = None,
+ ) -> tuple[Optional[int], bool]:
+ """Remove all association from an item to a property type in the ipco box."""
+ if self.ipma is None or self.ipco is None or self.ipco.sub_boxes is None:
+ return (None, True)
+ associations = self.ipma.body["associations"].get(item_id, [])
+
+ def _should_keep(prop_index: int, _essential: bool) -> bool:
+ assert self.ipco and self.ipco.sub_boxes
+ assert 1 <= prop_index <= len(self.ipco.sub_boxes)
+ box = self.ipco.sub_boxes[prop_index - 1]
+
+ keep = box.type != property_type
+ if header is not None:
+ keep = keep or box.header != header
+ if body is not None:
+ keep = keep or box.body != body
+ return keep
+
+ filtered_associations = []
+ first_removed_assoc: tuple[Optional[int], bool] = (None, True)
+ for position, (prop_index, essential) in enumerate(associations):
+ if _should_keep(prop_index, essential):
+ filtered_associations.append((prop_index, essential))
+ elif first_removed_assoc[0] is None:
+ first_removed_assoc = (position, essential)
+
+ if associations != filtered_associations:
+ self.ipma.body["associations"][item_id] = filtered_associations
+ self.ipma.mark_for_rewrite()
+ return first_removed_assoc
+ return (None, True)
+
+ def drop_unused_item_properties(self) -> None:
+ """Drops any item properties with no associations."""
+ if self.ipma is None or self.ipco is None or self.ipco.sub_boxes is None:
+ return
+ prop_assoc_count = [0] * len(self.ipco.sub_boxes)
+ for _, associations in self.ipma.body["associations"].items():
+ for prop_index, _ in associations:
+ prop_assoc_count[prop_index - 1] += 1
+
+ if prop_assoc_count.count(0) == 0:
+ return
+
+ # Change association indices to account for dropped properties
+ props_to_drop = [0 if v > 0 else 1 for v in prop_assoc_count]
+ decrement_count = list(accumulate(props_to_drop))
+ for _, associations in self.ipma.body["associations"].items():
+ for assoc_index, (prop_index, essential) in enumerate(associations):
+ associations[assoc_index] = (
+ prop_index - decrement_count[prop_index - 1],
+ essential,
+ )
+
+ # Drop unused properties
+ self.ipco.sub_boxes = [
+ box for index, box in enumerate(self.ipco.sub_boxes) if props_to_drop[index] == 0
+ ]
+ self.ipco.mark_for_rewrite()
+
+ def _add_property_if_needed(
+ self, property_type: BoxType, header: BoxHeader, body: BoxBody
+ ) -> int:
+ if self.ipma is None or self.ipco is None or self.ipco.sub_boxes is None:
+ return -1
+ existing_box_index = self.get_existing_property_if_present(property_type, header, body)
+ # No existing box, we need to add one
+ if existing_box_index == -1:
+ box = Box(property_type, self.ipco, 0, 0)
+ box.header = header if header is not None else {}
+ box.body = body
+ existing_box_index = len(self.ipco.sub_boxes)
+ self.ipco.sub_boxes += [box]
+ box.mark_for_rewrite()
+ return existing_box_index
+
+ def replace_property_for_item(
+ self,
+ property_type: BoxType,
+ header: BoxHeader,
+ body: BoxBody,
+ item_id: int,
+ old_header: Optional[BoxHeader] = None,
+ old_body: Optional[BoxBody] = None,
+ ) -> None:
+ """Replace a property for an item_id."""
+ box_index = self._add_property_if_needed(property_type, header, body)
+ position, essential = self.remove_property_associations(
+ item_id, property_type, old_header, old_body
+ )
+ self.add_property_association(item_id, box_index, essential, position=position)
+ self.drop_unused_item_properties()
+
+ def add_property_for_item(
+ self,
+ property_type: BoxType,
+ header: BoxHeader,
+ body: BoxBody,
+ item_id: int,
+ essential: bool,
+ position: Optional[int] = None,
+ ) -> None:
+ """Adds a new property box if needed and adds an association from the item_id to it."""
+ box_index = self._add_property_if_needed(property_type, header, body)
+ self.add_property_association(item_id, box_index, essential, position)
+
+ def mark_offset_boxes_for_rewrite(self) -> None:
+ """Marks boxes containing offsets as needing rewriting."""
+ iloc = self.get_box_from_hierarchy(["meta", "iloc"])
+ if iloc is not None:
+ iloc.mark_for_rewrite()
+
+ moov_box = self.get_box_from_hierarchy(["moov"])
+ if moov_box is not None and moov_box.sub_boxes is not None:
+ for box in moov_box.sub_boxes:
+ if box.type != "trak":
+ continue
+ stco = self.get_box_from_hierarchy(["mdia", "minf", "stbl", "stco"], box.sub_boxes)
+ if stco is not None:
+ stco.mark_for_rewrite()
+
+ def boxes_have_changed(self) -> bool:
+ """Returns true if any box has changed."""
+ return any(box.needs_rewrite for box in self.boxes)
+
+
+# ===========================================
+# Box rewriting
+# ===========================================
+class AVIFWriter:
+ """Class containing functionality for writing out AVIF files."""
+
+ def __init__(self, parsed_file: ParsedFile, output: BinaryIO) -> None:
+ self.parsed_file = parsed_file
+ self.output = output
+ self.box_writer_map: dict[BoxType, BoxWriter] = {
+ BoxType("av1C"): self._write_av1c_box,
+ BoxType("colr"): self._write_colr_box,
+ BoxType("pixi"): self._write_pixi_box,
+ BoxType("ipco"): self._write_generic_container_box,
+ BoxType("ipma"): self._write_ipma_box,
+ BoxType("iprp"): self._write_generic_container_box,
+ BoxType("iloc"): self._write_iloc_box,
+ BoxType("meta"): self._write_generic_container_box,
+ BoxType("moov"): self._write_generic_container_box,
+ BoxType("trak"): self._write_generic_container_box,
+ BoxType("mdia"): self._write_generic_container_box,
+ BoxType("minf"): self._write_generic_container_box,
+ BoxType("stbl"): self._write_generic_container_box,
+ BoxType("stco"): self._write_stco_box,
+ BoxType("hdlr"): self._write_hdlr_box,
+ BoxType("stsd"): self._write_stsd_box,
+ BoxType("av01"): self._write_av01_box,
+ BoxType("auxi"): self._write_auxi_box,
+ BoxType("tkhd"): self._write_tkhd_box,
+ BoxType("ccst"): self._write_ccst_box,
+ BoxType("ispe"): self._write_ispe_box,
+ BoxType("clap"): self._write_clap_box,
+ BoxType("ftyp"): self._write_ftyp_box,
+ BoxType("pitm"): self._write_pitm_box,
+ }
+
+ def _write_ftyp_box(self, box: Box, _current_offset: int) -> BoxWriterReturn:
+ assert box.needs_rewrite
+ body_data = bytes()
+ body_data += box.body["major"].encode("utf8")
+ body_data += write_integer_of_size(box.body["version"], 4)
+ for brand in box.body["compatible"]:
+ body_data += brand.encode("utf8")
+ data = box.write_box_header(len(body_data)) + body_data
+ return data, []
+
+ def _write_av1c_box(self, box: Box, _current_offset: int) -> BoxWriterReturn:
+ byte0 = (box.body["marker"] << 7) | (box.body["version"])
+ byte1 = (box.body["seq_profile"] << 5) | (box.body["seq_level_idx_0"])
+ byte2 = (box.body["seq_tier_0"] << 7) | (box.body["high_bitdepth"] << 6)
+ byte2 |= (box.body["twelve_bit"] << 5) | (box.body["monochrome"] << 4)
+ byte2 |= (box.body["chroma_subsampling_x"] << 3) | (box.body["chroma_subsampling_y"] << 2)
+ byte2 |= box.body["chroma_sample_position"]
+ byte3 = box.body["initial_presentation_delay_present"] << 4
+ assert box.body["initial_presentation_delay_present"] == 0
+ body_data = struct.pack(">BBBB", byte0, byte1, byte2, byte3)
+ return box.write_box_header(len(body_data)) + body_data, []
+
+ def _write_pitm_box(self, box: Box, _current_offset: int) -> BoxWriterReturn:
+ assert box.needs_rewrite
+ assert box.header["version"] in [0, 1]
+ body_data = bytes()
+ item_id_size = 2 if box.header["version"] < 1 else 4
+ body_data += write_integer_of_size(box.body["item_id"], item_id_size)
+ data = box.write_box_header(len(body_data)) + body_data
+ return data, []
+
+ def _write_colr_box(self, box: Box, _current_offset: int) -> BoxWriterReturn:
+ assert box.needs_rewrite
+ assert box.body["type"] == "nclx"
+ body_data = bytes()
+ body_data += "nclx".encode("utf-8")
+ body_data += write_integer_of_size(box.body["color_primaries"], 2)
+ body_data += write_integer_of_size(box.body["transfer_characteristics"], 2)
+ body_data += write_integer_of_size(box.body["matrix_coefficients"], 2)
+ body_data += write_integer_of_size(box.body["full_range_flag"] << 7, 1)
+ data = box.write_box_header(len(body_data)) + body_data
+ return data, []
+
+ def _write_pixi_box(self, box: Box, _current_offset: int) -> BoxWriterReturn:
+ assert box.needs_rewrite
+ body_data = bytes()
+ bpp = box.body["bits_per_channel"]
+ body_data += write_integer_of_size(len(bpp), 1)
+ for value in bpp:
+ body_data += write_integer_of_size(value, 1)
+ data = box.write_box_header(len(body_data)) + body_data
+ return data, []
+
+ def _write_clap_box(self, box: Box, _current_offset: int) -> BoxWriterReturn:
+ assert box.needs_rewrite
+ body_data = bytes()
+ body_data += write_integer_array_of_size(box.body["width"], 4, unsigned=False)
+ body_data += write_integer_array_of_size(box.body["height"], 4, unsigned=False)
+ body_data += write_integer_array_of_size(box.body["h_offset"], 4, unsigned=False)
+ body_data += write_integer_array_of_size(box.body["v_offset"], 4, unsigned=False)
+ data = box.write_box_header(len(body_data)) + body_data
+ return data, []
+
+ def _write_ispe_box(self, box: Box, _current_offset: int) -> BoxWriterReturn:
+ assert box.needs_rewrite
+ body_data = bytes()
+ body_data += write_integer_of_size(box.body["width"], 4)
+ body_data += write_integer_of_size(box.body["height"], 4)
+ data = box.write_box_header(len(body_data)) + body_data
+ return data, []
+
+ def _write_box_sequence(
+ self, boxes: Optional[list[Box]], current_offset: int
+ ) -> BoxWriterReturn:
+ body_data = bytes()
+ placeholder_offsets: list[PlaceholderFileOffset] = []
+ if boxes is None:
+ return body_data, placeholder_offsets
+ for sub_box in boxes:
+ if not sub_box.needs_rewrite:
+ body_data += self.parsed_file.reader.read_data_from_offset(
+ sub_box.start, sub_box.size
+ )
+ continue
+
+ writer = self.box_writer_map.get(sub_box.type, None)
+ if writer is None:
+ assert sub_box.body[
+ "serialized"
+ ], f"Have no box writer for un-serialized box of type '{sub_box.type}'"
+ writer = self._write_serialized_box
+ data, offsets = writer(sub_box, current_offset + len(body_data))
+ body_data += data
+ placeholder_offsets += offsets
+ return body_data, placeholder_offsets
+
+ def _write_generic_container_box(self, box: Box, current_offset: int) -> BoxWriterReturn:
+ assert box.needs_rewrite
+ current_offset += 8
+ if len(box.header) > 0:
+ current_offset += 4
+
+ body_data, placeholder_offsets = self._write_box_sequence(box.sub_boxes, current_offset)
+ return box.write_box_header(len(body_data)) + body_data, placeholder_offsets
+
+ def _write_ipma_box(self, box: Box, _current_offset: int) -> BoxWriterReturn:
+ assert box.needs_rewrite
+ associations = box.body["associations"]
+
+ item_id_type = ">H" if box.header["version"] < 1 else ">I"
+ association_size = 2 if (box.header["flags"] & 1) == 1 else 1
+ max_property_index = (1 << association_size * 8) - 1
+
+ body_data = bytes()
+ body_data += struct.pack(">I", len(associations))
+ item_ids = sorted(associations.keys())
+ for item_id in item_ids:
+ item_assocs = associations[item_id]
+ body_data += struct.pack(item_id_type, item_id)
+ body_data += struct.pack(">B", len(item_assocs))
+ for prop_index, essential in item_assocs:
+ assert prop_index <= max_property_index
+ essential_bit = 1 if essential else 0
+ if association_size == 2:
+ body_data += struct.pack(">H", (essential_bit << 15) | prop_index)
+ else:
+ body_data += struct.pack(">B", (essential_bit << 7) | prop_index)
+
+ return box.write_box_header(len(body_data)) + body_data, []
+
+ def _write_iloc_box(self, box: Box, current_offset: int) -> BoxWriterReturn:
+ assert box.needs_rewrite
+
+ version = box.header["version"]
+ offset_size = box.body["offset_size"]
+ length_size = box.body["length_size"]
+ base_offset_size = box.body["base_offset_size"]
+ index_size = box.body.get("index_size", 0)
+ item_count_and_id_size = 2 if version < 2 else 4
+
+ current_offset += 12 # Full-box header
+
+ # These offsets need to be corrected once it is known how offsets have moved.
+ placeholder_offsets = []
+
+ items = box.body["items"]
+ body_data = bytes()
+ body_data += struct.pack(">B", (offset_size << 4) | length_size)
+ body_data += struct.pack(">B", (base_offset_size << 4) | index_size)
+ body_data += write_integer_of_size(len(items), item_count_and_id_size)
+ for item in items:
+ base_placeholder = None
+ body_data += write_integer_of_size(item["item_ID"], item_count_and_id_size)
+ if version in [1, 2]:
+ body_data += struct.pack(">BB", 0, item["construction_method"])
+ body_data += struct.pack(">H", 0) # data_reference_index
+ if base_offset_size > 0:
+ if item["construction_method"] == 0:
+ base_placeholder = PlaceholderFileOffset(
+ box, current_offset + len(body_data), base_offset_size, item["base_offset"]
+ )
+ placeholder_offsets.append(base_placeholder)
+ body_data += write_integer_of_size(item["base_offset"], base_offset_size)
+
+ extents = item["extents"]
+ body_data += write_integer_of_size(len(extents), 2)
+ for extent in extents:
+ if index_size > 0:
+ body_data += write_integer_of_size(extent["item_reference_index"], index_size)
+ if offset_size > 0:
+ if item["construction_method"] == 0:
+ placeholder = PlaceholderFileOffset(
+ box,
+ current_offset + len(body_data),
+ offset_size,
+ extent["offset"],
+ base=base_placeholder,
+ )
+ if base_offset_size == 0:
+ placeholder_offsets.append(placeholder)
+ body_data += write_integer_of_size(extent["offset"], offset_size)
+ body_data += write_integer_of_size(extent["length"], length_size)
+
+ data = box.write_box_header(len(body_data)) + body_data
+ return data, placeholder_offsets
+
+ def _write_stco_box(self, box: Box, current_offset: int) -> BoxWriterReturn:
+ assert box.needs_rewrite
+
+ current_offset += 12 # Full-box header
+
+ # These offsets need to be corrected once it is known how offsets have moved.
+ placeholder_offsets = []
+
+ entries = box.body["entries"]
+ entry_count = len(entries)
+ body_data = bytes()
+ body_data += write_integer_of_size(entry_count, 4)
+ for entry in entries:
+ placeholder = PlaceholderFileOffset(box, current_offset + len(body_data), 4, entry)
+ placeholder_offsets.append(placeholder)
+ body_data += write_integer_of_size(entry, 4)
+ data = box.write_box_header(len(body_data)) + body_data
+ return data, placeholder_offsets
+
+ def _write_stsd_box(self, box: Box, current_offset: int) -> BoxWriterReturn:
+ assert box.needs_rewrite
+ current_offset += 12 # Full-box header
+ body_data = bytes()
+ sub_boxes = [] if box.sub_boxes is None else box.sub_boxes
+ body_data += write_integer_of_size(len(sub_boxes), 4)
+ current_offset += len(body_data)
+ sub_data, placeholder_offsets = self._write_box_sequence(sub_boxes, current_offset)
+ body_data += sub_data
+ data = box.write_box_header(len(body_data)) + body_data
+ return data, placeholder_offsets
+
+ def _write_av01_box(self, box: Box, current_offset: int) -> BoxWriterReturn:
+ assert box.needs_rewrite
+ current_offset += 8 # Box header
+ body_data = bytes()
+ body_data += box.body["sampleentry"]
+ body_data += box.body["visualsampleentry"]
+ current_offset += len(body_data)
+ sub_data, placeholder_offsets = self._write_box_sequence(box.sub_boxes, current_offset)
+ body_data += sub_data
+ data = box.write_box_header(len(body_data)) + body_data
+ return data, placeholder_offsets
+
+ def _write_auxi_box(self, box: Box, _current_offset: int) -> BoxWriterReturn:
+ assert box.needs_rewrite
+ body_data = box.body["aux_track_type"].encode("utf8")
+ body_data += write_integer_of_size(0, 1)
+ data = box.write_box_header(len(body_data)) + body_data
+ return data, []
+
+ def _write_hdlr_box(self, box: Box, _current_offset: int) -> BoxWriterReturn:
+ assert box.needs_rewrite
+ body_data = bytes()
+ body_data += write_integer_of_size(box.body["pre_defined"], 4)
+ body_data += box.body["hdlr_type"].encode("utf8")
+ body_data += write_integer_of_size(0, 4)
+ body_data += write_integer_of_size(0, 4)
+ body_data += write_integer_of_size(0, 4)
+ if box.body["name"] is not None:
+ body_data += box.body["name"].encode("utf8")
+ body_data += write_integer_of_size(0, 1)
+ return box.write_box_header(len(body_data)) + body_data, []
+
+ def _write_tkhd_box(self, box: Box, _current_offset: int) -> BoxWriterReturn:
+ time_size = 8 if box.header["version"] == 1 else 4
+ body_data = bytes()
+ body_data += write_integer_of_size(box.body["creation_time"], time_size)
+ body_data += write_integer_of_size(box.body["modification_time"], time_size)
+ body_data += write_integer_of_size(box.body["track_id"], 4)
+ body_data += write_integer_of_size(0, 4)
+ body_data += write_integer_of_size(box.body["duration"], time_size)
+ body_data += write_integer_of_size(0, 8)
+ body_data += write_integer_of_size(box.body["layer"], 2)
+ body_data += write_integer_of_size(box.body["alternate_group"], 2)
+ body_data += write_integer_of_size(box.body["volume"], 2)
+ body_data += write_integer_of_size(0, 2)
+ for value in box.body["matrix"]:
+ body_data += write_integer_of_size(value, 4)
+ body_data += write_integer_of_size(box.body["width"], 4)
+ body_data += write_integer_of_size(box.body["height"], 4)
+ return box.write_box_header(len(body_data)) + body_data, []
+
+ def _write_ccst_box(self, box: Box, _current_offset: int) -> BoxWriterReturn:
+ assert box.needs_rewrite
+ value = 0
+ value |= box.body["all_ref_pics_intra"] << 31
+ value |= box.body["intra_pred_used"] << 30
+ value |= box.body["max_ref_per_pic"] << 26
+ body_data = write_integer_of_size(value, 4)
+ return box.write_box_header(len(body_data)) + body_data, []
+
+ def _write_serialized_box(self, box: Box, _current_offset: int) -> BoxWriterReturn:
+ assert box.needs_rewrite
+ assert "serialized" in box.body
+ data = box.body["serialized"]
+ assert isinstance(data, bytes)
+ return box.write_box_header(len(data)) + data, []
+
+ def write(self) -> None:
+ """Writes out all boxes to the destination file."""
+ placeholder_offsets = []
+ mdat_boxes: list[tuple[Box, int]] = []
+
+ # Mark iloc/stco as needing rewrite if any boxes are changing
+ if self.parsed_file.boxes_have_changed():
+ self.parsed_file.mark_offset_boxes_for_rewrite()
+
+ for box in self.parsed_file.boxes:
+ if box.type == "mdat":
+ current_pos = self.output.tell()
+ mdat_boxes.append((box, current_pos))
+
+ if not box.needs_rewrite:
+ self.parsed_file.reader.copy_data_to_destination(self.output, box.start, box.size)
+ continue
+
+ writer = self.box_writer_map.get(box.type, None)
+ if writer is None:
+ assert isinstance(
+ box.body, bytes
+ ), f"Have no box writer for un-serialized box of type '{box.type}'"
+ writer = self._write_serialized_box
+ box_data, cur_offsets = writer(box, self.output.tell())
+ self.output.write(box_data)
+ placeholder_offsets += cur_offsets
+
+ # 'mdat's may have moved. We need to update any file offset placeholders.
+ for placeholder in placeholder_offsets:
+ offsets = placeholder.get_offset_list()
+
+ # Find which 'mdat' the offset belonged to
+ mdat_box, new_offset = None, None
+ for mdat_box, new_offset in mdat_boxes:
+ offsets_in_mdat = [mdat_box.start <= o < mdat_box.end for o in offsets]
+ if all(offsets_in_mdat):
+ break
+ assert not any(
+ offsets_in_mdat
+ ), "Items with base_offset + [offset] pointing to multiple 'mdat's not supported"
+ delta = new_offset - mdat_box.start
+ placeholder.write_delta(self.output, delta)
+
+ def __repr__(self) -> str:
+ return f"AVIFWriter(output: {self.output})"
+
+
+# ===========================================
+# File validation and fix-up
+# ===========================================
+
+
+def _get_max_profile_and_limit_for_items(parsed_file: ParsedFile) -> tuple[int, int]:
+ items = parsed_file.get_items()
+ max_profile = -1
+ max_level = -1
+ for _, item in items.items():
+ if item["infe"].body["item_type"] == "av01":
+ generated_av1c = item["av01_stream"].generate_av1c_from_sequence_header()
+ max_profile = max(max_profile, generated_av1c["seq_profile"])
+ max_level = max(max_level, generated_av1c["seq_level_idx_0"])
+ return max_profile, max_level
+
+
+def _get_max_profile_and_limit_for_tracks(parsed_file: ParsedFile) -> tuple[int, int]:
+ moov = parsed_file.get_box_from_hierarchy(["moov"])
+ max_profile = -1
+ max_level = -1
+ if moov is not None and moov.sub_boxes is not None:
+ for box in moov.sub_boxes:
+ if box.type != "trak":
+ continue
+ av1c_box = parsed_file.get_box_from_hierarchy(
+ ["mdia", "minf", "stbl", "stsd", "av01", "av1C"], box.sub_boxes
+ )
+ if av1c_box is None:
+ continue
+ max_profile = max(max_profile, av1c_box.body["seq_profile"])
+ max_level = max(max_level, av1c_box.body["seq_level_idx_0"])
+ return max_profile, max_level
+
+
+def _remove_brand_factory(ftyp: Box, brand: str) -> IssueFixer:
+ def _fix_brand() -> None:
+ if brand == ftyp.body["major"]:
+ ftyp.body["major"] = "avif"
+ ftyp.body["compatible"].remove("avif")
+ ftyp.body["compatible"].remove(brand)
+ else:
+ ftyp.body["compatible"].remove(brand)
+ ftyp.mark_for_rewrite()
+
+ return _fix_brand
+
+
+def validate_profile_brands(parsed_file: ParsedFile) -> list[BoxIssue]:
+ """Validates that profile brands are correct in the ftyp box."""
+ ftyp = parsed_file.get_box_from_hierarchy(["ftyp"])
+ assert ftyp
+ all_brands = [ftyp.body["major"]] + ftyp.body["compatible"]
+ max_prof_items, max_lvl_items = _get_max_profile_and_limit_for_items(parsed_file)
+ max_prof_sequences, max_lvl_sequences = _get_max_profile_and_limit_for_items(parsed_file)
+ max_prof = max(max_prof_items, max_prof_sequences)
+
+ issues = []
+ for brand in all_brands:
+ profile_limit = None
+ level_limit_items = None
+ level_limit_sequences = None
+ if brand == "MA1B":
+ profile_limit = 0 # main profile
+ level_limit_items = level_limit_sequences = 13 # level 5.1
+ elif brand == "MA1A":
+ profile_limit = 1 # main profile
+ level_limit_items = 16 # level 6.0
+ level_limit_sequences = 13 # level 5.1
+ else:
+ continue
+
+ issue = BoxIssue(-1, "ftyp")
+ template = "Max {} used exceeds highest allowed by {} brand. {} > {}"
+ if max_prof > profile_limit:
+ issue.add_issue("WARNING", template.format("profile", brand, max_prof, profile_limit))
+ if max_lvl_items > level_limit_items:
+ issue.add_issue(
+ "WARNING", template.format("item level", brand, max_lvl_items, level_limit_items)
+ )
+ if max_lvl_sequences > level_limit_sequences:
+ issue.add_issue(
+ "WARNING",
+ template.format("sequence level", brand, max_lvl_sequences, level_limit_sequences),
+ )
+ if len(issue.issues) == 0:
+ continue
+
+ issue.add_info_url("incorrect-profile-brands")
+ issue.add_fix(_remove_brand_factory(ftyp, brand), f"Remove {brand} from brands in ftyp")
+ issues.append(issue)
+ return issues
+
+
+def validate_av1c_property(parsed_file: ParsedFile, item: dict[str, Any]) -> list[BoxIssue]:
+ """Validates that av1C property is correct for an item."""
+ item_id = item["item_id"]
+ generated_av1c = item["av01_stream"].generate_av1c_from_sequence_header()
+ existing_av1c = None
+ for prop, _ in item["item_properties"]:
+ if prop.type == "av1C":
+ existing_av1c = prop.body
+ break
+ assert existing_av1c, "Could not find av1C"
+
+ issue = BoxIssue(item_id, "av1C")
+ if "configOBUs" in existing_av1c:
+ issue.add_issue("WARNING", "av1C in AVIF should not contain optional config OBUs")
+ section = "av1c-contains-optional-config-obus"
+ for key, value in generated_av1c.items():
+ if existing_av1c[key] != value:
+ severity = "CRITICAL"
+ description = (
+ f"av1C[{key}] does not match Sequence Header OBU. "
+ + f"'{existing_av1c[key]}' != '{value}'."
+ )
+ issue.add_issue(severity, description)
+ section = "bad-av1c"
+ if len(issue.issues) == 0:
+ return []
+
+ def _fix_av1c() -> None:
+ parsed_file.replace_property_for_item(BoxType("av1C"), {}, generated_av1c, item_id)
+
+ issue.add_info_url(section)
+ issue.add_fix(_fix_av1c, "Regenerate av1C from Sequence Header OBU")
+ return [issue]
+
+
+def validate_colr_property(
+ parsed_file: ParsedFile,
+ item: dict[str, Any],
+ default_nclx: dict[str, list[int]],
+ generated_nclx: Optional[BoxBody] = None,
+) -> list[BoxIssue]:
+ """Validates that colr properties are correct for an item."""
+ if generated_nclx is None:
+ generated_nclx = item["av01_stream"].generate_nclx_from_sequence_header()
+ assert generated_nclx, "Failed to create NCLX property from av01"
+
+ existing_nclx = None
+ existing_icc = None
+ is_aux_item = False
+ for prop, _ in item["item_properties"]:
+ if prop.type == "colr":
+ if prop.body["type"] == "nclx":
+ existing_nclx = prop.body
+ elif prop.body["type"] in ["rICC", "prof"]:
+ existing_icc = prop.body
+ elif prop.type == "auxC":
+ is_aux_item = True
+
+ issue = BoxIssue(item["item_id"], "colr")
+
+ if is_aux_item:
+ # TODO: Figure out what is correct here. Some stuff may only apply to alpha.
+ pass
+ elif existing_nclx is None:
+ severity = "RENDERING DIFFERENCES"
+ template = (
+ "Item lacks {} and Sequence Header OBU specifies {} = {}. "
+ + "This may not render correctly in all implementations."
+ )
+ missing = "nclx-colr box" if existing_icc else "any colr box"
+
+ specified_by_icc = ["color_primaries", "transfer_characteristics"] if existing_icc else []
+ for key, val in default_nclx.items():
+ if key in specified_by_icc:
+ continue
+ if generated_nclx[key] not in val:
+ issue.add_issue(severity, template.format(missing, key, generated_nclx[key]))
+ if len(issue.issues) == 0:
+ return []
+
+ if existing_icc:
+ # If we have existing ICC profile, we only want to add NCLX for matrix and full/video-range
+ generated_nclx["color_primaries"] = 2
+ generated_nclx["transfer_characteristics"] = 2
+ elif existing_nclx is None:
+ # If we have no colr box, and Sequence Header does not specify color,
+ # explicitly set to the defaults.
+ for key, value in default_nclx.items():
+ if key == "full_range_flag":
+ continue
+ if generated_nclx[key] == 2:
+ generated_nclx[key] = value[0]
+
+ def _fix_colr() -> None:
+ assert generated_nclx
+ parsed_file.add_property_for_item(
+ BoxType("colr"), {}, generated_nclx, item["item_id"], True
+ )
+
+ order = [
+ "color_primaries",
+ "transfer_characteristics",
+ "matrix_coefficients",
+ "full_range_flag",
+ ]
+ nclx_string = ",".join(str(generated_nclx[key]) for key in order)
+ description = f"Add 'colr' box of type 'nclx', with values {nclx_string}"
+ if existing_icc:
+ description = (
+ "Add second 'colr' box of type 'nclx' "
+ + f"(in addition to existing ICC box), with values {nclx_string}"
+ )
+
+ url_section = "missing-nclx-colr-box" if existing_icc else "missing-colr-box"
+ issue.add_info_url(url_section)
+ issue.add_fix(_fix_colr, description)
+ return [issue]
+
+
+def validate_pixi_property(
+ parsed_file: ParsedFile, item: dict[str, Any], generated_pixi: Optional[BoxBody] = None
+) -> list[BoxIssue]:
+ """Validates that pixi property is present and correct for an item."""
+ item_id = item["item_id"]
+ if generated_pixi is None:
+ generated_pixi = item["av01_stream"].generate_pixi_from_sequence_header()
+ assert generated_pixi, "Failed to create pixi from av01"
+ existing_pixi = None
+ for prop, _ in item["item_properties"]:
+ if prop.type == "pixi":
+ existing_pixi = prop.body
+ break
+
+ if existing_pixi == generated_pixi:
+ return []
+
+ issue = BoxIssue(item_id, "pixi")
+ severity = "WARNING"
+ if existing_pixi is None:
+ description = "No 'pixi' present. This is a requirement by MIAF."
+ else:
+ description = (
+ "'pixi' does not match AV1 Sequence Header OBU."
+ + f" {existing_pixi} != {generated_pixi}."
+ )
+ issue.add_issue(severity, description)
+
+ def _fix_pixi() -> None:
+ assert generated_pixi
+ header = {"version": 0, "flags": 0}
+ if existing_pixi is not None:
+ parsed_file.replace_property_for_item(BoxType("pixi"), header, generated_pixi, item_id)
+ else:
+ parsed_file.add_property_for_item(
+ BoxType("pixi"), header, generated_pixi, item_id, False
+ )
+
+ action_string = "Regenerate" if existing_pixi else "Add"
+ issue.add_info_url("missing-or-incorrect-pixi")
+ issue.add_fix(_fix_pixi, f"{action_string} pixi from Sequence Header OBU")
+ return [issue]
+
+
+def validate_lsel_property(parsed_file: ParsedFile, item: dict[str, Any]) -> list[BoxIssue]:
+ """Validates that lsel property is present for items with a1lx properties."""
+ item_id = item["item_id"]
+ is_multilayer = False
+ has_lsel = False
+ for prop, _ in item["item_properties"]:
+ if prop.type in ["a1lx", "a1op"]:
+ is_multilayer = True
+ elif prop.type == "lsel":
+ has_lsel = True
+
+ if is_multilayer == has_lsel or not is_multilayer:
+ return []
+
+ issue = BoxIssue(item_id, "lsel")
+ severity = "CRITICAL"
+ issue.add_issue(
+ severity,
+ "'a1lx' or 'a1op' property present, but 'lsel' not present. "
+ + "'lsel' is required for multilayer content.",
+ )
+
+ def _fix_lsel() -> None:
+ body: BoxBody = {"serialized": write_integer_of_size(0xFFFF, 2)}
+ parsed_file.add_property_for_item(BoxType("lsel"), {}, body, item_id, True)
+
+ issue.add_fix(_fix_lsel, "Add 0xFFFF 'lsel' property.")
+ return [issue]
+
+
+def validate_ispe_property(parsed_file: ParsedFile, item: dict[str, Any]) -> list[BoxIssue]:
+ """Validates that ispe property is present and comes before any transformational properties."""
+ generated_ispe = item["av01_stream"].generate_ispe_from_sequence_header()
+ assert generated_ispe, "Could not generate ispe from av01"
+ item_id = item["item_id"]
+ ispe_index = None
+ first_transform_index = None
+ for index, (prop, _) in enumerate(item["item_properties"]):
+ if prop.type in ["clap", "imir", "irot"] and first_transform_index is None:
+ first_transform_index = index
+ elif prop.type == "ispe":
+ ispe_index = index
+
+ issues = []
+ if ispe_index is None:
+ issue = BoxIssue(item_id, "ispe")
+ severity = "CRITICAL"
+ issue.add_issue(severity, "Image item lacks 'ispe' property.")
+
+ def _fix_add_ispe() -> None:
+ assert generated_ispe
+ parsed_file.add_property_for_item(
+ BoxType("ispe"),
+ {"version": 0, "flags": 0},
+ generated_ispe,
+ item_id,
+ True,
+ position=0,
+ )
+
+ issue.add_info_url("missing-ispe")
+ issue.add_fix(
+ _fix_add_ispe,
+ "Add 'ispe' with dimensions "
+ + f"{generated_ispe['width']}x{generated_ispe['height']}.",
+ )
+ issues.append(issue)
+ elif first_transform_index and ispe_index > first_transform_index:
+ issue = BoxIssue(item_id, "ispe")
+ severity = "WARNING"
+ issue.add_issue(severity, "'ispe' property comes after transformational properties.")
+
+ def _fix_ispe_order() -> None:
+ ispe_box = item["item_properties"][ispe_index][0]
+ ipco_index = parsed_file.get_existing_property_if_present(
+ BoxType("ispe"), ispe_box.header, ispe_box.body
+ )
+ parsed_file.remove_property_associations(item_id, BoxType("ispe"))
+ parsed_file.add_property_association(item_id, ipco_index, True, position=0)
+
+ issue.add_info_url("ispe-comes-after-transformational-properties")
+ issue.add_fix(
+ _fix_ispe_order, "Change order of property associations to place 'ispe' first."
+ )
+ issues.append(issue)
+ return issues
+
+
+def validate_clap_property(parsed_file: ParsedFile, item: dict[str, Any]) -> list[BoxIssue]:
+ """Validates that clap property is contained within the image spatial extents."""
+ item_id = item["item_id"]
+ ispe_box = None
+ clap_box = None
+ incorrect_order = False
+ for index, (prop, _) in enumerate(item["item_properties"]):
+ if prop.type in ["imir", "irot"] and clap_box is None:
+ incorrect_order = True
+ elif prop.type == "ispe":
+ ispe_box = prop
+ elif prop.type == "clap":
+ clap_box = prop
+
+ if clap_box is None:
+ return []
+ if ispe_box is None:
+ print("WARNING: Found 'clap' box but no 'ispe'. First fix file by adding 'ispe'.")
+ return []
+ if incorrect_order:
+ print(
+ "WARNING: 'clap' property comes after 'imir'/'irot'. "
+ + "Validating 'clap' for files like this is unsupported."
+ )
+ return []
+
+ def _origin_from_clap(image_dim: float, clap_dim: float, clap_offs: float) -> float:
+ return clap_offs + (image_dim - clap_dim) / 2
+
+ def _offset_from_crop(image_dim: float, clap_dim: float, origin: float) -> float:
+ return origin + (clap_dim - image_dim) / 2
+
+ ispe_dimensions = [ispe_box.body["width"], ispe_box.body["height"]]
+ offset = [
+ float_from_rational(clap_box.body["h_offset"]),
+ float_from_rational(clap_box.body["v_offset"]),
+ ]
+ dimensions = [
+ float_from_rational(clap_box.body["width"]),
+ float_from_rational(clap_box.body["height"]),
+ ]
+ origin = [
+ _origin_from_clap(ispe_dimensions[index], dimensions[index], offset[index])
+ for index in range(2)
+ ]
+ trunc_origin = [int(val) for val in origin]
+
+ issues = []
+ if any(val < 0 for val in trunc_origin):
+ issue = BoxIssue(item_id, "clap")
+ issue.add_issue("CRITICAL", f"'clap' origin is negative. {origin[0]}x{origin[1]}")
+ issues.append(issue)
+ elif any(abs(val1 - val2) > 0.0001 for val1, val2 in zip(origin, trunc_origin)):
+ issue = BoxIssue(item_id, "clap")
+ severity = "CRITICAL"
+ if all(origin[index] + dimensions[index] <= ispe_dimensions[index] for index in range(2)):
+ severity = "WARNING"
+ issue.add_issue(severity, f"'clap' origin is not integer valued. {origin[0]}x{origin[1]}")
+ fixed_offset = [
+ _offset_from_crop(ispe_dimensions[index], dimensions[index], trunc_origin[index])
+ for index in range(2)
+ ]
+
+ def _fix_clap_origin() -> None:
+ assert clap_box
+ fixed_clap = clap_box.body.copy()
+ fixed_clap["h_offset"] = [round(fixed_offset[0] * 2), 2]
+ fixed_clap["v_offset"] = [round(fixed_offset[1] * 2), 2]
+ parsed_file.replace_property_for_item(BoxType("clap"), {}, fixed_clap, item_id)
+
+ issue.add_fix(
+ _fix_clap_origin, f"Truncate 'clap' origin to {trunc_origin[0]}x{trunc_origin[1]}"
+ )
+ issues.append(issue)
+
+ if any(trunc_origin[index] + dimensions[index] > ispe_dimensions[index] for index in range(2)):
+ issue = BoxIssue(item_id, "clap")
+ severity = "CRITICAL"
+ issue.add_issue(severity, "'clap' property is out of bounds.")
+ issues.append(issue)
+ return issues
+
+
+def validate_grid_item(
+ parsed_file: ParsedFile, item: dict[str, Any], default_nclx: dict[str, list[int]]
+) -> list[BoxIssue]:
+ """Validates that a grid item is correct."""
+ item_id = item["item_id"]
+ iref_box = parsed_file.get_box_from_hierarchy(["meta", "iref"])
+ if iref_box is None or iref_box.sub_boxes is None:
+ return []
+ tile_items = None
+ for ref in iref_box.sub_boxes:
+ if ref.type == "dimg" and ref.body["from_item_ID"] == item_id:
+ tile_items = ref.body["to_item_ID"]
+ break
+ assert tile_items is not None, "Could not find tile references for grid item"
+
+ items = parsed_file.get_items()
+ first_av1c = items[tile_items[0]]["av01_stream"].generate_av1c_from_sequence_header()
+ for tile_item_id in tile_items[1:]:
+ other_av1c = items[tile_item_id]["av01_stream"].generate_av1c_from_sequence_header()
+ assert first_av1c == other_av1c, "Not all tiles in a grid have the same av1C"
+
+ issues = []
+ generated_nclx = items[tile_items[0]]["av01_stream"].generate_nclx_from_sequence_header()
+ generated_pixi = items[tile_items[0]]["av01_stream"].generate_pixi_from_sequence_header()
+ issues += validate_colr_property(parsed_file, item, default_nclx, generated_nclx)
+ issues += validate_pixi_property(parsed_file, item, generated_pixi)
+ return issues
+
+
+def validate_av01_item(
+ parsed_file: ParsedFile, item: dict[str, Any], default_nclx: dict[str, list[int]]
+) -> list[BoxIssue]:
+ """Validates that an av01 item is correct."""
+ issues = []
+ issues += validate_av1c_property(parsed_file, item)
+ issues += validate_colr_property(parsed_file, item, default_nclx)
+ issues += validate_pixi_property(parsed_file, item)
+ issues += validate_lsel_property(parsed_file, item)
+ issues += validate_ispe_property(parsed_file, item)
+ issues += validate_clap_property(parsed_file, item)
+ return issues
+
+
+def validate_primary_item(parsed_file: ParsedFile) -> list[BoxIssue]:
+ """Validates that 'meta' box contains a primary item."""
+ issues: list[BoxIssue] = []
+
+ meta_box = parsed_file.get_box_from_hierarchy(["meta"])
+ pitm_box = parsed_file.get_box_from_hierarchy(["meta", "pitm"])
+
+ if pitm_box is None and meta_box is not None:
+ # Get item ID of first non-hidden item
+ item_id = None
+ for cur_id, item in parsed_file.get_items().items():
+ if item["infe"].header["flags"] == 0:
+ item_id = cur_id
+ break
+ assert item_id is not None, "Could not find any non-hidden item"
+ issue = BoxIssue(item_id, "pitm")
+ issue.add_issue("CRITICAL", "No primary item found.")
+
+ def _fix_pitm() -> None:
+ assert meta_box
+ assert item_id is not None
+ pitm_box = Box(BoxType("pitm"), parent=meta_box, size=0, start=0)
+ version = 0 if item_id <= 0xFFFF else 1
+ pitm_box.header = {"version": version, "flags": 0}
+ pitm_box.body = {"item_id": item_id}
+ if meta_box.sub_boxes is not None:
+ meta_box.sub_boxes.append(pitm_box)
+ else:
+ meta_box.sub_boxes = [pitm_box]
+ pitm_box.mark_for_rewrite()
+
+ issue.add_fix(_fix_pitm, "Add primary item to first non-hidden item in file")
+ issues.append(issue)
+ return issues
+
+
+def validate_regular_track(parsed_file: ParsedFile, track: Box) -> list[BoxIssue]:
+ """Validates that a non-auxiliary track is correct."""
+ issues: list[BoxIssue] = []
+ if track.sub_boxes is None:
+ return issues
+ tkhd_box = parsed_file.get_box_from_hierarchy(["tkhd"], track.sub_boxes)
+ hdlr_box = parsed_file.get_box_from_hierarchy(["mdia", "hdlr"], track.sub_boxes)
+ if tkhd_box is None or hdlr_box is None:
+ return issues
+ track_id = tkhd_box.body["track_id"]
+
+ # TODO: Add checks for 'vide' tracks
+ if hdlr_box.body["hdlr_type"] != "pict":
+ return issues
+
+ if tkhd_box.header["flags"] & 0x2 == 0:
+ issue = BoxIssue(track_id, "tkhd", is_track=True)
+ issue.add_issue(
+ "WARNING",
+ "'pict' track has track_in_movie flag set to false. "
+ + "Some parsers may ignore this track.",
+ )
+
+ def _fix_tkhd() -> None:
+ assert tkhd_box
+ tkhd_box.header["flags"] |= 0x2
+ tkhd_box.mark_for_rewrite()
+
+ issue.add_info_url("incorrect-value-for-track_in_movie-flag")
+ issue.add_fix(_fix_tkhd, "Set track_in_movie flag to true.")
+ issues.append(issue)
+
+ av01_box = parsed_file.get_box_from_hierarchy(
+ ["mdia", "minf", "stbl", "stsd", "av01"], track.sub_boxes
+ )
+ if av01_box is not None:
+ ccst_box = parsed_file.get_box_from_hierarchy(["ccst"], av01_box.sub_boxes)
+ if ccst_box is None:
+ issue = BoxIssue(track_id, "av01", is_track=True)
+ issue.add_issue("WARNING", "'ccst' not present in sample entry.")
+
+ def _fix_ccst() -> None:
+ assert av01_box and av01_box.sub_boxes
+ ccst_box = Box(BoxType("ccst"), av01_box, 0, 0)
+ ccst_box.header = {"version": 0, "flags": 0}
+ # TODO: Populate this with less permissive values from the stss
+ ccst_box.body = {
+ "all_ref_pics_intra": 0,
+ "intra_pred_used": 1,
+ "max_ref_per_pic": 15,
+ }
+ av01_box.sub_boxes.append(ccst_box)
+ ccst_box.mark_for_rewrite()
+
+ issue.add_info_url("ccst-not-present-for-pict-track")
+ issue.add_fix(_fix_ccst, "Add most permissive 'ccst' box")
+ issues.append(issue)
+
+ return issues
+
+
+def validate_aux_track(parsed_file: ParsedFile, track: Box) -> list[BoxIssue]:
+ """Validates that an auxiliary track is correct."""
+ issues: list[BoxIssue] = []
+ if track.sub_boxes is None:
+ return issues
+ tkhd_box = parsed_file.get_box_from_hierarchy(["tkhd"], track.sub_boxes)
+ hdlr_box = parsed_file.get_box_from_hierarchy(["mdia", "hdlr"], track.sub_boxes)
+ if tkhd_box is None or hdlr_box is None:
+ return issues
+ track_id = tkhd_box.body["track_id"]
+
+ hdlr_type = hdlr_box.body["hdlr_type"]
+ if hdlr_type != "auxv":
+ issue = BoxIssue(track_id, "hdlr", is_track=True)
+ issue.add_issue(
+ "CRITICAL", "Handler type for auxiliary track is " + f"'{hdlr_type}', not 'auxv'"
+ )
+
+ def _fix_hdlr() -> None:
+ assert hdlr_box
+ hdlr_box.body["hdlr_type"] = "auxv"
+ hdlr_box.mark_for_rewrite()
+
+ issue.add_info_url("incorrect-track-handler-type-for-auxiliary-track")
+ issue.add_fix(_fix_hdlr, "Change handler type to auxv")
+ issues.append(issue)
+
+ av01_box = parsed_file.get_box_from_hierarchy(
+ ["mdia", "minf", "stbl", "stsd", "av01"], track.sub_boxes
+ )
+ if av01_box is not None:
+ auxi_box = parsed_file.get_box_from_hierarchy(["auxi"], av01_box.sub_boxes)
+ if auxi_box is None:
+ issue = BoxIssue(track_id, "av01", is_track=True)
+ issue.add_issue(
+ "WARNING",
+ "'auxi' not present in sample entry. Most readers will assume track is alpha.",
+ )
+
+ def _fix_auxi() -> None:
+ assert av01_box and av01_box.sub_boxes
+ auxi_box = Box(BoxType("auxi"), av01_box, 0, 0)
+ auxi_box.header = {"version": 0, "flags": 0}
+ auxi_box.body = {"aux_track_type": "urn:mpeg:mpegB:cicp:systems:auxiliary:alpha"}
+ av01_box.sub_boxes.append(auxi_box)
+ auxi_box.mark_for_rewrite()
+
+ issue.add_info_url("auxi-not-present-for-auxv-track")
+ issue.add_fix(_fix_auxi, "Add alpha 'auxi' box")
+ issues.append(issue)
+
+ if tkhd_box.header["flags"] & 0x2:
+ issue = BoxIssue(track_id, "tkhd", is_track=True)
+ issue.add_issue(
+ "WARNING",
+ "Auxiliary track has track_in_movie flag set to true. "
+ + "Some parsers may treat this track as directly displayable.",
+ )
+
+ def _fix_tkhd() -> None:
+ assert tkhd_box
+ tkhd_box.header["flags"] &= ~0x2
+ tkhd_box.mark_for_rewrite()
+
+ issue.add_info_url("incorrect-value-for-track_in_movie-flag")
+ issue.add_fix(_fix_tkhd, "Set track_in_movie flag to false.")
+ issues.append(issue)
+
+ return issues
+
+
+def validate_track(parsed_file: ParsedFile, track: Box) -> list[BoxIssue]:
+ """Validates that a track is correct."""
+ issues = []
+ is_aux_track = (
+ parsed_file.get_box_from_hierarchy(["tref", "auxl"], box_array=track.sub_boxes) is not None
+ )
+ if is_aux_track:
+ issues += validate_aux_track(parsed_file, track)
+ else:
+ issues += validate_regular_track(parsed_file, track)
+ return issues
+
+
+def validate_file(parsed_file: ParsedFile, default_nclx: dict[str, list[int]]) -> list[BoxIssue]:
+ """Validates that an AVIF file is correct."""
+ items = parsed_file.get_items()
+ issues = []
+ for _, item in items.items():
+ item_type = item["infe"].body["item_type"]
+ if item_type == "av01":
+ issues += validate_av01_item(parsed_file, item, default_nclx)
+ elif item_type == "grid":
+ issues += validate_grid_item(parsed_file, item, default_nclx)
+
+ issues += validate_primary_item(parsed_file)
+
+ moov_box = parsed_file.get_box_from_hierarchy(["moov"])
+ if moov_box and moov_box.sub_boxes:
+ for box in moov_box.sub_boxes:
+ if box.type != "trak":
+ continue
+ issues += validate_track(parsed_file, box)
+
+ issues += validate_profile_brands(parsed_file)
+ return issues
+
+
+# ===========================================
+# Entry point
+# ===========================================
+def query_issues(all_issues: list[BoxIssue], interactive_prompt: bool = False) -> list[BoxIssue]:
+ """Prints issues and optionally queries whether any should be ignored."""
+ filtered_issues = []
+ if interactive_prompt:
+ for issue in all_issues:
+ issue.print(0)
+ if input("Fix (Y/n)?: ").lower() == "n":
+ print_indent(0, "Skipping fix")
+ else:
+ filtered_issues.append(issue)
+ else:
+ # Try to condense the list into single issues that apply to multiple items
+ def issue_applier(
+ condenser: dict[int, list[BoxIssue]], issue: BoxIssue
+ ) -> dict[int, list[BoxIssue]]:
+ key = issue.issue_hash()
+ if key in condenser:
+ condenser[key].append(issue)
+ else:
+ condenser[key] = [issue]
+ return condenser
+
+ condensed_issues: dict[int, list[BoxIssue]] = {}
+ reduce(issue_applier, all_issues, condensed_issues)
+ for issue_list in condensed_issues.values():
+ issue_list[0].print(0, issue_list[1:])
+
+ filtered_issues = all_issues
+
+ return filtered_issues
+
+
+def process(args: argparse.Namespace) -> None:
+ """Process file."""
+ if not args.dry_run and args.dst_file is None:
+ print("'dst_file' must be specified if --dry-run is not set")
+ sys.exit(1)
+
+ if args.dry_run and args.interactive:
+ print("'dry-run' and 'interactive' are mutually exclusive")
+ sys.exit(1)
+
+ if args.src_file == args.dst_file:
+ print("'src_file' and 'dst_file' must be different files")
+ sys.exit(1)
+
+ default_nclx = {
+ "color_primaries": [1],
+ "transfer_characteristics": [13],
+ "matrix_coefficients": [6, 5],
+ "full_range_flag": [1],
+ }
+ if args.nclx_default is not None:
+ default_nclx["matrix_coefficients"] = [args.nclx_default[0]]
+ default_nclx["transfer_characteristics"] = [args.nclx_default[1]]
+ default_nclx["matrix_coefficients"] = [args.nclx_default[2]]
+ default_nclx["full_range_flag"] = [args.nclx_default[3]]
+
+ with open(args.src_file, "rb") as file:
+ parsed_file = ParsedFile(file, args.verbose)
+ issues = validate_file(parsed_file, default_nclx)
+
+ if args.verbose or args.interactive:
+ issues = query_issues(issues, args.interactive)
+
+ if args.dry_run:
+ if len(issues) > 0:
+ sys.exit(2)
+ sys.exit(0)
+
+ for issue in issues:
+ issue.apply_fix()
+
+ with open(args.dst_file, "wb") as output_file:
+ writer = AVIFWriter(parsed_file, output_file)
+ writer.write()
+
+
+HELP_TEXT = """Sanitize AVIF files without recompression.
+
+This script fixes some commonly identified container level issues in AVIF files.
+It is not exhaustive and should not be considered a replacement for the AVIF
+compliance warden available here:
+https://gpac.github.io/ComplianceWarden-wasm/avif.html
+
+It will not identify or fix issues that requires recompression.
+"""
+
+if __name__ == "__main__":
+
+ parser = argparse.ArgumentParser(
+ description=HELP_TEXT, formatter_class=argparse.RawDescriptionHelpFormatter
+ )
+ parser.add_argument(
+ "-o",
+ "--dry-run",
+ action="store_true",
+ help="Don't rewrite file, only check for known issues. Returns "
+ + "code 2 if errors are found.",
+ )
+ parser.add_argument("-v", "--verbose", action="store_true", help="Verbose output")
+ parser.add_argument(
+ "-i",
+ "--interactive",
+ action="store_true",
+ help="Ask whether a specific issue should be fixed or not",
+ )
+ parser.add_argument(
+ "-n",
+ "--nclx-default",
+ nargs=4,
+ type=int,
+ help="When adding missing nclx colr box, "
+ + "use these values instead of the default values of 1,13,6,1",
+ )
+ parser.add_argument("src_file", help="The source file")
+ parser.add_argument(
+ "dst_file", nargs="?", help="The destination file (required unless -o is set)"
+ )
+
+ process(parser.parse_args())
From 96fe1743b499deca7634b5cc7092c2783eb47831 Mon Sep 17 00:00:00 2001
From: Leo Barnes
Date: Tue, 10 Sep 2024 12:15:00 +0200
Subject: [PATCH 16/65] Fix Link-U files (closes #196) Also fix crash in
sanitizer for some profile 2 files
testFiles/Link-U/hato.profile0.10bpc.yuv420.monochrome.no-cdef.no-restoration.avif
testFiles/Link-U/hato.profile0.8bpc.yuv420.monochrome.no-cdef.avif
testFiles/Link-U/hato.profile2.10bpc.yuv422.monochrome.no-cdef.no-restoration.avif
testFiles/Link-U/hato.profile2.8bpc.yuv422.monochrome.no-cdef.avif
Remove optional config OBUs
Insert default colr box
Fix incorrect pixi
testFiles/Link-U/fox.profile2.10bpc.yuv422.avif
testFiles/Link-U/fox.profile2.10bpc.yuv422.odd-height.avif
testFiles/Link-U/fox.profile2.10bpc.yuv422.odd-width.avif
testFiles/Link-U/fox.profile2.10bpc.yuv422.odd-width.odd-height.avif
testFiles/Link-U/fox.profile2.12bpc.yuv422.avif
testFiles/Link-U/fox.profile2.12bpc.yuv422.odd-height.avif
testFiles/Link-U/fox.profile2.12bpc.yuv422.odd-width.avif
testFiles/Link-U/fox.profile2.12bpc.yuv422.odd-width.odd-height.avif
testFiles/Link-U/hato.profile2.10bpc.yuv422.no-cdef.no-restoration.avif
testFiles/Link-U/hato.profile2.12bpc.yuv422.monochrome.no-cdef.no-restoration.avif
testFiles/Link-U/hato.profile2.12bpc.yuv422.no-cdef.no-restoration.avif
testFiles/Link-U/fox.profile2.8bpc.yuv422.avif
testFiles/Link-U/fox.profile2.8bpc.yuv422.odd-height.avif
testFiles/Link-U/fox.profile2.8bpc.yuv422.odd-width.avif
testFiles/Link-U/fox.profile2.8bpc.yuv422.odd-width.odd-height.avif
Update av1C: av1C[chroma_subsampling_x] does not match Sequence Header OBU. '0' != '1'
Remove optional config OBUs
Insert default colr box
testFiles/Link-U/fox.profile0.10bpc.yuv420.avif
testFiles/Link-U/fox.profile0.10bpc.yuv420.monochrome.avif
testFiles/Link-U/fox.profile0.10bpc.yuv420.monochrome.odd-height.avif
testFiles/Link-U/fox.profile0.10bpc.yuv420.monochrome.odd-width.avif
testFiles/Link-U/fox.profile0.10bpc.yuv420.monochrome.odd-width.odd-height.avif
testFiles/Link-U/fox.profile0.10bpc.yuv420.odd-height.avif
testFiles/Link-U/fox.profile0.10bpc.yuv420.odd-width.avif
testFiles/Link-U/fox.profile0.10bpc.yuv420.odd-width.odd-height.avif
testFiles/Link-U/fox.profile0.8bpc.yuv420.avif
testFiles/Link-U/fox.profile0.8bpc.yuv420.monochrome.avif
testFiles/Link-U/fox.profile0.8bpc.yuv420.monochrome.odd-height.avif
testFiles/Link-U/fox.profile0.8bpc.yuv420.monochrome.odd-width.avif
testFiles/Link-U/fox.profile0.8bpc.yuv420.monochrome.odd-width.odd-height.avif
testFiles/Link-U/fox.profile0.8bpc.yuv420.odd-height.avif
testFiles/Link-U/fox.profile0.8bpc.yuv420.odd-width.avif
testFiles/Link-U/fox.profile0.8bpc.yuv420.odd-width.odd-height.avif
testFiles/Link-U/fox.profile1.10bpc.yuv444.avif
testFiles/Link-U/fox.profile1.10bpc.yuv444.odd-height.avif
testFiles/Link-U/fox.profile1.10bpc.yuv444.odd-width.avif
testFiles/Link-U/fox.profile1.10bpc.yuv444.odd-width.odd-height.avif
testFiles/Link-U/fox.profile1.8bpc.yuv444.avif
testFiles/Link-U/fox.profile1.8bpc.yuv444.odd-height.avif
testFiles/Link-U/fox.profile1.8bpc.yuv444.odd-width.avif
testFiles/Link-U/fox.profile1.8bpc.yuv444.odd-width.odd-height.avif
testFiles/Link-U/fox.profile2.10bpc.yuv422.avif
testFiles/Link-U/fox.profile2.10bpc.yuv422.monochrome.avif
testFiles/Link-U/fox.profile2.10bpc.yuv422.monochrome.odd-height.avif
testFiles/Link-U/fox.profile2.10bpc.yuv422.monochrome.odd-width.avif
testFiles/Link-U/fox.profile2.10bpc.yuv422.monochrome.odd-width.odd-height.avif
testFiles/Link-U/fox.profile2.12bpc.yuv420.avif
testFiles/Link-U/fox.profile2.12bpc.yuv420.monochrome.avif
testFiles/Link-U/fox.profile2.12bpc.yuv420.monochrome.odd-height.avif
testFiles/Link-U/fox.profile2.12bpc.yuv420.monochrome.odd-width.avif
testFiles/Link-U/fox.profile2.12bpc.yuv420.monochrome.odd-width.odd-height.avif
testFiles/Link-U/fox.profile2.12bpc.yuv420.odd-height.avif
testFiles/Link-U/fox.profile2.12bpc.yuv420.odd-width.avif
testFiles/Link-U/fox.profile2.12bpc.yuv420.odd-width.odd-height.avif
testFiles/Link-U/fox.profile2.12bpc.yuv422.monochrome.avif
testFiles/Link-U/fox.profile2.12bpc.yuv422.monochrome.odd-height.avif
testFiles/Link-U/fox.profile2.12bpc.yuv422.monochrome.odd-width.avif
testFiles/Link-U/fox.profile2.12bpc.yuv422.monochrome.odd-width.odd-height.avif
testFiles/Link-U/fox.profile2.12bpc.yuv444.avif
testFiles/Link-U/fox.profile2.12bpc.yuv444.monochrome.avif
testFiles/Link-U/fox.profile2.12bpc.yuv444.monochrome.odd-height.avif
testFiles/Link-U/fox.profile2.12bpc.yuv444.monochrome.odd-width.avif
testFiles/Link-U/fox.profile2.12bpc.yuv444.monochrome.odd-width.odd-height.avif
testFiles/Link-U/fox.profile2.12bpc.yuv444.odd-height.avif
testFiles/Link-U/fox.profile2.12bpc.yuv444.odd-width.avif
testFiles/Link-U/fox.profile2.12bpc.yuv444.odd-width.odd-height.avif
testFiles/Link-U/fox.profile2.8bpc.yuv422.monochrome.avif
testFiles/Link-U/fox.profile2.8bpc.yuv422.monochrome.odd-height.avif
testFiles/Link-U/fox.profile2.8bpc.yuv422.monochrome.odd-width.avif
testFiles/Link-U/fox.profile2.8bpc.yuv422.monochrome.odd-width.odd-height.avif
testFiles/Link-U/hato.profile0.10bpc.yuv420.no-cdef.no-restoration.avif
testFiles/Link-U/hato.profile0.8bpc.yuv420.no-cdef.avif
testFiles/Link-U/hato.profile2.12bpc.yuv422.monochrome.avif
Remove optional config OBUs
Insert default colr box
---
Tools/sanitize_avif.py | 3 ++-
.../Link-U/fox.profile0.10bpc.yuv420.avif | Bin 64420 -> 64431 bytes
.../fox.profile0.10bpc.yuv420.monochrome.avif | Bin 56436 -> 56447 bytes
...e0.10bpc.yuv420.monochrome.odd-height.avif | Bin 55494 -> 55505 bytes
...le0.10bpc.yuv420.monochrome.odd-width.avif | Bin 55574 -> 55585 bytes
...uv420.monochrome.odd-width.odd-height.avif | Bin 54909 -> 54920 bytes
.../fox.profile0.10bpc.yuv420.odd-height.avif | Bin 63584 -> 63595 bytes
.../fox.profile0.10bpc.yuv420.odd-width.avif | Bin 63764 -> 63775 bytes
...le0.10bpc.yuv420.odd-width.odd-height.avif | Bin 62941 -> 62952 bytes
.../Link-U/fox.profile0.8bpc.yuv420.avif | Bin 63479 -> 63490 bytes
.../fox.profile0.8bpc.yuv420.monochrome.avif | Bin 55649 -> 55660 bytes
...le0.8bpc.yuv420.monochrome.odd-height.avif | Bin 54696 -> 54707 bytes
...ile0.8bpc.yuv420.monochrome.odd-width.avif | Bin 54780 -> 54791 bytes
...uv420.monochrome.odd-width.odd-height.avif | Bin 54156 -> 54167 bytes
.../fox.profile0.8bpc.yuv420.odd-height.avif | Bin 62773 -> 62784 bytes
.../fox.profile0.8bpc.yuv420.odd-width.avif | Bin 62857 -> 62868 bytes
...ile0.8bpc.yuv420.odd-width.odd-height.avif | Bin 62272 -> 62283 bytes
.../Link-U/fox.profile1.10bpc.yuv444.avif | Bin 75067 -> 75078 bytes
.../fox.profile1.10bpc.yuv444.odd-height.avif | Bin 73534 -> 73545 bytes
.../fox.profile1.10bpc.yuv444.odd-width.avif | Bin 73588 -> 73599 bytes
...le1.10bpc.yuv444.odd-width.odd-height.avif | Bin 72701 -> 72712 bytes
.../Link-U/fox.profile1.8bpc.yuv444.avif | Bin 74224 -> 74235 bytes
.../fox.profile1.8bpc.yuv444.odd-height.avif | Bin 72800 -> 72811 bytes
.../fox.profile1.8bpc.yuv444.odd-width.avif | Bin 73091 -> 73102 bytes
...ile1.8bpc.yuv444.odd-width.odd-height.avif | Bin 72117 -> 72128 bytes
.../Link-U/fox.profile2.10bpc.yuv422.avif | Bin 68842 -> 68853 bytes
.../fox.profile2.10bpc.yuv422.monochrome.avif | Bin 56432 -> 56443 bytes
...e2.10bpc.yuv422.monochrome.odd-height.avif | Bin 55490 -> 55501 bytes
...le2.10bpc.yuv422.monochrome.odd-width.avif | Bin 55570 -> 55581 bytes
...uv422.monochrome.odd-width.odd-height.avif | Bin 54905 -> 54916 bytes
.../fox.profile2.10bpc.yuv422.odd-height.avif | Bin 67920 -> 67931 bytes
.../fox.profile2.10bpc.yuv422.odd-width.avif | Bin 68121 -> 68132 bytes
...le2.10bpc.yuv422.odd-width.odd-height.avif | Bin 67112 -> 67123 bytes
.../Link-U/fox.profile2.12bpc.yuv420.avif | Bin 65007 -> 65017 bytes
.../fox.profile2.12bpc.yuv420.monochrome.avif | Bin 56967 -> 56978 bytes
...e2.12bpc.yuv420.monochrome.odd-height.avif | Bin 55877 -> 55888 bytes
...le2.12bpc.yuv420.monochrome.odd-width.avif | Bin 55995 -> 56006 bytes
...uv420.monochrome.odd-width.odd-height.avif | Bin 55252 -> 55263 bytes
.../fox.profile2.12bpc.yuv420.odd-height.avif | Bin 64033 -> 64043 bytes
.../fox.profile2.12bpc.yuv420.odd-width.avif | Bin 64110 -> 64120 bytes
...le2.12bpc.yuv420.odd-width.odd-height.avif | Bin 63464 -> 63474 bytes
.../Link-U/fox.profile2.12bpc.yuv422.avif | Bin 69372 -> 69383 bytes
.../fox.profile2.12bpc.yuv422.monochrome.avif | Bin 56967 -> 56978 bytes
...e2.12bpc.yuv422.monochrome.odd-height.avif | Bin 55877 -> 55888 bytes
...le2.12bpc.yuv422.monochrome.odd-width.avif | Bin 55995 -> 56006 bytes
...uv422.monochrome.odd-width.odd-height.avif | Bin 55252 -> 55263 bytes
.../fox.profile2.12bpc.yuv422.odd-height.avif | Bin 68110 -> 68121 bytes
.../fox.profile2.12bpc.yuv422.odd-width.avif | Bin 68369 -> 68380 bytes
...le2.12bpc.yuv422.odd-width.odd-height.avif | Bin 67646 -> 67657 bytes
.../Link-U/fox.profile2.12bpc.yuv444.avif | Bin 75322 -> 75333 bytes
.../fox.profile2.12bpc.yuv444.monochrome.avif | Bin 56967 -> 56978 bytes
...e2.12bpc.yuv444.monochrome.odd-height.avif | Bin 55877 -> 55888 bytes
...le2.12bpc.yuv444.monochrome.odd-width.avif | Bin 55995 -> 56006 bytes
...uv444.monochrome.odd-width.odd-height.avif | Bin 55252 -> 55263 bytes
.../fox.profile2.12bpc.yuv444.odd-height.avif | Bin 74012 -> 74023 bytes
.../fox.profile2.12bpc.yuv444.odd-width.avif | Bin 74038 -> 74049 bytes
...le2.12bpc.yuv444.odd-width.odd-height.avif | Bin 73043 -> 73054 bytes
.../Link-U/fox.profile2.8bpc.yuv422.avif | Bin 67856 -> 67867 bytes
.../fox.profile2.8bpc.yuv422.monochrome.avif | Bin 55645 -> 55656 bytes
...le2.8bpc.yuv422.monochrome.odd-height.avif | Bin 54692 -> 54703 bytes
...ile2.8bpc.yuv422.monochrome.odd-width.avif | Bin 54776 -> 54787 bytes
...uv422.monochrome.odd-width.odd-height.avif | Bin 54152 -> 54163 bytes
.../fox.profile2.8bpc.yuv422.odd-height.avif | Bin 67132 -> 67143 bytes
.../fox.profile2.8bpc.yuv422.odd-width.avif | Bin 67292 -> 67303 bytes
...ile2.8bpc.yuv422.odd-width.odd-height.avif | Bin 66472 -> 66483 bytes
...420.monochrome.no-cdef.no-restoration.avif | Bin 179205 -> 179214 bytes
...0.10bpc.yuv420.no-cdef.no-restoration.avif | Bin 208593 -> 208604 bytes
...ofile0.8bpc.yuv420.monochrome.no-cdef.avif | Bin 177796 -> 177805 bytes
.../hato.profile0.8bpc.yuv420.no-cdef.avif | Bin 207736 -> 207747 bytes
...422.monochrome.no-cdef.no-restoration.avif | Bin 179201 -> 179210 bytes
...2.10bpc.yuv422.no-cdef.no-restoration.avif | Bin 226212 -> 226223 bytes
...hato.profile2.12bpc.yuv422.monochrome.avif | Bin 231850 -> 231858 bytes
...422.monochrome.no-cdef.no-restoration.avif | Bin 227050 -> 227060 bytes
...2.12bpc.yuv422.no-cdef.no-restoration.avif | Bin 227050 -> 227060 bytes
...ofile2.8bpc.yuv422.monochrome.no-cdef.avif | Bin 177792 -> 177801 bytes
.../hato.profile2.8bpc.yuv422.no-cdef.avif | Bin 226199 -> 226210 bytes
76 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/Tools/sanitize_avif.py b/Tools/sanitize_avif.py
index c7eaff9..9496c6b 100644
--- a/Tools/sanitize_avif.py
+++ b/Tools/sanitize_avif.py
@@ -1258,6 +1258,7 @@ def _parse_av1_sequence_header_obu(self, reader: FileReader.BitReader) -> dict[s
parsed["enable_restoration"] = reader.f(1)
# color_config()
+ bitdepth = 8
parsed["high_bitdepth"] = reader.f(1)
if parsed["seq_profile"] == 2 and parsed["high_bitdepth"]:
parsed["twelve_bit"] = reader.f(1)
@@ -1301,7 +1302,7 @@ def _parse_av1_sequence_header_obu(self, reader: FileReader.BitReader) -> dict[s
elif parsed["seq_profile"] == 1:
parsed["subsampling_x"] = parsed["subsampling_y"] = 0
else:
- if parsed["twelve_bit"]:
+ if bitdepth == 12:
parsed["subsampling_x"] = reader.f(1)
if parsed["subsampling_x"]:
parsed["subsampling_y"] = reader.f(1)
diff --git a/testFiles/Link-U/fox.profile0.10bpc.yuv420.avif b/testFiles/Link-U/fox.profile0.10bpc.yuv420.avif
index 025c185783831a08193557d764f280b79a55e27b..b0be8289e2d357810e22ee475af3be689d1dc776 100644
GIT binary patch
delta 89
zcmZ4Toq7Ft<_XG-suNYx8GR@AIC55J78DgQFfc?2}lUQcx+{o$!ZWME`vWNL0{-E75}^$P%xH5Ro1
delta 78
zcmZ4goq5T3<_XG-QWI6u8J#BfIC2(b78DgQFfas8yk@N_npkG&+{o&~z{M_^l{(M<
d3=2?3JhLD-5lDjoBLgD~BU5wBW>?0nUjVPI6(#@x
diff --git a/testFiles/Link-U/fox.profile0.10bpc.yuv420.monochrome.avif b/testFiles/Link-U/fox.profile0.10bpc.yuv420.monochrome.avif
index 5b8a127c33995a991c2e401b2d2743b3a06cdbfd..15ac47267ae50a9972529c2771997dce5e6ddf72 100644
GIT binary patch
delta 89
zcmeyegZcjs<_XG-$`e)68NDa=IC55I78DgQFfc?;yk=>_lUQcx+{hXOZWME`vWNL0{-E6^Va~lAgI~I-r
delta 78
zcmeyrgZax2<_XG-5))O@8676}ICAD?78DgQFfjN}yk@B>npkG&+{hZkz{M_^l{(M<
doB~irJhLD-5lDjoBLgD~BU5wBW@kp5+W@^|6&(No
diff --git a/testFiles/Link-U/fox.profile0.10bpc.yuv420.monochrome.odd-height.avif b/testFiles/Link-U/fox.profile0.10bpc.yuv420.monochrome.odd-height.avif
index 95c0f4d3c1393c487648473c6599719d84814eff..202a153c8b040fad53e89cd7b240dca8c0ebe825 100644
GIT binary patch
delta 89
zcmX@Mk@@0A<_XG-$`e)68NDa=IC55I78DgQFfc?;yk=>_lUQcx+{hXOZWME`vWNL0{-E6_wcO3wCt`>3t
delta 78
zcmcb(k@?t0<_XG-5))O@8676}ICAD?78DgQFfjN}yk@B>npkG&+{hZkz{M_^l{(M%
doB~irJhLD-5lDjoBLgD~BU5wBW@pB}>j0i66#oDK
diff --git a/testFiles/Link-U/fox.profile0.10bpc.yuv420.monochrome.odd-width.avif b/testFiles/Link-U/fox.profile0.10bpc.yuv420.monochrome.odd-width.avif
index 3a2f88f56d9c68357a9ef4811f09dfa12e3df992..df5b4bf861602923214b447d6b49f67c15ed9bf7 100644
GIT binary patch
delta 89
zcmbQXiFx5B<_XG-$`e)68NDa=IC55I78DgQFfc?;yk=>_lUQcx+{hXOZWME`vWNL0{-E6^l?>YcjD;8t`
delta 78
zcmZ3uiFw*4<_XG-5))O@8676}ICAD?78DgQFfjN}yk@B>npkG&+{hZkz{M_^l{(G-
doB~irJhLD-5lDjoBLgD~BU5wBW@pBG*8zd+6zc#0
diff --git a/testFiles/Link-U/fox.profile0.10bpc.yuv420.monochrome.odd-width.odd-height.avif b/testFiles/Link-U/fox.profile0.10bpc.yuv420.monochrome.odd-width.odd-height.avif
index 7a951c84b5076a231a33e8f5ee80ddc5c40e3b17..86f1cf7c25bbb6fcf00012bcc5a1624ba3bdbe54 100644
GIT binary patch
delta 89
zcmeynhPh)c^8{r^<%ufkjNTJ_962j93yKOD7#JcaUb8geNh~vTZe)!C@)?Aa^K**w
ml5;8;7#VmO*g!%OnFYCtAO;XHGBC0-GBvlfZnj`_y$S$srxpwV
delta 78
zcmeBJ%lvl@^8{r^iHR!dj1Cif969qc3yKOD7#RE~UbEB`O)N8XZe)#N;9{4|N}XnV
dP5~$*o>`Ea2&6%Pk%5tgk*T?5vooXXRRELA6p;V`
diff --git a/testFiles/Link-U/fox.profile0.10bpc.yuv420.odd-height.avif b/testFiles/Link-U/fox.profile0.10bpc.yuv420.odd-height.avif
index da87d791b5d01f52780dd61f2780b2cb3db043a4..a53a69bcadf76f67a193a54b1db4b98beb24b51b 100644
GIT binary patch
delta 89
zcmaFxf%)|Z<_XG-suNYx8GR@AIC55J78DgQFfc?2}lUQcx+{o$!ZWME`vWNL0{-E76E_8kDS^A^|u
delta 78
zcmaF;f%(A)<_XG-QWI6u8J#BfIC2(b78DgQFfas8yk@N_npkG&+{o&~z{M_^l{(M%
d3=2?3JhLD-5lDjoBLgD~BU5wBW>-eF?*Pu96-NL7
diff --git a/testFiles/Link-U/fox.profile0.10bpc.yuv420.odd-width.avif b/testFiles/Link-U/fox.profile0.10bpc.yuv420.odd-width.avif
index 0133d948ede463db2737f952d024233b869c3abe..c7f46e4fa662adc63a99fd8d810cda076943671c 100644
GIT binary patch
delta 89
zcmbR8iFy7f<_XG-suNYx8GR@AIC55J78DgQFfc?2}lUQcx+{o$!ZWME`vWNL0{-E75p>pK8}!4~)c
delta 78
zcmbRLiFwK=<_XG-QWI6u8J#BfIC2(b78DgQFfas8yk@N_npkG&+{o&~z{M_^l{(G-
d3=2?3JhLD-5lDjoBLgD~BU5wBW>>~r-vOfs6=47X
diff --git a/testFiles/Link-U/fox.profile0.10bpc.yuv420.odd-width.odd-height.avif b/testFiles/Link-U/fox.profile0.10bpc.yuv420.odd-width.odd-height.avif
index ccb2a71149ae6781059cb3649fa7c82dabec3266..ad97f4fbc3051666bfbd84c61963dc12f624d573 100644
GIT binary patch
delta 89
zcmccnn)$_R<_XG-suNYx8GR@AIC55J78DgQFfc?2}lUQcx+{o$!ZWME`vWNL0{-E76U_zM88d>29h
delta 78
zcmaFyn)&W)<_XG-QWI6u8J#BfIC2(b78DgQFfas8yk@N_npkG&+{o&~z{M_^l{(G#
d3=2?3JhLD-5lDjoBLgD~BU5wBW>?0=UjWJ26{!FK
diff --git a/testFiles/Link-U/fox.profile0.8bpc.yuv420.avif b/testFiles/Link-U/fox.profile0.8bpc.yuv420.avif
index cf23e6ea9fd5965ba665282581d1898996e9b7e1..cc54e168a2bdaffa26c62496c94f0d5ef2a84ee8 100644
GIT binary patch
delta 89
zcmezVp1J7*^8{r^)rl(UjJ^|l9675q3yKOD7#N}_Ub8mgNh~vTZe-;F@)?Aa^K**w
ml5;8;7#VmO*g!%OnFYCtAO;XHGBC0-GBvlfZnk3F`wak$0T$Z;
delta 78
zcmZqr!2JC^^8{r^sfjA-j7}4K961Xz3yKOD7#IR4UbEH|O)N8XZe-`Ea2&6%Pk%5tgk*T?5vn%7?Zvd=E6-WR8
diff --git a/testFiles/Link-U/fox.profile0.8bpc.yuv420.monochrome.avif b/testFiles/Link-U/fox.profile0.8bpc.yuv420.monochrome.avif
index 57ca3f16d12d6ff2eaf431af7c92ef37da6cc20d..59c77b116388fcc34393f9ef407d5f5877ce9bc8 100644
GIT binary patch
delta 89
zcmaF3iTTYY<_XG-$`e)68NDa=IC55I78DgQFfc?;yk=>_lUQcx+{h{eZWME`vWNL0{-E6_Ac>@4_hZY6^
delta 78
zcmaE}iTU9s<_XG-5))O@8676}ICAD?78DgQFfjN}yk@B>npkG&+{h}!z{M_^l{(M<
dlmbvjJhLD-5lDjoBLgD~BU5wBW@kpt8vvvo6p;V`
diff --git a/testFiles/Link-U/fox.profile0.8bpc.yuv420.monochrome.odd-height.avif b/testFiles/Link-U/fox.profile0.8bpc.yuv420.monochrome.odd-height.avif
index 4a7be39f021f811d27424f7d669047cffee32a6e..627266be31a5e0a9ea8f01821945947e9a327dfe 100644
GIT binary patch
delta 89
zcmZ3nntAhT<_XG-$`e)68NDa=IC55I78DgQFfc?;yk=>_lUQcx+{h{eZWME`vWNL0{-E6^Fa0LKTUlqv!
delta 78
zcmdnInt8=)<_XG-5))O@8676}ICAD?78DgQFfjN}yk@B>npkG&+{h}!z{M_^l{(M%
dlmbvjJhLD-5lDjoBLgD~BU5wBW@pBND*%2s6jA^H
diff --git a/testFiles/Link-U/fox.profile0.8bpc.yuv420.monochrome.odd-width.avif b/testFiles/Link-U/fox.profile0.8bpc.yuv420.monochrome.odd-width.avif
index 2c29fd2d0938507761ed91b88f149c49a05b8552..93b72bdab675f74eca97fbaab38a24e6a00033a4 100644
GIT binary patch
delta 89
zcmeyfnz?-q^8{r^<%ufkjNTJ_962j93yKOD7#JcaUb8geNh~vTZe*1K@)?Aa^K**w
ml5;8;7#VmO*g!%OnFYCtAO;XHGBC0-GBvlfZnj`Nas>ck$QDKb
delta 78
zcmZo)!~AD8^8{r^iHR!dj1Cif969qc3yKOD7#RE~UbEB`O)N8XZe*2V;9{4|N}XnZ
dN&zS%o>`Ea2&6%Pk%5tgk*T?5voqt7D*%a}6v+Sp
diff --git a/testFiles/Link-U/fox.profile0.8bpc.yuv420.monochrome.odd-width.odd-height.avif b/testFiles/Link-U/fox.profile0.8bpc.yuv420.monochrome.odd-width.odd-height.avif
index afbad94bd7f9216a93f6760817f2f9b454b7eba2..8f436776fd14cefd0400da28d0924fcb8abe5ea3 100644
GIT binary patch
delta 89
zcmeBK&OCiN^8{r^<%ufkjNTJ_962j93yKOD7#JcaUb8geNh~vTZe*1K@)?Aa^K**w
ml5;8;7#VmO*g!%OnFYCtAO;XHGBC0-GBvlfZnj_yxdZ?_O%-bZ
delta 78
zcmbQfoVjN?^8{r^iHR!dj1Cif969qc3yKOD7#RE~UbEB`O)N8XZe*2V;9{4|N}XnV
dN&zS%o>`Ea2&6%Pk%5tgk*T?5vomAJB>-vV6YKy0
diff --git a/testFiles/Link-U/fox.profile0.8bpc.yuv420.odd-height.avif b/testFiles/Link-U/fox.profile0.8bpc.yuv420.odd-height.avif
index 5b1b16dfc5b61745a278ffd6b9f13abe1d55b31e..a1bd556148dada3197c728fd424938ac67762103 100644
GIT binary patch
delta 89
zcmdn`iuu4R<_XG-suNYx8GR@AIC55J78DgQFfc?2}lUQcx+{nrUZWME`vWNL0{-E779`!fKBrWXeQ
delta 78
zcmX@`ih1iR<_XG-QWI6u8J#BfIC2(b78DgQFfas8yk@N_npkG&+{ntqz{M_^l{(M%
d1Pf3`JhLD-5lDjoBLgD~BU5wBW>?1Fp8=@Q6>`Ea2&6%Pk%5tgk*T?5vn!+j7XXa{6l(wg
diff --git a/testFiles/Link-U/fox.profile0.8bpc.yuv420.odd-width.odd-height.avif b/testFiles/Link-U/fox.profile0.8bpc.yuv420.odd-width.odd-height.avif
index 64507a67d38b33bad8669dd09289e7a2ff1a74e0..8eb8b7236c827021891527d2681b5d7ac0fee6ec 100644
GIT binary patch
delta 89
zcmX@`jQR94<_XG-suNYx8GR@AIC55J78DgQFfc?2}lUQcx+{nrUZWME`vWNL0{-E76k_6Y!qj20gN
delta 78
zcmX^8jQPMb<_XG-QWI6u8J#BfIC2(b78DgQFfas8yk@N_npkG&+{ntqz{M_^l{(G#
d1Pf3`JhLD-5lDjoBLgD~BU5wBW>-eGPXMYM6oLQ%
diff --git a/testFiles/Link-U/fox.profile1.10bpc.yuv444.avif b/testFiles/Link-U/fox.profile1.10bpc.yuv444.avif
index 132695e34833eb52aaa6d87cc790fd7b15db9b1f..ac1ee87e9ac79e024dc1d33cb81440ab45241f16 100644
GIT binary patch
delta 93
zcmdmeisjfTmI=y?suNYx8GR@AIC55J78DgQFfc?2}lUQcx+^FgRZWME`vWNL0{ZMI_EZpFyRr~&}oKNceZ
delta 82
zcmX?hie>jHmI=y?QWI6u8J#BfIC2(b78DgQFfas8yk@N_npkG&+^Finz{PHvl{(M<
hi~>+bJhLD-5lDjoBLgD~BU5urvn%6vS4Kug6#xJ)6x#p*
diff --git a/testFiles/Link-U/fox.profile1.10bpc.yuv444.odd-height.avif b/testFiles/Link-U/fox.profile1.10bpc.yuv444.odd-height.avif
index b2e31b5fbe9f99abab063d6216f67f6e049e05b9..58604e9b8f2d147725379c454ac01e0170ec29f8 100644
GIT binary patch
delta 93
zcmdnDkLBb(mI=y?suNYx8GR@AIC55J78DgQFfc?2}lUQcx+^FgRZWME`vWNL0{ZMI_EZpFyRA_oA~=oStD
delta 82
zcmX@Pk7eIJmI=y?QWI6u8J#BfIC2(b78DgQFfas8yk@N_npkG&+^Finz{PHvl{(M%
hi~>+bJhLD-5lDjoBLgD~BU5urvn%6vS4Kt_IRN@e6vO}k
diff --git a/testFiles/Link-U/fox.profile1.10bpc.yuv444.odd-width.avif b/testFiles/Link-U/fox.profile1.10bpc.yuv444.odd-width.avif
index 5be3874afc236c05de874617a8fe5f62b256f351..ce48b47ea6fc537dc02931d05e8f3842ff0b7056 100644
GIT binary patch
delta 93
zcmeyekLCY9mI=y?suNYx8GR@AIC55J78DgQFfc?2}lUQcx+^FgRZWME`vWNL0{ZMI_EZpFxGB?kcf?iR2B
delta 82
zcmeyrkLAlgmI=y?QWI6u8J#BfIC2(b78DgQFfas8yk@N_npkG&+^Finz{PHvl{(G-
hi~>+bJhLD-5lDjoBLgD~BU5urvn%6vS4KuFIRG2r6<`1W
diff --git a/testFiles/Link-U/fox.profile1.10bpc.yuv444.odd-width.odd-height.avif b/testFiles/Link-U/fox.profile1.10bpc.yuv444.odd-width.odd-height.avif
index 9d5e1a48fef334e13ca5db0863c2a18ee3ec64d6..4dcb01a19a9eb78a696cb5cf89b954112475cc21 100644
GIT binary patch
delta 93
zcmeynouy+3%LHXc)rl(UjJ^|l9675q3yKOD7#N}_Ub8mgNh~vTZd7#u@)?Aa^K**w
ql5;8;7#VmO*g!%OnFYCtAO;XHGBC0-GBvlfHd`@nw_;>GECm44(H6P@
delta 82
zcmeC!!SZ)I%LHXcsfjA-j7}4K961Xz3yKOD7#IR4UbEH|O)N8XZd7$(;9|GTN}XnV
hMgb@zo>`Ea2&6%Pk%5tgk*T?**_Cm-D2}lUQcx+^7oVGB5}y=jRmV
qCFfKyFf#Bmuz`dmG7EAOK@1>ZWME`vWNL0{ZMI_EZpFyBO#uM$6&COS
delta 82
zcmex;nB~J^mI=y?QWI6u8J#BfIC2(b78DgQFfas8yk@N_npkG&+^EXHz{PHvl{(M<
hgaS}TJhLD-5lDjoBLgD~BU5urvn%6vS4PHd3IG#H6{G+F
diff --git a/testFiles/Link-U/fox.profile1.8bpc.yuv444.odd-height.avif b/testFiles/Link-U/fox.profile1.8bpc.yuv444.odd-height.avif
index 2addc795a6e328f9df9e6e87c5290c4995f82a63..83bd5ac6e418a0a8d16ad96bc683483d30a9d091 100644
GIT binary patch
delta 93
zcmaE`gXQ%OmI=y?suNYx8GR@AIC55J78DgQFfc?2}lUQcx+^7oVGB5}y=jRmV
qCFfKyFf#Bmuz`dmG7EAOK@1>ZWME`vWNL0{ZMI_EZpFx`CJg}GxfUe=
delta 82
zcmaF8gXO^vmI=y?QWI6u8J#BfIC2(b78DgQFfas8yk@N_npkG&+^EXHz{PHvl{(M%
hgaS}TJhLD-5lDjoBLgD~BU5urvn%6vS4KuPX#fEE6xRR%
diff --git a/testFiles/Link-U/fox.profile1.8bpc.yuv444.odd-width.avif b/testFiles/Link-U/fox.profile1.8bpc.yuv444.odd-width.avif
index 6af47776cd57644dc71d4ebdfb3587f4f9068cca..5f73ad79988f6d9deaa065f0e58a64de315ec8f5 100644
GIT binary patch
delta 93
zcmZqP&C<7O_@vM&F4&j-1t*1w{o63=Gi|uUVV$B$gREH>v`;3=G1_`8h>-
q$vG7aj10UCY#xr)aIsrvrB1Uy
hp#YQ-&n(DI1kxbD$iT?L$kg1@?8>;^m66d?1^~ym6hQz0
diff --git a/testFiles/Link-U/fox.profile1.8bpc.yuv444.odd-width.odd-height.avif b/testFiles/Link-U/fox.profile1.8bpc.yuv444.odd-width.odd-height.avif
index 4c82deb1a7d97a886e4203ddbea190fc17a0d4ab..e840b0c2bf6381d476a318a17938be8866677918 100644
GIT binary patch
delta 93
zcmdnGndQJ{mI=y?suNYx8GR@AIC55J78DgQFfc?2}lUQcx+^7oVGB5}y=jRmV
qCFfKyFf#Bmuz`dmG7EAOK@1>ZWME`vWNL0{ZMI_EZpFx0Edc<#8WtA-
delta 82
zcmX@GnPux{mI=y?QWI6u8J#BfIC2(b78DgQFfas8yk@N_npkG&+^EXHz{PHvl{(G#
hgaS}TJhLD-5lDjoBLgD~BU5urvn%6vS4PHa2>{|t6u|%h
diff --git a/testFiles/Link-U/fox.profile2.10bpc.yuv422.avif b/testFiles/Link-U/fox.profile2.10bpc.yuv422.avif
index 61431682036bbbabce4c19653e5e5ea7f3d3f3fb..8e1ecc71d6316c6e34ae6e3b73a2a1f5055baaf9 100644
GIT binary patch
delta 93
zcmaDgljZA7mI?BVsuLB`89gU{lUQcx-0127ZWME`vWNL0{Z8l@vZpO&Cg&P3g%ofD}
delta 82
zcmex5ljYS+mI?BVQWF)@8SN%^IC2(b78DgQFfas8ykxB@npkG&-014Sz{MV!l{(M<
h3ZWME`vWNL0{-E6{Wa~lAkZx*fq
delta 78
zcmeypgZaY_<_YqQ5)&2D8EqzZICAD?78DgQFfjN}ykw~6(JhLD-5lDjoBLgD~BU5wBW_w1P+W^Mh6>IZWME`vWNL0{-E6|xcO3wG;uews
delta 78
zcmX@Rk@?U@<_YqQ5)&2D8EqzZICAD?78DgQFfjN}ykw~6(JhLD-5lDjoBLgD~BU5wBW_!lI>j0;q6;1#E
diff --git a/testFiles/Link-U/fox.profile2.10bpc.yuv422.monochrome.odd-width.avif b/testFiles/Link-U/fox.profile2.10bpc.yuv422.monochrome.odd-width.avif
index 230780b2c887059710b29e4cf556b175306de7c0..b176ede35c18d3f7b336a9d58078dad61d21ed1b 100644
GIT binary patch
delta 89
zcmbQViFxiO<_YqQ$`cjR8Qmv#IC55I78DgQFfc?;yku#@lUQcx+~^tuZWME`vWNL0{-E6{m?>YcnUlxP_
delta 78
zcmbQciFwi{<_YqQ5)&2D8EqzZICAD?78DgQFfjN}ykw~6(JhLD-5lDjoBLgD~BU5wBW_!ka*8z)V6*>R_
diff --git a/testFiles/Link-U/fox.profile2.10bpc.yuv422.monochrome.odd-width.odd-height.avif b/testFiles/Link-U/fox.profile2.10bpc.yuv422.monochrome.odd-width.odd-height.avif
index f33eac3c3ad985bac1b1c3c30804d591d102b350..12af828861bc97f5121bdf36e1aaed5437824c8d 100644
GIT binary patch
delta 89
zcmeylhPh=e^8|TD<%tUEjP4UV962j93yKOD7#JcaUa~adNh~vTZgh`Ea2&6%Pk%5tgk*T?5vpu8hRREnu6yN{=
diff --git a/testFiles/Link-U/fox.profile2.10bpc.yuv422.odd-height.avif b/testFiles/Link-U/fox.profile2.10bpc.yuv422.odd-height.avif
index 8a4fb1aecf5a9ff9c301b0e8147b944dceaf3d41..0a3ec3f586b2470ea263de9761ef8c5afc7067aa 100644
GIT binary patch
delta 93
zcmcaGiRJbrmI?BVsuLB`89gU{lUQcx-0127ZWME`vWNL0{Z8l@vZpO$c#Q^}u3>D@8
delta 82
zcmcaTiRHp1mI?BVQWF)@8SN%^IC2(b78DgQFfas8ykxB@npkG&-014Sz{MV!l{(M%
h3{lUQcx-0127ZWME`vWNL0{Z8l@vZpO&?m;(Tzw-!YJ
delta 82
zcmZ27g=OXxmI?BVQWF)@8SN%^IC2(b78DgQFfas8ykxB@npkG&-014Sz{MV!l{(G-
h3O_TfM$d^Ij-1t*1w{o63=Gi|FIk)LB$gREH@bQN`3%Cz`8h>-
q$vG7aj10UCY#Wr94T)I^1JM!Sg}j+_OV1w{o63=Dx2FIj7fCYBjGH@Z47aIr^brB1Uw
h!vT~L&n(DI1kxbD$iT?L$kg1@?8vy?k&*Ee3jojO6$}6X
diff --git a/testFiles/Link-U/fox.profile2.12bpc.yuv420.avif b/testFiles/Link-U/fox.profile2.12bpc.yuv420.avif
index 4299cf745f7d6fd57a033d5fbb00f94b32cf1aa8..fd43ddb056b8a901fd747ca5235ef46786a9db5f 100644
GIT binary patch
delta 89
zcmaF=oB8K&<_YqQsuLB`89gU{lUQcx+~}GEZWME`vWNL0{-E7Xd;|~DRsu$}3
delta 79
zcmezQoB923<_YqQ(i0WZ8SN)_IC2(d78DgQFfas7ykxB^8|TD<%tUEjP4UV962j93yKOD7#JcaUa~adNh~vTZgi~y@)?Aa^K**w
ml5;8;7#VmO*g!%OnFYCtAO;XHGBC0-GBvlfZZ=^Iz6$_hc@`f4
delta 78
zcmbQVm$`i}^8|TDiHQp7j5ZTH969qc3yKOD7#RE~Ub55_O)N8XZgj0-;9`%=N}Xqa
dUH~W~o>`Ea2&6%Pk%5tgk*T?5vpr+*T>y|<6yE><
diff --git a/testFiles/Link-U/fox.profile2.12bpc.yuv420.monochrome.odd-height.avif b/testFiles/Link-U/fox.profile2.12bpc.yuv420.monochrome.odd-height.avif
index b31afcaffab43f31286dd595d8819749ce1aa92b..566c655426b230ef1f6135ec28e31d8c41b45716 100644
GIT binary patch
delta 89
zcmX@Qh55o3<_YqQ$`cjR8Qmv#IC55I78DgQFfc?;yku#@lUQcx+~`^ZZWME`vWNL0{-E6`rcoP7HJ{Cg&
delta 78
zcmcbxh56_f<_YqQ5)&2D8EqzZICAD?78DgQFfjN}ykw~ZWME`vWNL0{-E6|xeiHzI0T!nK
delta 78
zcmX@Mm3jA8<_YqQ5)&2D8EqzZICAD?78DgQFfjN}ykw~ZWME`vWNL0{-E6|R;2HppITqsp
delta 78
zcmcb=p83jp<_YqQ5)&2D8EqzZICAD?78DgQFfjN}ykw~{lUQcx+~}GEZWME`vWNL0{-E7YI>IVRr{TFWl
delta 79
zcmZ4eg?Zr@<_YqQ(i0WZ8SN)_IC2(d78DgQFfas7ykxB{lUQcx+~}GEZWME`vWNL0{-E7Wi{u2PqI~P{~
delta 79
zcmezIh56kV<_YqQ(i0WZ8SN)_IC2(d78DgQFfas7ykxB{lUQcx+~}GEZWME`vWNL0{-E7Xd@f!feu@|@i
delta 79
zcmezLp83Ul<_YqQ(i0WZ8SN)_IC2(d78DgQFfas7ykxB`Ea2&6%Pk%5tgk*T?**^zO(BO~K6UI6g06?y;w
diff --git a/testFiles/Link-U/fox.profile2.12bpc.yuv422.monochrome.avif b/testFiles/Link-U/fox.profile2.12bpc.yuv422.monochrome.avif
index 34293c2f3a71d44287a55ebaef7b00dc86eb0161..96920eed767dfee5a38982eaa118e18ede41195a 100644
GIT binary patch
delta 89
zcmZqQ%RFf>^8|TD<%tUEjP4UV962j93yKOD7#JcaUa~adNh~vTZgi~y@)?Aa^K**w
ml5;8;7#VmO*g!%OnFYCtAO;XHGBC0-GBvlfZZ=^Iz6$_hc@`f4
delta 78
zcmbQVm$`i}^8|TDiHQp7j5ZTH969qc3yKOD7#RE~Ub55_O)N8XZgj0-;9`%=N}Xqa
dUH~W~o>`Ea2&6%Pk%5tgk*T?5vpr+*T>y|<6yE><
diff --git a/testFiles/Link-U/fox.profile2.12bpc.yuv422.monochrome.odd-height.avif b/testFiles/Link-U/fox.profile2.12bpc.yuv422.monochrome.odd-height.avif
index b31afcaffab43f31286dd595d8819749ce1aa92b..566c655426b230ef1f6135ec28e31d8c41b45716 100644
GIT binary patch
delta 89
zcmX@Qh55o3<_YqQ$`cjR8Qmv#IC55I78DgQFfc?;yku#@lUQcx+~`^ZZWME`vWNL0{-E6`rcoP7HJ{Cg&
delta 78
zcmcbxh56_f<_YqQ5)&2D8EqzZICAD?78DgQFfjN}ykw~ZWME`vWNL0{-E6|xeiHzI0T!nK
delta 78
zcmX@Mm3jA8<_YqQ5)&2D8EqzZICAD?78DgQFfjN}ykw~ZWME`vWNL0{-E6|R;2HppITqsp
delta 78
zcmcb=p83jp<_YqQ5)&2D8EqzZICAD?78DgQFfjN}ykw~`Ea2&6%Pk%5tgk*T?**^zO(BO~Jt4gk(`6&3&h
diff --git a/testFiles/Link-U/fox.profile2.12bpc.yuv422.odd-width.avif b/testFiles/Link-U/fox.profile2.12bpc.yuv422.odd-width.avif
index 6895c3306e2c941f3bb0cc1605ed11288c976572..ecb10e97861796c1b653f942b0a288b4f392328b 100644
GIT binary patch
delta 93
zcmbO@jb+X>mI?BVsuLB`89gU{lUQcx+~}GCZWME`vWNL0{Z8l@vZpO%Xn-c(}8WvIj
delta 82
zcmbO;jb-9AmI?BVQWF)@8SN%^IC2(b78DgQFfas8ykxB@npkG&+~}IXz{MV!l{(G-
hoDxt*JhLD-5lDjoBLgD~BU5urvm@hnM@GimoB+_l6&?Tp
diff --git a/testFiles/Link-U/fox.profile2.12bpc.yuv422.odd-width.odd-height.avif b/testFiles/Link-U/fox.profile2.12bpc.yuv422.odd-width.odd-height.avif
index d4d29ae7ca095cf163a1c2c1ee76484c528479b8..49f6c4ff0c5194ec55d93e5cfdc0876294bcd9f2 100644
GIT binary patch
delta 93
zcmdltf#u``mI?BVsuLB`89gU{lUQcx+~}GCZWME`vWNL0{Z8l@vZpO&S!43evUlq#$
delta 82
zcmX>(fo0zWmI?BVQWF)@8SN%^IC2(b78DgQFfas8ykxB@npkG&+~}IXz{MV!l{(G#
hoDxt*JhLD-5lDjoBLgD~BU5urvm@hnM@B{tb^zyQ6qNt~
diff --git a/testFiles/Link-U/fox.profile2.12bpc.yuv444.avif b/testFiles/Link-U/fox.profile2.12bpc.yuv444.avif
index 03c3599c8b1d868af67b15c2c26c52892c94360b..133ea6770b1bbb6949efb8bae161a0f4470f2005 100644
GIT binary patch
delta 93
zcmdmWhUMrPmI?BVsuLB`89gU{lUQcx+~}GBZWME`vWNL0{Z8l@vZpO&Sq6z@yRTfPE
delta 82
zcmX?lhGo|omI?BVQWF)@8SN%^IC2(b78DgQFfas8ykxB@npkG&+~}IXz{MV!l{(M<
h91BoJJhLD-5lDjoBLgD~BU5urvm@hnM@B{#RR9Om6$=0W
diff --git a/testFiles/Link-U/fox.profile2.12bpc.yuv444.monochrome.avif b/testFiles/Link-U/fox.profile2.12bpc.yuv444.monochrome.avif
index 34293c2f3a71d44287a55ebaef7b00dc86eb0161..96920eed767dfee5a38982eaa118e18ede41195a 100644
GIT binary patch
delta 89
zcmZqQ%RFf>^8|TD<%tUEjP4UV962j93yKOD7#JcaUa~adNh~vTZgi~y@)?Aa^K**w
ml5;8;7#VmO*g!%OnFYCtAO;XHGBC0-GBvlfZZ=^Iz6$_hc@`f4
delta 78
zcmbQVm$`i}^8|TDiHQp7j5ZTH969qc3yKOD7#RE~Ub55_O)N8XZgj0-;9`%=N}Xqa
dUH~W~o>`Ea2&6%Pk%5tgk*T?5vpr+*T>y|<6yE><
diff --git a/testFiles/Link-U/fox.profile2.12bpc.yuv444.monochrome.odd-height.avif b/testFiles/Link-U/fox.profile2.12bpc.yuv444.monochrome.odd-height.avif
index b31afcaffab43f31286dd595d8819749ce1aa92b..566c655426b230ef1f6135ec28e31d8c41b45716 100644
GIT binary patch
delta 89
zcmX@Qh55o3<_YqQ$`cjR8Qmv#IC55I78DgQFfc?;yku#@lUQcx+~`^ZZWME`vWNL0{-E6`rcoP7HJ{Cg&
delta 78
zcmcbxh56_f<_YqQ5)&2D8EqzZICAD?78DgQFfjN}ykw~ZWME`vWNL0{-E6|xeiHzI0T!nK
delta 78
zcmX@Mm3jA8<_YqQ5)&2D8EqzZICAD?78DgQFfjN}ykw~ZWME`vWNL0{-E6|R;2HppITqsp
delta 78
zcmcb=p83jp<_YqQ5)&2D8EqzZICAD?78DgQFfjN}ykw~{lUQcx+~}GBZWME`vWNL0{Z8l@vZpO&?OdbHqj~3Yg
delta 82
zcmZ2}h-J{lUQcx+~}GBZWME`vWNL0{Z8l?EZpO%{006`S78n2k
delta 81
zcmX?jh-KR$mI?BVQWF)@8SN%^IC2(b78DgQFfas8ykxB@npkG&+~}IXz{MV!l{(G-
g91BoJJhLD-5lDjoBLgD~BU5urvm@hjM@B{k0O-#Y&Hw-a
diff --git a/testFiles/Link-U/fox.profile2.12bpc.yuv444.odd-width.odd-height.avif b/testFiles/Link-U/fox.profile2.12bpc.yuv444.odd-width.odd-height.avif
index 43417ba647d8188ebda4f61793fdcb68831d067f..7073c3194e6bf5bb81494c69046eb069c6ba14b3 100644
GIT binary patch
delta 93
zcmcb-i{;)fmI?BVsuLB`89gU{lUQcx+~}GBZWME`vWNL0{Z8l@vZpO$cD+2)OqZVrb
delta 82
zcmcb&i{{lUQcx+~~>yZWME`vWNL0{Z8l@vZpO%XiyZ)rOBLk+
delta 82
zcmbO|iDd#1$umk#R7hvEo7myVS&&&!RKUQ%5IFIYwWerdnW1x|D+2=;dt_GXJo^&@
gKpFAOg4{$P4FZe|j4X^y%`MH2jN2U<8E>%z0K0+|p#T5?
diff --git a/testFiles/Link-U/fox.profile2.8bpc.yuv422.monochrome.avif b/testFiles/Link-U/fox.profile2.8bpc.yuv422.monochrome.avif
index 07041878fd1a9dd2769b4b188271e9cfd75dc92a..482344a2e0b46ddc4b408b583dcd66ffc56b6553 100644
GIT binary patch
delta 89
zcmcb+iTTAQ<_YqQ$`cjR8Qmv#IC55I78DgQFfc?;yku#@lUQcx+~_I;ZWME`vWNL0{-E6|Bc>@4}yA~z@
delta 78
zcmaE{iTUm(<_YqQ5)&2D8EqzZICAD?78DgQFfjN}ykw~8vw6`6!8E6
diff --git a/testFiles/Link-U/fox.profile2.8bpc.yuv422.monochrome.odd-height.avif b/testFiles/Link-U/fox.profile2.8bpc.yuv422.monochrome.odd-height.avif
index 29b032c8d16724c175965266ec92b519cd9f6527..d0a40165ec4a731f0ea7b6478808843302fcefe2 100644
GIT binary patch
delta 89
zcmZ3ontAZWME`vWNL0{-E6{Ga0LKXlNIRz
delta 78
zcmZ3#nt91;<_YqQ5)&2D8EqzZICAD?78DgQFfjN}ykw~co{1#>a
delta 78
zcmZo(!~A14^8|TDiHQp7j5ZTH969qc3yKOD7#RE~Ub55_O)N8XZgiDl;9`%=N}XnZ
dN&zS%o>`Ea2&6%Pk%5tgk*T?5vpwUHD*%-S6)6A!
diff --git a/testFiles/Link-U/fox.profile2.8bpc.yuv422.monochrome.odd-width.odd-height.avif b/testFiles/Link-U/fox.profile2.8bpc.yuv422.monochrome.odd-width.odd-height.avif
index 3726a6cb19ea97f7ce2ac1e39d873ab50ceedc02..1f559fc3848a40d77a76e9ea616683f053097beb 100644
GIT binary patch
delta 89
zcmeBJ&OCWJ^8|TD<%tUEjP4UV962j93yKOD7#JcaUa~adNh~vTZgiCa@)?Aa^K**w
ml5;8;7#VmO*g!%OnFYCtAO;XHGBC0-GBvlfZZ=^IxdZ?}ffb7Y
delta 78
zcmbQdoVjB;^8|TDiHQp7j5ZTH969qc3yKOD7#RE~Ub55_O)N8XZgiDl;9`%=N}XnV
dN&zS%o>`Ea2&6%Pk%5tgk*T?5vpr+TB>;6z6ifgB
diff --git a/testFiles/Link-U/fox.profile2.8bpc.yuv422.odd-height.avif b/testFiles/Link-U/fox.profile2.8bpc.yuv422.odd-height.avif
index c66e07065d68f919c566adaa2227e3ddddc8cd9e..1a7b05b224596c04a5cbe407296ef33178a8362d 100644
GIT binary patch
delta 93
zcmdnf!*aZbWr94T>O_TfM$d^Ij-1t*1w{o63=Gi|FIk)LB$gREH@b2F`3%Cz`8h>-
q$vG7aj10UCY#t_4*A-g;
delta 82
zcmX@!!?LG`Wr94T)I^1JM!Sg}j+_OV1w{o63=Dx2FIj7fCYBjGH@Y$~aIr^brOvZG
hApn#S&n(DI1kxbD$iT?L$kg1@?8vy?k&%&&6#&tM6cqpf
diff --git a/testFiles/Link-U/fox.profile2.8bpc.yuv422.odd-width.avif b/testFiles/Link-U/fox.profile2.8bpc.yuv422.odd-width.avif
index 258e2a54fe58599d5573a85f3f1c903ea557c3c0..718b405c63c27e08a823e37169a51423b4c75143 100644
GIT binary patch
delta 93
zcmcc9%ksRJWr94T>O_TfM$d^Ij-1t*1w{o63=Gi|FIk)LB$gREH@b2F`3%Cz`8h>-
q$vG7aj10UCY#O_TfM$d^Ij-1t*1w{o63=Gi|FIk)LB$gREH@b2F`3%Cz`8h>-
q$vG7aj10UCY#`*06hr_3
diff --git a/testFiles/Link-U/hato.profile0.10bpc.yuv420.monochrome.no-cdef.no-restoration.avif b/testFiles/Link-U/hato.profile0.10bpc.yuv420.monochrome.no-cdef.no-restoration.avif
index 8c6aaab879dd320a94239d2b6abe0d31e121e584..87dc34969565c353e5dea241cd05ba6e2a02fd21 100644
GIT binary patch
delta 109
zcmZqu!PWPJYl1SP@F|j+~X51w{o63=EMIuW38*B$gREH}b>)`3%Cz`8h>-
z$vG7aj10UCY#<@Ng3O9c5QC8mNJwNB@EO0
C(-{B&
delta 100
zcmeDC!PWYMYl1SP)I^nZMyH8Aj+_OV1w{o63=Dx2uW6eL6l7Lp0yzxKTwGj0N;I*|
x(7BN(hJlM+T5p5;|BoF&LGjFj+(eKfAYf!*WMO1#c4TaKWMtg#$jEed7XWGu7^VOK
diff --git a/testFiles/Link-U/hato.profile0.10bpc.yuv420.no-cdef.no-restoration.avif b/testFiles/Link-U/hato.profile0.10bpc.yuv420.no-cdef.no-restoration.avif
index 93a68be3ca0e8c44285b9b949012fcf61c24c821..27cecc549891f10c5b7d0823de50c01469eaa3a2 100644
GIT binary patch
delta 101
zcmcb3m*>u1o(al~suNYx8GR@AIC55J78DgQFfc?2}lUQcx+{ohtZWME`vWNL0{ZMI@;w_*fgrtMaY%+qxNx>~`S4I$K+V0B8JY5$6+N2k*
diff --git a/testFiles/Link-U/hato.profile0.8bpc.yuv420.monochrome.no-cdef.avif b/testFiles/Link-U/hato.profile0.8bpc.yuv420.monochrome.no-cdef.avif
index 056d8556b75186a31c0683b5ea556ab222f0b56f..e9e55f921526226c58ec2ca9860d643624732b5e 100644
GIT binary patch
delta 109
zcmZp9%hmgqYl1SP@F|j+~X51w{o63=EMIuW38*B$gREH}c2;`3%Cz`8h>-
z$vG7aj10UCY#<@Ng3O9c5QC8eNJwNBoK&je*g)rl(UjJ^|l9675q3yKOD7#N}_Ub8mgNh~vTZsg$s@)?Aa^K**w
vl5;8;7#VmO*g!%OnFYCtAO;XHGBC0-GBvlfHd`^aTQPz#({?LHW;-nal3o|Z
delta 90
zcmZp^&hz6M&je*gsfjA-j7}4K961Xz3yKOD7#IR4UbEH|O)N8XZsg%%;9{57+o1mc
n6C+SYJhLD-5lDjoBLgD~BU5urvnyk}D-
z$vG7aj10UCY#<@Ng3O9c5QC8mNJwNB@EO7
Ce;F76
delta 100
zcmeDB!PWSKYl1wZ)I^1JM!Sg}j+_OV1w{o63=Dx2FKL?#6l7Lp0yzxKTwGj0N;I*|
x(7DkkhJlMcT5p5;|Bo&}LGjFj+(eKfAYf!*WMO1#wq{lUQcx-00&0ZWME`vWNL0{Z8l?UH)8~0rtM~o%y~rsryUrO
delta 90
zcmZ4goOj7{-U;%IQWF)@8SN%^IC2(b78DgQFfas8ykxB@npkG&-00)Lz{MV|w?X~?
nM<$?*cxFLvB9I0FMg~R}MyBSLW=F<$M@A54+V056oL2+@(*hUQ
diff --git a/testFiles/Link-U/hato.profile2.12bpc.yuv422.monochrome.avif b/testFiles/Link-U/hato.profile2.12bpc.yuv422.monochrome.avif
index 8ad85fc354f31882b6c5b4dacd337a2c1301391d..b8c11e9372bb78de40f2873b85f6d2540a7b25c6 100644
GIT binary patch
delta 101
zcmZ2AnQzl%z6tV-$`cjR8Qmv#IC55I78DgQFfc?;yku#@lUQcx+~`vSZWME`vWNL0{Z8m3YH)jN4rtRj8%*7o5bodxQ
delta 93
zcmdlqnQzr(z6tV-(i0WZ8SN)_IC2(d78DgQFfas7ykw~(kyvKv+~`xoz{M4{lUQcx+~|`5ZWME`vWNL0{Z8m3YH)jN4rtRj8%$rLA>N^>e
delta 91
zcmezJmiN_L-U;%I(i0WZ8SN)_IC2(d78DgQFfas7ykxBw^$h^4}089B9;{X5v
diff --git a/testFiles/Link-U/hato.profile2.12bpc.yuv422.no-cdef.no-restoration.avif b/testFiles/Link-U/hato.profile2.12bpc.yuv422.no-cdef.no-restoration.avif
index 40165e2220435a1749ff0ef0170d3a3fc50fe55f..de9e2912a244893778cdd55305f19710dcf3786c 100644
GIT binary patch
delta 101
zcmaF$miNnB-U;%IsuLB`89gU{lUQcx+~|`5ZWME`vWNL0{Z8m3YH)jN4rtRj8%$rLA>N^>e
delta 91
zcmezJmiN_L-U;%I(i0WZ8SN)_IC2(d78DgQFfas7ykxBw^$h^4}089B9;{X5v
diff --git a/testFiles/Link-U/hato.profile2.8bpc.yuv422.monochrome.no-cdef.avif b/testFiles/Link-U/hato.profile2.8bpc.yuv422.monochrome.no-cdef.avif
index af9069c0eca38de68461c3b00ae0fb0548693122..89478938cfd1e347495b9a7de4728828191511c9 100644
GIT binary patch
delta 109
zcmZp8%hmaoYl1wZ@-
z$vG7aj10UCY#<@Ng3O9c5QC8eNJwNB{lUQcx+~~srZWME`vWNL0{Z8l?UH)8~0rtM~o%!x$+jc6Dt
delta 90
zcmZ4VoOk+j-U;%IQWF)@8SN%^IC2(b78DgQFfas8ykxB@npkG&+~~u=z{MV|w?X~?
nCl;WLcxFLvB9I0FMg~R}MyBSLW=F<$M@A54+V056oLB?^y{8v*
From b9ea3d88ab14004113db3b04c31b64adf1548d18 Mon Sep 17 00:00:00 2001
From: Leo Barnes
Date: Wed, 11 Sep 2024 11:45:50 +0200
Subject: [PATCH 17/65] Add iso8 to sequence test files
---
Tools/sanitize_avif.py | 31 ++++++++++++++++++
.../avis/Chimera-AV1-10bit-480x270.avif | Bin 164547 -> 164551 bytes
testFiles/Netflix/avis/alpha_video.avif | Bin 10743 -> 10743 bytes
3 files changed, 31 insertions(+)
diff --git a/Tools/sanitize_avif.py b/Tools/sanitize_avif.py
index 9496c6b..e1e7d69 100644
--- a/Tools/sanitize_avif.py
+++ b/Tools/sanitize_avif.py
@@ -2669,6 +2669,35 @@ def validate_track(parsed_file: ParsedFile, track: Box) -> list[BoxIssue]:
return issues
+def validate_sequence_brands(parsed_file: ParsedFile) -> list[BoxIssue]:
+ """Validates that file containing an AVIF sequence has the required brands."""
+ issues = []
+
+ ftyp = parsed_file.get_box_from_hierarchy(["ftyp"])
+ assert ftyp
+ all_brands = [ftyp.body["major"]] + ftyp.body["compatible"]
+ required_brands = ["msf1", "iso8"]
+ missing_brands = [brand for brand in required_brands if brand not in all_brands]
+ if "avis" in all_brands and len(missing_brands) > 0:
+ issue = BoxIssue(-1, "ftyp")
+ for brand in missing_brands:
+ issue.add_issue("CRITICAL", f"Compatible brands is missing '{brand}' brand")
+ def _fix_ftyp() -> None:
+ assert ftyp
+ assert missing_brands
+ for brand in missing_brands:
+ if brand == "iso8":
+ # Remove iso3 to iso7 brands since those are implied by iso8
+ for sub_brand in ["iso3", "iso4", "iso5", "iso6", "iso7"]:
+ if sub_brand in ftyp.body["compatible"]:
+ ftyp.body["compatible"].remove(sub_brand)
+ ftyp.body["compatible"].append(brand)
+ ftyp.mark_for_rewrite()
+ issue.add_fix(_fix_ftyp, "Add missing brands to compatible brands")
+ issues.append(issue)
+ return issues
+
+
def validate_file(parsed_file: ParsedFile, default_nclx: dict[str, list[int]]) -> list[BoxIssue]:
"""Validates that an AVIF file is correct."""
items = parsed_file.get_items()
@@ -2688,6 +2717,8 @@ def validate_file(parsed_file: ParsedFile, default_nclx: dict[str, list[int]]) -
if box.type != "trak":
continue
issues += validate_track(parsed_file, box)
+ issues += validate_sequence_brands(parsed_file)
+
issues += validate_profile_brands(parsed_file)
return issues
diff --git a/testFiles/Netflix/avis/Chimera-AV1-10bit-480x270.avif b/testFiles/Netflix/avis/Chimera-AV1-10bit-480x270.avif
index 56288b363d3fc06a170d67d09a6a6c5482f0d792..2563819bf2c1e83a841bb4eb6c1be62cf28b0a4e 100644
GIT binary patch
delta 99
zcmX@y%5}VzOND`fK_#uEvLLZ6vlz%`0MWU{X@s
A2LJ#7
delta 95
zcmX@!%5}JvOM!ubK_RWAvLLZ6vlz%`0MWU{X@zDZ)4fnj1f#
Date: Tue, 10 Sep 2024 11:12:50 +0200
Subject: [PATCH 18/65] Add list of required boxes for image items.
Closes #167.
This is a rebase and fixup of PR #170.
The section on box requirements for sequences has been removed until someone has taken the time to fully go through it.
---
index.bs | 360 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 359 insertions(+), 1 deletion(-)
diff --git a/index.bs b/index.bs
index a62172a..90c19c3 100755
--- a/index.bs
+++ b/index.bs
@@ -93,6 +93,8 @@ url: https://www.iso.org/standard/68960.html; spec: ISOBMFF; type: property;
text: mdcv
text: clap
text: iloc
+ text: mdat
+ text: idat
url: https://www.iso.org/standard/74417.html; spec: MIAF; type: property;
text: miaf
@@ -431,6 +433,362 @@ A file containing a 'pict' track compliant with this profile is expected to list
avis, msf1, miaf, MA1A
+Box requirements
+
+Image item boxes
+This section discusses the box requirements for an AVIF file containing only image items.
+
+Minimum set of boxes
+
+As indicated in [[#file-constraints]], an AVIF file is a compliant [[!MIAF]] file. As a consequence, some [[!ISOBMFF]] or [[!HEIF]] boxes are required, as indicated in the following table. The order of the boxes is indicative in the table. The specifications listed in the "Specification"
+column may require a specific order for the box or for its children and shall be respected. For example, per [[!ISOBMFF]], the FileTypeBox
is required to appear first in an AVIF file.
+The "Version(s)" column in the following table lists the version(s) of the boxes allowed by this brand.
+Other versions of the boxes shall not be used. "-" means that the box does not have a version.
+
+
+
+
+ Top-Level |
+ Level 1 |
+ Level 2 |
+ Level 3 |
+ Version(s) |
+ Specification |
+ Note |
+
+
+
+
+ ftyp |
+ |
+ |
+ |
+ - |
+ ISOBMFF |
+ |
+
+
+ meta |
+ |
+ |
+ |
+ 0 |
+ ISOBMFF |
+ |
+
+
+ |
+ hdlr |
+ |
+ |
+ 0 |
+ ISOBMFF |
+ |
+
+
+ |
+ pitm |
+ |
+ |
+ 0, 1 |
+ ISOBMFF |
+ |
+
+
+ |
+ iloc |
+ |
+ |
+ 0, 1, 2 |
+ ISOBMFF |
+ |
+
+
+ |
+ iinf |
+ |
+ |
+ 0, 1 |
+ ISOBMFF |
+ |
+
+
+ |
+ |
+ infe |
+ |
+ 2, 3 |
+ ISOBMFF |
+ |
+
+
+ |
+ iprp |
+ |
+ |
+ - |
+ ISOBMFF |
+ |
+
+
+ |
+ |
+ ipco |
+ |
+ - |
+ ISOBMFF |
+ |
+
+
+ |
+ |
+ |
+ av1C |
+ - |
+ AVIF |
+ |
+
+
+ |
+ |
+ |
+ ispe |
+ 0 |
+ HEIF |
+ |
+
+
+ |
+ |
+ |
+ pixi |
+ 0 |
+ HEIF |
+ |
+
+
+ |
+ |
+ ipma |
+ |
+ 0, 1 |
+ ISOBMFF |
+ |
+
+
+ mdat |
+ |
+ |
+ |
+ - |
+ ISOBMFF |
+ The coded payload may be placed in 'idat' rather than 'mdat', in which case 'mdat' is not required. |
+
+
+
+
+Requirements on additional image item related boxes
+
+The boxes indicated in the following table may be present in an AVIF file to provide additional signaling for image items. The boxes may be present inside the box indicated in the "Containing box" column. If present, they shall use the version indicated in the table and AVIF readers are expected to understand them. The order of the boxes is indicative in the table. Specifications may require specific order and shall be respected. Additionally, the free
and skip
boxes may be present at any level in the hierarchy. AVIF readers are expected to ignore them. Additional boxes in the meta
hierarchy not listed in the following table may also be present and may be ignored by AVIF readers.
+
+
+
+ Level 1 |
+ Level 2 |
+ Version(s) |
+ Specification |
+ Containing Box |
+ Description |
+
+
+
+
+ dinf |
+ |
+ - |
+ ISOBMFF |
+ meta |
+ Used to indicate the location of the media information in a track |
+
+
+ |
+ dref |
+ 0 |
+ ISOBMFF |
+ |
+ |
+
+
+ iref |
+ |
+ 0, 1 |
+ ISOBMFF |
+ meta |
+ Used to indicate directional relationships between images or metadata |
+
+
+ |
+ auxl |
+ - |
+ HEIF |
+ |
+ Used when an image is auxiliary to another image |
+
+
+ |
+ thmb |
+ - |
+ HEIF |
+ |
+ Used when an image is a thumbnail of another image |
+
+
+ |
+ dimg |
+ - |
+ HEIF |
+ |
+ Used when an image is derived from another image |
+
+
+ |
+ prem |
+ - |
+ HEIF |
+ |
+ Used when when an alpha image contains premultiplied color values from another image |
+
+
+ |
+ cdsc |
+ - |
+ HEIF |
+ |
+ Used to link metadata with an image |
+
+
+ idat |
+ |
+ - |
+ ISOBMFF |
+ meta |
+ Used to store derived image definitions |
+
+
+ grpl |
+ |
+ - |
+ ISOBMFF |
+ meta |
+ Used to indicate that multiple images are semantically grouped |
+
+
+ |
+ altr |
+ 0 |
+ ISOBMFF |
+ |
+ Used when images in a group are alternative to each other |
+
+
+ pasp |
+ |
+ - |
+ ISOBMFF |
+ ipco |
+ Used to signal pixel aspect ratio. If present, shall indicate a pixel aspect ratio of 1:1 |
+
+
+ colr |
+ |
+ - |
+ ISOBMFF |
+ ipco |
+ Used to signal information such as color primaries. |
+
+
+ auxC |
+ |
+ 0 |
+ HEIF |
+ ipco |
+ Used to signal the type of an auxiliary image (e.g. alpha, depth). |
+
+
+ clap |
+ |
+ - |
+ ISOBMFF |
+ ipco |
+ Used to signal cropping applied to an image |
+
+
+ irot |
+ |
+ - |
+ HEIF |
+ ipco |
+ Used to signal a rotation applied to an image |
+
+
+ imir |
+ |
+ - |
+ HEIF |
+ ipco |
+ Used to signal a mirroring applied to an image |
+
+
+ clli |
+ |
+ - |
+ ISOBMFF |
+ ipco |
+ Used to signal HDR light level information for an image |
+
+
+ cclv |
+ |
+ - |
+ ISOBMFF |
+ ipco |
+ Used to signal HDR color volume for an image |
+
+
+ mdcv |
+ |
+ - |
+ ISOBMFF |
+ ipco |
+ Used to signal HDR mastering information for an image |
+
+
+ a1op |
+ |
+ - |
+ AVIF |
+ ipco |
+ Used to configure rendering of a multiple operating points image |
+
+
+ lsel |
+ |
+ - |
+ HEIF |
+ ipco |
+ Used to configure rendering of a multilayered image |
+
+
+ a1lx |
+ |
+ - |
+ AVIF |
+ ipco |
+ Used to assist reader in parsing a multilayered image |
+
+
+
+
AVIF Media Type Registration
The media type "image/avif"
is officially registered with IANA and available at: https://www.iana.org/assignments/media-types/image/avif.
@@ -438,4 +796,4 @@ A file containing a 'pict' track compliant with this profile is expected to list
Changes since v1.1.0 release
- EDITORIAL: Stop using `dfn value` for definitions.
- EDITORIAL: Add assert-ids in the spec for conformance file testing and ComplianceWarden
-
+ - Add required list of boxes for AVIF files
From 732e53d6d648bed7865055e42887b53494d44a9c Mon Sep 17 00:00:00 2001
From: Leo Barnes
Date: Wed, 11 Sep 2024 09:08:47 +0200
Subject: [PATCH 19/65] Add list of required boxes and versions.
This closes #182
---
index.bs | 26 ++++++++++++++------------
1 file changed, 14 insertions(+), 12 deletions(-)
diff --git a/index.bs b/index.bs
index 90c19c3..5775ee6 100755
--- a/index.bs
+++ b/index.bs
@@ -176,8 +176,8 @@ When an item is of type av01, it is
Box Type: av1C
Property type: Descriptive item property
Container: ItemPropertyContainerBox
- Mandatory (per item): Yes, for an image item of type 'av01'
- Quantity: One for an image item of type 'av01'
+ Mandatory (per item): Yes, for an image item of type 'av01', no otherwise
+ Quantity (per item): One for an image item of type 'av01', zero otherwise
The syntax and semantics of the AV1ItemConfigurationProperty are identical to those of the [=AV1CodecConfigurationBox=] defined in [[!AV1-ISOBMFF]], with the following constraints:
@@ -234,11 +234,11 @@ NOTE: When such a progressive decoding of the layers within an [=Operating Point
Definition
- Box Type: a1op
- Property type: Descriptive item property
- Container: ItemPropertyContainerBox
- Mandatory: No
- Quantity: Zero or one
+ Box Type: a1op
+ Property type: Descriptive item property
+ Container: ItemPropertyContainerBox
+ Mandatory (per item): No
+ Quantity (per item): Zero or one
Description
@@ -265,11 +265,11 @@ The 'lsel' property defined in [[!HEIF]] may be associated with an [=AV1 Image I
Definition
- Box Type: a1lx
- Property type: Descriptive item property
- Container: ItemPropertyContainerBox
- Mandatory: No
- Quantity: Zero or one
+ Box Type: a1lx
+ Property type: Descriptive item property
+ Container: ItemPropertyContainerBox
+ Mandatory (per item): No
+ Quantity (per item): Zero or one
Description
@@ -797,3 +797,5 @@ Other versions of the boxes shall not be used. "-" means that the box does not h
- EDITORIAL: Stop using `dfn value` for definitions.
- EDITORIAL: Add assert-ids in the spec for conformance file testing and ComplianceWarden
- Add required list of boxes for AVIF files
+ - EDITORIAL: Add "per item" to item property definitions
+
From cc68618af8f5020b92f79e97317200fb3a30b0aa Mon Sep 17 00:00:00 2001
From: Leo Barnes
Date: Wed, 11 Sep 2024 09:47:12 +0200
Subject: [PATCH 20/65] Fix broken link to latest draft at the top of the
document.
This closes #179
---
index.bs | 6 +++---
latest-draft.html | 1 -
2 files changed, 3 insertions(+), 4 deletions(-)
delete mode 120000 latest-draft.html
diff --git a/index.bs b/index.bs
index 5775ee6..b518654 100755
--- a/index.bs
+++ b/index.bs
@@ -14,9 +14,9 @@ Abstract: This document specifies syntax and semantics for the storage of [[!AV1
Date: 2024-06-25
Repository: AOMediaCodec/av1-avif
Text Macro: ADDITIONALLOGO https://aomedia.org/assets/images/avif-logo-rgb.svg
-!Previously approved version: https://aomediacodec.github.io/av1-avif/v1.1.0.html
!Latest approved version: https://aomediacodec.github.io/av1-avif/latest-approved.html
-!Latest draft version: https://aomediacodec.github.io/av1-avif/latest-draft.html
+!Latest version (published or draft): https://aomediacodec.github.io/av1-avif/index.html
+!Previously approved version: https://aomediacodec.github.io/av1-avif/v1.1.0.html
Metadata Order: This version, !*, *
@@ -798,4 +798,4 @@ Other versions of the boxes shall not be used. "-" means that the box does not h
- EDITORIAL: Add assert-ids in the spec for conformance file testing and ComplianceWarden
- Add required list of boxes for AVIF files
- EDITORIAL: Add "per item" to item property definitions
-
+ - EDITORIAL: Fix broken link for latest-draft.html
diff --git a/latest-draft.html b/latest-draft.html
deleted file mode 120000
index 64233a9..0000000
--- a/latest-draft.html
+++ /dev/null
@@ -1 +0,0 @@
-index.html
\ No newline at end of file
From bbeec5fdc1559baf724fc01ce0220e3e6318caa8 Mon Sep 17 00:00:00 2001
From: Leo Barnes
Date: Tue, 10 Sep 2024 12:43:16 +0200
Subject: [PATCH 21/65] Relax constraint on derivation chains
---
index.bs | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/index.bs b/index.bs
index b518654..1e70de3 100755
--- a/index.bs
+++ b/index.bs
@@ -360,9 +360,9 @@ NOTE: As defined in [[!MIAF]], a file that is primarily an image sequence still
The following constraints are common to files compliant with this specification:
- The file shall be compliant with the [[!MIAF]] specification and list 'miaf' in the [=compatible_brands=] field of the [=FileTypeBox=].
- The file shall list '[=avif=]'
or '[=avis=]'
in the [=compatible_brands=] field of the [=FileTypeBox=].
- - If transformative properties are used in derivation chains (as defined in [[MIAF]]), they shall only be associated with items that are not referenced by another derived item. For example, if a file contains a grid item and its referenced coded image items, cropping, mirroring or rotation transformations are only permitted on the grid item itself.
+ - Transformative properties shall not be associated with items in a derivation chain (as defined in [[!MIAF]]) that serves as an input to a grid item. For example, if a file contains a grid item and its referenced coded image items, cropping, mirroring or rotation transformations are only permitted on the grid item itself.
-NOTE: This constraint further restricts files compared to [[MIAF]].
+NOTE: This constraint further restricts files compared to [[!MIAF]].
Profiles
@@ -799,3 +799,5 @@ Other versions of the boxes shall not be used. "-" means that the box does not h
- Add required list of boxes for AVIF files
- EDITORIAL: Add "per item" to item property definitions
- EDITORIAL: Fix broken link for latest-draft.html
+ - Relax constraint on transformative properties in derivation chains to only apply to grid items
+
From 7a095c156c3fa9a86860fee53df20a3a8b446a7d Mon Sep 17 00:00:00 2001
From: Leo Barnes
Date: Wed, 11 Sep 2024 20:08:09 +0200
Subject: [PATCH 22/65] Change 'ispe' width to correspond to UpscaledWidth
---
index.bs | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/index.bs b/index.bs
index 1e70de3..06f07f4 100755
--- a/index.bs
+++ b/index.bs
@@ -132,7 +132,7 @@ url: https://aomediacodec.github.io/av1-spec/av1-spec.pdf; spec: AV1; type: dfn;
text: seq_level_idx
text: render_width_minus1
text: render_height_minus1
- text: FrameWidth
+ text: UpscaledWidth
text: FrameHeight
text: max_frame_width_minus1
text: max_frame_height_minus1
@@ -191,7 +191,7 @@ The syntax and semantics of the AV1ItemConfigurationProperty a
Image Spatial Extents Property
-The semantics of the 'ispe' property as defined in [[!HEIF]] apply. More specifically, for AV1 images, the values of 'image_width' and 'image_height' shall respectively equal the values of [=FrameWidth=] and [=FrameHeight=] as defined in [[!AV1]] but for a specific frame in the item payload. The exact frame depends on the presence and content of the 'lsel' and [=OperatingPointSelectorProperty=] properties as follows:
+The semantics of the 'ispe' property as defined in [[!HEIF]] apply. More specifically, for AV1 images, the values of 'image_width' and 'image_height' shall respectively equal the values of [=UpscaledWidth=] and [=FrameHeight=] as defined in [[!AV1]] but for a specific frame in the item payload. The exact frame depends on the presence and content of the 'lsel' and [=OperatingPointSelectorProperty=] properties as follows:
- In the absence of a 'lsel' property associated with the item, or if it is present and its 'layer_id' value is set to 0xFFFF:
- If no [=OperatingPointSelectorProperty=] is associated with the item, the 'ispe' shall document the dimensions of the last frame decoded when processing the operating point whose index is 0.
@@ -800,4 +800,4 @@ Other versions of the boxes shall not be used. "-" means that the box does not h
- EDITORIAL: Add "per item" to item property definitions
- EDITORIAL: Fix broken link for latest-draft.html
- Relax constraint on transformative properties in derivation chains to only apply to grid items
-
+ - Change ispe width to correspond to UpscaledWidth
From b2b2a23b0ae611a3846132dd9e6236b742c84500 Mon Sep 17 00:00:00 2001
From: Leo Barnes
Date: Wed, 11 Sep 2024 10:39:54 +0200
Subject: [PATCH 23/65] Clarify relationship between av1C and metadata OBUs
---
index.bs | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/index.bs b/index.bs
index 06f07f4..84b519b 100755
--- a/index.bs
+++ b/index.bs
@@ -185,7 +185,8 @@ The syntax and semantics of the AV1ItemConfigurationProperty a
- [=Sequence Header OBUs=] should not be present in the [=AV1CodecConfigurationBox=].
- If a [=Sequence Header OBU=] is present in the [=AV1CodecConfigurationBox=], it shall match the [=Sequence Header OBU=] in the [=AV1 Image Item Data=].
- The values of the fields in the [=AV1CodecConfigurationBox=] shall match those of the [=Sequence Header OBU=] in the [=AV1 Image Item Data=].
- - [=Metadata OBUs=], if present, shall match the values given in other item properties, such as the PixelInformationProperty or ColourInformationBox.
+ - The bit depth and number of channels in the [=AV1CodecConfigurationBox=] shall match the PixelInformationProperty if present.
+ - [=Metadata OBUs=], if present, shall match the values given in other item properties, such as the MasteringDisplayColourVolumeBox or ContentLightLevelBox.
This property should be marked as essential.
@@ -801,3 +802,4 @@ Other versions of the boxes shall not be used. "-" means that the box does not h
- EDITORIAL: Fix broken link for latest-draft.html
- Relax constraint on transformative properties in derivation chains to only apply to grid items
- Change ispe width to correspond to UpscaledWidth
+ - Clarify relationship between av1C, metadata OBUs and item properties
From 01e3ea344a5492ded76ec4557364f4b0b25c8c0d Mon Sep 17 00:00:00 2001
From: Leo Barnes
Date: Wed, 11 Sep 2024 10:22:37 +0200
Subject: [PATCH 24/65] Update list of other item properties
---
index.bs | 31 ++++++++++++++++++++++++++-----
1 file changed, 26 insertions(+), 5 deletions(-)
diff --git a/index.bs b/index.bs
index 84b519b..3f8c476 100755
--- a/index.bs
+++ b/index.bs
@@ -77,6 +77,17 @@ url: https://www.iso.org/standard/66067.html; spec: HEIF; type: property;
text: pixi
text: ispe
text: lsel
+ text: irot
+ text: imir
+ text: clap
+ text: cclv
+ text: clli
+ text: mdcv
+ text: reve
+ text: amve
+ text: ndwt
+ text: cmin
+ text: cmex
text: layer_id
text: image_width
text: image_height
@@ -88,10 +99,6 @@ url: https://www.iso.org/standard/68960.html; spec: ISOBMFF; type: dfn;
url: https://www.iso.org/standard/68960.html; spec: ISOBMFF; type: property;
text: sync
- text: cclv
- text: clli
- text: mdcv
- text: clap
text: iloc
text: mdat
text: idat
@@ -209,7 +216,20 @@ NOTE: The values of [=render_width_minus1=] and [=render_height_minus1=] possibl
Other Item Properties
-In addition to the Image Properties defined in [[!HEIF]], such as 'colr', 'pixi' or 'pasp', [=AV1 image items=] MAY also be associated with 'clli', 'cclv' and 'mdcv' introduced in [[!MIAF]].
+In addition to the Image Properties defined in this document, [=AV1 image items=] MAY also be associated with item properties defined in other specifications such as [[!HEIF]] and [[!MIAF]]. Examples of commonly used item properties are:
+ - 'colr'
+ - 'pixi'
+ - 'pasp'
+ - 'irot'
+ - 'imir'
+ - 'clli'
+ - 'cclv'
+ - 'mdcv'
+ - 'amve'
+ - 'reve'
+ - 'ndwt'
+ - 'cmin'
+ - 'cmex'
In general, it is recommended to use properties instead of [=Metadata OBUs=] in the [=AV1ItemConfigurationProperty=].
@@ -803,3 +823,4 @@ Other versions of the boxes shall not be used. "-" means that the box does not h
- Relax constraint on transformative properties in derivation chains to only apply to grid items
- Change ispe width to correspond to UpscaledWidth
- Clarify relationship between av1C, metadata OBUs and item properties
+ - EDITORIAL: Update list of other item properties
From 24508d699f55e6feba816f627dba68f75ba7355e Mon Sep 17 00:00:00 2001
From: Leo Barnes
Date: Mon, 16 Sep 2024 16:28:36 +0200
Subject: [PATCH 25/65] Reword av1C vs pixi conformance
---
index.bs | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/index.bs b/index.bs
index 3f8c476..7eb5639 100755
--- a/index.bs
+++ b/index.bs
@@ -192,7 +192,7 @@ The syntax and semantics of the AV1ItemConfigurationProperty a
- [=Sequence Header OBUs=] should not be present in the [=AV1CodecConfigurationBox=].
- If a [=Sequence Header OBU=] is present in the [=AV1CodecConfigurationBox=], it shall match the [=Sequence Header OBU=] in the [=AV1 Image Item Data=].
- The values of the fields in the [=AV1CodecConfigurationBox=] shall match those of the [=Sequence Header OBU=] in the [=AV1 Image Item Data=].
- - The bit depth and number of channels in the [=AV1CodecConfigurationBox=] shall match the PixelInformationProperty if present.
+ - The values of the bit depth and the number of channels derived from the [=AV1CodecConfigurationBox=] shall match the PixelInformationProperty if present.
- [=Metadata OBUs=], if present, shall match the values given in other item properties, such as the MasteringDisplayColourVolumeBox or ContentLightLevelBox.
This property should be marked as essential.
@@ -824,3 +824,4 @@ Other versions of the boxes shall not be used. "-" means that the box does not h
- Change ispe width to correspond to UpscaledWidth
- Clarify relationship between av1C, metadata OBUs and item properties
- EDITORIAL: Update list of other item properties
+ - Further clarify relationship between av1C, metadata OBUs and item properties
From 3d2d175c9779bcb8b0cbc104e72cc2f79ca8c87d Mon Sep 17 00:00:00 2001
From: leo-barnes
Date: Tue, 17 Sep 2024 12:23:05 +0200
Subject: [PATCH 26/65] Add tmap and altr text (#239)
Add tmap and altr text
---
index.bs | 40 ++++++++++++++++++++++++++++++++++++----
1 file changed, 36 insertions(+), 4 deletions(-)
diff --git a/index.bs b/index.bs
index 7eb5639..271f7c5 100755
--- a/index.bs
+++ b/index.bs
@@ -91,6 +91,8 @@ url: https://www.iso.org/standard/66067.html; spec: HEIF; type: property;
text: layer_id
text: image_width
text: image_height
+ text: ster
+ text: tmap
url: https://www.iso.org/standard/68960.html; spec: ISOBMFF; type: dfn;
text: compatible_brands
@@ -102,6 +104,7 @@ url: https://www.iso.org/standard/68960.html; spec: ISOBMFF; type: property;
text: iloc
text: mdat
text: idat
+ text: altr
url: https://www.iso.org/standard/74417.html; spec: MIAF; type: property;
text: miaf
@@ -327,7 +330,9 @@ NOTE: The size of the last layer can be determined by subtracting the sum of the
- The track shall have only one sample description entry.
- If multiple [=Sequence Header OBUs=] are present in the track payload, they shall be identical.
-Auxiliary Image Items and Sequences
+Other Image Items and Sequences
+
+Auxiliary Image Items and Sequences
An AV1 Auxiliary Image Item (respectively an AV1 Auxiliary Image Sequence) is an [=AV1 Image Item=] (respectively [=AV1 Image Sequence=]) with the following additional constraints:
- It shall be a compliant [=MIAF Auxiliary Image Item=] (respectively [=MIAF Auxiliary Image Sequence=]).
@@ -342,6 +347,24 @@ NOTE: The size of the last layer can be determined by subtracting the sum of the
NOTE: [[!AV1]] supports encoding either 3-component images (whose semantics are given by the matrix_coefficients
element), or 1-component images (monochrome). When an image requires a different number of components, multiple auxiliary images may be used, each providing additional component(s), according to the semantics of their aux_type
field. In such case, the maximum number of components is restricted by number of possible items in a file, coded on 16 or 32 bits.
+
Derived Image Items
+
+Tone Map Derived Image Item
+
+A tone map derived image item ('tmap') as defined in [[!HEIF]] may be used in an [=AVIF=] file. When present, the base image item and the 'tmap' image item should be grouped together by an '[=AVIF/altr=]' entity group as recommended in [[!HEIF]].
+
+Entity groups
+
+The GroupsListBox ('grpl') defined in [[!ISOBMFF]] may be used to group multiple image items in a file together. The type of the group describes how the image items are related. Decoders should ignore groups of unknown type.
+
+'altr' group
+
+The 'altr' entity group as defined in [[!ISOBMFF]] may be used to mark multiple items as alternatives to each other. Only one item in the 'altr' group should be played or processed. This grouping is useful for defining a fallback for parsers when new types of items or essential item properties are introduced.
+
+'ster' group
+
+The 'ster' entity group as defined in [[!HEIF]] may be used to indicate that two image items form a stereo pair suitable for stereoscopic viewing.
+
Brands, Internet media types and file extensions
Brands overview
@@ -696,7 +719,7 @@ Other versions of the boxes shall not be used. "-" means that the box does not h
Used to store derived image definitions |
- grpl |
+ [=AVIF/grpl=] |
|
- |
ISOBMFF |
@@ -705,12 +728,20 @@ Other versions of the boxes shall not be used. "-" means that the box does not h
|
- altr |
+ [=AVIF/altr=] |
0 |
ISOBMFF |
|
Used when images in a group are alternative to each other |
-
+
+
+ |
+ [=AVIF/ster=] |
+ 0 |
+ HEIF |
+ |
+ Used when images in a group form a stereo pair |
+
pasp |
|
@@ -825,3 +856,4 @@ Other versions of the boxes shall not be used. "-" means that the box does not h
- Clarify relationship between av1C, metadata OBUs and item properties
- EDITORIAL: Update list of other item properties
- Further clarify relationship between av1C, metadata OBUs and item properties
+ - Add information on tmap, grpl and altr
From 2286f6c1a642310f8d42523a1a784b0a8e7dfb8b Mon Sep 17 00:00:00 2001
From: Yannis Guyon
Date: Tue, 17 Sep 2024 11:41:16 +0000
Subject: [PATCH 27/65] Replace AV1 still_picture=1 shoulds with a note (#228)
---
index.bs | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/index.bs b/index.bs
index 271f7c5..6dd328e 100755
--- a/index.bs
+++ b/index.bs
@@ -174,9 +174,8 @@ When an item is of type av01, it is
- The content of an [=AV1 Image Item=] is called the AV1 Image Item Data and shall obey the following constraints:
- The [=AV1 Image Item Data=] shall be identical to the content of an [=AV1 Sample=] marked as 'sync', as defined in [[!AV1-ISOBMFF]].
- The [=AV1 Image Item Data=] shall have exactly one [=Sequence Header OBU=].
- - If the [=AV1 Image Item Data=] consists of a single frame (i.e. when using a single layer),
- - It should have its [=still_picture=]
flag set to 1.
- - It should have its [=reduced_still_picture_header=]
flag set to 1.
+
+NOTE: File writers may want to set the [=still_picture=]
and [=reduced_still_picture_header=]
flags to 1 when possible in the [=Sequence Header OBU=] part of the [=AV1 Image Item Data=] so that AV1 header overhead is minimized.
Image Item Properties
@@ -857,3 +856,4 @@ Other versions of the boxes shall not be used. "-" means that the box does not h
- EDITORIAL: Update list of other item properties
- Further clarify relationship between av1C, metadata OBUs and item properties
- Add information on tmap, grpl and altr
+ - Replace recommendations regarding still picture flags in image items by a note
From 70d14e6f18427cffd134a0bc2a785778a4b21c78 Mon Sep 17 00:00:00 2001
From: Yannis Guyon
Date: Tue, 17 Sep 2024 13:19:51 +0000
Subject: [PATCH 28/65] Add Sample Transform Derived Image Items (#224)
Introduce Sample Transform Derived Image Items in AVIF.
Add the Definition, Syntax, Semantics and Constraints sections.
---
index.bs | 303 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 300 insertions(+), 3 deletions(-)
diff --git a/index.bs b/index.bs
index 6dd328e..bd99d0c 100755
--- a/index.bs
+++ b/index.bs
@@ -63,6 +63,15 @@ Metadata Order: This version, !*, *
"status": "Enquiry",
"publisher": "ISO/IEC",
"isoNumber": "ISO/IEC DIS 23000-22"
+ },
+
+ "CICP": {
+ "href": "https://www.itu.int/rec/T-REC-H.273",
+ "id": "CICP",
+ "title": "H.273 : Coding-independent code points for video signal type identification",
+ "status": "International Standard",
+ "publisher": "ITU-T",
+ "isoNumber": "ITU-T H.273"
}
}
@@ -88,16 +97,27 @@ url: https://www.iso.org/standard/66067.html; spec: HEIF; type: property;
text: ndwt
text: cmin
text: cmex
+ text: dimg
text: layer_id
text: image_width
text: image_height
text: ster
text: tmap
+url: https://www.iso.org/standard/66067.html; spec: HEIF; type: dfn;
+ text: derived image item
+
url: https://www.iso.org/standard/68960.html; spec: ISOBMFF; type: dfn;
text: compatible_brands
text: FileTypeBox
text: major_brand
+ text: SingleItemTypeReferenceBox
+ text: SingleItemTypeReferenceBoxLarge
+ text: ItemReferenceBox
+ text: reference_count
+ text: from_item_ID
+ text: to_item_ID
+ text: nclx
url: https://www.iso.org/standard/68960.html; spec: ISOBMFF; type: property;
text: sync
@@ -115,7 +135,6 @@ url: https://www.iso.org/standard/74417.html; spec: MIAF; type: dfn;
text: MIAF image sequence
text: MIAF auxiliary image item
text: MIAF auxiliary image sequence
- text: MIAF file
url: https://aomediacodec.github.io/av1-isobmff/; spec: AV1-ISOBMFF; type: dfn;
text: AV1CodecConfigurationBox
@@ -326,7 +345,7 @@ NOTE: The size of the last layer can be determined by subtracting the sum of the
- The track shall be a valid [=MIAF image sequence=].
- The track handler for an [=AV1 Image Sequence=] shall be pict
.
- - The track shall have only one sample description entry.
+ - The track shall have only one [=AV1 Sample=] description entry.
- If multiple [=Sequence Header OBUs=] are present in the track payload, they shall be identical.
Other Image Items and Sequences
@@ -352,6 +371,283 @@ NOTE: [[!AV1]] supports encoding either 3-component images (whose semantics are
A tone map derived image item ('tmap') as defined in [[!HEIF]] may be used in an [=AVIF=] file. When present, the base image item and the 'tmap' image item should be grouped together by an '[=AVIF/altr=]' entity group as recommended in [[!HEIF]].
+
+
+In these sections, a "sample" refers to the value of a pixel for a given channel.
+
+
+
+When a [=derived image item=] is of type sato, it is called a Sample Transform Derived Image Item, and its reconstructed image is formed from a set of input image items, constants and operators.
+
+The input images are specified in the [=SingleItemTypeReferenceBox=]
or [=SingleItemTypeReferenceBoxLarge=]
entries of type 'dimg' for this [=Sample Transform Derived Image Item=] within the [=ItemReferenceBox=]
. The input images are in the same order as specified in these entries. In the [=SingleItemTypeReferenceBox=]
or [=SingleItemTypeReferenceBoxLarge=]
of type 'dimg', the value of the [=from_item_ID=]
field identifies the [=Sample Transform Derived Image Item=], and the values of the [=to_item_ID=]
field identify the input images. There are [=reference_count=]
input image items as specified by the [=ItemReferenceBox=]
.
+
+The input image items and the [=Sample Transform Derived Image Item=] shall:
+ - each have a 'pixi' property and an 'ispe' property;
+ - have the same number of channels and the same chroma subsampling (or lack thereof) as defined by the 'pixi' and '[=AV1ItemConfigurationProperty/av1C=]' properties;
+ - have the same dimensions as defined by the 'ispe' property;
+ - have the same color information as defined by the 'colr' properties (or lack thereof).
+
+Each output sample of the [=Sample Transform Derived Image Item=] is obtained by evaluating an expression consisting of a series of integer operators and operands. An operand is a constant or a sample from an input image item located at the same channel index and at the same spatial coordinates as the output sample.
+
+No color space conversion, matrix coefficients, or transfer characteristics function shall be applied to the input samples. They are already in the same color space as the output samples.
+
+The output reconstructed image is made up of the output samples, whose values shall be each clamped to fit in the number of bits per sample as defined by the 'pixi' property of the reconstructed image item. The full_range_flag
field of the 'colr' property of colour_type
nclx
also defines a range of values to clamp to, as defined in [[!CICP]].
+
+An 8-bit primary [=MIAF image item=] can be combined with another 8-bit hidden [=MIAF image item=], both used as input image items to a [=Sample Transform Derived Image Item=], with an expression corresponding to ReconstructedSample = 256 × PrimarySample + HiddenSample. The primary [=MIAF image item=] and the [=Sample Transform Derived Image Item=] are both part of the same altr
group. This will be perceived as a backward-compatible regular 8-bit image to readers not supporting [=Sample Transform Derived Image Items=], and can be decoded as a 16-bit image otherwise, making that pattern a bit-depth extension mechanism.
+
+
+
+An expression is a series of tokens. A token is an operand or an operator. An operand can be a literal constant value or a sample value. A stack is used to keep track of the results of the subexpressions. An operator takes either one or two input operands. Each unary operator pops one value from the stack. Each binary operator pops two values from the stack, the first being the right operand and the second being the left operand. Each token results in a value pushed to the stack. The single remaining value in the stack after evaluating the whole expression is the resulting output sample.
+
+```c
+aligned(8) class SampleTransform {
+ unsigned int(2) version = 0;
+ unsigned int(4) reserved;
+ unsigned int(2) bit_depth; // Signed 8, 16, 32 or 64-bit.
+ unsigned int(8) token_count;
+ for (i=0; iSemantics
+
+version shall be equal to 0. Readers shall not process a SampleTransform
with an unrecognized version
number.
+
+reserved shall be equal to 0 in files conforming to this version of this specification. The value of reserved
shall be ignored by readers.
+
+bit_depth determines the precision (from 8 to 64 bits, see Table 1) of the signed integer temporary variable supporting the intermediate results of the operations. It also determines the precision of the stack elements and the field size of the constant
fields. This intermediate precision shall be high enough so that all input sample values fit into that signed bit depth.
+
+
+
+ Table 1 - Mapping from bit_depth
to the intermediate bit depth.
+
+
+
+ Value of bit_depth |
+ Intermediate bit depth (sign bit inclusive) num_bits |
+
+
+
+ 0 | 8 |
+ 1 | 16 |
+ 2 | 32 |
+ 3 | 64 |
+
+
+
+The result of any computation underflowing or overflowing the intermediate bit depth is replaced by -2num_bits
-1 and 2num_bits
-1-1, respectively. Encoder implementations should not create files leading to potential computation underflow or overflow. Decoder implementations shall check for computation underflow or overflow and clamp the results accordingly. Computations with operands of negative values use the two’s-complement representation.
+
+token_count is the expected number of tokens to read.
+
+token determines the type of the operand (constant or input image item sample) or the operator (how to transform one or two operands into the result). See Table 2. Values other than the ones in the table below are reserved.
+
+Note: token
values greater than 1 and less than 128 are unary operators, and token
values greater than or equal to 128 are binary operators.
+
+
+
+ Table 2 - Meaning of the value of token
.
+
+
+
+ Value of token |
+ Name |
+ Input count |
+ Meaning before pushing to the stack |
+ Value pushed to the stack ( and refer to operands popped from the stack for operators) |
+
+
+
+
+ 0 |
+ constant operand |
+ 0 |
+ bits from the stream read as a signed integer. |
+ constant value |
+
+
+ 1 |
+ sample operand |
+ 0 |
+ Sample value from the input_image_item_index th input image item. |
+ input image item sample value |
+
+
+ 2 |
+ negation operator |
+ 1 |
+ Negation of the left operand. |
+ |
+
+
+ 3 |
+ absolute value operator |
+ 1 |
+ Absolute value of the left operand. |
+ |
+
+
+ 4 |
+ not operator |
+ 1 |
+ Bitwise complement of the operand. |
+ |
+
+
+ 5 |
+ bsr operator |
+ 1 |
+ 0-based index of the most significant set bit of the left operand if the left operand is strictly positive, zero otherwise. |
+
+
+ |
+
+
+ 128 |
+ sum operator |
+ 2 |
+ Left operand added to the right operand. |
+ |
+
+
+ 129 |
+ difference operator |
+ 2 |
+ Right operand subtracted from the left operand. |
+ |
+
+
+ 130 |
+ product operator |
+ 2 |
+ Left operand multiplied by the right operand. |
+ |
+
+
+ 131 |
+ quotient operator |
+ 2 |
+ Left operand divided by the right operand if the right operand is not zero, left operand otherwise. The result is truncated toward zero (integer division). |
+
+
+ |
+
+
+ 132 |
+ and operator |
+ 2 |
+ Bitwise conjunction of the operands. |
+ |
+
+
+ 133 |
+ or operator |
+ 2 |
+ Bitwise inclusive disjunction of the operands. |
+ |
+
+
+ 134 |
+ xor operator |
+ 2 |
+ Bitwise exclusive disjunction of the operands. |
+ |
+
+
+ 135 |
+ pow operator |
+ 2 |
+ Left operand raised to the power of the right operand if the left operand is not zero, zero otherwise. |
+
+
+ |
+
+
+ 136 |
+ min operator |
+ 2 |
+ Minimum value among the operands. |
+
+
+ |
+
+
+ 137 |
+ max operator |
+ 2 |
+ Maximum value among the operands. |
+
+
+ |
+
+
+
+
+constant is a literal signed value extracted from the stream with a precision of intermediate bit depth, pushed to the stack.
+
+input_image_item_index is the 1-based index of the input image item whose sample is pushed to the stack. Shall be at least 1 and at most [=reference_count=]
.
+
+
+
+[=Sample Transform Derived Image Items=] use the postfix notation to evaluate the result of the whole expression for each reconstructed image item sample.
+
+ - The tokens shall be evaluated in the order they are defined in the metadata (the SampleTransform
structure) of the [=Sample Transform Derived Image Item=].
+ - There shall be at least one token.
+ - The stack is empty before evaluating the first token.
+ - There shall be at least C elements in the stack before evaluating a token
, where C is that token
's input count (defined by Table 2).
+ - There shall be exactly one remaining element in the stack after evaluating the last token. This element is the value of the reconstructed image item sample.
+
+Non-compliant expressions shall be rejected by parsers as invalid files.
+
+Note: Because each operator pops one or two elements and then pushes one element to the stack, there is at most one more operand than operators in the expression. There are at least operators and at most operands. token_count
is at most 255, meaning the maximum stack size for a valid expression is 128.
+
Entity groups
The GroupsListBox ('grpl') defined in [[!ISOBMFF]] may be used to group multiple image items in a file together. The type of the group describes how the image items are related. Decoders should ignore groups of unknown type.
@@ -445,7 +741,7 @@ A file containing a 'pict' track compliant with this profile is expected to list
avis, msf1, miaf, MA1B
-A file containing a 'pict' track compliant with this profile and made only of samples marked 'sync' is expected to list the following brands, in any order, in the [=compatible_brands=] of the [=FileTypeBox=]:
+A file containing a 'pict' track compliant with this profile and made only of [=AV1 Samples=] marked 'sync' is expected to list the following brands, in any order, in the [=compatible_brands=] of the [=FileTypeBox=]:
avis, avio, msf1, miaf, MA1B
@@ -857,3 +1153,4 @@ Other versions of the boxes shall not be used. "-" means that the box does not h
- Further clarify relationship between av1C, metadata OBUs and item properties
- Add information on tmap, grpl and altr
- Replace recommendations regarding still picture flags in image items by a note
+ - Add section 4.2.2 "Sample Transform Derived Image Item"
From b21779dd2a50721f055c1ec4245b6f378cc1499a Mon Sep 17 00:00:00 2001
From: Yannis Guyon
Date: Wed, 18 Sep 2024 07:50:55 +0000
Subject: [PATCH 29/65] Add Sample Transform rationale (#245)
Make it obvious that AVIF also supports 16-bit.
---
index.bs | 2 ++
1 file changed, 2 insertions(+)
diff --git a/index.bs b/index.bs
index bd99d0c..5c3b1b8 100755
--- a/index.bs
+++ b/index.bs
@@ -375,6 +375,8 @@ A tone map derived image item ('tmap') as defined in [[!HEIF]] may be used in an
In these sections, a "sample" refers to the value of a pixel for a given channel.
+With a Sample Transform Derived Image Item, pixels at the same position in multiple input image items can be combined into a single output pixel using basic mathematical operations. This makes it possible for [=AVIF=] to support 16 or more bits of precision per sample, while still offering backward compatibility through a regular 8 to 12-bit [=AV1 Image Item=] containing the most significant bits of each sample.
+
When a [=derived image item=] is of type sato, it is called a Sample Transform Derived Image Item, and its reconstructed image is formed from a set of input image items, constants and operators.
From b6758cadb9be71ed6680a520a629d5180858de2e Mon Sep 17 00:00:00 2001
From: Yannis Guyon
Date: Fri, 20 Sep 2024 11:05:13 +0000
Subject: [PATCH 30/65] Specify Sample Transform syntax versioning (#246)
Increase unary operator range to 64+ to leave room for more operand
token types.
---
index.bs | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/index.bs b/index.bs
index 5c3b1b8..a4f14c2 100755
--- a/index.bs
+++ b/index.bs
@@ -417,9 +417,9 @@ aligned(8) class SampleTransform {
// input image item to the stack. At most 'reference_count'.
unsigned int(8) input_image_item_index; // 1-based
} else {
- if (token < 128) {
+ if (token >= 64 && token <= 67) {
// Unary operator. Pop an operand from the stack.
- } else {
+ } else if (token >= 128 && token <= 137) {
// Binary operator. Pop the right operand
// and then the left operand from the stack.
}
@@ -431,9 +431,9 @@ aligned(8) class SampleTransform {
-version shall be equal to 0. Readers shall not process a SampleTransform
with an unrecognized version
number.
+version shall be equal to 0. Readers shall ignore a SampleTransform
with an unrecognized version
number.
-reserved shall be equal to 0 in files conforming to this version of this specification. The value of reserved
shall be ignored by readers.
+reserved shall be equal to 0. The value of reserved
shall be ignored by readers.
bit_depth determines the precision (from 8 to 64 bits, see Table 1) of the signed integer temporary variable supporting the intermediate results of the operations. It also determines the precision of the stack elements and the field size of the constant
fields. This intermediate precision shall be high enough so that all input sample values fit into that signed bit depth.
@@ -459,9 +459,9 @@ The result of any computation underflowing or overflowing the intermediate bit d
token_count is the expected number of tokens to read.
-token determines the type of the operand (constant or input image item sample) or the operator (how to transform one or two operands into the result). See Table 2. Values other than the ones in the table below are reserved.
+token determines the type of the operand (constant or input image item sample) or the operator (how to transform one or two operands into the result). See Table 2. Values other than the ones in Table 2 below are reserved. Readers shall ignore a SampleTransform
with a reserved token
value.
-Note: token
values greater than 1 and less than 128 are unary operators, and token
values greater than or equal to 128 are binary operators.
+Note: token
values greater than or equal to 64 and less than or equal to 67 are unary operators, and token
values greater than or equal to 128 and less than or equal to 137 are binary operators.
@@ -492,28 +492,28 @@ Note: token
values greater than 1 and less than 128 are unary opera
input image item sample value |
- 2 |
+ 64 |
negation operator |
1 |
Negation of the left operand. |
|
- 3 |
+ 65 |
absolute value operator |
1 |
Absolute value of the left operand. |
|
- 4 |
+ 66 |
not operator |
1 |
Bitwise complement of the operand. |
|
- 5 |
+ 67 |
bsr operator |
1 |
0-based index of the most significant set bit of the left operand if the left operand is strictly positive, zero otherwise. |
From 81ad232924df6f35703d9de19b1e397f2950c0ad Mon Sep 17 00:00:00 2001
From: Yannis Guyon
Date: Tue, 24 Sep 2024 09:15:31 +0000
Subject: [PATCH 31/65] Replace explicit input_image_item_index by token (#248)
Clarify the comments of the SampleTransform syntax code snippet.
Refactor Table 2 columns.
---
index.bs | 104 ++++++++++++++++++++++++++++++-------------------------
1 file changed, 57 insertions(+), 47 deletions(-)
diff --git a/index.bs b/index.bs
index a4f14c2..a6a0774 100755
--- a/index.bs
+++ b/index.bs
@@ -412,13 +412,12 @@ aligned(8) class SampleTransform {
if (token == 0) {
// Push the 'constant' value to the stack.
signed int(1<<(bit_depth+3)) constant;
- } else if (token == 1) {
- // Push the sample value from the 'input_image_item_index'th
- // input image item to the stack. At most 'reference_count'.
- unsigned int(8) input_image_item_index; // 1-based
+ } else if (token <= 32) {
+ // Push the sample value from the 'token'th input image item
+ // to the stack.
} else {
if (token >= 64 && token <= 67) {
- // Unary operator. Pop an operand from the stack.
+ // Unary operator. Pop the operand from the stack.
} else if (token >= 128 && token <= 137) {
// Binary operator. Pop the right operand
// and then the left operand from the stack.
@@ -426,6 +425,7 @@ aligned(8) class SampleTransform {
// Apply operator 'token' and push the result to the stack.
}
}
+ // Output the single remaining stack element.
}
```
@@ -459,9 +459,7 @@ The result of any computation underflowing or overflowing the intermediate bit d
token_count is the expected number of tokens to read.
-token determines the type of the operand (constant or input image item sample) or the operator (how to transform one or two operands into the result). See Table 2. Values other than the ones in Table 2 below are reserved. Readers shall ignore a SampleTransform
with a reserved token
value.
-
-Note: token
values greater than or equal to 64 and less than or equal to 67 are unary operators, and token
values greater than or equal to 128 and less than or equal to 137 are binary operators.
+token determines the type of the operand (constant or input image item sample) or the operator (how to transform one or two operands into the result). See Table 2. Readers shall ignore a SampleTransform
with a reserved token
value.
@@ -470,8 +468,8 @@ Note: token
values greater than or equal to 64 and less than or equ
Value of token |
- Name |
- Input count |
+ Token name |
+ Token type |
Meaning before pushing to the stack |
Value pushed to the stack ( and refer to operands popped from the stack for operators) |
@@ -479,43 +477,47 @@ Note: token
values greater than or equal to 64 and less than or equ
0 |
- constant operand |
- 0 |
+ constant |
+ operand |
bits from the stream read as a signed integer. |
constant value |
- 1 |
- sample operand |
- 0 |
- Sample value from the input_image_item_index th input image item. |
+ 1..32 |
+ sample |
+ operand |
+ Sample value from the token th input image item (token is the 1-based index of the input image item whose sample is pushed to the stack). |
input image item sample value |
+
+ 33..63 |
+ Reserved |
+
64 |
- negation operator |
- 1 |
+ negation |
+ unary operator |
Negation of the left operand. |
|
65 |
- absolute value operator |
- 1 |
+ absolute value |
+ unary operator |
Absolute value of the left operand. |
|
66 |
- not operator |
- 1 |
+ not |
+ unary operator |
Bitwise complement of the operand. |
|
67 |
- bsr operator |
- 1 |
+ bsr |
+ unary operator |
0-based index of the most significant set bit of the left operand if the left operand is strictly positive, zero otherwise. |
|
+
+ 68..127 |
+ Reserved |
+
128 |
- sum operator |
- 2 |
+ sum |
+ binary operator |
Left operand added to the right operand. |
|
129 |
- difference operator |
- 2 |
+ difference |
+ binary operator |
Right operand subtracted from the left operand. |
|
130 |
- product operator |
- 2 |
+ product |
+ binary operator |
Left operand multiplied by the right operand. |
|
131 |
- quotient operator |
- 2 |
+ quotient |
+ binary operator |
Left operand divided by the right operand if the right operand is not zero, left operand otherwise. The result is truncated toward zero (integer division). |
|
132 |
- and operator |
- 2 |
+ and |
+ binary operator |
Bitwise conjunction of the operands. |
|
133 |
- or operator |
- 2 |
+ or |
+ binary operator |
Bitwise inclusive disjunction of the operands. |
|
134 |
- xor operator |
- 2 |
+ xor |
+ binary operator |
Bitwise exclusive disjunction of the operands. |
|
135 |
- pow operator |
- 2 |
+ pow |
+ binary operator |
Left operand raised to the power of the right operand if the left operand is not zero, zero otherwise. |
|
136 |
- min operator |
- 2 |
+ min |
+ binary operator |
Minimum value among the operands. |
|
137 |
- max operator |
- 2 |
+ max |
+ binary operator |
Maximum value among the operands. |
|
+
+ 138..255 |
+ Reserved |
+
constant is a literal signed value extracted from the stream with a precision of intermediate bit depth, pushed to the stack.
-input_image_item_index is the 1-based index of the input image item whose sample is pushed to the stack. Shall be at least 1 and at most [=reference_count=]
.
-
[=Sample Transform Derived Image Items=] use the postfix notation to evaluate the result of the whole expression for each reconstructed image item sample.
- The tokens shall be evaluated in the order they are defined in the metadata (the SampleTransform
structure) of the [=Sample Transform Derived Image Item=].
+ - token
shall be at most [=reference_count=]
when evaluating a sample operand (when ).
- There shall be at least one token.
- The stack is empty before evaluating the first token.
- - There shall be at least C elements in the stack before evaluating a token
, where C is that token
's input count (defined by Table 2).
+ - There shall be at least 1 element in the stack before evaluating a unary operator.
+ - There shall be at least 2 elements in the stack before evaluating a binary operator.
- There shall be exactly one remaining element in the stack after evaluating the last token. This element is the value of the reconstructed image item sample.
Non-compliant expressions shall be rejected by parsers as invalid files.
From e82a232bd4d157671fd771ca9c99545ed19da35f Mon Sep 17 00:00:00 2001
From: Wan-Teh Chang
Date: Mon, 23 Sep 2024 08:27:50 -0700
Subject: [PATCH 32/65] Add Wan-Teh Chang as an editor
---
index.bs | 1 +
1 file changed, 1 insertion(+)
diff --git a/index.bs b/index.bs
index a6a0774..f5857b4 100755
--- a/index.bs
+++ b/index.bs
@@ -7,6 +7,7 @@ URL: https://AOMediaCodec.github.io/av1-avif
Shortname: av1-avif
Editor: Yannis Guyon, Google, yguyon@google.com
Editor: Leo Barnes, Apple, lbarnes@apple.com
+Editor: Wan-Teh Chang, Google, wtc@google.com
Former Editor: Cyril Concolato, Netflix, cconcolato@netflix.com
Former Editor: Paul Kerr, Netflix, pkerr@netflix.com
Former Editor: Anders Klemets, Microsoft, Anders.Klemets@microsoft.com
From adc56d5124e860b1f0ffdef2162f4311ac71082e Mon Sep 17 00:00:00 2001
From: leo-barnes
Date: Wed, 25 Sep 2024 09:01:54 +0200
Subject: [PATCH 33/65] Add restriction on 'clap' property (#232)
Add restriction on 'clap' property. This closes #188.
---
index.bs | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/index.bs b/index.bs
index f5857b4..28b6c6e 100755
--- a/index.bs
+++ b/index.bs
@@ -236,6 +236,12 @@ NOTE: The dimensions indicated in the 'ispe' property might not match the values
NOTE: The values of [=render_width_minus1=] and [=render_height_minus1=] possibly present in the AV1 bistream are not exposed in the AVIF container level.
+Clean Aperture Property
+
+The semantics of the clean aperture property ('clap') as defined in [[!HEIF]] apply. In addition to the restrictions on transformative item property ordering specified in [[!MIAF]], the following restriction also applies:
+
+The origin of the 'clap' item property shall be anchored to 0,0 (top-left) of the input image unless the full, un-cropped image item is included as a secondary non-hidden image item.
+
Other Item Properties
In addition to the Image Properties defined in this document, [=AV1 image items=] MAY also be associated with item properties defined in other specifications such as [[!HEIF]] and [[!MIAF]]. Examples of commonly used item properties are:
@@ -255,8 +261,6 @@ In addition to the Image Properties defined in this document, [=AV1 image items=
In general, it is recommended to use properties instead of [=Metadata OBUs=] in the [=AV1ItemConfigurationProperty=].
-NOTE: Although the clean aperture property ('clap') defined in [[!HEIF]] is applicable to AVIF, implementers of authoring tools should be aware of the possibility of unintended consequences since users may not realize image data outside the clap region is still in the file. A future revision of this specification may place normative restrictions on how clap can be used.
-
AV1 Layered Image Items
Overview
@@ -1167,3 +1171,4 @@ Other versions of the boxes shall not be used. "-" means that the box does not h
- Add information on tmap, grpl and altr
- Replace recommendations regarding still picture flags in image items by a note
- Add section 4.2.2 "Sample Transform Derived Image Item"
+ - Add restriction on usage of clap property
From 1796daebfe3edf4a3a8d07341072904d2312f2ca Mon Sep 17 00:00:00 2001
From: leo-barnes
Date: Wed, 25 Sep 2024 09:07:43 +0200
Subject: [PATCH 34/65] Adopt MIAF shared constraints (#240)
Adopt MIAF shared constraints. This closes #169.
---
index.bs | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/index.bs b/index.bs
index 28b6c6e..23117d8 100755
--- a/index.bs
+++ b/index.bs
@@ -136,6 +136,11 @@ url: https://www.iso.org/standard/74417.html; spec: MIAF; type: dfn;
text: MIAF image sequence
text: MIAF auxiliary image item
text: MIAF auxiliary image sequence
+ text: self-containment
+ text: grid-limit
+ text: single-track
+ text: edit-lists
+ text: matched-duration
url: https://aomediacodec.github.io/av1-isobmff/; spec: AV1-ISOBMFF; type: dfn;
text: AV1CodecConfigurationBox
@@ -742,6 +747,15 @@ This section defines the MIAF AV1 Baseline profile of [[!HEIF]], specifically fo
If the brand MA1B
is in the list of [=compatible_brands=] of the [=FileTypeBox=], the common constraints in the section [[#brands]] shall apply.
+The following shared conditions and requirements from [[!MIAF]] shall apply:
+ - [=self-containment=] (subclause 8.2)
+
+The following shared conditions and requirements from [[!MIAF]] should apply:
+ - [=grid-limit=] (subclause 8.4)
+ - [=single-track=] (subclause 8.5)
+ - [=edit-lists=] (subclause 8.6)
+ - [=matched-duration=] (subclause 8.7)
+
The following additional constraints apply to all [=AV1 Image Items=] and all [=AV1 Image Sequences=]:
- The AV1 profile shall be the Main Profile and the level shall be 5.1 or lower.
@@ -769,6 +783,15 @@ This section defines the MIAF AV1 Advanced profile of [[!HEIF]], specifically fo
If the brand MA1A
is in the list of [=compatible_brands=] of the [=FileTypeBox=], the common constraints in the section [[#brands]] shall apply.
+The following shared conditions and requirements from [[!MIAF]] shall apply:
+ - [=self-containment=] (subclause 8.2)
+
+The following shared conditions and requirements from [[!MIAF]] should apply:
+ - [=grid-limit=] (subclause 8.4)
+ - [=single-track=] (subclause 8.5)
+ - [=edit-lists=] (subclause 8.6)
+ - [=matched-duration=] (subclause 8.7)
+
The following additional constraints apply to all [=AV1 Image Items=]:
- The AV1 profile shall be the High Profile and the level shall be 6.0 or lower.
@@ -1172,3 +1195,4 @@ Other versions of the boxes shall not be used. "-" means that the box does not h
- Replace recommendations regarding still picture flags in image items by a note
- Add section 4.2.2 "Sample Transform Derived Image Item"
- Add restriction on usage of clap property
+ - Adopt MIAF shared constraints
From 7f87801c978721f83d8a9980b84dcc07283ae9c8 Mon Sep 17 00:00:00 2001
From: leo-barnes
Date: Wed, 25 Sep 2024 19:46:51 +0200
Subject: [PATCH 35/65] Clean up use of dfn and linking (#251)
Clean up use of dfn and linking. This closes #244.
---
index.bs | 294 ++++++++++++++++++++++++++++---------------------------
1 file changed, 148 insertions(+), 146 deletions(-)
diff --git a/index.bs b/index.bs
index 23117d8..e070a90 100755
--- a/index.bs
+++ b/index.bs
@@ -78,7 +78,7 @@ Metadata Order: This version, !*, *
-url: https://www.iso.org/standard/66067.html; spec: HEIF; type: property;
+url: https://www.iso.org/standard/66067.html; spec: HEIF; type: dfn;
text: colr
text: mif1
text: msf1
@@ -104,9 +104,10 @@ url: https://www.iso.org/standard/66067.html; spec: HEIF; type: property;
text: image_height
text: ster
text: tmap
-
-url: https://www.iso.org/standard/66067.html; spec: HEIF; type: dfn;
text: derived image item
+ text: aux_type
+ text: AuxiliaryTypeInfoBox
+ text: AuxiliaryTypeProperty
url: https://www.iso.org/standard/68960.html; spec: ISOBMFF; type: dfn;
text: compatible_brands
@@ -119,18 +120,20 @@ url: https://www.iso.org/standard/68960.html; spec: ISOBMFF; type: dfn;
text: from_item_ID
text: to_item_ID
text: nclx
-
-url: https://www.iso.org/standard/68960.html; spec: ISOBMFF; type: property;
text: sync
text: iloc
text: mdat
text: idat
text: altr
-
-url: https://www.iso.org/standard/74417.html; spec: MIAF; type: property;
- text: miaf
+ text: matrix_coefficients
+ text: full_range_flag
+ text: colour_type
+ text: meta
+ text: free
+ text: skip
url: https://www.iso.org/standard/74417.html; spec: MIAF; type: dfn;
+ text: miaf
text: primary image
text: MIAF image item
text: MIAF image sequence
@@ -155,8 +158,6 @@ url: https://aomediacodec.github.io/av1-spec/av1-spec.pdf; spec: AV1; type: dfn;
text: Temporal Unit
text: Operating Point
text: Intra Frame
-
-url: https://aomediacodec.github.io/av1-spec/av1-spec.pdf; spec: AV1; type: dfn;
text: mono_chrome
text: color_range
text: still_picture
@@ -195,9 +196,9 @@ This specification reuses syntax and semantics used in [[!AV1-ISOBMFF]].
When an item is of type av01, it is called an AV1 Image Item, and shall obey the following constraints:
- The [=AV1 Image Item=] shall be a conformant [=MIAF image item=].
- - The [=AV1 Image Item=] shall be associated with an [=AV1ItemConfigurationProperty=].
+ - The [=AV1 Image Item=] shall be associated with an [=AV1ItemConfigurationProperty=]
.
- The content of an [=AV1 Image Item=] is called the AV1 Image Item Data and shall obey the following constraints:
- - The [=AV1 Image Item Data=] shall be identical to the content of an [=AV1 Sample=] marked as 'sync', as defined in [[!AV1-ISOBMFF]].
+ - The [=AV1 Image Item Data=] shall be identical to the content of an [=AV1 Sample=] marked as '[=sync=]'
, as defined in [[!AV1-ISOBMFF]].
- The [=AV1 Image Item Data=] shall have exactly one [=Sequence Header OBU=].
NOTE: File writers may want to set the [=still_picture=]
and [=reduced_still_picture_header=]
flags to 1 when possible in the [=Sequence Header OBU=] part of the [=AV1 Image Item Data=] so that AV1 header overhead is minimized.
@@ -210,61 +211,61 @@ NOTE: File writers may want to set the [=still_picture=]
and
Box Type: av1C
Property type: Descriptive item property
Container: ItemPropertyContainerBox
- Mandatory (per item): Yes, for an image item of type 'av01', no otherwise
- Quantity (per item): One for an image item of type 'av01', zero otherwise
+ Mandatory (per item): Yes, for an image item of type 'av01'
, no otherwise
+ Quantity (per item): One for an image item of type 'av01'
, zero otherwise
-The syntax and semantics of the AV1ItemConfigurationProperty are identical to those of the [=AV1CodecConfigurationBox=] defined in [[!AV1-ISOBMFF]], with the following constraints:
+The syntax and semantics of the AV1ItemConfigurationProperty are identical to those of the [=AV1CodecConfigurationBox=]
defined in [[!AV1-ISOBMFF]], with the following constraints:
- - [=Sequence Header OBUs=] should not be present in the [=AV1CodecConfigurationBox=].
- - If a [=Sequence Header OBU=] is present in the [=AV1CodecConfigurationBox=], it shall match the [=Sequence Header OBU=] in the [=AV1 Image Item Data=].
- - The values of the fields in the [=AV1CodecConfigurationBox=] shall match those of the [=Sequence Header OBU=] in the [=AV1 Image Item Data=].
- - The values of the bit depth and the number of channels derived from the [=AV1CodecConfigurationBox=] shall match the PixelInformationProperty if present.
+ - [=Sequence Header OBUs=] should not be present in the [=AV1CodecConfigurationBox=]
.
+ - If a [=Sequence Header OBU=] is present in the [=AV1CodecConfigurationBox=]
, it shall match the [=Sequence Header OBU=] in the [=AV1 Image Item Data=].
+ - The values of the fields in the [=AV1CodecConfigurationBox=]
shall match those of the [=Sequence Header OBU=] in the [=AV1 Image Item Data=].
+ - The values of the bit depth and the number of channels derived from the [=AV1CodecConfigurationBox=]
shall match the PixelInformationProperty if present.
- [=Metadata OBUs=], if present, shall match the values given in other item properties, such as the MasteringDisplayColourVolumeBox or ContentLightLevelBox.
This property should be marked as essential.
Image Spatial Extents Property
-The semantics of the 'ispe' property as defined in [[!HEIF]] apply. More specifically, for AV1 images, the values of 'image_width' and 'image_height' shall respectively equal the values of [=UpscaledWidth=] and [=FrameHeight=] as defined in [[!AV1]] but for a specific frame in the item payload. The exact frame depends on the presence and content of the 'lsel' and [=OperatingPointSelectorProperty=] properties as follows:
+The semantics of the '[=ispe=]'
property as defined in [[!HEIF]] apply. More specifically, for AV1 images, the values of [=image_width=]
and [=image_height=]
shall respectively equal the values of [=UpscaledWidth=]
and [=FrameHeight=]
as defined in [[!AV1]] but for a specific frame in the item payload. The exact frame depends on the presence and content of the '[=lsel=]'
and [=OperatingPointSelectorProperty=]
properties as follows:
- - In the absence of a 'lsel' property associated with the item, or if it is present and its 'layer_id' value is set to 0xFFFF:
- - If no [=OperatingPointSelectorProperty=] is associated with the item, the 'ispe' shall document the dimensions of the last frame decoded when processing the operating point whose index is 0.
+ - In the absence of a '[=lsel=]'
property associated with the item, or if it is present and its [=layer_id=]
value is set to 0xFFFF:
+ - If no [=OperatingPointSelectorProperty=]
is associated with the item, the '[=ispe=]'
shall document the dimensions of the last frame decoded when processing the operating point whose index is 0.
- - If an [=OperatingPointSelectorProperty=] is associated with the item, the 'ispe' property shall document the dimensions of the last frame decoded when processing the corresponding operating point.
+ - If an [=OperatingPointSelectorProperty=]
is associated with the item, the '[=ispe=]'
property shall document the dimensions of the last frame decoded when processing the corresponding operating point.
- NOTE: The dimensions of possible intermediate output images might not match the ones given in the 'ispe' property. If they display these intermediate images, renderers are expected to scale the output image to match the 'ispe' property.
+ NOTE: The dimensions of possible intermediate output images might not match the ones given in the '[=ispe=]'
property. If they display these intermediate images, renderers are expected to scale the output image to match the '[=ispe=]'
property.
- - If a 'lsel' property is associated with an item and its 'layer_id' is different from 0xFFFF, the 'ispe' property documents the dimensions of the output frame produced by decoding the corresponding layer.
+ - If a '[=lsel=]'
property is associated with an item and its [=layer_id=]
is different from 0xFFFF, the '[=ispe=]'
property documents the dimensions of the output frame produced by decoding the corresponding layer.
-NOTE: The dimensions indicated in the 'ispe' property might not match the values [=max_frame_width_minus1=]+1 and [=max_frame_height_minus1=]+1 indicated in the AV1 bitstream.
+NOTE: The dimensions indicated in the '[=ispe=]'
property might not match the values [=max_frame_width_minus1=]+1
and [=max_frame_height_minus1=]+1
indicated in the AV1 bitstream.
-NOTE: The values of [=render_width_minus1=] and [=render_height_minus1=] possibly present in the AV1 bistream are not exposed in the AVIF container level.
+NOTE: The values of [=render_width_minus1=]
and [=render_height_minus1=]
possibly present in the AV1 bistream are not exposed in the AVIF container level.
Clean Aperture Property
-The semantics of the clean aperture property ('clap') as defined in [[!HEIF]] apply. In addition to the restrictions on transformative item property ordering specified in [[!MIAF]], the following restriction also applies:
+The semantics of the clean aperture property ('[=clap=]'
) as defined in [[!HEIF]] apply. In addition to the restrictions on transformative item property ordering specified in [[!MIAF]], the following restriction also applies:
-The origin of the 'clap' item property shall be anchored to 0,0 (top-left) of the input image unless the full, un-cropped image item is included as a secondary non-hidden image item.
+The origin of the '[=clap=]'
item property shall be anchored to 0,0 (top-left) of the input image unless the full, un-cropped image item is included as a secondary non-hidden image item.
Other Item Properties
In addition to the Image Properties defined in this document, [=AV1 image items=] MAY also be associated with item properties defined in other specifications such as [[!HEIF]] and [[!MIAF]]. Examples of commonly used item properties are:
- - 'colr'
- - 'pixi'
- - 'pasp'
- - 'irot'
- - 'imir'
- - 'clli'
- - 'cclv'
- - 'mdcv'
- - 'amve'
- - 'reve'
- - 'ndwt'
- - 'cmin'
- - 'cmex'
-
-In general, it is recommended to use properties instead of [=Metadata OBUs=] in the [=AV1ItemConfigurationProperty=].
+ - '[=colr=]'
+ - '[=pixi=]'
+ - '[=pasp=]'
+ - '[=irot=]'
+ - '[=imir=]'
+ - '[=clli=]'
+ - '[=cclv=]'
+ - '[=mdcv=]'
+ - '[=amve=]'
+ - '[=reve=]'
+ - '[=ndwt=]'
+ - '[=cmin=]'
+ - '[=cmex=]'
+
+In general, it is recommended to use properties instead of [=Metadata OBUs=] in the [=AV1ItemConfigurationProperty=]
.
AV1 Layered Image Items
@@ -272,13 +273,13 @@ In general, it is recommended to use properties instead of [=Metadata OBUs=] in
[[!AV1]] supports encoding a frame using multiple spatial layers. A spatial layer may improve the resolution or quality of the image decoded based on one or more of the previous layers. A layer may also provide an image that does not depend on the previous layers. Additionally, not all layers are expected to produce an image meant to be rendered. Some decoded images may be used only as intermediate decodes. Finally, layers are grouped into one or more [=Operating Points=]. The [=Sequence Header OBU=] defines the list of [=Operating Points=], provides required decoding capabilities, and indicates which layers form each [=Operating Point=].
-[[!AV1]] delegates the selection of which [=Operating Point=] to process to the application, by means of a function called choose_operating_point()
. AVIF defines the [=OperatingPointSelectorProperty=] to control this selection. In the absence of an [=OperatingPointSelectorProperty=] associated with an [=AV1 Image Item=], the AVIF renderer is free to process any [=Operating Point=] present in the [=AV1 Image Item Data=]. In particular, when the [=AV1 Image Item=] is composed of a unique [=Operating Point=], the [=OperatingPointSelectorProperty=] should not be present. If an [=OperatingPointSelectorProperty=] is associated with an [=AV1 Image Item=], the op_index
field indicates which [=Operating Point=] is expected to be processed for this item.
+[[!AV1]] delegates the selection of which [=Operating Point=] to process to the application, by means of a function called choose_operating_point()
. AVIF defines the [=OperatingPointSelectorProperty=]
to control this selection. In the absence of an [=OperatingPointSelectorProperty=]
associated with an [=AV1 Image Item=], the AVIF renderer is free to process any [=Operating Point=] present in the [=AV1 Image Item Data=]. In particular, when the [=AV1 Image Item=] is composed of a unique [=Operating Point=], the [=OperatingPointSelectorProperty=]
should not be present. If an [=OperatingPointSelectorProperty=]
is associated with an [=AV1 Image Item=], the [=op_index=]
field indicates which [=Operating Point=] is expected to be processed for this item.
-NOTE: When an author wants to offer the ability to render multiple [=Operating Points=] from the same AV1 image (e.g. in the case of multi-view images), multiple [=AV1 Image Items=] can be created that share the same [=AV1 Image Item Data=] but have different [=OperatingPointSelectorProperty=]s.
+NOTE: When an author wants to offer the ability to render multiple [=Operating Points=] from the same AV1 image (e.g. in the case of multi-view images), multiple [=AV1 Image Items=] can be created that share the same [=AV1 Image Item Data=] but have different [=OperatingPointSelectorProperty=]
s.
-[[!AV1]] expects the renderer to display only one frame within the selected [=Operating Point=], which should be the highest spatial layer that is both within the [=Operating Point=] and present within the temporal unit, but [[!AV1]] leaves the option for other applications to set their own policy about which frames are output, as defined in the general output process. AVIF sets a different policy, and defines how the 'lsel' property (mandated by [[!HEIF]] for layered images) is used to control which layer is rendered. According to [[!HEIF]], the interpretation of the 'layer_id' field in the 'lsel' property is codec specific. In this specification, the value 0xFFFF is reserved for a special meaning. If a 'lsel' property is associated with an [=AV1 Image Item=] but its 'layer_id' value is set to 0xFFFF, the renderer is free to render either only the output image of the highest spatial layer, or to render all output images of all the intermediate layers and the highest spatial layer, resulting in a form of progressive decoding. If a 'lsel' property is associated with an [=AV1 Image Item=] and the value of 'layer_id' is not 0xFFFF, the renderer is expected to render only the output image for that layer.
+[[!AV1]] expects the renderer to display only one frame within the selected [=Operating Point=], which should be the highest spatial layer that is both within the [=Operating Point=] and present within the temporal unit, but [[!AV1]] leaves the option for other applications to set their own policy about which frames are output, as defined in the general output process. AVIF sets a different policy, and defines how the '[=lsel=]'
property (mandated by [[!HEIF]] for layered images) is used to control which layer is rendered. According to [[!HEIF]], the interpretation of the [=layer_id=]
field in the '[=lsel=]'
property is codec specific. In this specification, the value 0xFFFF is reserved for a special meaning. If a '[=lsel=]'
property is associated with an [=AV1 Image Item=] but its [=layer_id=]
value is set to 0xFFFF, the renderer is free to render either only the output image of the highest spatial layer, or to render all output images of all the intermediate layers and the highest spatial layer, resulting in a form of progressive decoding. If a '[=lsel=]'
property is associated with an [=AV1 Image Item=] and the value of [=layer_id=]
is not 0xFFFF, the renderer is expected to render only the output image for that layer.
-NOTE: When such a progressive decoding of the layers within an [=Operating Point=] is not desired or when an author wants to expose each layer as a specific item, multiple [=AV1 Image Items=] sharing the same [=AV1 Image Item Data=] can be created and associated with different 'lsel' properties, each with a different value of 'layer_id'.
+NOTE: When such a progressive decoding of the layers within an [=Operating Point=] is not desired or when an author wants to expose each layer as a specific item, multiple [=AV1 Image Items=] sharing the same [=AV1 Image Item Data=] can be created and associated with different '[=lsel=]'
properties, each with a different value of [=layer_id=]
.
Properties
Operating Point Selector Property
@@ -310,7 +311,7 @@ class OperatingPointSelectorProperty extends ItemProperty('a1op') {
op_index indicates the index of the operating point to be processed for this item. Its value shall be between 0 and [=operating_points_cnt_minus_1=].
Layer Selector Property
-The 'lsel' property defined in [[!HEIF]] may be associated with an [=AV1 Image Item=]. The 'layer_id' indicates the value of the [=spatial_id=] to render. The value shall be between 0 and 3, or the special value 0xFFFF. When a value between 0 and 3 is used, the corresponding spatial layer shall be present in the bitstream and shall produce an output frame. Other layers may be needed to decode the indicated layer. When the special value 0xFFFF is used, progressive decoding is allowed as described in [[#layered-items-overview]].
+The '[=lsel=]'
property defined in [[!HEIF]] may be associated with an [=AV1 Image Item=]. The [=layer_id=]
indicates the value of the [=spatial_id=]
to render. The value shall be between 0 and 3, or the special value 0xFFFF. When a value between 0 and 3 is used, the corresponding spatial layer shall be present in the bitstream and shall produce an output frame. Other layers may be needed to decode the indicated layer. When the special value 0xFFFF is used, progressive decoding is allowed as described in [[#layered-items-overview]].
Layered Image Indexing Property
@@ -328,7 +329,7 @@ The 'lsel' property defined in [[!HEIF]] may be associated with an [=AV1 Image I
The AV1LayeredImageIndexingProperty property may be associated with an [=AV1 Image Item=]. It should not be associated with [=AV1 Image Items=] consisting of only one layer.
-The [=AV1LayeredImageIndexingProperty=] documents the size in bytes of each layer (except the last one) in the [=AV1 Image Item Data=], and enables determining the byte ranges required to process one or more layers of an [=Operating Point=]. If associated, it shall not be marked as essential.
+The [=AV1LayeredImageIndexingProperty=]
documents the size in bytes of each layer (except the last one) in the [=AV1 Image Item Data=], and enables determining the byte ranges required to process one or more layers of an [=Operating Point=]. If associated, it shall not be marked as essential.
Syntax
@@ -343,18 +344,18 @@ class AV1LayeredImageIndexingProperty extends ItemProperty('a1lx') {
Semantics
-layer_size indicates the number of bytes corresponding to each layer in the item payload, except for the last layer. Values are provided in increasing order of [=spatial_id=]. A value of zero means that all the layers except the last one have been documented and following values shall be 0. The number of non-zero values shall match the number of layers in the image minus one..
+layer_size indicates the number of bytes corresponding to each layer in the item payload, except for the last layer. Values are provided in increasing order of [=spatial_id=]
. A value of zero means that all the layers except the last one have been documented and following values shall be 0. The number of non-zero values shall match the number of layers in the image minus one..
NOTE: The size of the last layer can be determined by subtracting the sum of the sizes of all layers indicated in this property from the entire item size.
-A property indicating [X,0,0] is used for an image item composed of 2 layers. The size of the first layer is X and the size of the second layer is ItemSize - X. Note that the [=spatial_id=] for the first layer does not necessarily match the index in the array that provides the size. In other words, in this case the index giving value X is 0, but the corresponding [=spatial_id=] could be 0, 1 or 2. Similarly, a property indicating [X,Y,0] is used for an image made of 3 layers.
+A property indicating [X,0,0] is used for an image item composed of 2 layers. The size of the first layer is X and the size of the second layer is ItemSize - X. Note that the [=spatial_id=]
for the first layer does not necessarily match the index in the array that provides the size. In other words, in this case the index giving value X is 0, but the corresponding [=spatial_id=]
could be 0, 1 or 2. Similarly, a property indicating [X,Y,0] is used for an image made of 3 layers.
Image Sequences
An AV1 Image Sequence is defined as a set of AV1 [=Temporal Units=] stored in an [=AV1 track=] as defined in [[!AV1-ISOBMFF]] with the following constraints:
- The track shall be a valid [=MIAF image sequence=].
- - The track handler for an [=AV1 Image Sequence=] shall be pict
.
+ - The track handler for an [=AV1 Image Sequence=] shall be '[=pict=]'
.
- The track shall have only one [=AV1 Sample=] description entry.
- If multiple [=Sequence Header OBUs=] are present in the track payload, they shall be identical.
@@ -367,19 +368,19 @@ NOTE: The size of the last layer can be determined by subtracting the sum of the
- The [=mono_chrome=]
field in the [=Sequence Header OBU=] shall be set to 1.
- The [=color_range=]
field in the [=Sequence Header OBU=] shall be set to 1.
-An AV1 Alpha Image Item (respectively an AV1 Alpha Image Sequence) is an [=AV1 Auxiliary Image Item=] (respectively an [=AV1 Auxiliary Image Sequence=]), and as defined in [[!MIAF]], with the aux_type
field of the AuxiliaryTypeProperty
(respectively AuxiliaryTypeInfoBox
) set to urn:mpeg:mpegB:cicp:systems:auxiliary:alpha
. An [=AV1 Alpha Image Item=] (respectively an [=AV1 Alpha Image Sequence=]) shall be encoded with the same bit depth as the associated master [=AV1 Image Item=] (respectively [=AV1 Image Sequence=]).
+An AV1 Alpha Image Item (respectively an AV1 Alpha Image Sequence) is an [=AV1 Auxiliary Image Item=] (respectively an [=AV1 Auxiliary Image Sequence=]), and as defined in [[!MIAF]], with the [=aux_type=]
field of the [=AuxiliaryTypeProperty=]
(respectively [=AuxiliaryTypeInfoBox=]
) set to urn:mpeg:mpegB:cicp:systems:auxiliary:alpha
. An [=AV1 Alpha Image Item=] (respectively an [=AV1 Alpha Image Sequence=]) shall be encoded with the same bit depth as the associated master [=AV1 Image Item=] (respectively [=AV1 Image Sequence=]).
For [=AV1 Alpha Image Item=] and [=AV1 Alpha Image Sequence=], the ColourInformationBox should be omitted. If present, readers shall ignore it.
-An AV1 Depth Image Item (respectively an AV1 Depth Image Sequence) is an [=AV1 Auxiliary Image Item=] (respectively an [=AV1 Auxiliary Image Sequence=]), and as defined in [[!MIAF]], with the aux_type
field of the AuxiliaryTypeProperty
(respectively AuxiliaryTypeInfoBox
) set to urn:mpeg:mpegB:cicp:systems:auxiliary:depth
.
+An AV1 Depth Image Item (respectively an AV1 Depth Image Sequence) is an [=AV1 Auxiliary Image Item=] (respectively an [=AV1 Auxiliary Image Sequence=]), and as defined in [[!MIAF]], with the [=aux_type=]
field of the [=AuxiliaryTypeProperty=]
(respectively [=AuxiliaryTypeInfoBox=]
) set to urn:mpeg:mpegB:cicp:systems:auxiliary:depth
.
-NOTE: [[!AV1]] supports encoding either 3-component images (whose semantics are given by the matrix_coefficients
element), or 1-component images (monochrome). When an image requires a different number of components, multiple auxiliary images may be used, each providing additional component(s), according to the semantics of their aux_type
field. In such case, the maximum number of components is restricted by number of possible items in a file, coded on 16 or 32 bits.
+NOTE: [[!AV1]] supports encoding either 3-component images (whose semantics are given by the [=matrix_coefficients=]
element), or 1-component images (monochrome). When an image requires a different number of components, multiple auxiliary images may be used, each providing additional component(s), according to the semantics of their [=aux_type=]
field. In such case, the maximum number of components is restricted by number of possible items in a file, coded on 16 or 32 bits.
Derived Image Items
Tone Map Derived Image Item
-A tone map derived image item ('tmap') as defined in [[!HEIF]] may be used in an [=AVIF=] file. When present, the base image item and the 'tmap' image item should be grouped together by an '[=AVIF/altr=]' entity group as recommended in [[!HEIF]].
+A tone map derived image item ('[=tmap=]'
) as defined in [[!HEIF]] may be used in an [=AVIF=] file. When present, the base image item and the '[=tmap=]'
image item should be grouped together by an '[=AVIF/altr=]' entity group as recommended in [[!HEIF]].
@@ -389,27 +390,27 @@ With a Sample Transform Derived Image Item, pixels at the same position in multi
-When a [=derived image item=] is of type sato, it is called a Sample Transform Derived Image Item, and its reconstructed image is formed from a set of input image items, constants and operators.
+When a [=derived image item=] is of type sato, it is called a Sample Transform Derived Image Item, and its reconstructed image is formed from a set of input image items, [=sato/constants=] and [=sato/operators=].
-The input images are specified in the [=SingleItemTypeReferenceBox=]
or [=SingleItemTypeReferenceBoxLarge=]
entries of type 'dimg' for this [=Sample Transform Derived Image Item=] within the [=ItemReferenceBox=]
. The input images are in the same order as specified in these entries. In the [=SingleItemTypeReferenceBox=]
or [=SingleItemTypeReferenceBoxLarge=]
of type 'dimg', the value of the [=from_item_ID=]
field identifies the [=Sample Transform Derived Image Item=], and the values of the [=to_item_ID=]
field identify the input images. There are [=reference_count=]
input image items as specified by the [=ItemReferenceBox=]
.
+The input images are specified in the [=SingleItemTypeReferenceBox=]
or [=SingleItemTypeReferenceBoxLarge=]
entries of type '[=dimg=]'
for this [=Sample Transform Derived Image Item=] within the [=ItemReferenceBox=]
. The input images are in the same order as specified in these entries. In the [=SingleItemTypeReferenceBox=]
or [=SingleItemTypeReferenceBoxLarge=]
of type '[=dimg=]'
, the value of the [=from_item_ID=]
field identifies the [=Sample Transform Derived Image Item=], and the values of the [=to_item_ID=]
field identify the input images. There are [=reference_count=]
input image items as specified by the [=ItemReferenceBox=]
.
The input image items and the [=Sample Transform Derived Image Item=] shall:
- - each have a 'pixi' property and an 'ispe' property;
- - have the same number of channels and the same chroma subsampling (or lack thereof) as defined by the 'pixi' and '[=AV1ItemConfigurationProperty/av1C=]' properties;
- - have the same dimensions as defined by the 'ispe' property;
- - have the same color information as defined by the 'colr' properties (or lack thereof).
+ - each have a '[=pixi=]'
property and an '[=ispe=]'
property;
+ - have the same number of channels and the same chroma subsampling (or lack thereof) as defined by the '[=pixi=]'
and '[=AV1ItemConfigurationProperty/av1C=]'
properties;
+ - have the same dimensions as defined by the '[=ispe=]'
property;
+ - have the same color information as defined by the '[=colr=]'
properties (or lack thereof).
-Each output sample of the [=Sample Transform Derived Image Item=] is obtained by evaluating an expression consisting of a series of integer operators and operands. An operand is a constant or a sample from an input image item located at the same channel index and at the same spatial coordinates as the output sample.
+Each output sample of the [=Sample Transform Derived Image Item=] is obtained by evaluating an expression consisting of a series of integer [=sato/operators=] and [=sato/operands=]. An [=sato/operand=] is a constant or a sample from an input image item located at the same channel index and at the same spatial coordinates as the output sample.
No color space conversion, matrix coefficients, or transfer characteristics function shall be applied to the input samples. They are already in the same color space as the output samples.
-The output reconstructed image is made up of the output samples, whose values shall be each clamped to fit in the number of bits per sample as defined by the 'pixi' property of the reconstructed image item. The full_range_flag
field of the 'colr' property of colour_type
nclx
also defines a range of values to clamp to, as defined in [[!CICP]].
+The output reconstructed image is made up of the output samples, whose values shall be each clamped to fit in the number of bits per sample as defined by the '[=pixi=]'
property of the reconstructed image item. The [=full_range_flag=]
field of the '[=colr=]'
property of [=colour_type=]
'[=nclx=]'
also defines a range of values to clamp to, as defined in [[!CICP]].
-An 8-bit primary [=MIAF image item=] can be combined with another 8-bit hidden [=MIAF image item=], both used as input image items to a [=Sample Transform Derived Image Item=], with an expression corresponding to ReconstructedSample = 256 × PrimarySample + HiddenSample. The primary [=MIAF image item=] and the [=Sample Transform Derived Image Item=] are both part of the same altr
group. This will be perceived as a backward-compatible regular 8-bit image to readers not supporting [=Sample Transform Derived Image Items=], and can be decoded as a 16-bit image otherwise, making that pattern a bit-depth extension mechanism.
+An 8-bit primary [=MIAF image item=] can be combined with another 8-bit hidden [=MIAF image item=], both used as input image items to a [=Sample Transform Derived Image Item=], with an expression corresponding to ReconstructedSample = 256 × PrimarySample + HiddenSample. The primary [=MIAF image item=] and the [=Sample Transform Derived Image Item=] are both part of the same '[=AVIF/altr=]'
group. This will be perceived as a backward-compatible regular 8-bit image to readers not supporting [=Sample Transform Derived Image Items=], and can be decoded as a 16-bit image otherwise, making that pattern a bit-depth extension mechanism.
-An expression is a series of tokens. A token is an operand or an operator. An operand can be a literal constant value or a sample value. A stack is used to keep track of the results of the subexpressions. An operator takes either one or two input operands. Each unary operator pops one value from the stack. Each binary operator pops two values from the stack, the first being the right operand and the second being the left operand. Each token results in a value pushed to the stack. The single remaining value in the stack after evaluating the whole expression is the resulting output sample.
+An expression is a series of [=sato/tokens=]. A [=sato/token=] is an [=sato/operand=] or an [=sato/operator=]. An [=sato/operand=] can be a literal constant value or a sample value. A stack is used to keep track of the results of the subexpressions. An [=sato/operator=] takes either one or two input [=sato/operands=]. Each unary [=sato/operator=] pops one value from the stack. Each binary [=sato/operator=] pops two values from the stack, the first being the right [=sato/operand=] and the second being the left [=sato/operand=]. Each [=sato/token=] results in a value pushed to the stack. The single remaining value in the stack after evaluating the whole expression is the resulting output sample.
```c
aligned(8) class SampleTransform {
@@ -441,20 +442,20 @@ aligned(8) class SampleTransform {
-version shall be equal to 0. Readers shall ignore a SampleTransform
with an unrecognized version
number.
+version shall be equal to 0. Readers shall ignore a [=Sample Transform Derived Image Item=] with an unrecognized [=sato/version=]
number.
-reserved shall be equal to 0. The value of reserved
shall be ignored by readers.
+reserved shall be equal to 0. The value of [=sato/reserved=]
shall be ignored by readers.
-bit_depth determines the precision (from 8 to 64 bits, see Table 1) of the signed integer temporary variable supporting the intermediate results of the operations. It also determines the precision of the stack elements and the field size of the constant
fields. This intermediate precision shall be high enough so that all input sample values fit into that signed bit depth.
+bit_depth determines the precision (from 8 to 64 bits, see Table 1) of the signed integer temporary variable supporting the intermediate results of the operations. It also determines the precision of the stack elements and the field size of the [=sato/constant=]
fields. This intermediate precision shall be high enough so that all input sample values fit into that signed bit depth.
- Table 1 - Mapping from bit_depth
to the intermediate bit depth.
+ Table 1 - Mapping from [=sato/bit_depth=]
to the intermediate bit depth.
- Value of bit_depth |
- Intermediate bit depth (sign bit inclusive) num_bits |
+ Value of [=sato/bit_depth=] |
+ Intermediate bit depth (sign bit inclusive) num_bits |
@@ -465,38 +466,38 @@ aligned(8) class SampleTransform {
-The result of any computation underflowing or overflowing the intermediate bit depth is replaced by -2num_bits
-1 and 2num_bits
-1-1, respectively. Encoder implementations should not create files leading to potential computation underflow or overflow. Decoder implementations shall check for computation underflow or overflow and clamp the results accordingly. Computations with operands of negative values use the two’s-complement representation.
+The result of any computation underflowing or overflowing the intermediate bit depth is replaced by -2[=sato/num_bits=]
-1 and 2[=sato/num_bits=]
-1-1, respectively. Encoder implementations should not create files leading to potential computation underflow or overflow. Decoder implementations shall check for computation underflow or overflow and clamp the results accordingly. Computations with [=sato/operands=] of negative values use the two’s-complement representation.
-token_count is the expected number of tokens to read.
+token_count is the expected number of [=sato/tokens=] to read.
-token determines the type of the operand (constant or input image item sample) or the operator (how to transform one or two operands into the result). See Table 2. Readers shall ignore a SampleTransform
with a reserved token
value.
+token determines the type of the operand ([=sato/constant=]
or input image item sample) or the operator (how to transform one or two [=sato/operands=] into the result). See Table 2. Readers shall ignore a [=Sample Transform Derived Image Item=] with a reserved [=sato/token=]
value.
- Table 2 - Meaning of the value of token
.
+ Table 2 - Meaning of the value of [=sato/token=]
.
- Value of token |
+ Value of [=sato/token=] |
Token name |
Token type |
Meaning before pushing to the stack |
- Value pushed to the stack ( and refer to operands popped from the stack for operators) |
+ Value pushed to the stack ( and refer to [=sato/operands=] popped from the stack for [=sato/operators=]) |
0 |
constant |
- operand |
- bits from the stream read as a signed integer. |
+ [=sato/operand=] |
+ bits from the stream read as a signed integer. |
constant value |
1..32 |
sample |
- operand |
- Sample value from the token th input image item (token is the 1-based index of the input image item whose sample is pushed to the stack). |
+ [=sato/operand=] |
+ Sample value from the [=sato/token=] th input image item ([=sato/token=] is the 1-based index of the input image item whose sample is pushed to the stack). |
input image item sample value |
@@ -506,29 +507,29 @@ The result of any computation underflowing or overflowing the intermediate bit d
64 |
negation |
- unary operator |
- Negation of the left operand. |
+ unary [=sato/operator=] |
+ Negation of the left [=sato/operand=]. |
|
65 |
absolute value |
- unary operator |
- Absolute value of the left operand. |
+ unary [=sato/operator=] |
+ Absolute value of the left [=sato/operand=]. |
|
66 |
not |
- unary operator |
- Bitwise complement of the operand. |
+ unary [=sato/operator=] |
+ Bitwise complement of the [=sato/operand=]. |
|
67 |
bsr |
- unary operator |
- 0-based index of the most significant set bit of the left operand if the left operand is strictly positive, zero otherwise. |
+ unary [=sato/operator=] |
+ 0-based index of the most significant set bit of the left [=sato/operand=] if the left [=sato/operand=] is strictly positive, zero otherwise. |
|
-constant is a literal signed value extracted from the stream with a precision of intermediate bit depth, pushed to the stack.
+constant is a literal signed value extracted from the stream with a precision of [=sato/intermediate bit depth=], pushed to the stack.
[=Sample Transform Derived Image Items=] use the postfix notation to evaluate the result of the whole expression for each reconstructed image item sample.
- - The tokens shall be evaluated in the order they are defined in the metadata (the SampleTransform
structure) of the [=Sample Transform Derived Image Item=].
- - token
shall be at most [=reference_count=]
when evaluating a sample operand (when 1≤token≤32).
- - There shall be at least one token.
- - The stack is empty before evaluating the first token.
- - There shall be at least 1 element in the stack before evaluating a unary operator.
- - There shall be at least 2 elements in the stack before evaluating a binary operator.
- - There shall be exactly one remaining element in the stack after evaluating the last token. This element is the value of the reconstructed image item sample.
+ - The [=sato/tokens=] shall be evaluated in the order they are defined in the metadata (the SampleTransform
structure) of the [=Sample Transform Derived Image Item=].
+ - [=sato/token=]
shall be at most [=reference_count=]
when evaluating a sample [=sato/operand=] (when 1≤token≤32).
+ - There shall be at least one [=sato/token=]
.
+ - The stack is empty before evaluating the first [=sato/token=]
.
+ - There shall be at least 1 element in the stack before evaluating a unary [=sato/operator=].
+ - There shall be at least 2 elements in the stack before evaluating a binary [=sato/operator=].
+ - There shall be exactly one remaining element in the stack after evaluating the last [=sato/token=]
. This element is the value of the reconstructed image item sample.
Non-compliant expressions shall be rejected by parsers as invalid files.
-Note: Because each operator pops one or two elements and then pushes one element to the stack, there is at most one more operand than operators in the expression. There are at least floor(token_count2) operators and at most ceil(token_count2) operands. token_count
is at most 255, meaning the maximum stack size for a valid expression is 128.
+Note: Because each [=sato/operator=] pops one or two elements and then pushes one element to the stack, there is at most one more [=sato/operand=] than [=sato/operators=] in the expression. There are at least floor([=sato/token_count=]2) [=sato/operators=] and at most ceil(token_count2) [=sato/operands=]. [=sato/token_count=]
is at most 255, meaning the maximum stack size for a valid expression is 128.
Entity groups
The GroupsListBox ('grpl') defined in [[!ISOBMFF]] may be used to group multiple image items in a file together. The type of the group describes how the image items are related. Decoders should ignore groups of unknown type.
-'altr' group
+'[=/altr=]'
group
-The 'altr' entity group as defined in [[!ISOBMFF]] may be used to mark multiple items as alternatives to each other. Only one item in the 'altr' group should be played or processed. This grouping is useful for defining a fallback for parsers when new types of items or essential item properties are introduced.
+The 'altr' entity group as defined in [[!ISOBMFF]] may be used to mark multiple items as alternatives to each other. Only one item in the '[=AVIF/altr=]'
group should be played or processed. This grouping is useful for defining a fallback for parsers when new types of items or essential item properties are introduced.
-'ster' group
+'[=/ster=]'
group
The 'ster' entity group as defined in [[!HEIF]] may be used to indicate that two image items form a stereo pair suitable for stereoscopic viewing.
@@ -690,37 +691,37 @@ The 'ster' entity group as defined in [[!HEIF]] may be use
An [=AV1 Image File Format=] file may conform to multiple brands. Similarly, an [=AV1 Image File Format=] reader/parser or [=AV1 Image File Format=] renderer may be capable of processing the features associated with one or more brands.
-If any of the brands defined in this document is specified in the [=major_brand=]
field of the [=FileTypeBox=], the file extension and Internet Media Type should respectively be ".avif
" and "image/avif
" as defined in [[#mime-registration]].
+If any of the brands defined in this document is specified in the [=major_brand=]
field of the [=FileTypeBox=]
, the file extension and Internet Media Type should respectively be ".avif
" and "image/avif
" as defined in [[#mime-registration]].
AVIF image and image collection brand
The brand to identify [=AV1 image items=] is avif.
-Files that indicate this brand in the [=compatible_brands=] field of the [=FileTypeBox=] shall comply with the following:
+Files that indicate this brand in the [=compatible_brands=]
field of the [=FileTypeBox=]
shall comply with the following:
- The primary item shall be an [=AV1 Image Item=] or be a derived image that references directly or indirectly one or more items that all are [=AV1 Image Items=].
- [=AV1 auxiliary image items=] may be present in the file.
-Files that conform with these constraints should include the brand [=avif=]
in the [=compatible_brands=] field of the [=FileTypeBox=].
+Files that conform with these constraints should include the brand [=avif=]
in the [=compatible_brands=]
field of the [=FileTypeBox=]
.
-Additionally, the brand avio is defined. If the file indicates the brand [=avio=]
in the [=compatible_brands=] field of the [=FileTypeBox=], then the primary item or all the items referenced by the primary item shall be [=AV1 image items=] made only of [=Intra Frames=]. Conversely, if the previous constraint applies, the brand [=avio=]
should be used in the [=compatible_brands=] field of the [=FileTypeBox=].
+Additionally, the brand avio is defined. If the file indicates the brand [=avio=]
in the [=compatible_brands=]
field of the [=FileTypeBox=]
, then the primary item or all the items referenced by the primary item shall be [=AV1 image items=] made only of [=Intra Frames=]. Conversely, if the previous constraint applies, the brand [=avio=]
should be used in the [=compatible_brands=]
field of the [=FileTypeBox=]
.
AVIF image sequence brands
The brand to identify AVIF image sequences is avis.
-Files that indicate this brand in the [=compatible_brands=] field of the [=FileTypeBox=] shall comply with the following:
+Files that indicate this brand in the [=compatible_brands=]
field of the [=FileTypeBox=]
shall comply with the following:
- they shall contain one or more [=AV1 image sequences=].
- they may contain [=AV1 auxiliary image sequences=].
-Files that conform with these constraints should include the brand [=avis=]
in the [=compatible_brands=] field of the [=FileTypeBox=].
+Files that conform with these constraints should include the brand [=avis=]
in the [=compatible_brands=]
field of the [=FileTypeBox=]
.
-Additionally, if a file contains [=AV1 image sequences=] and the brand [=avio=]
is used in the [=compatible_brands=] field of the [=FileTypeBox=], the item constraints for this brand shall be met and at least one of the [=AV1 image sequences=] shall be made only of [=AV1 Samples=] marked as 'sync'. Conversely, if such a track exists and the constraints of the brand [=avio=]
on [=AV1 image items=] are met, the brand should be used.
+Additionally, if a file contains [=AV1 image sequences=] and the brand [=avio=]
is used in the [=compatible_brands=]
field of the [=FileTypeBox=]
, the item constraints for this brand shall be met and at least one of the [=AV1 image sequences=] shall be made only of [=AV1 Samples=] marked as '[=sync=]'
. Conversely, if such a track exists and the constraints of the brand [=avio=]
on [=AV1 image items=] are met, the brand should be used.
NOTE: As defined in [[!MIAF]], a file that is primarily an image sequence still has at least an image item. Hence, it can also declare brands for signaling the image item.
General constraints
The following constraints are common to files compliant with this specification:
- - The file shall be compliant with the [[!MIAF]] specification and list 'miaf' in the [=compatible_brands=] field of the [=FileTypeBox=].
- - The file shall list '[=avif=]'
or '[=avis=]'
in the [=compatible_brands=] field of the [=FileTypeBox=].
+ - The file shall be compliant with the [[!MIAF]] specification and list '[=miaf=]'
in the [=compatible_brands=]
field of the [=FileTypeBox=]
.
+ - The file shall list '[=avif=]'
or '[=avis=]'
in the [=compatible_brands=]
field of the [=FileTypeBox=]
.
- Transformative properties shall not be associated with items in a derivation chain (as defined in [[!MIAF]]) that serves as an input to a grid item. For example, if a file contains a grid item and its referenced coded image items, cropping, mirroring or rotation transformations are only permitted on the grid item itself.
NOTE: This constraint further restricts files compared to [[!MIAF]].
@@ -731,13 +732,13 @@ NOTE: This constraint further restricts files compared to [[!MIAF]].
The profiles defined in this section are for enabling interoperability between [=AV1 Image File Format=] files and [=AV1 Image File Format=] readers/parsers. A profile imposes a set of specific restrictions and is signaled by brands defined in this specification.
-The [=FileTypeBox=] should declare at least one profile that enables decoding of the primary image item. It is not an error for the encoder to include an auxiliary image that is not allowed by the specified profile(s).
+The [=FileTypeBox=]
should declare at least one profile that enables decoding of the primary image item. It is not an error for the encoder to include an auxiliary image that is not allowed by the specified profile(s).
-If '[=avis=]'
is declared in the [=FileTypeBox=] and a profile is declared in the [=FileTypeBox=], the profile shall also enable decoding of at least one image sequence track. The profile should allow decoding of any associated auxiliary image sequence tracks, unless it is acceptable to decode the image sequence without its auxiliary image sequence tracks.
+If '[=avis=]'
is declared in the [=FileTypeBox=]
and a profile is declared in the [=FileTypeBox=]
, the profile shall also enable decoding of at least one image sequence track. The profile should allow decoding of any associated auxiliary image sequence tracks, unless it is acceptable to decode the image sequence without its auxiliary image sequence tracks.
It is possible for a file compliant to this [=AV1 Image File Format=] to not be able to declare an AVIF profile, if the corresponding AV1 encoding characteristics do not match any of the defined profiles.
-NOTE: [[!AV1]] supports 3 bit depths: 8, 10 and 12 bits, and the maximum dimensions of a coded image is 65536x65536, when [=seq_level_idx=] is set to 31 (maximum parameters level).
+NOTE: [[!AV1]] supports 3 bit depths: 8, 10 and 12 bits, and the maximum dimensions of a coded image is 65536x65536, when [=seq_level_idx=]
is set to 31 (maximum parameters level).
If an image is encoded with dimensions (respectively a bit depth) that exceed the maximum dimensions (respectively bit depth) required by the AV1 profile and level of the AVIF profiles defined in this specification, the file will only signal general AVIF brands.
@@ -745,7 +746,7 @@ NOTE: [[!AV1]] supports 3 bit depths: 8, 10 and 12 bits, and the maximum dimensi
This section defines the MIAF AV1 Baseline profile of [[!HEIF]], specifically for [[!AV1]] bitstreams, based on the constraints specified in [[!MIAF]] and identified by the brand MA1B.
-If the brand MA1B
is in the list of [=compatible_brands=] of the [=FileTypeBox=], the common constraints in the section [[#brands]] shall apply.
+If the brand '[=MA1B=]'
is in the list of [=compatible_brands=]
of the [=FileTypeBox=]
, the common constraints in the section [[#brands]] shall apply.
The following shared conditions and requirements from [[!MIAF]] shall apply:
- [=self-containment=] (subclause 8.2)
@@ -764,15 +765,15 @@ NOTE: AV1 tiers are not constrained because timing is optional in image sequenc
NOTE: Level 5.1 is chosen for the Baseline profile to ensure that no single coded image exceeds 4k resolution, as some decoder may not be able to handle larger images. More precisely, following [[!AV1]] level definitions, coded image items compliant to the AVIF Baseline profile may not have a number of pixels greater than 8912896, a width greater than 8192 or a height greater than 4352. It is still possible to use the Baseline profile to create larger images using grid derivation.
-A file containing items compliant with this profile is expected to list the following brands, in any order, in the [=compatible_brands=] of the [=FileTypeBox=]:
+A file containing items compliant with this profile is expected to list the following brands, in any order, in the [=compatible_brands=]
of the [=FileTypeBox=]
:
avif, mif1, miaf, MA1B
-A file containing a 'pict' track compliant with this profile is expected to list the following brands, in any order, in the [=compatible_brands=] of the [=FileTypeBox=]:
+A file containing a '[=pict=]'
track compliant with this profile is expected to list the following brands, in any order, in the [=compatible_brands=]
of the [=FileTypeBox=]
:
avis, msf1, miaf, MA1B
-A file containing a 'pict' track compliant with this profile and made only of [=AV1 Samples=] marked 'sync' is expected to list the following brands, in any order, in the [=compatible_brands=] of the [=FileTypeBox=]:
+A file containing a '[=pict=]'
track compliant with this profile and made only of [=AV1 Samples=] marked '[=sync=]'
is expected to list the following brands, in any order, in the [=compatible_brands=]
of the [=FileTypeBox=]
:
avis, avio, msf1, miaf, MA1B
@@ -781,7 +782,7 @@ A file containing a 'pict' track compliant with this profile and made only of [=
This section defines the MIAF AV1 Advanced profile of [[!HEIF]], specifically for [[!AV1]] bitstreams, based on the constraints specified in [[!MIAF]] and identified by the brand MA1A.
-If the brand MA1A
is in the list of [=compatible_brands=] of the [=FileTypeBox=], the common constraints in the section [[#brands]] shall apply.
+If the brand '[=MA1A=]'
is in the list of [=compatible_brands=]
of the [=FileTypeBox=]
, the common constraints in the section [[#brands]] shall apply.
The following shared conditions and requirements from [[!MIAF]] shall apply:
- [=self-containment=] (subclause 8.2)
@@ -803,11 +804,11 @@ The following additional constraints apply only to [=AV1 Image Sequences=]:
- The AV1 level for High Profile shall be 5.1 or lower.
-A file containing items compliant with this profile is expected to list the following brands, in any order, in the [=compatible_brands=] of the [=FileTypeBox=]:
+A file containing items compliant with this profile is expected to list the following brands, in any order, in the [=compatible_brands=]
of the [=FileTypeBox=]
:
avif, mif1, miaf, MA1A
-A file containing a 'pict' track compliant with this profile is expected to list the following brands, in any order, in the [=compatible_brands=] of the [=FileTypeBox=]:
+A file containing a '[=pict=]'
track compliant with this profile is expected to list the following brands, in any order, in the [=compatible_brands=]
of the [=FileTypeBox=]
:
avis, msf1, miaf, MA1A
@@ -820,7 +821,7 @@ This section discusses the box requirements for an AVIF file containing only ima
Minimum set of boxes
As indicated in [[#file-constraints]], an AVIF file is a compliant [[!MIAF]] file. As a consequence, some [[!ISOBMFF]] or [[!HEIF]] boxes are required, as indicated in the following table. The order of the boxes is indicative in the table. The specifications listed in the "Specification"
-column may require a specific order for the box or for its children and shall be respected. For example, per [[!ISOBMFF]], the FileTypeBox
is required to appear first in an AVIF file.
+column may require a specific order for the box or for its children and shall be respected. For example, per [[!ISOBMFF]], the [=FileTypeBox=]
is required to appear first in an AVIF file.
The "Version(s)" column in the following table lists the version(s) of the boxes allowed by this brand.
Other versions of the boxes shall not be used. "-" means that the box does not have a version.
@@ -961,14 +962,14 @@ Other versions of the boxes shall not be used. "-" means that the box does not h
|
- |
ISOBMFF |
- The coded payload may be placed in 'idat' rather than 'mdat', in which case 'mdat' is not required. |
+ The coded payload may be placed in '[=idat=]' rather than '[=mdat=]' , in which case '[=mdat=]' is not required. |
Requirements on additional image item related boxes
-The boxes indicated in the following table may be present in an AVIF file to provide additional signaling for image items. The boxes may be present inside the box indicated in the "Containing box" column. If present, they shall use the version indicated in the table and AVIF readers are expected to understand them. The order of the boxes is indicative in the table. Specifications may require specific order and shall be respected. Additionally, the free
and skip
boxes may be present at any level in the hierarchy. AVIF readers are expected to ignore them. Additional boxes in the meta
hierarchy not listed in the following table may also be present and may be ignored by AVIF readers.
+The boxes indicated in the following table may be present in an AVIF file to provide additional signaling for image items. The boxes may be present inside the box indicated in the "Containing box" column. If present, they shall use the version indicated in the table and AVIF readers are expected to understand them. The order of the boxes is indicative in the table. Specifications may require specific order and shall be respected. Additionally, the '[=free=]'
and '[=skip=]'
boxes may be present at any level in the hierarchy. AVIF readers are expected to ignore them. Additional boxes in the '[=meta=]'
hierarchy not listed in the following table may also be present and may be ignored by AVIF readers.
@@ -1195,4 +1196,5 @@ Other versions of the boxes shall not be used. "-" means that the box does not h
- Replace recommendations regarding still picture flags in image items by a note
- Add section 4.2.2 "Sample Transform Derived Image Item"
- Add restriction on usage of clap property
- - Adopt MIAF shared constraints
+ - Adopt MIAF shared constraints
+ - EDITORIAL: Clean up usage of dfn and linking
From 434dbe121f81b9d191ccd26d4ff948ebb4f931ef Mon Sep 17 00:00:00 2001
From: leo-barnes
Date: Fri, 27 Sep 2024 10:51:49 +0200
Subject: [PATCH 36/65] Clarify that non-essential item properties may use
other versions (#250)
Clarify that non-essential item properties may use other versions. This closes #247.
---
index.bs | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/index.bs b/index.bs
index e070a90..31c91d0 100755
--- a/index.bs
+++ b/index.bs
@@ -822,8 +822,7 @@ This section discusses the box requirements for an AVIF file containing only ima
As indicated in [[#file-constraints]], an AVIF file is a compliant [[!MIAF]] file. As a consequence, some [[!ISOBMFF]] or [[!HEIF]] boxes are required, as indicated in the following table. The order of the boxes is indicative in the table. The specifications listed in the "Specification"
column may require a specific order for the box or for its children and shall be respected. For example, per [[!ISOBMFF]], the [=FileTypeBox=]
is required to appear first in an AVIF file.
-The "Version(s)" column in the following table lists the version(s) of the boxes allowed by this brand.
-Other versions of the boxes shall not be used. "-" means that the box does not have a version.
+The "Version(s)" column in the following table lists the version(s) of the boxes allowed by this brand. With the exception of item properties marked as non-essential, other versions of the boxes shall not be used. "-" means that the box does not have a version.
@@ -969,7 +968,7 @@ Other versions of the boxes shall not be used. "-" means that the box does not h
Requirements on additional image item related boxes
-The boxes indicated in the following table may be present in an AVIF file to provide additional signaling for image items. The boxes may be present inside the box indicated in the "Containing box" column. If present, they shall use the version indicated in the table and AVIF readers are expected to understand them. The order of the boxes is indicative in the table. Specifications may require specific order and shall be respected. Additionally, the '[=free=]'
and '[=skip=]'
boxes may be present at any level in the hierarchy. AVIF readers are expected to ignore them. Additional boxes in the '[=meta=]'
hierarchy not listed in the following table may also be present and may be ignored by AVIF readers.
+The boxes indicated in the following table may be present in an AVIF file to provide additional signaling for image items. The boxes may be present inside the box indicated in the "Containing box" column. If present, they shall use the version indicated in the table unless the box is an item property marked as non-essential. AVIF readers are expected to understand the boxes and versions listed in this table. The order of the boxes is indicative in the table. Specifications may require specific order and shall be respected. Additionally, the '[=free=]'
and '[=skip=]'
boxes may be present at any level in the hierarchy. AVIF readers are expected to ignore them. Additional boxes in the '[=meta=]'
hierarchy not listed in the following table may also be present and may be ignored by AVIF readers.
@@ -1198,3 +1197,4 @@ Other versions of the boxes shall not be used. "-" means that the box does not h
- Add restriction on usage of clap property
- Adopt MIAF shared constraints
- EDITORIAL: Clean up usage of dfn and linking
+ - Clarify required versions of non-essential item properties
From 1b5720e31474ba7f91c0dff70aed3a36c02e3990 Mon Sep 17 00:00:00 2001
From: leo-barnes
Date: Fri, 27 Sep 2024 13:46:08 +0200
Subject: [PATCH 37/65] Remove "value" from sato definition (#255)
---
index.bs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/index.bs b/index.bs
index 31c91d0..539ed85 100755
--- a/index.bs
+++ b/index.bs
@@ -390,7 +390,7 @@ With a Sample Transform Derived Image Item, pixels at the same position in multi
-When a [=derived image item=] is of type sato, it is called a Sample Transform Derived Image Item, and its reconstructed image is formed from a set of input image items, [=sato/constants=] and [=sato/operators=].
+When a [=derived image item=] is of type sato, it is called a Sample Transform Derived Image Item, and its reconstructed image is formed from a set of input image items, [=sato/constants=] and [=sato/operators=].
The input images are specified in the [=SingleItemTypeReferenceBox=]
or [=SingleItemTypeReferenceBoxLarge=]
entries of type '[=dimg=]'
for this [=Sample Transform Derived Image Item=] within the [=ItemReferenceBox=]
. The input images are in the same order as specified in these entries. In the [=SingleItemTypeReferenceBox=]
or [=SingleItemTypeReferenceBoxLarge=]
of type '[=dimg=]'
, the value of the [=from_item_ID=]
field identifies the [=Sample Transform Derived Image Item=], and the values of the [=to_item_ID=]
field identify the input images. There are [=reference_count=]
input image items as specified by the [=ItemReferenceBox=]
.
From fa78f2b44497cf98ee8bc2e6cf9d8dd170d55c9f Mon Sep 17 00:00:00 2001
From: Yannis Guyon
Date: Mon, 7 Oct 2024 08:52:44 +0000
Subject: [PATCH 38/65] Add Appendix A on sato examples (#253)
---
index.bs | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 91 insertions(+), 6 deletions(-)
diff --git a/index.bs b/index.bs
index 539ed85..0be36cc 100755
--- a/index.bs
+++ b/index.bs
@@ -108,6 +108,7 @@ url: https://www.iso.org/standard/66067.html; spec: HEIF; type: dfn;
text: aux_type
text: AuxiliaryTypeInfoBox
text: AuxiliaryTypeProperty
+ text: bits_per_channel
url: https://www.iso.org/standard/68960.html; spec: ISOBMFF; type: dfn;
text: compatible_brands
@@ -134,7 +135,7 @@ url: https://www.iso.org/standard/68960.html; spec: ISOBMFF; type: dfn;
url: https://www.iso.org/standard/74417.html; spec: MIAF; type: dfn;
text: miaf
- text: primary image
+ text: primary image item
text: MIAF image item
text: MIAF image sequence
text: MIAF auxiliary image item
@@ -406,7 +407,7 @@ No color space conversion, matrix coefficients, or transfer characteristics func
The output reconstructed image is made up of the output samples, whose values shall be each clamped to fit in the number of bits per sample as defined by the '[=pixi=]'
property of the reconstructed image item. The [=full_range_flag=]
field of the '[=colr=]'
property of [=colour_type=]
'[=nclx=]'
also defines a range of values to clamp to, as defined in [[!CICP]].
-An 8-bit primary [=MIAF image item=] can be combined with another 8-bit hidden [=MIAF image item=], both used as input image items to a [=Sample Transform Derived Image Item=], with an expression corresponding to ReconstructedSample = 256 × PrimarySample + HiddenSample. The primary [=MIAF image item=] and the [=Sample Transform Derived Image Item=] are both part of the same '[=AVIF/altr=]'
group. This will be perceived as a backward-compatible regular 8-bit image to readers not supporting [=Sample Transform Derived Image Items=], and can be decoded as a 16-bit image otherwise, making that pattern a bit-depth extension mechanism.
+NOTE: [[#sato-examples]] contains examples of Sample Transform Derived Image Item usage.
@@ -659,7 +660,7 @@ The result of any computation underflowing or overflowing the intermediate bit d
[=Sample Transform Derived Image Items=] use the postfix notation to evaluate the result of the whole expression for each reconstructed image item sample.
- - The [=sato/tokens=] shall be evaluated in the order they are defined in the metadata (the SampleTransform
structure) of the [=Sample Transform Derived Image Item=].
+ - The [=sato/tokens=] shall be evaluated in the order they are defined in the metadata (the SampleTransform
structure) of the [=Sample Transform Derived Image Item=].
- [=sato/token=]
shall be at most [=reference_count=]
when evaluating a sample [=sato/operand=] (when 1≤token≤32).
- There shall be at least one [=sato/token=]
.
- The stack is empty before evaluating the first [=sato/token=]
.
@@ -697,12 +698,12 @@ The 'ster' entity group as defined in [[!HEIF]] may be use
The brand to identify [=AV1 image items=] is avif.
Files that indicate this brand in the [=compatible_brands=]
field of the [=FileTypeBox=]
shall comply with the following:
- - The primary item shall be an [=AV1 Image Item=] or be a derived image that references directly or indirectly one or more items that all are [=AV1 Image Items=].
+ - The [=primary image item=] shall be an [=AV1 Image Item=] or be a derived image that references directly or indirectly one or more items that all are [=AV1 Image Items=].
- [=AV1 auxiliary image items=] may be present in the file.
Files that conform with these constraints should include the brand [=avif=]
in the [=compatible_brands=]
field of the [=FileTypeBox=]
.
-Additionally, the brand avio is defined. If the file indicates the brand [=avio=]
in the [=compatible_brands=]
field of the [=FileTypeBox=]
, then the primary item or all the items referenced by the primary item shall be [=AV1 image items=] made only of [=Intra Frames=]. Conversely, if the previous constraint applies, the brand [=avio=]
should be used in the [=compatible_brands=]
field of the [=FileTypeBox=]
.
+Additionally, the brand avio is defined. If the file indicates the brand [=avio=]
in the [=compatible_brands=]
field of the [=FileTypeBox=]
, then the [=primary image item=] or all the items referenced by the [=primary image item=] shall be [=AV1 image items=] made only of [=Intra Frames=]. Conversely, if the previous constraint applies, the brand [=avio=]
should be used in the [=compatible_brands=]
field of the [=FileTypeBox=]
.
AVIF image sequence brands
The brand to identify AVIF image sequences is avis.
@@ -732,7 +733,7 @@ NOTE: This constraint further restricts files compared to [[!MIAF]].
The profiles defined in this section are for enabling interoperability between [=AV1 Image File Format=] files and [=AV1 Image File Format=] readers/parsers. A profile imposes a set of specific restrictions and is signaled by brands defined in this specification.
-The [=FileTypeBox=]
should declare at least one profile that enables decoding of the primary image item. It is not an error for the encoder to include an auxiliary image that is not allowed by the specified profile(s).
+The [=FileTypeBox=]
should declare at least one profile that enables decoding of the [=primary image item=]. It is not an error for the encoder to include an auxiliary image that is not allowed by the specified profile(s).
If '[=avis=]'
is declared in the [=FileTypeBox=]
and a profile is declared in the [=FileTypeBox=]
, the profile shall also enable decoding of at least one image sequence track. The profile should allow decoding of any associated auxiliary image sequence tracks, unless it is acceptable to decode the image sequence without its auxiliary image sequence tracks.
@@ -1194,7 +1195,91 @@ The "Version(s)" column in the following table lists the version(s) of the boxes
- Add information on tmap, grpl and altr
- Replace recommendations regarding still picture flags in image items by a note
- Add section 4.2.2 "Sample Transform Derived Image Item"
+ - Add Appendix A "Sample Transform Derived Image Item Examples"
- Add restriction on usage of clap property
- Adopt MIAF shared constraints
- EDITORIAL: Clean up usage of dfn and linking
- Clarify required versions of non-essential item properties
+
+Appendix A: Sample Transform Derived Image Item Examples
+
+This informative appendix contains example recipes for extending base AVIF features with [=Sample Transform Derived Image Items=].
+
+Bit depth extension
+
+[=Sample Transform Derived Image Items=] allow for more than 12 bits per channel per sample by combining several [=AV1 image items=] in multiple ways.
+
+Suffix bit depth extension
+
+The following example describes how to leverage a [=Sample Transform Derived Image Item=] on top of a regular 8-bit [=MIAF image item=] to extend the decoded bit depth to 16 bits.
+
+Consider the following:
+ - A [=MIAF image item=] being a losslessly coded image item,
and its '[=pixi=]'
property with [=bits_per_channel=]
=8,
+ - Another [=MIAF image item=] being a lossily or losslessly coded image item with the same dimensions and number of samples as the first input image item,
and its '[=pixi=]'
property with [=bits_per_channel=]
=8,
+ - A [=Sample Transform Derived Image Item=] with the two items above as input in this order,
and its '[=pixi=]'
property with [=bits_per_channel=]
=16,
and the following [=SampleTransform=]
fields:
+ - [=sato/version=]
=0
+ - [=sato/bit_depth=]
=2 (signed 32-bit [=sato/constant=]
s, stack values and intermediate results)
+ - [=sato/token_count=]
=5
+ - [=sato/token=]
=0, [=sato/constant=]
=256
+ - [=sato/token=]
=1 (sample from 1st input image item)
+ - [=sato/token=]
=130 (product)
+ - [=sato/token=]
=2 (sample from 2nd input image item)
+ - [=sato/token=]
=128 (sum)
+
+This is equivalent to the following postfix notation (parentheses for clarity):
+
+sampleoutput=(256sample1×)sample2+
+
+This is equivalent to the following infix notation:
+
+sampleoutput=256×sample1+sample2
+
+Each output sample is equal to the sum of a sample of the first input image item shifted to the left by 8 and of a sample of the second input image item. This can be viewed as a bit depth extension of the first input image item by the second input image item. The first input image item contains the 8 most significant bits and the second input image item contains the 8 least significant bits of the output reconstructed image item which has a bit depth of 16, something that is impossible to achieve with a single [=AV1 image item=].
+
+NOTE: If the first input image item is the [=primary image item=] and is enclosed in an '[=AVIF/altr=]'
group with the [=Sample Transform Derived Image Item=], the first input image item is also a backward-compatible 8-bit regular coded image item that can be used by readers that do not support [=Sample Transform Derived Image Items=] or do not need extra precision.
+
+NOTE: The second input image item loses its meaning of least significant part if any of the most significant bits changes, so the first input image item has to be losslessly encoded. The second input image item supports reasonable loss during encoding.
+
+NOTE: This pattern can be used for reconstructed bit depths beyond 16 by combining more than two input image items or with various input bit depth configurations and operations.
+
+Residual bit depth extension
+
+The following example describes how to leverage a [=Sample Transform Derived Image Item=] on top of a regular 12-bit [=MIAF image item=] to extend the decoded bit depth to 16 bits.
+It differs from the [[#sato-example-suffix-bit-depth-extension]] by its slightly longer series of operations allowing its first input image item to be lossily encoded.
+
+Consider the following:
+ - A [=MIAF image item=] being a lossily coded image item,
and its '[=pixi=]'
property with [=bits_per_channel=]
=12,
+ - Another [=MIAF image item=] being a lossily or losslessly coded image item with the same dimensions and number of samples as the first input image item,
and its '[=pixi=]'
property with [=bits_per_channel=]
=8,
with the following contraints:
+ - For each sample position in each plane,
sampleoriginal being the value of the 16-bit original sample at that position in that plane,
sample1 being the value of the 12-bit sample of the first input image at that position in that plane,
sample2 being the value of the sample of the second input image at that position in that plane,
≈ representing similarity within compression loss range,
+ - sample1≈sampleoriginal24
+ - sample2≈sampleoriginal-24×sample1+27
+ - 0≤sample1<212
+ - 0≤sample2<28
+ - 0≤24×sample1+sample2-27<216
NOTE: Files that do not respect this constraint will still decode successfully because Clause [[#sample-transform-definition]] mandates the resulting values to be each clamped to fit in the number of bits per sample as defined by the '[=pixi=]'
property of the reconstructed image item.
+ - A [=Sample Transform Derived Image Item=] with the two items above as input in this order,
and its '[=pixi=]'
property with [=bits_per_channel=]
=16,
and the following [=SampleTransform=]
fields:
+ - [=sato/version=]
=0
+ - [=sato/bit_depth=]
=2 (signed 32-bit [=sato/constant=]
s, stack values and intermediate results)
+ - [=sato/token_count=]
=7
+ - [=sato/token=]
=0, [=sato/constant=]
=16
+ - [=sato/token=]
=1 (sample from 1st input image item)
+ - [=sato/token=]
=130 (product)
+ - [=sato/token=]
=2 (sample from 2nd input image item)
+ - [=sato/token=]
=128 (sum)
+ - [=sato/token=]
=0, [=sato/constant=]
=-128
+ - [=sato/token=]
=128 (sum)
+
+This is equivalent to the following postfix notation (parentheses for clarity):
+
+sampleoutput=((16sample1×)sample2+)128-
+
+This is equivalent to the following infix notation:
+
+sampleoutput=16×sample1+sample2-128
+
+Each output sample is equal to the sum of a sample of the first input image item shifted to the left by 4 and of a sample of the second input image item offset by -128. This can be viewed as a bit depth extension of the first input image item by the second input image item which contains the residuals to correct the precision loss of the first input image item.
+
+NOTE: If the first input image item is the [=primary image item=] and is enclosed in an '[=AVIF/altr=]'
group with the derived image item, the first input image item is also a backward-compatible 12-bit regular coded image item that can be used by decoding contexts that do not support [=Sample Transform Derived Image Items=] or do not need extra precision.
+
+NOTE: The first input image item supports reasonable loss during encoding because the second input image item "overlaps" by 4 bits to correct the loss. The second input image item supports reasonable loss during encoding.
+
+NOTE: This pattern can be used for reconstructed bit depths beyond 16 by combining more than two input image items or with various input bit depth configurations and operations.
From 506c1e42310110984888f02c5e45dfac6cce1baf Mon Sep 17 00:00:00 2001
From: Yannis Guyon
Date: Thu, 10 Oct 2024 08:52:53 +0000
Subject: [PATCH 39/65] Add refs, fix wording and format in clauses 1,2 (#257)
---
index.bs | 38 ++++++++++++++++++++++----------------
1 file changed, 22 insertions(+), 16 deletions(-)
diff --git a/index.bs b/index.bs
index 0be36cc..fab5c70 100755
--- a/index.bs
+++ b/index.bs
@@ -109,6 +109,7 @@ url: https://www.iso.org/standard/66067.html; spec: HEIF; type: dfn;
text: AuxiliaryTypeInfoBox
text: AuxiliaryTypeProperty
text: bits_per_channel
+ text: PixelInformationProperty
url: https://www.iso.org/standard/68960.html; spec: ISOBMFF; type: dfn;
text: compatible_brands
@@ -132,6 +133,9 @@ url: https://www.iso.org/standard/68960.html; spec: ISOBMFF; type: dfn;
text: meta
text: free
text: skip
+ text: ItemPropertyContainerBox
+ text: MasteringDisplayColourVolumeBox
+ text: ContentLightLevelBox
url: https://www.iso.org/standard/74417.html; spec: MIAF; type: dfn;
text: miaf
@@ -180,14 +184,13 @@ url: https://aomediacodec.github.io/av1-spec/av1-spec.pdf; spec: AV1; type: dfn;
[[!AV1]] defines the syntax and semantics of an [=AV1 bitstream=]. The AV1 Image File Format (AVIF) defined in this document supports the storage of a subset of the syntax and semantics of an [=AV1 bitstream=] in a [[!HEIF]] file.
The [=AV1 Image File Format=] defines multiple profiles, which restrict the allowed syntax and semantics of the [=AV1 bitstream=] with the goal to improve interoperability, especially for hardware implementations.
The profiles defined in this specification follow the conventions of the [[!MIAF]] specification.
-Images encoded with AV1 and not meeting the restrictions of the defined profiles may still be compliant to this [=AV1 Image File Format=] if they adhere to the general AVIF requirements.
+Images encoded with [[!AV1]] and not meeting the restrictions of the defined profiles may still be compliant to this [=AV1 Image File Format=] if they adhere to the general AVIF requirements.
[=AV1 Image File Format=] supports High Dynamic Range (HDR) and Wide Color Gamut (WCG) images as well as Standard Dynamic Range (SDR). It supports monochrome images as well as multi-channel images with all the bit depths and color spaces specified in [[!AV1]].
[=AV1 Image File Format=] also supports multi-layer images as specified in [[!AV1]] to be stored both in image items and image sequences.
-An AVIF file is designed to be a conformant [[!HEIF]] file for both image items and image sequences. Specifically, this specification follows the recommendations given in "Annex I: Guidelines On Defining
-New Image Formats and Brands" of [[!HEIF]].
+An AVIF file is designed to be a conformant [[!HEIF]] file for both image items and image sequences. Specifically, this specification follows the recommendations given in "Annex I: Guidelines On Defining New Image Formats and Brands" of [[!HEIF]].
This specification reuses syntax and semantics used in [[!AV1-ISOBMFF]].
@@ -212,26 +215,26 @@ NOTE: File writers may want to set the [=still_picture=]
and
Box Type: av1C
Property type: Descriptive item property
Container: ItemPropertyContainerBox
- Mandatory (per item): Yes, for an image item of type 'av01'
, no otherwise
+ Mandatory (per item): Yes, for an image item of type 'av01'
, no otherwise
Quantity (per item): One for an image item of type 'av01'
, zero otherwise
The syntax and semantics of the AV1ItemConfigurationProperty are identical to those of the [=AV1CodecConfigurationBox=]
defined in [[!AV1-ISOBMFF]], with the following constraints:
- - [=Sequence Header OBUs=] should not be present in the [=AV1CodecConfigurationBox=]
.
- - If a [=Sequence Header OBU=] is present in the [=AV1CodecConfigurationBox=]
, it shall match the [=Sequence Header OBU=] in the [=AV1 Image Item Data=].
- - The values of the fields in the [=AV1CodecConfigurationBox=]
shall match those of the [=Sequence Header OBU=] in the [=AV1 Image Item Data=].
- - The values of the bit depth and the number of channels derived from the [=AV1CodecConfigurationBox=]
shall match the PixelInformationProperty if present.
- - [=Metadata OBUs=], if present, shall match the values given in other item properties, such as the MasteringDisplayColourVolumeBox or ContentLightLevelBox.
+ - [=Sequence Header OBUs=] should not be present in the [=AV1ItemConfigurationProperty=]
.
+ - If a [=Sequence Header OBU=] is present in the [=AV1ItemConfigurationProperty=]
, it shall match the [=Sequence Header OBU=] in the [=AV1 Image Item Data=].
+ - The values of the fields in the [=AV1ItemConfigurationProperty=]
shall match those of the [=Sequence Header OBU=] in the [=AV1 Image Item Data=].
+ - The values of the bit depth and the number of channels derived from the [=AV1ItemConfigurationProperty=]
shall match the [=PixelInformationProperty=]
if present.
+ - [=Metadata OBUs=], if present, shall match the values given in other item properties, such as the [=MasteringDisplayColourVolumeBox=]
or [=ContentLightLevelBox=]
.
This property should be marked as essential.
Image Spatial Extents Property
-The semantics of the '[=ispe=]'
property as defined in [[!HEIF]] apply. More specifically, for AV1 images, the values of [=image_width=]
and [=image_height=]
shall respectively equal the values of [=UpscaledWidth=]
and [=FrameHeight=]
as defined in [[!AV1]] but for a specific frame in the item payload. The exact frame depends on the presence and content of the '[=lsel=]'
and [=OperatingPointSelectorProperty=]
properties as follows:
+The semantics of the '[=ispe=]'
property as defined in [[!HEIF]] apply. More specifically, for [[!AV1]] images, the values of [=image_width=]
and [=image_height=]
shall respectively equal the values of [=UpscaledWidth=]
and [=FrameHeight=]
as defined in [[!AV1]] but for a specific frame in the item payload. The exact frame depends on the presence and content of the '[=lsel=]'
and [=OperatingPointSelectorProperty=]
properties as follows:
- In the absence of a '[=lsel=]'
property associated with the item, or if it is present and its [=layer_id=]
value is set to 0xFFFF:
- - If no [=OperatingPointSelectorProperty=]
is associated with the item, the '[=ispe=]'
shall document the dimensions of the last frame decoded when processing the operating point whose index is 0.
+ - If no [=OperatingPointSelectorProperty=]
is associated with the item, the '[=ispe=]'
property shall document the dimensions of the last frame decoded when processing the operating point whose index is 0.
- If an [=OperatingPointSelectorProperty=]
is associated with the item, the '[=ispe=]'
property shall document the dimensions of the last frame decoded when processing the corresponding operating point.
@@ -241,7 +244,7 @@ The semantics of the '[=ispe=]'
property as defined in [[!HEIF]] ap
NOTE: The dimensions indicated in the '[=ispe=]'
property might not match the values [=max_frame_width_minus1=]+1
and [=max_frame_height_minus1=]+1
indicated in the AV1 bitstream.
-NOTE: The values of [=render_width_minus1=]
and [=render_height_minus1=]
possibly present in the AV1 bistream are not exposed in the AVIF container level.
+NOTE: The values of [=render_width_minus1=]
and [=render_height_minus1=]
possibly present in the AV1 bistream are not exposed at the AVIF container level.
Clean Aperture Property
@@ -283,6 +286,7 @@ NOTE: When an author wants to offer the ability to render multiple [=Operating P
NOTE: When such a progressive decoding of the layers within an [=Operating Point=] is not desired or when an author wants to expose each layer as a specific item, multiple [=AV1 Image Items=] sharing the same [=AV1 Image Item Data=] can be created and associated with different '[=lsel=]'
properties, each with a different value of [=layer_id=]
.
Properties
+
Operating Point Selector Property
Definition
@@ -290,7 +294,7 @@ NOTE: When such a progressive decoding of the layers within an [=Operating Point
Box Type: a1op
Property type: Descriptive item property
- Container: ItemPropertyContainerBox
+ Container: ItemPropertyContainerBox
Mandatory (per item): No
Quantity (per item): Zero or one
@@ -309,9 +313,10 @@ class OperatingPointSelectorProperty extends ItemProperty('a1op') {
Semantics
-op_index indicates the index of the operating point to be processed for this item. Its value shall be between 0 and [=operating_points_cnt_minus_1=].
+op_index indicates the index of the operating point to be processed for this item. Its value shall be between 0 and [=operating_points_cnt_minus_1=]
inclusive.
Layer Selector Property
+
The '[=lsel=]'
property defined in [[!HEIF]] may be associated with an [=AV1 Image Item=]. The [=layer_id=]
indicates the value of the [=spatial_id=]
to render. The value shall be between 0 and 3, or the special value 0xFFFF. When a value between 0 and 3 is used, the corresponding spatial layer shall be present in the bitstream and shall produce an output frame. Other layers may be needed to decode the indicated layer. When the special value 0xFFFF is used, progressive decoding is allowed as described in [[#layered-items-overview]].
Layered Image Indexing Property
@@ -321,7 +326,7 @@ The '[=lsel=]'
property defined in [[!HEIF]] may be associated with
Box Type: a1lx
Property type: Descriptive item property
- Container: ItemPropertyContainerBox
+ Container: ItemPropertyContainerBox
Mandatory (per item): No
Quantity (per item): Zero or one
@@ -345,7 +350,7 @@ class AV1LayeredImageIndexingProperty extends ItemProperty('a1lx') {
Semantics
-layer_size indicates the number of bytes corresponding to each layer in the item payload, except for the last layer. Values are provided in increasing order of [=spatial_id=]
. A value of zero means that all the layers except the last one have been documented and following values shall be 0. The number of non-zero values shall match the number of layers in the image minus one..
+layer_size indicates the number of bytes corresponding to each layer in the item payload, except for the last layer. Values are provided in increasing order of [=spatial_id=]
. A value of zero means that all the layers except the last one have been documented and following values shall be 0. The number of non-zero values shall match the number of layers in the image minus one.
NOTE: The size of the last layer can be determined by subtracting the sum of the sizes of all layers indicated in this property from the entire item size.
@@ -1200,6 +1205,7 @@ The "Version(s)" column in the following table lists the version(s) of the boxes
- Adopt MIAF shared constraints
- EDITORIAL: Clean up usage of dfn and linking
- Clarify required versions of non-essential item properties
+ - EDITORIAL: Add refs, fix wording and format in clauses 1,2
Appendix A: Sample Transform Derived Image Item Examples
From e0e048e809a9815d96cc93562d5d962239e67ab5 Mon Sep 17 00:00:00 2001
From: Yannis Guyon
Date: Thu, 10 Oct 2024 09:01:43 +0000
Subject: [PATCH 40/65] Add sato, alpha, depth, progressive in Scope (#258)
along other supported features.
---
index.bs | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/index.bs b/index.bs
index fab5c70..fad5a05 100755
--- a/index.bs
+++ b/index.bs
@@ -186,9 +186,9 @@ The [=AV1 Image File Format=] defines multiple profiles, which restrict the allo
The profiles defined in this specification follow the conventions of the [[!MIAF]] specification.
Images encoded with [[!AV1]] and not meeting the restrictions of the defined profiles may still be compliant to this [=AV1 Image File Format=] if they adhere to the general AVIF requirements.
-[=AV1 Image File Format=] supports High Dynamic Range (HDR) and Wide Color Gamut (WCG) images as well as Standard Dynamic Range (SDR). It supports monochrome images as well as multi-channel images with all the bit depths and color spaces specified in [[!AV1]].
+The [=AV1 Image File Format=] supports High Dynamic Range (HDR) and Wide Color Gamut (WCG) images as well as Standard Dynamic Range (SDR). It supports monochrome images as well as multi-channel images with all the bit depths and color spaces specified in [[!AV1]], and other bit depths with [=Sample Transform Derived Image Items=]. The [=AV1 Image File Format=] also supports transparency (alpha) and other types of data such as depth maps through auxiliary [=AV1 bitstreams=].
-[=AV1 Image File Format=] also supports multi-layer images as specified in [[!AV1]] to be stored both in image items and image sequences.
+The [=AV1 Image File Format=] also supports multi-layer images as specified in [[!AV1]] to be stored both in image items and image sequences. The [=AV1 Image File Format=] supports progressive image decoding through layered images.
An AVIF file is designed to be a conformant [[!HEIF]] file for both image items and image sequences. Specifically, this specification follows the recommendations given in "Annex I: Guidelines On Defining New Image Formats and Brands" of [[!HEIF]].
@@ -1206,6 +1206,7 @@ The "Version(s)" column in the following table lists the version(s) of the boxes
- EDITORIAL: Clean up usage of dfn and linking
- Clarify required versions of non-essential item properties
- EDITORIAL: Add refs, fix wording and format in clauses 1,2
+ - EDITORIAL: Add sato, alpha, depth, progressive in Scope
Appendix A: Sample Transform Derived Image Item Examples
From 727501ad5122db883ca546d8ae683076ea660ee4 Mon Sep 17 00:00:00 2001
From: leo-barnes
Date: Wed, 16 Oct 2024 08:56:44 +0200
Subject: [PATCH 41/65] Fix final review comments (#256)
Moved box type definition anchors to the root spec listed in table of boxes
Added links to all box types in table of boxes
Sorted all anchors, removed duplicates
Removed duplicated lists of boxes
---
index.bs | 503 ++++++++++++++++++++++++++++++-------------------------
1 file changed, 277 insertions(+), 226 deletions(-)
diff --git a/index.bs b/index.bs
index fad5a05..1d23843 100755
--- a/index.bs
+++ b/index.bs
@@ -79,118 +79,137 @@ Metadata Order: This version, !*, *
url: https://www.iso.org/standard/66067.html; spec: HEIF; type: dfn;
- text: colr
+ text: aux_type
+ text: auxC
+ text: AuxiliaryTypeInfoBox
+ text: AuxiliaryTypeProperty
+ text: auxl
+ text: bits_per_channel
+ text: cdsc
+ text: cmex
+ text: cmin
+ text: derived image item
+ text: dimg
+ text: grid
+ text: image_height
+ text: image_width
+ text: imir
+ text: irot
+ text: ispe
+ text: layer_id
+ text: lsel
text: mif1
text: msf1
- text: pasp
+ text: ndwt
text: pict
+ text: PixelInformationProperty
text: pixi
- text: ispe
- text: lsel
- text: irot
- text: imir
- text: clap
- text: cclv
- text: clli
- text: mdcv
+ text: prem
text: reve
- text: amve
- text: ndwt
- text: cmin
- text: cmex
- text: dimg
- text: layer_id
- text: image_width
- text: image_height
text: ster
+ text: thmb
text: tmap
- text: derived image item
- text: aux_type
- text: AuxiliaryTypeInfoBox
- text: AuxiliaryTypeProperty
- text: bits_per_channel
- text: PixelInformationProperty
url: https://www.iso.org/standard/68960.html; spec: ISOBMFF; type: dfn;
+ text: altr
+ text: amve
+ text: cclv
+ text: clap
+ text: clli
+ text: colour_type
+ text: ColourInformationBox
+ text: colr
text: compatible_brands
+ text: ContentLightLevelBox
+ text: dinf
+ text: dref
text: FileTypeBox
- text: major_brand
- text: SingleItemTypeReferenceBox
- text: SingleItemTypeReferenceBoxLarge
- text: ItemReferenceBox
- text: reference_count
+ text: free
text: from_item_ID
- text: to_item_ID
- text: nclx
- text: sync
- text: iloc
- text: mdat
+ text: ftyp
+ text: full_range_flag
+ text: GroupsListBox
+ text: grpl
+ text: hdlr
text: idat
- text: altr
+ text: iinf
+ text: iloc
+ text: infe
+ text: ipco
+ text: ipma
+ text: iprp
+ text: iref
+ text: ItemReferenceBox
+ text: major_brand
+ text: MasteringDisplayColourVolumeBox
text: matrix_coefficients
- text: full_range_flag
- text: colour_type
+ text: mdat
+ text: mdcv
text: meta
- text: free
+ text: nclx
+ text: pasp
+ text: pitm
+ text: reference_count
+ text: SingleItemTypeReferenceBox
+ text: SingleItemTypeReferenceBoxLarge
text: skip
- text: ItemPropertyContainerBox
- text: MasteringDisplayColourVolumeBox
- text: ContentLightLevelBox
+ text: sync
+ text: to_item_ID
url: https://www.iso.org/standard/74417.html; spec: MIAF; type: dfn;
+ text: edit-lists
+ text: grid-limit
+ text: matched-duration
text: miaf
- text: primary image item
- text: MIAF image item
- text: MIAF image sequence
text: MIAF auxiliary image item
text: MIAF auxiliary image sequence
+ text: MIAF image item
+ text: MIAF image sequence
+ text: primary image item
text: self-containment
- text: grid-limit
text: single-track
- text: edit-lists
- text: matched-duration
url: https://aomediacodec.github.io/av1-isobmff/; spec: AV1-ISOBMFF; type: dfn;
- text: AV1CodecConfigurationBox
text: AV1 Sample
text: AV1 Track
+ text: AV1CodecConfigurationBox
url: https://aomediacodec.github.io/av1-spec/av1-spec.pdf; spec: AV1; type: dfn;
text: AV1 bitstream
text: AV1 Frame
- text: Sequence Header OBU
- text: Metadata OBU
- text: Temporal Unit
- text: Operating Point
+ text: choose_operating_point
+ text: color_range
+ text: FrameHeight
text: Intra Frame
+ text: max_frame_height_minus1
+ text: max_frame_width_minus1
+ text: Metadata OBU
text: mono_chrome
- text: color_range
- text: still_picture
- text: reduced_still_picture_header
+ text: Operating Point
text: operating_points_cnt_minus_1
- text: choose_operating_point
- text: spatial_id
- text: seq_level_idx
- text: render_width_minus1
+ text: reduced_still_picture_header
text: render_height_minus1
+ text: render_width_minus1
+ text: seq_level_idx
+ text: Sequence Header OBU
+ text: spatial_id
+ text: still_picture
+ text: Temporal Unit
text: UpscaledWidth
- text: FrameHeight
- text: max_frame_width_minus1
- text: max_frame_height_minus1
Scope
-[[!AV1]] defines the syntax and semantics of an [=AV1 bitstream=]. The AV1 Image File Format (AVIF) defined in this document supports the storage of a subset of the syntax and semantics of an [=AV1 bitstream=] in a [[!HEIF]] file.
+[[!AV1]] defines the syntax and semantics of an [=AV1 bitstream=]. The AV1 Image File Format (AVIF) defined in this document supports the storage of a subset of the syntax and semantics of an [=AV1 bitstream=] in a [[!HEIF]] file.
The [=AV1 Image File Format=] defines multiple profiles, which restrict the allowed syntax and semantics of the [=AV1 bitstream=] with the goal to improve interoperability, especially for hardware implementations.
The profiles defined in this specification follow the conventions of the [[!MIAF]] specification.
-Images encoded with [[!AV1]] and not meeting the restrictions of the defined profiles may still be compliant to this [=AV1 Image File Format=] if they adhere to the general AVIF requirements.
+Images encoded with [[!AV1]] and not meeting the restrictions of the defined profiles may still be compliant to this [=AV1 Image File Format=] if they adhere to the general [=/AVIF=] requirements.
The [=AV1 Image File Format=] supports High Dynamic Range (HDR) and Wide Color Gamut (WCG) images as well as Standard Dynamic Range (SDR). It supports monochrome images as well as multi-channel images with all the bit depths and color spaces specified in [[!AV1]], and other bit depths with [=Sample Transform Derived Image Items=]. The [=AV1 Image File Format=] also supports transparency (alpha) and other types of data such as depth maps through auxiliary [=AV1 bitstreams=].
The [=AV1 Image File Format=] also supports multi-layer images as specified in [[!AV1]] to be stored both in image items and image sequences. The [=AV1 Image File Format=] supports progressive image decoding through layered images.
-An AVIF file is designed to be a conformant [[!HEIF]] file for both image items and image sequences. Specifically, this specification follows the recommendations given in "Annex I: Guidelines On Defining New Image Formats and Brands" of [[!HEIF]].
+An AVIF file is designed to be a conformant [[!HEIF]] file for both image items and image sequences. Specifically, this specification follows the recommendations given in "Annex I: Guidelines On Defining New Image Formats and Brands" of [[!HEIF]].
This specification reuses syntax and semantics used in [[!AV1-ISOBMFF]].
@@ -224,8 +243,8 @@ The syntax and semantics of the AV1ItemConfigurationProperty a
- [=Sequence Header OBUs=] should not be present in the [=AV1ItemConfigurationProperty=]
.
- If a [=Sequence Header OBU=] is present in the [=AV1ItemConfigurationProperty=]
, it shall match the [=Sequence Header OBU=] in the [=AV1 Image Item Data=].
- The values of the fields in the [=AV1ItemConfigurationProperty=]
shall match those of the [=Sequence Header OBU=] in the [=AV1 Image Item Data=].
- - The values of the bit depth and the number of channels derived from the [=AV1ItemConfigurationProperty=]
shall match the [=PixelInformationProperty=]
if present.
- - [=Metadata OBUs=], if present, shall match the values given in other item properties, such as the [=MasteringDisplayColourVolumeBox=]
or [=ContentLightLevelBox=]
.
+ - The values of the bit depth and the number of channels derived from the [=AV1ItemConfigurationProperty=]
shall match the [=PixelInformationProperty=]
('[=pixi=]'
) if present.
+ - [=Metadata OBUs=], if present, shall match the values given in other item properties, such as the [=MasteringDisplayColourVolumeBox=]
('[=mdcv=]'
) or [=ContentLightLevelBox=]
('[=clli=]'
).
This property should be marked as essential.
@@ -234,17 +253,17 @@ The syntax and semantics of the AV1ItemConfigurationProperty a
The semantics of the '[=ispe=]'
property as defined in [[!HEIF]] apply. More specifically, for [[!AV1]] images, the values of [=image_width=]
and [=image_height=]
shall respectively equal the values of [=UpscaledWidth=]
and [=FrameHeight=]
as defined in [[!AV1]] but for a specific frame in the item payload. The exact frame depends on the presence and content of the '[=lsel=]'
and [=OperatingPointSelectorProperty=]
properties as follows:
- In the absence of a '[=lsel=]'
property associated with the item, or if it is present and its [=layer_id=]
value is set to 0xFFFF:
- - If no [=OperatingPointSelectorProperty=]
is associated with the item, the '[=ispe=]'
property shall document the dimensions of the last frame decoded when processing the operating point whose index is 0.
+ - If no [=OperatingPointSelectorProperty=]
is associated with the item, the '[=ispe=]'
property shall document the dimensions of the last frame decoded when processing the [=operating point=] whose index is 0.
- - If an [=OperatingPointSelectorProperty=]
is associated with the item, the '[=ispe=]'
property shall document the dimensions of the last frame decoded when processing the corresponding operating point.
+ - If an [=OperatingPointSelectorProperty=]
is associated with the item, the '[=ispe=]'
property shall document the dimensions of the last frame decoded when processing the corresponding [=operating point=].
- NOTE: The dimensions of possible intermediate output images might not match the ones given in the '[=ispe=]'
property. If they display these intermediate images, renderers are expected to scale the output image to match the '[=ispe=]'
property.
+ NOTE: The dimensions of possible intermediate output images might not match the ones given in the '[=ispe=]'
property. If renderers display these intermediate images, they are expected to scale the output image to match the '[=ispe=]'
property.
- If a '[=lsel=]'
property is associated with an item and its [=layer_id=]
is different from 0xFFFF, the '[=ispe=]'
property documents the dimensions of the output frame produced by decoding the corresponding layer.
NOTE: The dimensions indicated in the '[=ispe=]'
property might not match the values [=max_frame_width_minus1=]+1
and [=max_frame_height_minus1=]+1
indicated in the AV1 bitstream.
-NOTE: The values of [=render_width_minus1=]
and [=render_height_minus1=]
possibly present in the AV1 bistream are not exposed at the AVIF container level.
+NOTE: The values of [=render_width_minus1=]
and [=render_height_minus1=]
possibly present in the AV1 bistream are not exposed at the [=/AVIF=] container level.
Clean Aperture Property
@@ -254,22 +273,9 @@ The semantics of the clean aperture property ('[=clap=]'
) as define
Other Item Properties
-In addition to the Image Properties defined in this document, [=AV1 image items=] MAY also be associated with item properties defined in other specifications such as [[!HEIF]] and [[!MIAF]]. Examples of commonly used item properties are:
- - '[=colr=]'
- - '[=pixi=]'
- - '[=pasp=]'
- - '[=irot=]'
- - '[=imir=]'
- - '[=clli=]'
- - '[=cclv=]'
- - '[=mdcv=]'
- - '[=amve=]'
- - '[=reve=]'
- - '[=ndwt=]'
- - '[=cmin=]'
- - '[=cmex=]'
-
-In general, it is recommended to use properties instead of [=Metadata OBUs=] in the [=AV1ItemConfigurationProperty=]
.
+In addition to the Image Properties defined in this document, [=AV1 image items=] may also be associated with item properties defined in other specifications such as [[!HEIF]] and [[!MIAF]]. Commonly used item properties can be found in [[#avif-required-boxes]] and [[#avif-required-boxes-additional]].
+
+In general, it is recommended to use item properties instead of [=Metadata OBUs=] in the [=AV1ItemConfigurationProperty=]
.
AV1 Layered Image Items
@@ -277,11 +283,11 @@ In general, it is recommended to use properties instead of [=Metadata OBUs=] in
[[!AV1]] supports encoding a frame using multiple spatial layers. A spatial layer may improve the resolution or quality of the image decoded based on one or more of the previous layers. A layer may also provide an image that does not depend on the previous layers. Additionally, not all layers are expected to produce an image meant to be rendered. Some decoded images may be used only as intermediate decodes. Finally, layers are grouped into one or more [=Operating Points=]. The [=Sequence Header OBU=] defines the list of [=Operating Points=], provides required decoding capabilities, and indicates which layers form each [=Operating Point=].
-[[!AV1]] delegates the selection of which [=Operating Point=] to process to the application, by means of a function called choose_operating_point()
. AVIF defines the [=OperatingPointSelectorProperty=]
to control this selection. In the absence of an [=OperatingPointSelectorProperty=]
associated with an [=AV1 Image Item=], the AVIF renderer is free to process any [=Operating Point=] present in the [=AV1 Image Item Data=]. In particular, when the [=AV1 Image Item=] is composed of a unique [=Operating Point=], the [=OperatingPointSelectorProperty=]
should not be present. If an [=OperatingPointSelectorProperty=]
is associated with an [=AV1 Image Item=], the [=op_index=]
field indicates which [=Operating Point=] is expected to be processed for this item.
+[[!AV1]] delegates the selection of which [=Operating Point=] to process to the application, by means of a function called choose_operating_point()
. [=/AVIF=] defines the [=OperatingPointSelectorProperty=]
to control this selection. In the absence of an [=OperatingPointSelectorProperty=]
associated with an [=AV1 Image Item=], the [=/AVIF=] renderer is free to process any [=Operating Point=] present in the [=AV1 Image Item Data=]. In particular, when the [=AV1 Image Item=] is composed of a unique [=Operating Point=], the [=OperatingPointSelectorProperty=]
should not be present. If an [=OperatingPointSelectorProperty=]
is associated with an [=AV1 Image Item=], the [=op_index=]
field indicates which [=Operating Point=] is expected to be processed for this item.
-NOTE: When an author wants to offer the ability to render multiple [=Operating Points=] from the same AV1 image (e.g. in the case of multi-view images), multiple [=AV1 Image Items=] can be created that share the same [=AV1 Image Item Data=] but have different [=OperatingPointSelectorProperty=]
s.
+NOTE: When an author wants to offer the ability to render multiple [=Operating Points=] from the same AV1 image (e.g. in the case of multi-view images), multiple [=AV1 Image Items=] can be created that share the same [=AV1 Image Item Data=] but have different [=OperatingPointSelectorProperties=]
.
-[[!AV1]] expects the renderer to display only one frame within the selected [=Operating Point=], which should be the highest spatial layer that is both within the [=Operating Point=] and present within the temporal unit, but [[!AV1]] leaves the option for other applications to set their own policy about which frames are output, as defined in the general output process. AVIF sets a different policy, and defines how the '[=lsel=]'
property (mandated by [[!HEIF]] for layered images) is used to control which layer is rendered. According to [[!HEIF]], the interpretation of the [=layer_id=]
field in the '[=lsel=]'
property is codec specific. In this specification, the value 0xFFFF is reserved for a special meaning. If a '[=lsel=]'
property is associated with an [=AV1 Image Item=] but its [=layer_id=]
value is set to 0xFFFF, the renderer is free to render either only the output image of the highest spatial layer, or to render all output images of all the intermediate layers and the highest spatial layer, resulting in a form of progressive decoding. If a '[=lsel=]'
property is associated with an [=AV1 Image Item=] and the value of [=layer_id=]
is not 0xFFFF, the renderer is expected to render only the output image for that layer.
+[[!AV1]] expects the renderer to display only one frame within the selected [=Operating Point=], which should be the highest spatial layer that is both within the [=Operating Point=] and present within the temporal unit, but [[!AV1]] leaves the option for other applications to set their own policy about which frames are output, as defined in the general output process. [=/AVIF=] sets a different policy, and defines how the '[=lsel=]'
property (mandated by [[!HEIF]] for layered images) is used to control which layer is rendered. According to [[!HEIF]], the interpretation of the [=layer_id=]
field in the '[=lsel=]'
property is codec specific. In this specification, the value 0xFFFF is reserved for a special meaning. If a '[=lsel=]'
property is associated with an [=AV1 Image Item=] but its [=layer_id=]
value is set to 0xFFFF, the renderer is free to render either only the output image of the highest spatial layer, or to render all output images of all the intermediate layers and the highest spatial layer, resulting in a form of progressive decoding. If a '[=lsel=]'
property is associated with an [=AV1 Image Item=] and the value of [=layer_id=]
is not 0xFFFF, the renderer is expected to render only the output image for that layer.
NOTE: When such a progressive decoding of the layers within an [=Operating Point=] is not desired or when an author wants to expose each layer as a specific item, multiple [=AV1 Image Items=] sharing the same [=AV1 Image Item Data=] can be created and associated with different '[=lsel=]'
properties, each with a different value of [=layer_id=]
.
@@ -301,7 +307,7 @@ NOTE: When such a progressive decoding of the layers within an [=Operating Point
Description
-An OperatingPointSelectorProperty may be associated with an [=AV1 Image Item=] to provide the index of the operating point to be processed for this item. If associated, it shall be marked as essential.
+An OperatingPointSelectorProperty may be associated with an [=AV1 Image Item=] to provide the index of the [=operating point=] to be processed for this item. If associated, it shall be marked as essential.
Syntax
@@ -313,7 +319,7 @@ class OperatingPointSelectorProperty extends ItemProperty('a1op') {
Semantics
-op_index indicates the index of the operating point to be processed for this item. Its value shall be between 0 and [=operating_points_cnt_minus_1=]
inclusive.
+op_index indicates the index of the [=operating point=] to be processed for this item. Its value shall be between 0 and [=operating_points_cnt_minus_1=]
inclusive.
Layer Selector Property
@@ -376,7 +382,7 @@ NOTE: The size of the last layer can be determined by subtracting the sum of the
An AV1 Alpha Image Item (respectively an AV1 Alpha Image Sequence) is an [=AV1 Auxiliary Image Item=] (respectively an [=AV1 Auxiliary Image Sequence=]), and as defined in [[!MIAF]], with the [=aux_type=]
field of the [=AuxiliaryTypeProperty=]
(respectively [=AuxiliaryTypeInfoBox=]
) set to urn:mpeg:mpegB:cicp:systems:auxiliary:alpha
. An [=AV1 Alpha Image Item=] (respectively an [=AV1 Alpha Image Sequence=]) shall be encoded with the same bit depth as the associated master [=AV1 Image Item=] (respectively [=AV1 Image Sequence=]).
-For [=AV1 Alpha Image Item=] and [=AV1 Alpha Image Sequence=], the ColourInformationBox should be omitted. If present, readers shall ignore it.
+For [=AV1 Alpha Image Items=] and [=AV1 Alpha Image Sequences=], the [=ColourInformationBox=]
('[=colr=]'
) should be omitted. If present, readers shall ignore it.
An AV1 Depth Image Item (respectively an AV1 Depth Image Sequence) is an [=AV1 Auxiliary Image Item=] (respectively an [=AV1 Auxiliary Image Sequence=]), and as defined in [[!MIAF]], with the [=aux_type=]
field of the [=AuxiliaryTypeProperty=]
(respectively [=AuxiliaryTypeInfoBox=]
) set to urn:mpeg:mpegB:cicp:systems:auxiliary:depth
.
@@ -384,15 +390,19 @@ NOTE: [[!AV1]] supports encoding either 3-component images (whose semantics are
Derived Image Items
+Grid Derived Image Item
+
+A grid derived image item ('[=grid=]'
) as defined in [[!HEIF]] may be used in an [=AVIF file=].
+
Tone Map Derived Image Item
-A tone map derived image item ('[=tmap=]'
) as defined in [[!HEIF]] may be used in an [=AVIF=] file. When present, the base image item and the '[=tmap=]'
image item should be grouped together by an '[=AVIF/altr=]' entity group as recommended in [[!HEIF]].
+A tone map derived image item ('[=tmap=]'
) as defined in [[!HEIF]] may be used in an [=AVIF file=]. When present, the base image item and the '[=tmap=]'
image item should be grouped together by an '[=altr=]'
(see [[#altr-group]]) entity group as recommended in [[!HEIF]].
-In these sections, a "sample" refers to the value of a pixel for a given channel.
+With a [=Sample Transform Derived Image Item=], pixels at the same position in multiple input image items can be combined into a single output pixel using basic mathematical operations. This can for example be used to work around codec limitations or for storing alterations to an image as non-destructive residuals. With a [=Sample Transform Derived Image Item=] it is possible for [=/AVIF=] to support 16 or more bits of precision per sample, while still offering backward compatibility through a regular 8 to 12-bit [=AV1 Image Item=] containing the most significant bits of each sample.
-With a Sample Transform Derived Image Item, pixels at the same position in multiple input image items can be combined into a single output pixel using basic mathematical operations. This makes it possible for [=AVIF=] to support 16 or more bits of precision per sample, while still offering backward compatibility through a regular 8 to 12-bit [=AV1 Image Item=] containing the most significant bits of each sample.
+In these sections, a "sample" refers to the value of a pixel for a given channel.
@@ -401,7 +411,7 @@ When a [=derived image item=] is of type reserved shall be equal to 0. The value of [=sato/reserved=]
shall be ignored by readers.
-bit_depth determines the precision (from 8 to 64 bits, see Table 1) of the signed integer temporary variable supporting the intermediate results of the operations. It also determines the precision of the stack elements and the field size of the [=sato/constant=]
fields. This intermediate precision shall be high enough so that all input sample values fit into that signed bit depth.
+bit_depth determines the precision (from 8 to 64 bits, see Table 1) of the signed integer temporary variable supporting the intermediate results of the operations. It also determines the precision of the stack elements and the field size of the [=sato/constant=]
fields. This intermediate precision shall be high enough so that all input sample values fit into that signed bit depth.
-
+
- Table 1 - Mapping from [=sato/bit_depth=]
to the intermediate bit depth.
+ Table 1 - Mapping from [=sato/bit_depth=]
to the intermediate bit depth ([=num_bits=]
).
@@ -474,11 +484,11 @@ aligned(8) class SampleTransform {
The result of any computation underflowing or overflowing the intermediate bit depth is replaced by -2[=sato/num_bits=]
-1 and 2[=sato/num_bits=]
-1-1, respectively. Encoder implementations should not create files leading to potential computation underflow or overflow. Decoder implementations shall check for computation underflow or overflow and clamp the results accordingly. Computations with [=sato/operands=] of negative values use the two’s-complement representation.
-token_count is the expected number of [=sato/tokens=] to read.
+token_count is the expected number of [=sato/tokens=] to read. The value of [=sato/token_count=]
shall be greater than 0.
-token determines the type of the operand ([=sato/constant=]
or input image item sample) or the operator (how to transform one or two [=sato/operands=] into the result). See Table 2. Readers shall ignore a [=Sample Transform Derived Image Item=] with a reserved [=sato/token=]
value.
+token determines the type of the operand ([=sato/constant=]
or input image item sample) or the operator (how to transform one or two [=sato/operands=] into the result). See Table 2. Readers shall ignore a [=Sample Transform Derived Image Item=] with a reserved [=sato/token=]
value.
-
+
Table 2 - Meaning of the value of [=sato/token=]
.
@@ -679,15 +689,15 @@ Note: Because each [=sato/operator=] pops one or two elements and then pushes on
Entity groups
-The GroupsListBox ('grpl') defined in [[!ISOBMFF]] may be used to group multiple image items in a file together. The type of the group describes how the image items are related. Decoders should ignore groups of unknown type.
+The [=GroupsListBox=]
('[=grpl=]'
) defined in [[!ISOBMFF]] may be used to group multiple image items or tracks in a file together. The type of the group describes how the image items or tracks are related. Decoders should ignore groups of unknown type.
-'[=/altr=]'
group
+'[=altr=]'
group
-The 'altr' entity group as defined in [[!ISOBMFF]] may be used to mark multiple items as alternatives to each other. Only one item in the '[=AVIF/altr=]'
group should be played or processed. This grouping is useful for defining a fallback for parsers when new types of items or essential item properties are introduced.
+The '[=altr=]'
entity group as defined in [[!ISOBMFF]] may be used to mark multiple items or tracks as alternatives to each other. Only one item or track in the '[=altr=]'
group should be played or processed. This grouping is useful for defining a fallback for parsers when new types of items or essential item properties are introduced.
-'[=/ster=]'
group
+'[=ster=]'
group
-The 'ster' entity group as defined in [[!HEIF]] may be used to indicate that two image items form a stereo pair suitable for stereoscopic viewing.
+The '[=ster=]'
entity group as defined in [[!HEIF]] may be used to indicate that two image items form a stereo pair suitable for stereoscopic viewing.
Brands, Internet media types and file extensions
@@ -706,12 +716,12 @@ Files that indicate this brand in the [=compatible_brands=]
field o
- The [=primary image item=] shall be an [=AV1 Image Item=] or be a derived image that references directly or indirectly one or more items that all are [=AV1 Image Items=].
- [=AV1 auxiliary image items=] may be present in the file.
-Files that conform with these constraints should include the brand [=avif=]
in the [=compatible_brands=]
field of the [=FileTypeBox=]
.
+Files that conform with these constraints should include the brand [=AVIF Image brand/avif=]
in the [=compatible_brands=]
field of the [=FileTypeBox=]
.
Additionally, the brand avio is defined. If the file indicates the brand [=avio=]
in the [=compatible_brands=]
field of the [=FileTypeBox=]
, then the [=primary image item=] or all the items referenced by the [=primary image item=] shall be [=AV1 image items=] made only of [=Intra Frames=]. Conversely, if the previous constraint applies, the brand [=avio=]
should be used in the [=compatible_brands=]
field of the [=FileTypeBox=]
.
AVIF image sequence brands
-The brand to identify AVIF image sequences is avis.
+The brand to identify [=AV1 image sequences=] is avis.
Files that indicate this brand in the [=compatible_brands=]
field of the [=FileTypeBox=]
shall comply with the following:
- they shall contain one or more [=AV1 image sequences=].
@@ -727,8 +737,8 @@ NOTE: As defined in [[!MIAF]], a file that is primarily an image sequence still
The following constraints are common to files compliant with this specification:
- The file shall be compliant with the [[!MIAF]] specification and list '[=miaf=]'
in the [=compatible_brands=]
field of the [=FileTypeBox=]
.
- - The file shall list '[=avif=]'
or '[=avis=]'
in the [=compatible_brands=]
field of the [=FileTypeBox=]
.
- - Transformative properties shall not be associated with items in a derivation chain (as defined in [[!MIAF]]) that serves as an input to a grid item. For example, if a file contains a grid item and its referenced coded image items, cropping, mirroring or rotation transformations are only permitted on the grid item itself.
+ - The file shall list '[=AVIF Image brand/avif=]'
or '[=avis=]'
in the [=compatible_brands=]
field of the [=FileTypeBox=]
.
+ - Transformative properties shall not be associated with items in a derivation chain (as defined in [[!MIAF]]) that serves as an input to a [=grid derived image item=]. For example, if a file contains a grid item and its referenced coded image items, cropping, mirroring or rotation transformations are only permitted on the grid item itself.
NOTE: This constraint further restricts files compared to [[!MIAF]].
@@ -742,13 +752,13 @@ The profiles defined in this section are for enabling interoperability between [
If '[=avis=]'
is declared in the [=FileTypeBox=]
and a profile is declared in the [=FileTypeBox=]
, the profile shall also enable decoding of at least one image sequence track. The profile should allow decoding of any associated auxiliary image sequence tracks, unless it is acceptable to decode the image sequence without its auxiliary image sequence tracks.
-It is possible for a file compliant to this [=AV1 Image File Format=] to not be able to declare an AVIF profile, if the corresponding AV1 encoding characteristics do not match any of the defined profiles.
+It is possible for a file compliant to this [=AV1 Image File Format=] to not be able to declare an [=/AVIF=] profile, if the corresponding AV1 encoding characteristics do not match any of the defined profiles.
NOTE: [[!AV1]] supports 3 bit depths: 8, 10 and 12 bits, and the maximum dimensions of a coded image is 65536x65536, when [=seq_level_idx=]
is set to 31 (maximum parameters level).
-If an image is encoded with dimensions (respectively a bit depth) that exceed the maximum dimensions (respectively bit depth) required by the AV1 profile and level of the AVIF profiles defined in this specification, the file will only signal general AVIF brands.
+If an image is encoded with dimensions (respectively a bit depth) that exceed the maximum dimensions (respectively bit depth) required by the AV1 profile and level of the [=/AVIF=] profiles defined in this specification, the file will only signal general [=/AVIF=] brands.
-AVIF Baseline Profile
+AVIF Baseline Profile
This section defines the MIAF AV1 Baseline profile of [[!HEIF]], specifically for [[!AV1]] bitstreams, based on the constraints specified in [[!MIAF]] and identified by the brand MA1B.
@@ -768,7 +778,7 @@ The following additional constraints apply to all [=AV1 Image Items=] and all [=
NOTE: AV1 tiers are not constrained because timing is optional in image sequences and are not relevant in image items or collections.
-NOTE: Level 5.1 is chosen for the Baseline profile to ensure that no single coded image exceeds 4k resolution, as some decoder may not be able to handle larger images. More precisely, following [[!AV1]] level definitions, coded image items compliant to the AVIF Baseline profile may not have a number of pixels greater than 8912896, a width greater than 8192 or a height greater than 4352. It is still possible to use the Baseline profile to create larger images using grid derivation.
+NOTE: Level 5.1 is chosen for the Baseline profile to ensure that no single coded image exceeds 4k resolution, as some decoder may not be able to handle larger images. More precisely, following [[!AV1]] level definitions, coded image items compliant to the [=AVIF Baseline profile=] may not have a number of pixels greater than 8912896, a width greater than 8192 or a height greater than 4352. It is still possible to use the Baseline profile to create larger images using a [=grid derived image item=].
A file containing items compliant with this profile is expected to list the following brands, in any order, in the [=compatible_brands=]
of the [=FileTypeBox=]
:
@@ -784,7 +794,7 @@ A file containing a '[=pict=]'
track compliant with this profile an
avis, avio, msf1, miaf, MA1B
-AVIF Advanced Profile
+AVIF Advanced Profile
This section defines the MIAF AV1 Advanced profile of [[!HEIF]], specifically for [[!AV1]] bitstreams, based on the constraints specified in [[!MIAF]] and identified by the brand MA1A.
@@ -802,7 +812,7 @@ The following shared conditions and requirements from [[!MIAF]] should apply:
The following additional constraints apply to all [=AV1 Image Items=]:
- The AV1 profile shall be the High Profile and the level shall be 6.0 or lower.
-NOTE: Following [[!AV1]] level definitions, coded image items compliant to the AVIF Advanced profile may not have a number of pixels greater than 35651584, a width greater than 16384 or a height greater than 8704. It is still possible to use the Advanced profile to create larger images using grid derivation.
+NOTE: Following [[!AV1]] level definitions, coded image items compliant to the [=AVIF Advanced profile=] may not have a number of pixels greater than 35651584, a width greater than 16384 or a height greater than 8704. It is still possible to use the Advanced profile to create larger images using a [=grid derived image item=].
The following additional constraints apply only to [=AV1 Image Sequences=]:
- The AV1 profile shall be either Main Profile or High Profile.
@@ -822,12 +832,12 @@ A file containing a '[=pict=]'
track compliant with this profile is
Box requirements
Image item boxes
-This section discusses the box requirements for an AVIF file containing only image items.
+This section discusses the box requirements for an [=AVIF file=] containing only image items.
Minimum set of boxes
-As indicated in [[#file-constraints]], an AVIF file is a compliant [[!MIAF]] file. As a consequence, some [[!ISOBMFF]] or [[!HEIF]] boxes are required, as indicated in the following table. The order of the boxes is indicative in the table. The specifications listed in the "Specification"
-column may require a specific order for the box or for its children and shall be respected. For example, per [[!ISOBMFF]], the [=FileTypeBox=]
is required to appear first in an AVIF file.
+
As indicated in [[#file-constraints]], an [=AVIF file=] is a compliant [[!MIAF]] file. As a consequence, some [[!ISOBMFF]] or [[!HEIF]] boxes are required, as indicated in the following table. The order of the boxes is indicative in the table. The specifications listed in the "Specification"
+column may require a specific order for the box or for its children and shall be respected. For example, per [[!ISOBMFF]], the [=FileTypeBox=]
is required to appear first in an [=AVIF file=].
The "Version(s)" column in the following table lists the version(s) of the boxes allowed by this brand. With the exception of item properties marked as non-essential, other versions of the boxes shall not be used. "-" means that the box does not have a version.
@@ -844,129 +854,129 @@ The "Version(s)" column in the following table lists the version(s) of the boxes
- ftyp |
+ [=ftyp=] |
|
|
|
- |
- ISOBMFF |
+ [[!ISOBMFF]] |
|
- meta |
+ [=meta=] |
|
|
|
0 |
- ISOBMFF |
+ [[!ISOBMFF]] |
|
|
- hdlr |
+ [=hdlr=] |
|
|
0 |
- ISOBMFF |
+ [[!ISOBMFF]] |
|
|
- pitm |
+ [=pitm=] |
|
|
0, 1 |
- ISOBMFF |
+ [[!ISOBMFF]] |
|
|
- iloc |
+ [=iloc=] |
|
|
0, 1, 2 |
- ISOBMFF |
+ [[!ISOBMFF]] |
|
|
- iinf |
+ [=iinf=] |
|
|
0, 1 |
- ISOBMFF |
+ [[!ISOBMFF]] |
|
|
|
- infe |
+ [=infe=] |
|
2, 3 |
- ISOBMFF |
+ [[!ISOBMFF]] |
|
|
- iprp |
+ [=iprp=] |
|
|
- |
- ISOBMFF |
+ [[!ISOBMFF]] |
|
|
|
- ipco |
+ [=ipco=] |
|
- |
- ISOBMFF |
+ [[!ISOBMFF]] |
|
|
|
|
- av1C |
+ [=/av1C=] |
- |
- AVIF |
+ [=/AVIF=] |
|
|
|
|
- ispe |
+ [=ispe=] |
0 |
- HEIF |
+ [[!HEIF]] |
|
|
|
|
- pixi |
+ [=pixi=] |
0 |
- HEIF |
+ [[!HEIF]] |
|
|
|
- ipma |
+ [=ipma=] |
|
0, 1 |
- ISOBMFF |
+ [[!ISOBMFF]] |
|
- mdat |
+ [=mdat=] |
|
|
|
- |
- ISOBMFF |
+ [[!ISOBMFF]] |
The coded payload may be placed in '[=idat=]' rather than '[=mdat=]' , in which case '[=mdat=]' is not required. |
@@ -974,7 +984,7 @@ The "Version(s)" column in the following table lists the version(s) of the boxes
Requirements on additional image item related boxes
-The boxes indicated in the following table may be present in an AVIF file to provide additional signaling for image items. The boxes may be present inside the box indicated in the "Containing box" column. If present, they shall use the version indicated in the table unless the box is an item property marked as non-essential. AVIF readers are expected to understand the boxes and versions listed in this table. The order of the boxes is indicative in the table. Specifications may require specific order and shall be respected. Additionally, the '[=free=]'
and '[=skip=]'
boxes may be present at any level in the hierarchy. AVIF readers are expected to ignore them. Additional boxes in the '[=meta=]'
hierarchy not listed in the following table may also be present and may be ignored by AVIF readers.
+The boxes indicated in the following table may be present in an [=AVIF file=] to provide additional signaling for image items. The boxes may be present inside the box indicated in the "Containing Box" column. If present, they shall use the version indicated in the table unless the box is an item property marked as non-essential. [=/AVIF=] readers are expected to understand the boxes and versions listed in this table. The order of the boxes is indicative in the table. Specifications may require specific order and shall be respected. Additionally, the '[=free=]'
and '[=skip=]'
boxes may be present at any level in the hierarchy and [=/AVIF=] readers are expected to ignore them. Additional boxes in the '[=meta=]'
hierarchy not listed in the following table may also be present and may be ignored by [=/AVIF=] readers.
@@ -988,197 +998,237 @@ The "Version(s)" column in the following table lists the version(s) of the boxes
- dinf |
+ [=dinf=] |
|
- |
- ISOBMFF |
- meta |
+ [[!ISOBMFF]] |
+ [=meta=] |
Used to indicate the location of the media information in a track |
|
- dref |
+ [=dref=] |
0 |
- ISOBMFF |
+ [[!ISOBMFF]] |
|
|
- iref |
+ [=iref=] |
|
0, 1 |
- ISOBMFF |
- meta |
+ [[!ISOBMFF]] |
+ [=meta=] |
Used to indicate directional relationships between images or metadata |
|
- auxl |
+ [=auxl=] |
- |
- HEIF |
+ [[!HEIF]] |
|
Used when an image is auxiliary to another image |
|
- thmb |
+ [=thmb=] |
- |
- HEIF |
+ [[!HEIF]] |
|
Used when an image is a thumbnail of another image |
|
- dimg |
+ [=dimg=] |
- |
- HEIF |
+ [[!HEIF]] |
|
- Used when an image is derived from another image |
+ Used when an image is [[#derived-images|derived from another image]] |
|
- prem |
+ [=prem=] |
- |
- HEIF |
+ [[!HEIF]] |
|
- Used when when an alpha image contains premultiplied color values from another image |
+ Used when the color values in an image have been premultiplied with alpha values |
|
- cdsc |
+ [=cdsc=] |
- |
- HEIF |
+ [[!HEIF]] |
|
Used to link metadata with an image |
- idat |
+ [=idat=] |
|
- |
- ISOBMFF |
- meta |
+ [[!ISOBMFF]] |
+ [=meta=] |
Used to store derived image definitions |
- [=AVIF/grpl=] |
+ [[#groups|grpl]] |
|
- |
- ISOBMFF |
- meta |
+ [[!ISOBMFF]] |
+ [=meta=] |
Used to indicate that multiple images are semantically grouped |
|
- [=AVIF/altr=] |
+ [[#altr-group|altr]] |
0 |
- ISOBMFF |
+ [[!ISOBMFF]] |
|
- Used when images in a group are alternative to each other |
+ Used when images in a group are alternatives to each other |
|
- [=AVIF/ster=] |
+ [[#ster-group|ster]] |
0 |
- HEIF |
+ [[!HEIF]] |
|
Used when images in a group form a stereo pair |
- pasp |
+ [=pasp=] |
|
- |
- ISOBMFF |
- ipco |
+ [[!ISOBMFF]] |
+ [=ipco=] |
Used to signal pixel aspect ratio. If present, shall indicate a pixel aspect ratio of 1:1 |
- colr |
+ [=colr=] |
|
- |
- ISOBMFF |
- ipco |
+ [[!ISOBMFF]] |
+ [=ipco=] |
Used to signal information such as color primaries. |
- auxC |
+ [=auxC=] |
|
0 |
- HEIF |
- ipco |
+ [[!HEIF]] |
+ [=ipco=] |
Used to signal the type of an auxiliary image (e.g. alpha, depth). |
- clap |
+ [[#clean-aperture-property|clap]] |
|
- |
- ISOBMFF |
- ipco |
+ [[!ISOBMFF]] |
+ [=ipco=] |
Used to signal cropping applied to an image |
- irot |
+ [=irot=] |
|
- |
- HEIF |
- ipco |
+ [[!HEIF]] |
+ [=ipco=] |
Used to signal a rotation applied to an image |
- imir |
+ [=imir=] |
|
- |
- HEIF |
- ipco |
+ [[!HEIF]] |
+ [=ipco=] |
Used to signal a mirroring applied to an image |
- clli |
+ [=clli=] |
|
- |
- ISOBMFF |
- ipco |
+ [[!ISOBMFF]] |
+ [=ipco=] |
Used to signal HDR light level information for an image |
- cclv |
+ [=cclv=] |
|
- |
- ISOBMFF |
- ipco |
+ [[!ISOBMFF]] |
+ [=ipco=] |
Used to signal HDR color volume for an image |
- mdcv |
+ [=mdcv=] |
|
- |
- ISOBMFF |
- ipco |
+ [[!ISOBMFF]] |
+ [=ipco=] |
Used to signal HDR mastering information for an image |
- a1op |
+ [=amve=] |
|
- |
- AVIF |
- ipco |
- Used to configure rendering of a multiple operating points image |
+ [[!ISOBMFF]] |
+ [=ipco=] |
+ Used to signal the nominal ambient viewing environment for the display of the content |
- lsel |
+ [=reve=] |
+ |
+ 0 |
+ [[!HEIF]] |
+ [=ipco=] |
+ Used to signal the viewing environment in which the image was mastered |
+
+
+ [=ndwt=] |
+ |
+ 0 |
+ [[!HEIF]] |
+ [=ipco=] |
+ Used to signal the nominal diffuse white luminance of the content |
+
+
+ [=a1op=] |
+ |
+ - |
+ [=/AVIF=] |
+ [=ipco=] |
+ Used to configure which operating point to select when there are multiple choices |
+
+
+ [=lsel=] |
|
- |
- HEIF |
- ipco |
+ [[!HEIF]] |
+ [=ipco=] |
Used to configure rendering of a multilayered image |
- a1lx |
+ [=a1lx=] |
|
- |
- AVIF |
- ipco |
+ [=/AVIF=] |
+ [=ipco=] |
Used to assist reader in parsing a multilayered image |
+
+ [=cmin=] |
+ |
+ 0 |
+ [[!HEIF]] |
+ [=ipco=] |
+ Used to signal the camera intrinsic matrix |
+
+
+ [=cmex=] |
+ |
+ 0 |
+ [[!HEIF]] |
+ [=ipco=] |
+ Used to signal the camera extrinsic matrix |
+
@@ -1207,10 +1257,11 @@ The "Version(s)" column in the following table lists the version(s) of the boxes
- Clarify required versions of non-essential item properties
- EDITORIAL: Add refs, fix wording and format in clauses 1,2
- EDITORIAL: Add sato, alpha, depth, progressive in Scope
+ - Clean up linking to base specs and duplicated information
-Appendix A: Sample Transform Derived Image Item Examples
+Appendix A: (informative) Sample Transform Derived Image Item Examples
-This informative appendix contains example recipes for extending base AVIF features with [=Sample Transform Derived Image Items=].
+This informative appendix contains example recipes for extending base [=/AVIF=] features with [=Sample Transform Derived Image Items=].
Bit depth extension
@@ -1235,7 +1286,7 @@ Consider the following:
This is equivalent to the following postfix notation (parentheses for clarity):
-sampleoutput=(256sample1×)sample2+
+sampleoutput=(256sample1×)sample2+
This is equivalent to the following infix notation:
@@ -1243,7 +1294,7 @@ This is equivalent to the following infix notation:
Each output sample is equal to the sum of a sample of the first input image item shifted to the left by 8 and of a sample of the second input image item. This can be viewed as a bit depth extension of the first input image item by the second input image item. The first input image item contains the 8 most significant bits and the second input image item contains the 8 least significant bits of the output reconstructed image item which has a bit depth of 16, something that is impossible to achieve with a single [=AV1 image item=].
-NOTE: If the first input image item is the [=primary image item=] and is enclosed in an '[=AVIF/altr=]'
group with the [=Sample Transform Derived Image Item=], the first input image item is also a backward-compatible 8-bit regular coded image item that can be used by readers that do not support [=Sample Transform Derived Image Items=] or do not need extra precision.
+NOTE: If the first input image item is the [=primary image item=] and is enclosed in an '[=altr=]'
group (see [[#altr-group]]) with the [=Sample Transform Derived Image Item=], the first input image item is also a backward-compatible 8-bit regular coded image item that can be used by readers that do not support [=Sample Transform Derived Image Items=] or do not need extra precision.
NOTE: The second input image item loses its meaning of least significant part if any of the most significant bits changes, so the first input image item has to be losslessly encoded. The second input image item supports reasonable loss during encoding.
@@ -1277,7 +1328,7 @@ Consider the following:
This is equivalent to the following postfix notation (parentheses for clarity):
-sampleoutput=((16sample1×)sample2+)128-
+sampleoutput=((16sample1×)sample2+)128-
This is equivalent to the following infix notation:
@@ -1285,7 +1336,7 @@ This is equivalent to the following infix notation:
Each output sample is equal to the sum of a sample of the first input image item shifted to the left by 4 and of a sample of the second input image item offset by -128. This can be viewed as a bit depth extension of the first input image item by the second input image item which contains the residuals to correct the precision loss of the first input image item.
-NOTE: If the first input image item is the [=primary image item=] and is enclosed in an '[=AVIF/altr=]'
group with the derived image item, the first input image item is also a backward-compatible 12-bit regular coded image item that can be used by decoding contexts that do not support [=Sample Transform Derived Image Items=] or do not need extra precision.
+NOTE: If the first input image item is the [=primary image item=] and is enclosed in an '[=altr=]'
group (see [[#altr-group]]) with the derived image item, the first input image item is also a backward-compatible 12-bit regular coded image item that can be used by decoding contexts that do not support [=Sample Transform Derived Image Items=] or do not need extra precision.
NOTE: The first input image item supports reasonable loss during encoding because the second input image item "overlaps" by 4 bits to correct the loss. The second input image item supports reasonable loss during encoding.
From 94c679e37c9ceb6a81ae0684b0b776824e98e50d Mon Sep 17 00:00:00 2001
From: Yannis Guyon
Date: Mon, 21 Oct 2024 14:30:56 +0000
Subject: [PATCH 42/65] Use Markdown syntax coloring for code snippets (#259)
---
index.bs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/index.bs b/index.bs
index 1d23843..b359bbb 100755
--- a/index.bs
+++ b/index.bs
@@ -311,7 +311,7 @@ An OperatingPointSelectorProperty may be associated with an [=
Syntax
-```
+```c
class OperatingPointSelectorProperty extends ItemProperty('a1op') {
unsigned int(8) op_index;
}
@@ -345,7 +345,7 @@ The [=AV1LayeredImageIndexingProperty=]
documents the size in bytes
Syntax
-```
+```c
class AV1LayeredImageIndexingProperty extends ItemProperty('a1lx') {
unsigned int(7) reserved = 0;
unsigned int(1) large_size;
From f0b2f2937161436f1a90b01d9c524d7a7c3e6385 Mon Sep 17 00:00:00 2001
From: Yannis Guyon
Date: Mon, 21 Oct 2024 14:31:10 +0000
Subject: [PATCH 43/65] Consistently use dfn noexport for derived items (#261)
To make sure the first sentence of each derived image item section is
rendered in a similar way.
---
index.bs | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/index.bs b/index.bs
index b359bbb..650d1ac 100755
--- a/index.bs
+++ b/index.bs
@@ -396,17 +396,17 @@ A grid derived image item ('[=grid=]'
) as defin
Tone Map Derived Image Item
-A tone map derived image item ('[=tmap=]'
) as defined in [[!HEIF]] may be used in an [=AVIF file=]. When present, the base image item and the '[=tmap=]'
image item should be grouped together by an '[=altr=]'
(see [[#altr-group]]) entity group as recommended in [[!HEIF]].
+A tone map derived image item ('[=tmap=]'
) as defined in [[!HEIF]] may be used in an [=AVIF file=]. When present, the base image item and the '[=tmap=]'
image item should be grouped together by an '[=altr=]'
(see [[#altr-group]]) entity group as recommended in [[!HEIF]].
-With a [=Sample Transform Derived Image Item=], pixels at the same position in multiple input image items can be combined into a single output pixel using basic mathematical operations. This can for example be used to work around codec limitations or for storing alterations to an image as non-destructive residuals. With a [=Sample Transform Derived Image Item=] it is possible for [=/AVIF=] to support 16 or more bits of precision per sample, while still offering backward compatibility through a regular 8 to 12-bit [=AV1 Image Item=] containing the most significant bits of each sample.
+With a Sample Transform Derived Image Item, pixels at the same position in multiple input image items can be combined into a single output pixel using basic mathematical operations. This can for example be used to work around codec limitations or for storing alterations to an image as non-destructive residuals. With a [=Sample Transform Derived Image Item=] it is possible for [=/AVIF=] to support 16 or more bits of precision per sample, while still offering backward compatibility through a regular 8 to 12-bit [=AV1 Image Item=] containing the most significant bits of each sample.
In these sections, a "sample" refers to the value of a pixel for a given channel.
-When a [=derived image item=] is of type sato, it is called a Sample Transform Derived Image Item, and its reconstructed image is formed from a set of input image items, [=sato/constants=] and [=sato/operators=].
+When a [=derived image item=] is of type sato, it is called a [=Sample Transform Derived Image Item=], and its reconstructed image is formed from a set of input image items, [=sato/constants=] and [=sato/operators=].
The input images are specified in the [=SingleItemTypeReferenceBox=]
or [=SingleItemTypeReferenceBoxLarge=]
entries of type '[=dimg=]'
for this [=Sample Transform Derived Image Item=] within the [=ItemReferenceBox=]
. The input images are in the same order as specified in these entries. In the [=SingleItemTypeReferenceBox=]
or [=SingleItemTypeReferenceBoxLarge=]
of type '[=dimg=]'
, the value of the [=from_item_ID=]
field identifies the [=Sample Transform Derived Image Item=], and the values of the [=to_item_ID=]
field identify the input images. There are [=reference_count=]
input image items as specified by the [=ItemReferenceBox=]
.
From b1a66afc159373f7e838d8056b3ebb1727dfc280 Mon Sep 17 00:00:00 2001
From: Yannis Guyon
Date: Mon, 21 Oct 2024 14:31:23 +0000
Subject: [PATCH 44/65] Remove Sample Transform sections from TOC (#262)
Same as for Operating Point Selector Property sections.
---
index.bs | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/index.bs b/index.bs
index 650d1ac..ece19b6 100755
--- a/index.bs
+++ b/index.bs
@@ -404,7 +404,7 @@ With a Sample Transform Derived Image Item, pixels at the same
In these sections, a "sample" refers to the value of a pixel for a given channel.
-
+
When a [=derived image item=] is of type sato, it is called a [=Sample Transform Derived Image Item=], and its reconstructed image is formed from a set of input image items, [=sato/constants=] and [=sato/operators=].
@@ -424,7 +424,7 @@ The output reconstructed image is made up of the output samples, whose values sh
NOTE: [[#sato-examples]] contains examples of Sample Transform Derived Image Item usage.
-
+
An expression is a series of [=sato/tokens=]. A [=sato/token=] is an [=sato/operand=] or an [=sato/operator=]. An [=sato/operand=] can be a literal constant value or a sample value. A stack is used to keep track of the results of the subexpressions. An [=sato/operator=] takes either one or two input [=sato/operands=]. Each unary [=sato/operator=] pops one value from the stack. Each binary [=sato/operator=] pops two values from the stack, the first being the right [=sato/operand=] and the second being the left [=sato/operand=]. Each [=sato/token=] results in a value pushed to the stack. The single remaining value in the stack after evaluating the whole expression is the resulting output sample.
@@ -456,7 +456,7 @@ aligned(8) class SampleTransform {
}
```
-
+
version shall be equal to 0. Readers shall ignore a [=Sample Transform Derived Image Item=] with an unrecognized [=sato/version=]
number.
@@ -671,7 +671,7 @@ The result of any computation underflowing or overflowing the intermediate bit d
constant is a literal signed value extracted from the stream with a precision of [=sato/intermediate bit depth=], pushed to the stack.
-
+
[=Sample Transform Derived Image Items=] use the postfix notation to evaluate the result of the whole expression for each reconstructed image item sample.
From b89eb19eb2cd1f0ef43e92750212d143da93b92f Mon Sep 17 00:00:00 2001
From: Yannis Guyon
Date: Mon, 21 Oct 2024 14:33:55 +0000
Subject: [PATCH 45/65] Add references in the Sample Transform sections (#263)
Use box names instead of some property 4CC types.
Add a comment about creating the stack in the Syntax section.
---
index.bs | 41 +++++++++++++++++++++--------------------
1 file changed, 21 insertions(+), 20 deletions(-)
diff --git a/index.bs b/index.bs
index ece19b6..4892628 100755
--- a/index.bs
+++ b/index.bs
@@ -406,33 +406,34 @@ In these sections, a "sample" refers to the value of a pixel for a given channel
-When a [=derived image item=] is of type sato, it is called a [=Sample Transform Derived Image Item=], and its reconstructed image is formed from a set of input image items, [=sato/constants=] and [=sato/operators=].
+When a [=derived image item=] is of type 'sato'
, it is called a [=Sample Transform Derived Image Item=], and its reconstructed image is formed from a set of input image items, [=sato/constants=] and [=sato/operators=].
The input images are specified in the [=SingleItemTypeReferenceBox=]
or [=SingleItemTypeReferenceBoxLarge=]
entries of type '[=dimg=]'
for this [=Sample Transform Derived Image Item=] within the [=ItemReferenceBox=]
. The input images are in the same order as specified in these entries. In the [=SingleItemTypeReferenceBox=]
or [=SingleItemTypeReferenceBoxLarge=]
of type '[=dimg=]'
, the value of the [=from_item_ID=]
field identifies the [=Sample Transform Derived Image Item=], and the values of the [=to_item_ID=]
field identify the input images. There are [=reference_count=]
input image items as specified by the [=ItemReferenceBox=]
.
The input image items and the [=Sample Transform Derived Image Item=] shall:
- - each be associated with a '[=pixi=]'
property and an '[=ispe=]'
property;
- - have the same number of channels and the same chroma subsampling (or lack thereof) as defined by the '[=pixi=]'
and '[=AV1ItemConfigurationProperty/av1C=]'
properties;
+ - each be associated with a [=PixelInformationProperty=]
and an '[=ispe=]'
property;
+ - have the same number of channels and the same chroma subsampling (or lack thereof) as defined by the [=PixelInformationProperty=]
and [=AV1ItemConfigurationProperty=]
;
- have the same dimensions as defined by the '[=ispe=]'
property;
- - have the same color information as defined by the '[=colr=]'
properties (or lack thereof).
+ - have the same color information as defined by the [=ColourInformationBox=]
properties (or lack thereof).
-Each output sample of the [=Sample Transform Derived Image Item=] is obtained by evaluating an expression consisting of a series of integer [=sato/operators=] and [=sato/operands=]. An [=sato/operand=] is a constant or a sample from an input image item located at the same channel index and at the same spatial coordinates as the output sample.
+Each output sample of the [=Sample Transform Derived Image Item=] is obtained by evaluating an [=sato/expression=] consisting of a series of integer [=sato/operators=] and [=sato/operands=]. An [=sato/operand=] is a constant or a sample from an input image item located at the same channel index and at the same spatial coordinates as the output sample.
No color space conversion, matrix coefficients, or transfer characteristics function shall be applied to the input samples. They are already in the same color space as the output samples.
-The output reconstructed image is made up of the output samples, whose values shall each be clamped to fit in the number of bits per sample as defined by the '[=pixi=]'
property of the reconstructed image item. The [=full_range_flag=]
field of the '[=colr=]'
property of [=colour_type=]
'[=nclx=]'
also defines a range of values to clamp to, as defined in [[!CICP]].
+The output reconstructed image is made up of the output samples, whose values shall each be clamped to fit in the number of bits per sample as defined by the [=PixelInformationProperty=]
of the reconstructed image item. The [=full_range_flag=]
field of the [=ColourInformationBox=]
property of [=colour_type=]
'[=nclx=]'
also defines a range of values to clamp to, as defined in [[!CICP]].
-NOTE: [[#sato-examples]] contains examples of Sample Transform Derived Image Item usage.
+NOTE: [[#sato-examples]] contains examples of [=Sample Transform Derived Image Item=] usage.
-An expression is a series of [=sato/tokens=]. A [=sato/token=] is an [=sato/operand=] or an [=sato/operator=]. An [=sato/operand=] can be a literal constant value or a sample value. A stack is used to keep track of the results of the subexpressions. An [=sato/operator=] takes either one or two input [=sato/operands=]. Each unary [=sato/operator=] pops one value from the stack. Each binary [=sato/operator=] pops two values from the stack, the first being the right [=sato/operand=] and the second being the left [=sato/operand=]. Each [=sato/token=] results in a value pushed to the stack. The single remaining value in the stack after evaluating the whole expression is the resulting output sample.
+An expression is a series of [=sato/tokens=]. A [=sato/token=] is an [=sato/operand=] or an [=sato/operator=]. An [=sato/operand=] can be a literal constant value or a sample value. A stack is used to keep track of the results of the [=sato/expression|subexpressions=]. An [=sato/operator=] takes either one or two input [=sato/operands=]. Each unary [=sato/operator=] pops one value from the stack. Each binary [=sato/operator=] pops two values from the stack, the first being the right [=sato/operand=] and the second being the left [=sato/operand=]. Each [=sato/token=] results in a value pushed to the stack. The single remaining value in the stack after evaluating the whole [=sato/expression=] is the resulting output sample.
```c
aligned(8) class SampleTransform {
unsigned int(2) version = 0;
unsigned int(4) reserved;
unsigned int(2) bit_depth; // Enum signaling signed 8, 16, 32 or 64-bit.
+ // Create an empty stack of signed integer elements of that depth.
unsigned int(8) token_count;
for (i=0; i
Value of [=sato/bit_depth=] |
- Intermediate bit depth (sign bit inclusive) num_bits |
+ Intermediate bit depth (sign bit inclusive) num_bits |
@@ -673,9 +674,9 @@ The result of any computation underflowing or overflowing the intermediate bit d
-[=Sample Transform Derived Image Items=] use the postfix notation to evaluate the result of the whole expression for each reconstructed image item sample.
+[=Sample Transform Derived Image Items=] use the postfix notation to evaluate the result of the whole [=sato/expression=] for each reconstructed image item sample.
- - The [=sato/tokens=] shall be evaluated in the order they are defined in the metadata (the SampleTransform
structure) of the [=Sample Transform Derived Image Item=].
+ - The [=sato/tokens=] shall be evaluated in the order they are defined in the metadata (the SampleTransform
structure defined in [[#sample-transform-syntax]]) of the [=Sample Transform Derived Image Item=].
- [=sato/token=]
shall be at most [=reference_count=]
when evaluating a sample [=sato/operand=] (when 1≤token≤32).
- There shall be at least one [=sato/token=]
.
- The stack is empty before evaluating the first [=sato/token=]
.
@@ -683,9 +684,9 @@ The result of any computation underflowing or overflowing the intermediate bit d
- There shall be at least 2 elements in the stack before evaluating a binary [=sato/operator=].
- There shall be exactly one remaining element in the stack after evaluating the last [=sato/token=]
. This element is the value of the reconstructed image item sample.
-Non-compliant expressions shall be rejected by parsers as invalid files.
+Non-compliant [=sato/expressions=] shall be rejected by parsers as invalid files.
-Note: Because each [=sato/operator=] pops one or two elements and then pushes one element to the stack, there is at most one more [=sato/operand=] than [=sato/operators=] in the expression. There are at least floor([=sato/token_count=]2) [=sato/operators=] and at most ceil(token_count2) [=sato/operands=]. [=sato/token_count=]
is at most 255, meaning the maximum stack size for a valid expression is 128.
+Note: Because each [=sato/operator=] pops one or two elements and then pushes one element to the stack, there is at most one more [=sato/operand=] than [=sato/operators=] in the [=sato/expression=]. There are at least floor([=sato/token_count=]2) [=sato/operators=] and at most ceil(token_count2) [=sato/operands=]. [=sato/token_count=]
is at most 255, meaning the maximum stack size for a valid [=sato/expression=] is 128.
Entity groups
@@ -1272,9 +1273,9 @@ This informative appendix contains example recipes for extending base [=/AVIF=]
The following example describes how to leverage a [=Sample Transform Derived Image Item=] on top of a regular 8-bit [=MIAF image item=] to extend the decoded bit depth to 16 bits.
Consider the following:
- - A [=MIAF image item=] being a losslessly coded image item,
and its '[=pixi=]'
property with [=bits_per_channel=]
=8,
- - Another [=MIAF image item=] being a lossily or losslessly coded image item with the same dimensions and number of samples as the first input image item,
and its '[=pixi=]'
property with [=bits_per_channel=]
=8,
- - A [=Sample Transform Derived Image Item=] with the two items above as input in this order,
and its '[=pixi=]'
property with [=bits_per_channel=]
=16,
and the following [=SampleTransform=]
fields:
+ - A [=MIAF image item=] being a losslessly coded image item,
and its [=PixelInformationProperty=]
with [=bits_per_channel=]
=8,
+ - Another [=MIAF image item=] being a lossily or losslessly coded image item with the same dimensions and number of samples as the first input image item,
and its [=PixelInformationProperty=]
with [=bits_per_channel=]
=8,
+ - A [=Sample Transform Derived Image Item=] with the two items above as input in this order,
and its [=PixelInformationProperty=]
with [=bits_per_channel=]
=16,
and the following [=SampleTransform=]
fields:
- [=sato/version=]
=0
- [=sato/bit_depth=]
=2 (signed 32-bit [=sato/constant=]
s, stack values and intermediate results)
- [=sato/token_count=]
=5
@@ -1306,15 +1307,15 @@ The following example describes how to leverage a [=Sample Transform Derived Ima
It differs from the [[#sato-example-suffix-bit-depth-extension]] by its slightly longer series of operations allowing its first input image item to be lossily encoded.
Consider the following:
- - A [=MIAF image item=] being a lossily coded image item,
and its '[=pixi=]'
property with [=bits_per_channel=]
=12,
- - Another [=MIAF image item=] being a lossily or losslessly coded image item with the same dimensions and number of samples as the first input image item,
and its '[=pixi=]'
property with [=bits_per_channel=]
=8,
with the following contraints:
+ - A [=MIAF image item=] being a lossily coded image item,
and its [=PixelInformationProperty=]
with [=bits_per_channel=]
=12,
+ - Another [=MIAF image item=] being a lossily or losslessly coded image item with the same dimensions and number of samples as the first input image item,
and its [=PixelInformationProperty=]
with [=bits_per_channel=]
=8,
with the following contraints:
- For each sample position in each plane,
sampleoriginal being the value of the 16-bit original sample at that position in that plane,
sample1 being the value of the 12-bit sample of the first input image at that position in that plane,
sample2 being the value of the sample of the second input image at that position in that plane,
≈ representing similarity within compression loss range,
- sample1≈sampleoriginal24
- sample2≈sampleoriginal-24×sample1+27
- 0≤sample1<212
- 0≤sample2<28
- - 0≤24×sample1+sample2-27<216
NOTE: Files that do not respect this constraint will still decode successfully because Clause [[#sample-transform-definition]] mandates the resulting values to be each clamped to fit in the number of bits per sample as defined by the '[=pixi=]'
property of the reconstructed image item.
- - A [=Sample Transform Derived Image Item=] with the two items above as input in this order,
and its '[=pixi=]'
property with [=bits_per_channel=]
=16,
and the following [=SampleTransform=]
fields:
+ - 0≤24×sample1+sample2-27<216
NOTE: Files that do not respect this constraint will still decode successfully because Clause [[#sample-transform-definition]] mandates the resulting values to be each clamped to fit in the number of bits per sample as defined by the [=PixelInformationProperty=]
of the reconstructed image item.
+ - A [=Sample Transform Derived Image Item=] with the two items above as input in this order,
and its [=PixelInformationProperty=]
with [=bits_per_channel=]
=16,
and the following [=SampleTransform=]
fields:
- [=sato/version=]
=0
- [=sato/bit_depth=]
=2 (signed 32-bit [=sato/constant=]
s, stack values and intermediate results)
- [=sato/token_count=]
=7
From 263536c6160546fae9fd6b2aadd807d088bf65d5 Mon Sep 17 00:00:00 2001
From: Yannis Guyon
Date: Mon, 21 Oct 2024 14:34:29 +0000
Subject: [PATCH 46/65] Indent notes as the list items they refer to (#266)
---
index.bs | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/index.bs b/index.bs
index 4892628..89f83f2 100755
--- a/index.bs
+++ b/index.bs
@@ -224,7 +224,7 @@ When an item is of type av01, it is
- The [=AV1 Image Item Data=] shall be identical to the content of an [=AV1 Sample=] marked as '[=sync=]'
, as defined in [[!AV1-ISOBMFF]].
- The [=AV1 Image Item Data=] shall have exactly one [=Sequence Header OBU=].
-NOTE: File writers may want to set the [=still_picture=]
and [=reduced_still_picture_header=]
flags to 1 when possible in the [=Sequence Header OBU=] part of the [=AV1 Image Item Data=] so that AV1 header overhead is minimized.
+ NOTE: File writers may want to set the [=still_picture=]
and [=reduced_still_picture_header=]
flags to 1 when possible in the [=Sequence Header OBU=] part of the [=AV1 Image Item Data=] so that AV1 header overhead is minimized.
Image Item Properties
@@ -741,7 +741,7 @@ The following constraints are common to files compliant with this specification:
- The file shall list '[=AVIF Image brand/avif=]'
or '[=avis=]'
in the [=compatible_brands=]
field of the [=FileTypeBox=]
.
- Transformative properties shall not be associated with items in a derivation chain (as defined in [[!MIAF]]) that serves as an input to a [=grid derived image item=]. For example, if a file contains a grid item and its referenced coded image items, cropping, mirroring or rotation transformations are only permitted on the grid item itself.
-NOTE: This constraint further restricts files compared to [[!MIAF]].
+ NOTE: This constraint further restricts files compared to [[!MIAF]].
Profiles
@@ -777,9 +777,9 @@ The following shared conditions and requirements from [[!MIAF]] should apply:
The following additional constraints apply to all [=AV1 Image Items=] and all [=AV1 Image Sequences=]:
- The AV1 profile shall be the Main Profile and the level shall be 5.1 or lower.
-NOTE: AV1 tiers are not constrained because timing is optional in image sequences and are not relevant in image items or collections.
+ NOTE: AV1 tiers are not constrained because timing is optional in image sequences and are not relevant in image items or collections.
-NOTE: Level 5.1 is chosen for the Baseline profile to ensure that no single coded image exceeds 4k resolution, as some decoder may not be able to handle larger images. More precisely, following [[!AV1]] level definitions, coded image items compliant to the [=AVIF Baseline profile=] may not have a number of pixels greater than 8912896, a width greater than 8192 or a height greater than 4352. It is still possible to use the Baseline profile to create larger images using a [=grid derived image item=].
+ NOTE: Level 5.1 is chosen for the Baseline profile to ensure that no single coded image exceeds 4k resolution, as some decoder may not be able to handle larger images. More precisely, following [[!AV1]] level definitions, coded image items compliant to the [=AVIF Baseline profile=] may not have a number of pixels greater than 8912896, a width greater than 8192 or a height greater than 4352. It is still possible to use the Baseline profile to create larger images using a [=grid derived image item=].
A file containing items compliant with this profile is expected to list the following brands, in any order, in the
[=compatible_brands=]
of the
[=FileTypeBox=]
:
@@ -813,7 +813,7 @@ The following shared conditions and requirements from [[!MIAF]] should apply:
The following additional constraints apply to all [=AV1 Image Items=]:
-
The AV1 profile shall be the High Profile and the level shall be 6.0 or lower.
-NOTE: Following [[!AV1]] level definitions, coded image items compliant to the [=AVIF Advanced profile=] may not have a number of pixels greater than 35651584, a width greater than 16384 or a height greater than 8704. It is still possible to use the Advanced profile to create larger images using a [=grid derived image item=].
+ NOTE: Following [[!AV1]] level definitions, coded image items compliant to the [=AVIF Advanced profile=] may not have a number of pixels greater than 35651584, a width greater than 16384 or a height greater than 8704. It is still possible to use the Advanced profile to create larger images using a [=grid derived image item=].
The following additional constraints apply only to [=AV1 Image Sequences=]:
-
The AV1 profile shall be either Main Profile or High Profile.
From 08f65d4461a2678dca8666c0ded501a7f70124ba Mon Sep 17 00:00:00 2001
From: Yannis Guyon
Date: Mon, 21 Oct 2024 14:34:39 +0000
Subject: [PATCH 47/65] Remove inconsistent dots in 9.1.2 (#267)
---
index.bs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/index.bs b/index.bs
index 89f83f2..1f28024 100755
--- a/index.bs
+++ b/index.bs
@@ -1108,7 +1108,7 @@ The "Version(s)" column in the following table lists the version(s) of the boxes
- |
[[!ISOBMFF]] |
[=ipco=] |
- Used to signal information such as color primaries. |
+ Used to signal information such as color primaries |
[=auxC=] |
@@ -1116,7 +1116,7 @@ The "Version(s)" column in the following table lists the version(s) of the boxes
0 |
[[!HEIF]] |
[=ipco=] |
- Used to signal the type of an auxiliary image (e.g. alpha, depth). |
+ Used to signal the type of an auxiliary image (e.g. alpha, depth) |
[[#clean-aperture-property|clap]] |
From d980c529b9a6197abe2e1895d32c2954d6ffb876 Mon Sep 17 00:00:00 2001
From: Yannis Guyon
Date: Mon, 21 Oct 2024 19:29:17 +0000
Subject: [PATCH 48/65] Update change-list (#271)
---
index.bs | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/index.bs b/index.bs
index 1f28024..ef09ba6 100755
--- a/index.bs
+++ b/index.bs
@@ -1259,6 +1259,12 @@ The "Version(s)" column in the following table lists the version(s) of the boxes
- EDITORIAL: Add refs, fix wording and format in clauses 1,2
- EDITORIAL: Add sato, alpha, depth, progressive in Scope
- Clean up linking to base specs and duplicated information
+ - EDITORIAL: Use Markdown syntax coloring for code snippets
+ - EDITORIAL: Consistently use dfn noexport for derived items
+ - EDITORIAL: Remove Sample Transform sections from TOC
+ - EDITORIAL: Add references in the Sample Transform sections
+ - EDITORIAL: Indent notes as the list items they refer to
+ - EDITORIAL: Remove inconsistent dots in 9.1.2
Appendix A: (informative) Sample Transform Derived Image Item Examples
From 439b57e9303a483d45f78e192a0baca5a895f92a Mon Sep 17 00:00:00 2001
From: Yannis Guyon
Date: Mon, 21 Oct 2024 19:30:00 +0000
Subject: [PATCH 49/65] Use exact tokens as sato math expr example (#272)
---
index.bs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/index.bs b/index.bs
index ef09ba6..899da38 100755
--- a/index.bs
+++ b/index.bs
@@ -1330,8 +1330,8 @@ Consider the following:
- [=sato/token=]
=130 (product)
- [=sato/token=]
=2 (sample from 2nd input image item)
- [=sato/token=]
=128 (sum)
- - [=sato/token=]
=0, [=sato/constant=]
=-128
- - [=sato/token=]
=128 (sum)
+ - [=sato/token=]
=0, [=sato/constant=]
=128
+ - [=sato/token=]
=129 (difference)
This is equivalent to the following postfix notation (parentheses for clarity):
From 751dffea955a196e89d6e88526708af01a6ace25 Mon Sep 17 00:00:00 2001
From: leo-barnes
Date: Wed, 23 Oct 2024 11:17:11 +0200
Subject: [PATCH 50/65] Change optional boxes table layering (#273)
- Change optional boxes table to have same layering as required boxes table.
- Change text on box order
- Change text on `dinf`
---
index.bs | 158 +++++++++++++++++++++++++++++++++++++------------------
1 file changed, 108 insertions(+), 50 deletions(-)
diff --git a/index.bs b/index.bs
index 899da38..4aa0a67 100755
--- a/index.bs
+++ b/index.bs
@@ -985,249 +985,306 @@ The "Version(s)" column in the following table lists the version(s) of the boxes
Requirements on additional image item related boxes
-The boxes indicated in the following table may be present in an [=AVIF file=] to provide additional signaling for image items. The boxes may be present inside the box indicated in the "Containing Box" column. If present, they shall use the version indicated in the table unless the box is an item property marked as non-essential. [=/AVIF=] readers are expected to understand the boxes and versions listed in this table. The order of the boxes is indicative in the table. Specifications may require specific order and shall be respected. Additionally, the '[=free=]'
and '[=skip=]'
boxes may be present at any level in the hierarchy and [=/AVIF=] readers are expected to ignore them. Additional boxes in the '[=meta=]'
hierarchy not listed in the following table may also be present and may be ignored by [=/AVIF=] readers.
+The boxes indicated in the following table may be present in an [=AVIF file=] to provide additional signaling for image items. If present, the boxes shall use the version indicated in the table unless the box is an item property marked as non-essential. [=/AVIF=] readers are expected to understand the boxes and versions listed in this table. The order of the boxes in the table may not be the order of the boxes in the file. Specifications may require specific order and shall be respected. Additionally, the '[=free=]'
and '[=skip=]'
boxes may be present at any level in the hierarchy and [=/AVIF=] readers are expected to ignore them. Additional boxes in the '[=meta=]'
hierarchy not listed in the following table may also be present and may be ignored by [=/AVIF=] readers.
+ Top-Level |
Level 1 |
Level 2 |
+ Level 3 |
Version(s) |
Specification |
- Containing Box |
Description |
+ [=meta=] |
+ |
+ |
+ |
+ |
+ |
+ See [[#avif-required-boxes]] |
+
+
+ |
[=dinf=] |
|
+ |
- |
[[!ISOBMFF]] |
- [=meta=] |
- Used to indicate the location of the media information in a track |
+ Used to indicate the location of the media information |
+ |
|
[=dref=] |
+ |
0 |
[[!ISOBMFF]] |
|
- |
+ |
[=iref=] |
|
+ |
0, 1 |
[[!ISOBMFF]] |
- [=meta=] |
Used to indicate directional relationships between images or metadata |
+ |
|
[=auxl=] |
+ |
- |
[[!HEIF]] |
- |
Used when an image is auxiliary to another image |
+ |
|
[=thmb=] |
+ |
- |
[[!HEIF]] |
- |
Used when an image is a thumbnail of another image |
+ |
|
[=dimg=] |
+ |
- |
[[!HEIF]] |
- |
Used when an image is [[#derived-images|derived from another image]] |
+ |
|
[=prem=] |
+ |
- |
[[!HEIF]] |
- |
Used when the color values in an image have been premultiplied with alpha values |
+ |
|
[=cdsc=] |
+ |
- |
[[!HEIF]] |
- |
Used to link metadata with an image |
+ |
[=idat=] |
|
+ |
- |
[[!ISOBMFF]] |
- [=meta=] |
- Used to store derived image definitions |
+ Typically used to store derived image definitions or small pieces of metadata |
+ |
[[#groups|grpl]] |
|
+ |
- |
[[!ISOBMFF]] |
- [=meta=] |
Used to indicate that multiple images are semantically grouped |
+ |
|
[[#altr-group|altr]] |
+ |
0 |
[[!ISOBMFF]] |
- |
Used when images in a group are alternatives to each other |
+ |
|
[[#ster-group|ster]] |
+ |
0 |
[[!HEIF]] |
- |
Used when images in a group form a stereo pair |
- [=pasp=] |
|
+ [=iprp=] |
+ |
+ |
+ |
+ |
+ See [[#avif-required-boxes]] |
+
+
+ |
+ |
+ [=ipco=] |
+ |
+ |
+ |
+ See [[#avif-required-boxes]] |
+
+
+ |
+ |
+ |
+ [=pasp=] |
- |
[[!ISOBMFF]] |
- [=ipco=] |
Used to signal pixel aspect ratio. If present, shall indicate a pixel aspect ratio of 1:1 |
- [=colr=] |
|
+ |
+ |
+ [=colr=] |
- |
[[!ISOBMFF]] |
- [=ipco=] |
Used to signal information such as color primaries |
- [=auxC=] |
|
+ |
+ |
+ [=auxC=] |
0 |
[[!HEIF]] |
- [=ipco=] |
Used to signal the type of an auxiliary image (e.g. alpha, depth) |
- [[#clean-aperture-property|clap]] |
|
+ |
+ |
+ [[#clean-aperture-property|clap]] |
- |
[[!ISOBMFF]] |
- [=ipco=] |
Used to signal cropping applied to an image |
- [=irot=] |
|
+ |
+ |
+ [=irot=] |
- |
[[!HEIF]] |
- [=ipco=] |
Used to signal a rotation applied to an image |
- [=imir=] |
|
+ |
+ |
+ [=imir=] |
- |
[[!HEIF]] |
- [=ipco=] |
Used to signal a mirroring applied to an image |
- [=clli=] |
|
+ |
+ |
+ [=clli=] |
- |
[[!ISOBMFF]] |
- [=ipco=] |
Used to signal HDR light level information for an image |
- [=cclv=] |
|
+ |
+ |
+ [=cclv=] |
- |
[[!ISOBMFF]] |
- [=ipco=] |
Used to signal HDR color volume for an image |
- [=mdcv=] |
|
+ |
+ |
+ [=mdcv=] |
- |
[[!ISOBMFF]] |
- [=ipco=] |
Used to signal HDR mastering information for an image |
- [=amve=] |
|
+ |
+ |
+ [=amve=] |
- |
[[!ISOBMFF]] |
- [=ipco=] |
Used to signal the nominal ambient viewing environment for the display of the content |
- [=reve=] |
|
+ |
+ |
+ [=reve=] |
0 |
[[!HEIF]] |
- [=ipco=] |
Used to signal the viewing environment in which the image was mastered |
- [=ndwt=] |
|
+ |
+ |
+ [=ndwt=] |
0 |
[[!HEIF]] |
- [=ipco=] |
Used to signal the nominal diffuse white luminance of the content |
- [=a1op=] |
|
+ |
+ |
+ [=a1op=] |
- |
[=/AVIF=] |
- [=ipco=] |
Used to configure which operating point to select when there are multiple choices |
- [=lsel=] |
|
+ |
+ |
+ [=lsel=] |
- |
[[!HEIF]] |
- [=ipco=] |
Used to configure rendering of a multilayered image |
- [=a1lx=] |
|
+ |
+ |
+ [=a1lx=] |
- |
[=/AVIF=] |
- [=ipco=] |
Used to assist reader in parsing a multilayered image |
- [=cmin=] |
|
+ |
+ |
+ [=cmin=] |
0 |
[[!HEIF]] |
- [=ipco=] |
Used to signal the camera intrinsic matrix |
- [=cmex=] |
|
+ |
+ |
+ [=cmex=] |
0 |
[[!HEIF]] |
- [=ipco=] |
Used to signal the camera extrinsic matrix |
@@ -1265,6 +1322,7 @@ The "Version(s)" column in the following table lists the version(s) of the boxes
- EDITORIAL: Add references in the Sample Transform sections
- EDITORIAL: Indent notes as the list items they refer to
- EDITORIAL: Remove inconsistent dots in 9.1.2
+ - Change structure of optional table of boxes
Appendix A: (informative) Sample Transform Derived Image Item Examples
From 7e5c8c7dbea853bbd076cd1cb6e3155e302a40eb Mon Sep 17 00:00:00 2001
From: Yannis Guyon
Date: Wed, 23 Oct 2024 09:40:06 +0000
Subject: [PATCH 51/65] Use precise dim/chan constraints in sato examples
(#287)
---
index.bs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/index.bs b/index.bs
index 4aa0a67..2abc4d2 100755
--- a/index.bs
+++ b/index.bs
@@ -1338,7 +1338,7 @@ The following example describes how to leverage a [=Sample Transform Derived Ima
Consider the following:
- A [=MIAF image item=] being a losslessly coded image item,
and its [=PixelInformationProperty=]
with [=bits_per_channel=]
=8,
- - Another [=MIAF image item=] being a lossily or losslessly coded image item with the same dimensions and number of samples as the first input image item,
and its [=PixelInformationProperty=]
with [=bits_per_channel=]
=8,
+ - Another [=MIAF image item=] being a lossily or losslessly coded image item with the same spatial dimensions, the same number of channels, and the same chroma subsampling (or lack thereof) as the first input image item,
and its [=PixelInformationProperty=]
with [=bits_per_channel=]
=8,
- A [=Sample Transform Derived Image Item=] with the two items above as input in this order,
and its [=PixelInformationProperty=]
with [=bits_per_channel=]
=16,
and the following [=SampleTransform=]
fields:
- [=sato/version=]
=0
- [=sato/bit_depth=]
=2 (signed 32-bit [=sato/constant=]
s, stack values and intermediate results)
@@ -1372,7 +1372,7 @@ It differs from the [[#sato-example-suffix-bit-depth-extension]] by its slightly
Consider the following:
- A [=MIAF image item=] being a lossily coded image item,
and its [=PixelInformationProperty=]
with [=bits_per_channel=]
=12,
- - Another [=MIAF image item=] being a lossily or losslessly coded image item with the same dimensions and number of samples as the first input image item,
and its [=PixelInformationProperty=]
with [=bits_per_channel=]
=8,
with the following contraints:
+ - Another [=MIAF image item=] being a lossily or losslessly coded image item with the same spatial dimensions, the same number of channels, and the same chroma subsampling (or lack thereof) as the first input image item,
and its [=PixelInformationProperty=]
with [=bits_per_channel=]
=8,
with the following contraints:
- For each sample position in each plane,
sampleoriginal being the value of the 16-bit original sample at that position in that plane,
sample1 being the value of the 12-bit sample of the first input image at that position in that plane,
sample2 being the value of the sample of the second input image at that position in that plane,
≈ representing similarity within compression loss range,
- sample1≈sampleoriginal24
- sample2≈sampleoriginal-24×sample1+27
From d81c366cdaae43dc1f02d3fb7cee1c7b21b5d340 Mon Sep 17 00:00:00 2001
From: Yannis Guyon
Date: Wed, 23 Oct 2024 11:03:00 +0000
Subject: [PATCH 52/65] Add hidden image item recommendation (#288)
---
index.bs | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/index.bs b/index.bs
index 2abc4d2..5859c34 100755
--- a/index.bs
+++ b/index.bs
@@ -91,6 +91,7 @@ url: https://www.iso.org/standard/66067.html; spec: HEIF; type: dfn;
text: derived image item
text: dimg
text: grid
+ text: hidden image item
text: image_height
text: image_width
text: imir
@@ -269,7 +270,7 @@ NOTE: The values of [=render_width_minus1=]
and [=render_heig
The semantics of the clean aperture property ('[=clap=]'
) as defined in [[!HEIF]] apply. In addition to the restrictions on transformative item property ordering specified in [[!MIAF]], the following restriction also applies:
-The origin of the '[=clap=]'
item property shall be anchored to 0,0 (top-left) of the input image unless the full, un-cropped image item is included as a secondary non-hidden image item.
+The origin of the '[=clap=]'
item property shall be anchored to 0,0 (top-left) of the input image unless the full, un-cropped image item is included as a secondary [=hidden image item|non-hidden image item=].
Other Item Properties
@@ -396,7 +397,7 @@ A grid derived image item ('[=grid=]'
) as defin
Tone Map Derived Image Item
-A tone map derived image item ('[=tmap=]'
) as defined in [[!HEIF]] may be used in an [=AVIF file=]. When present, the base image item and the '[=tmap=]'
image item should be grouped together by an '[=altr=]'
(see [[#altr-group]]) entity group as recommended in [[!HEIF]].
+A tone map derived image item ('[=tmap=]'
) as defined in [[!HEIF]] may be used in an [=AVIF file=]. When present, the base image item and the '[=tmap=]'
image item should be grouped together by an '[=altr=]'
(see [[#altr-group]]) entity group as recommended in [[!HEIF]]. When present, the gainmap image item should be a [=hidden image item=].
@@ -1323,6 +1324,7 @@ The "Version(s)" column in the following table lists the version(s) of the boxes
- EDITORIAL: Indent notes as the list items they refer to
- EDITORIAL: Remove inconsistent dots in 9.1.2
- Change structure of optional table of boxes
+ - Add hidden image item recommendation
Appendix A: (informative) Sample Transform Derived Image Item Examples
@@ -1361,6 +1363,8 @@ Each output sample is equal to the sum of a sample of the first input image item
NOTE: If the first input image item is the [=primary image item=] and is enclosed in an '[=altr=]'
group (see [[#altr-group]]) with the [=Sample Transform Derived Image Item=], the first input image item is also a backward-compatible 8-bit regular coded image item that can be used by readers that do not support [=Sample Transform Derived Image Items=] or do not need extra precision.
+NOTE: The second input image item can be marked as [=hidden image item|hidden=] to prevent readers from surfacing it to users.
+
NOTE: The second input image item loses its meaning of least significant part if any of the most significant bits changes, so the first input image item has to be losslessly encoded. The second input image item supports reasonable loss during encoding.
NOTE: This pattern can be used for reconstructed bit depths beyond 16 by combining more than two input image items or with various input bit depth configurations and operations.
@@ -1403,6 +1407,8 @@ Each output sample is equal to the sum of a sample of the first input image item
NOTE: If the first input image item is the [=primary image item=] and is enclosed in an '[=altr=]'
group (see [[#altr-group]]) with the derived image item, the first input image item is also a backward-compatible 12-bit regular coded image item that can be used by decoding contexts that do not support [=Sample Transform Derived Image Items=] or do not need extra precision.
+NOTE: The second input image item can be marked as [=hidden image item|hidden=] to prevent readers from surfacing it to users.
+
NOTE: The first input image item supports reasonable loss during encoding because the second input image item "overlaps" by 4 bits to correct the loss. The second input image item supports reasonable loss during encoding.
NOTE: This pattern can be used for reconstructed bit depths beyond 16 by combining more than two input image items or with various input bit depth configurations and operations.
From 198515cb86afae7a298dc0465715483bfaec615c Mon Sep 17 00:00:00 2001
From: Wan-Teh Chang
Date: Tue, 22 Oct 2024 16:54:51 -0700
Subject: [PATCH 53/65] Minor edits in Section 8 Profiles
---
index.bs | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/index.bs b/index.bs
index 5859c34..044c03f 100755
--- a/index.bs
+++ b/index.bs
@@ -752,7 +752,7 @@ The profiles defined in this section are for enabling interoperability between [
The [=FileTypeBox=]
should declare at least one profile that enables decoding of the [=primary image item=]. It is not an error for the encoder to include an auxiliary image that is not allowed by the specified profile(s).
-If '[=avis=]'
is declared in the [=FileTypeBox=]
and a profile is declared in the [=FileTypeBox=]
, the profile shall also enable decoding of at least one image sequence track. The profile should allow decoding of any associated auxiliary image sequence tracks, unless it is acceptable to decode the image sequence without its auxiliary image sequence tracks.
+If '[=avis=]'
is declared in the [=FileTypeBox=]
and a profile is declared in the [=FileTypeBox=]
, the profile shall also enable decoding of at least one image sequence track. The profile should allow decoding of any associated auxiliary image sequence tracks, unless it is acceptable to decode the image sequence track without its auxiliary image sequence tracks.
It is possible for a file compliant to this [=AV1 Image File Format=] to not be able to declare an [=/AVIF=] profile, if the corresponding AV1 encoding characteristics do not match any of the defined profiles.
@@ -778,9 +778,9 @@ The following shared conditions and requirements from [[!MIAF]] should apply:
The following additional constraints apply to all [=AV1 Image Items=] and all [=AV1 Image Sequences=]:
- The AV1 profile shall be the Main Profile and the level shall be 5.1 or lower.
- NOTE: AV1 tiers are not constrained because timing is optional in image sequences and are not relevant in image items or collections.
+ NOTE: AV1 tiers are not constrained because timing is optional in image sequences and is not relevant in image items or collections.
- NOTE: Level 5.1 is chosen for the Baseline profile to ensure that no single coded image exceeds 4k resolution, as some decoder may not be able to handle larger images. More precisely, following [[!AV1]] level definitions, coded image items compliant to the [=AVIF Baseline profile=] may not have a number of pixels greater than 8912896, a width greater than 8192 or a height greater than 4352. It is still possible to use the Baseline profile to create larger images using a [=grid derived image item=].
+ NOTE: Level 5.1 is chosen for the Baseline profile to ensure that no single coded image exceeds 4k resolution, as some decoders may not be able to handle larger images. More precisely, following [[!AV1]] level definitions, coded image items compliant to the [=AVIF Baseline profile=] may not have a number of pixels greater than 8912896, a width greater than 8192 or a height greater than 4352. It is still possible to use the Baseline profile to create larger images using a [=grid derived image item=].
A file containing items compliant with this profile is expected to list the following brands, in any order, in the
[=compatible_brands=]
of the
[=FileTypeBox=]
:
From 83d518809249f0960c5988f8006c318259565490 Mon Sep 17 00:00:00 2001
From: Wan-Teh Chang
Date: Tue, 22 Oct 2024 14:06:03 -0700
Subject: [PATCH 54/65] Remove an extraneous "only"
Section 9.1 also applies to an AVIF file containing image items and
image sequences, so remove "only" from "containing only image items".
---
index.bs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/index.bs b/index.bs
index 044c03f..e2362aa 100755
--- a/index.bs
+++ b/index.bs
@@ -834,7 +834,7 @@ A file containing a '[=pict=]'
track compliant with this profile is
Box requirements
Image item boxes
-This section discusses the box requirements for an [=AVIF file=] containing only image items.
+This section discusses the box requirements for an [=AVIF file=] containing image items.
Minimum set of boxes
From 20b9eaf60d37da17dbab89093c534553a7072d0e Mon Sep 17 00:00:00 2001
From: Wan-Teh Chang
Date: Tue, 22 Oct 2024 15:05:02 -0700
Subject: [PATCH 55/65] Add the word "bits" to the amount of shift
---
index.bs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/index.bs b/index.bs
index e2362aa..fd5a323 100755
--- a/index.bs
+++ b/index.bs
@@ -1359,7 +1359,7 @@ This is equivalent to the following infix notation:
sampleoutput=256×sample1+sample2
-Each output sample is equal to the sum of a sample of the first input image item shifted to the left by 8 and of a sample of the second input image item. This can be viewed as a bit depth extension of the first input image item by the second input image item. The first input image item contains the 8 most significant bits and the second input image item contains the 8 least significant bits of the output reconstructed image item which has a bit depth of 16, something that is impossible to achieve with a single [=AV1 image item=].
+Each output sample is equal to the sum of a sample of the first input image item shifted to the left by 8 bits and of a sample of the second input image item. This can be viewed as a bit depth extension of the first input image item by the second input image item. The first input image item contains the 8 most significant bits and the second input image item contains the 8 least significant bits of the output reconstructed image item which has a bit depth of 16, something that is impossible to achieve with a single [=AV1 image item=].
NOTE: If the first input image item is the [=primary image item=] and is enclosed in an '[=altr=]'
group (see [[#altr-group]]) with the [=Sample Transform Derived Image Item=], the first input image item is also a backward-compatible 8-bit regular coded image item that can be used by readers that do not support [=Sample Transform Derived Image Items=] or do not need extra precision.
@@ -1403,7 +1403,7 @@ This is equivalent to the following infix notation:
sampleoutput=16×sample1+sample2-128
-Each output sample is equal to the sum of a sample of the first input image item shifted to the left by 4 and of a sample of the second input image item offset by -128. This can be viewed as a bit depth extension of the first input image item by the second input image item which contains the residuals to correct the precision loss of the first input image item.
+Each output sample is equal to the sum of a sample of the first input image item shifted to the left by 4 bits and of a sample of the second input image item offset by -128. This can be viewed as a bit depth extension of the first input image item by the second input image item which contains the residuals to correct the precision loss of the first input image item.
NOTE: If the first input image item is the [=primary image item=] and is enclosed in an '[=altr=]'
group (see [[#altr-group]]) with the derived image item, the first input image item is also a backward-compatible 12-bit regular coded image item that can be used by decoding contexts that do not support [=Sample Transform Derived Image Items=] or do not need extra precision.
From a83f92178297df364d65b273b747166b7a6a77dd Mon Sep 17 00:00:00 2001
From: Wan-Teh Chang
Date: Tue, 22 Oct 2024 15:06:58 -0700
Subject: [PATCH 56/65] Add the word "added" to "parentheses for clarity"
---
index.bs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/index.bs b/index.bs
index fd5a323..c2f0d36 100755
--- a/index.bs
+++ b/index.bs
@@ -1351,7 +1351,7 @@ Consider the following:
- [=sato/token=]
=2 (sample from 2nd input image item)
- [=sato/token=]
=128 (sum)
-This is equivalent to the following postfix notation (parentheses for clarity):
+This is equivalent to the following postfix notation (parentheses added for clarity):
sampleoutput=(256sample1×)sample2+
@@ -1395,7 +1395,7 @@ Consider the following:
- [=sato/token=]
=0, [=sato/constant=]
=128
- [=sato/token=]
=129 (difference)
-This is equivalent to the following postfix notation (parentheses for clarity):
+This is equivalent to the following postfix notation (parentheses added for clarity):
sampleoutput=((16sample1×)sample2+)128-
From 2acad7e75744094d83d596537db4cc8b8553a4fd Mon Sep 17 00:00:00 2001
From: Wan-Teh Chang
Date: Wed, 23 Oct 2024 08:51:56 -0700
Subject: [PATCH 57/65] Clarify it is the order that shall be respected
Otherwise, it seems that it is the specifications that shall be
respected.
Also make the second instance of this sentence more similar to the first
instance.
---
index.bs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/index.bs b/index.bs
index c2f0d36..ea352a6 100755
--- a/index.bs
+++ b/index.bs
@@ -839,7 +839,7 @@ This section discusses the box requirements for an [=AVIF file=] containing imag
Minimum set of boxes
As indicated in [[#file-constraints]], an [=AVIF file=] is a compliant [[!MIAF]] file. As a consequence, some [[!ISOBMFF]] or [[!HEIF]] boxes are required, as indicated in the following table. The order of the boxes is indicative in the table. The specifications listed in the "Specification"
-column may require a specific order for the box or for its children and shall be respected. For example, per [[!ISOBMFF]], the [=FileTypeBox=]
is required to appear first in an [=AVIF file=].
+column may require a specific order for a box or for its children and the order shall be respected. For example, per [[!ISOBMFF]], the [=FileTypeBox=]
is required to appear first in an [=AVIF file=].
The "Version(s)" column in the following table lists the version(s) of the boxes allowed by this brand. With the exception of item properties marked as non-essential, other versions of the boxes shall not be used. "-" means that the box does not have a version.
@@ -986,7 +986,7 @@ The "Version(s)" column in the following table lists the version(s) of the boxes
Requirements on additional image item related boxes
-The boxes indicated in the following table may be present in an [=AVIF file=] to provide additional signaling for image items. If present, the boxes shall use the version indicated in the table unless the box is an item property marked as non-essential. [=/AVIF=] readers are expected to understand the boxes and versions listed in this table. The order of the boxes in the table may not be the order of the boxes in the file. Specifications may require specific order and shall be respected. Additionally, the '[=free=]'
and '[=skip=]'
boxes may be present at any level in the hierarchy and [=/AVIF=] readers are expected to ignore them. Additional boxes in the '[=meta=]'
hierarchy not listed in the following table may also be present and may be ignored by [=/AVIF=] readers.
+The boxes indicated in the following table may be present in an [=AVIF file=] to provide additional signaling for image items. If present, the boxes shall use the version indicated in the table unless the box is an item property marked as non-essential. [=/AVIF=] readers are expected to understand the boxes and versions listed in this table. The order of the boxes in the table may not be the order of the boxes in the file. Specifications may require a specific order for a box or for its children and the order shall be respected. Additionally, the '[=free=]'
and '[=skip=]'
boxes may be present at any level in the hierarchy and [=/AVIF=] readers are expected to ignore them. Additional boxes in the '[=meta=]'
hierarchy not listed in the following table may also be present and may be ignored by [=/AVIF=] readers.
From aa77c7076ead0b6c947d864d956b7480e8040cab Mon Sep 17 00:00:00 2001
From: Wan-Teh Chang
Date: Wed, 23 Oct 2024 09:01:22 -0700
Subject: [PATCH 58/65] Add the word "color"
The 'colr' box specifies color information.
---
index.bs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/index.bs b/index.bs
index ea352a6..5ad3033 100755
--- a/index.bs
+++ b/index.bs
@@ -1151,7 +1151,7 @@ The "Version(s)" column in the following table lists the version(s) of the boxes
[=colr=] |
- |
[[!ISOBMFF]] |
- Used to signal information such as color primaries |
+ Used to signal color information such as color primaries |
|
From 486d3ff5ab0e2ea47abb582641f74a66a56c1221 Mon Sep 17 00:00:00 2001
From: Wan-Teh Chang
Date: Wed, 23 Oct 2024 09:05:58 -0700
Subject: [PATCH 59/65] Use full names of HDR image item properties
---
index.bs | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/index.bs b/index.bs
index 5ad3033..6bb2188 100755
--- a/index.bs
+++ b/index.bs
@@ -1196,7 +1196,7 @@ The "Version(s)" column in the following table lists the version(s) of the boxes
[=clli=] |
- |
[[!ISOBMFF]] |
- Used to signal HDR light level information for an image |
+ Used to signal HDR content light level information for an image |
|
@@ -1205,7 +1205,7 @@ The "Version(s)" column in the following table lists the version(s) of the boxes
[=cclv=] |
- |
[[!ISOBMFF]] |
- Used to signal HDR color volume for an image |
+ Used to signal HDR content color volume for an image |
|
@@ -1214,7 +1214,7 @@ The "Version(s)" column in the following table lists the version(s) of the boxes
[=mdcv=] |
- |
[[!ISOBMFF]] |
- Used to signal HDR mastering information for an image |
+ Used to signal HDR mastering display color volume for an image |
|
From e352a2f964fda46fb5d5d57cee7808896f1a4876 Mon Sep 17 00:00:00 2001
From: Wan-Teh Chang
Date: Wed, 23 Oct 2024 09:23:18 -0700
Subject: [PATCH 60/65] Minor edits and punctuation fixes in sato examples
---
index.bs | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/index.bs b/index.bs
index 6bb2188..e8c203b 100755
--- a/index.bs
+++ b/index.bs
@@ -1359,13 +1359,13 @@ This is equivalent to the following infix notation:
sampleoutput=256×sample1+sample2
-Each output sample is equal to the sum of a sample of the first input image item shifted to the left by 8 bits and of a sample of the second input image item. This can be viewed as a bit depth extension of the first input image item by the second input image item. The first input image item contains the 8 most significant bits and the second input image item contains the 8 least significant bits of the output reconstructed image item which has a bit depth of 16, something that is impossible to achieve with a single [=AV1 image item=].
+Each output sample is equal to the sum of a sample of the first input image item shifted to the left by 8 bits and of a sample of the second input image item. This can be viewed as a bit depth extension of the first input image item by the second input image item. The first input image item contains the 8 most significant bits and the second input image item contains the 8 least significant bits of the 16-bit output reconstructed image item. It is impossible to achieve a bit depth of 16 with a single [=AV1 image item=].
NOTE: If the first input image item is the [=primary image item=] and is enclosed in an '[=altr=]'
group (see [[#altr-group]]) with the [=Sample Transform Derived Image Item=], the first input image item is also a backward-compatible 8-bit regular coded image item that can be used by readers that do not support [=Sample Transform Derived Image Items=] or do not need extra precision.
NOTE: The second input image item can be marked as [=hidden image item|hidden=] to prevent readers from surfacing it to users.
-NOTE: The second input image item loses its meaning of least significant part if any of the most significant bits changes, so the first input image item has to be losslessly encoded. The second input image item supports reasonable loss during encoding.
+NOTE: The second input image item loses its meaning of the least significant part if any of the most significant bits changes, so the first input image item has to be losslessly encoded. The second input image item supports reasonable loss during encoding.
NOTE: This pattern can be used for reconstructed bit depths beyond 16 by combining more than two input image items or with various input bit depth configurations and operations.
@@ -1403,7 +1403,7 @@ This is equivalent to the following infix notation:
sampleoutput=16×sample1+sample2-128
-Each output sample is equal to the sum of a sample of the first input image item shifted to the left by 4 bits and of a sample of the second input image item offset by -128. This can be viewed as a bit depth extension of the first input image item by the second input image item which contains the residuals to correct the precision loss of the first input image item.
+Each output sample is equal to the sum of a sample of the first input image item shifted to the left by 4 bits and of a sample of the second input image item offset by -128. This can be viewed as a bit depth extension of the first input image item by the second input image item, which contains the residuals to correct the precision loss of the first input image item.
NOTE: If the first input image item is the [=primary image item=] and is enclosed in an '[=altr=]'
group (see [[#altr-group]]) with the derived image item, the first input image item is also a backward-compatible 12-bit regular coded image item that can be used by decoding contexts that do not support [=Sample Transform Derived Image Items=] or do not need extra precision.
From 2a57acab417ba9fd3179e560c6b83b287c92d82f Mon Sep 17 00:00:00 2001
From: Yannis Guyon
Date: Thu, 24 Oct 2024 08:43:56 +0000
Subject: [PATCH 61/65] Remove mentions of ftyp compatible_brands (#289)
In prevision of the major_brand field of the FileTypeBox not needing
to be repeated in the compatible_brands field.
---
index.bs | 34 +++++++++++++++++-----------------
1 file changed, 17 insertions(+), 17 deletions(-)
diff --git a/index.bs b/index.bs
index e8c203b..fd975a9 100755
--- a/index.bs
+++ b/index.bs
@@ -120,7 +120,6 @@ url: https://www.iso.org/standard/68960.html; spec: ISOBMFF; type: dfn;
text: colour_type
text: ColourInformationBox
text: colr
- text: compatible_brands
text: ContentLightLevelBox
text: dinf
text: dref
@@ -705,7 +704,7 @@ The '[=ster=]'
entity group as defined in [[!HEIF]] may be used to
Brands overview
-As defined by [[!ISOBMFF]], the presence of a brand in the [=compatible_brands=]
list in the [=FileTypeBox=]
can be interpreted as the permission for those [=AV1 Image File Format=] readers/parsers and [=AV1 Image File Format=] renderers that only implement the features required by the brand, to process the corresponding file and only the parts (e.g. items or sequences) that comply with the brand.
+As defined by [[!ISOBMFF]], the presence of a brand in the [=FileTypeBox=]
can be interpreted as the permission for those [=AV1 Image File Format=] readers/parsers and [=AV1 Image File Format=] renderers that only implement the features required by the brand, to process the corresponding file and only the parts (e.g. items or sequences) that comply with the brand.
An [=AV1 Image File Format=] file may conform to multiple brands. Similarly, an [=AV1 Image File Format=] reader/parser or [=AV1 Image File Format=] renderer may be capable of processing the features associated with one or more brands.
@@ -714,32 +713,32 @@ The '[=ster=]'
entity group as defined in [[!HEIF]] may be used to
AVIF image and image collection brand
The brand to identify [=AV1 image items=] is avif.
-Files that indicate this brand in the [=compatible_brands=]
field of the [=FileTypeBox=]
shall comply with the following:
+Files that indicate this brand in the [=FileTypeBox=]
shall comply with the following:
- The [=primary image item=] shall be an [=AV1 Image Item=] or be a derived image that references directly or indirectly one or more items that all are [=AV1 Image Items=].
- [=AV1 auxiliary image items=] may be present in the file.
-Files that conform with these constraints should include the brand [=AVIF Image brand/avif=]
in the [=compatible_brands=]
field of the [=FileTypeBox=]
.
+Files that conform with these constraints should include the brand [=AVIF Image brand/avif=]
in the [=FileTypeBox=]
.
-Additionally, the brand avio is defined. If the file indicates the brand [=avio=]
in the [=compatible_brands=]
field of the [=FileTypeBox=]
, then the [=primary image item=] or all the items referenced by the [=primary image item=] shall be [=AV1 image items=] made only of [=Intra Frames=]. Conversely, if the previous constraint applies, the brand [=avio=]
should be used in the [=compatible_brands=]
field of the [=FileTypeBox=]
.
+Additionally, the brand avio is defined. If the file indicates the brand [=avio=]
in the [=FileTypeBox=]
, then the [=primary image item=] or all the items referenced by the [=primary image item=] shall be [=AV1 image items=] made only of [=Intra Frames=]. Conversely, if the previous constraint applies, the brand [=avio=]
should be used in the [=FileTypeBox=]
.
AVIF image sequence brands
The brand to identify [=AV1 image sequences=] is avis.
-Files that indicate this brand in the [=compatible_brands=]
field of the [=FileTypeBox=]
shall comply with the following:
+Files that indicate this brand in the [=FileTypeBox=]
shall comply with the following:
- they shall contain one or more [=AV1 image sequences=].
- they may contain [=AV1 auxiliary image sequences=].
-Files that conform with these constraints should include the brand [=avis=]
in the [=compatible_brands=]
field of the [=FileTypeBox=]
.
+Files that conform with these constraints should include the brand [=avis=]
in the [=FileTypeBox=]
.
-Additionally, if a file contains [=AV1 image sequences=] and the brand [=avio=]
is used in the [=compatible_brands=]
field of the [=FileTypeBox=]
, the item constraints for this brand shall be met and at least one of the [=AV1 image sequences=] shall be made only of [=AV1 Samples=] marked as '[=sync=]'
. Conversely, if such a track exists and the constraints of the brand [=avio=]
on [=AV1 image items=] are met, the brand should be used.
+Additionally, if a file contains [=AV1 image sequences=] and the brand [=avio=]
is used in the [=FileTypeBox=]
, the item constraints for this brand shall be met and at least one of the [=AV1 image sequences=] shall be made only of [=AV1 Samples=] marked as '[=sync=]'
. Conversely, if such a track exists and the constraints of the brand [=avio=]
on [=AV1 image items=] are met, the brand should be used.
NOTE: As defined in [[!MIAF]], a file that is primarily an image sequence still has at least an image item. Hence, it can also declare brands for signaling the image item.
General constraints
The following constraints are common to files compliant with this specification:
- - The file shall be compliant with the [[!MIAF]] specification and list '[=miaf=]'
in the [=compatible_brands=]
field of the [=FileTypeBox=]
.
- - The file shall list '[=AVIF Image brand/avif=]'
or '[=avis=]'
in the [=compatible_brands=]
field of the [=FileTypeBox=]
.
+ - The file shall be compliant with the [[!MIAF]] specification and list '[=miaf=]'
in the [=FileTypeBox=]
.
+ - The file shall list '[=AVIF Image brand/avif=]'
or '[=avis=]'
in the [=FileTypeBox=]
.
- Transformative properties shall not be associated with items in a derivation chain (as defined in [[!MIAF]]) that serves as an input to a [=grid derived image item=]. For example, if a file contains a grid item and its referenced coded image items, cropping, mirroring or rotation transformations are only permitted on the grid item itself.
NOTE: This constraint further restricts files compared to [[!MIAF]].
@@ -764,7 +763,7 @@ NOTE: [[!AV1]] supports 3 bit depths: 8, 10 and 12 bits, and the maximum dimensi
This section defines the MIAF AV1 Baseline profile of [[!HEIF]], specifically for [[!AV1]] bitstreams, based on the constraints specified in [[!MIAF]] and identified by the brand MA1B.
-If the brand '[=MA1B=]'
is in the list of [=compatible_brands=]
of the [=FileTypeBox=]
, the common constraints in the section [[#brands]] shall apply.
+If the brand '[=MA1B=]'
is in the [=FileTypeBox=]
, the common constraints in the section [[#brands]] shall apply.
The following shared conditions and requirements from [[!MIAF]] shall apply:
- [=self-containment=] (subclause 8.2)
@@ -783,15 +782,15 @@ The following additional constraints apply to all [=AV1 Image Items=] and all [=
NOTE: Level 5.1 is chosen for the Baseline profile to ensure that no single coded image exceeds 4k resolution, as some decoders may not be able to handle larger images. More precisely, following [[!AV1]] level definitions, coded image items compliant to the [=AVIF Baseline profile=] may not have a number of pixels greater than 8912896, a width greater than 8192 or a height greater than 4352. It is still possible to use the Baseline profile to create larger images using a [=grid derived image item=].
-A file containing items compliant with this profile is expected to list the following brands, in any order, in the [=compatible_brands=]
of the [=FileTypeBox=]
:
+A file containing items compliant with this profile is expected to list the following brands, in any order, in the [=FileTypeBox=]
:
avif, mif1, miaf, MA1B
-A file containing a '[=pict=]'
track compliant with this profile is expected to list the following brands, in any order, in the [=compatible_brands=]
of the [=FileTypeBox=]
:
+A file containing a '[=pict=]'
track compliant with this profile is expected to list the following brands, in any order, in the [=FileTypeBox=]
:
avis, msf1, miaf, MA1B
-A file containing a '[=pict=]'
track compliant with this profile and made only of [=AV1 Samples=] marked '[=sync=]'
is expected to list the following brands, in any order, in the [=compatible_brands=]
of the [=FileTypeBox=]
:
+A file containing a '[=pict=]'
track compliant with this profile and made only of [=AV1 Samples=] marked '[=sync=]'
is expected to list the following brands, in any order, in the [=FileTypeBox=]
:
avis, avio, msf1, miaf, MA1B
@@ -800,7 +799,7 @@ A file containing a '[=pict=]'
track compliant with this profile an
This section defines the MIAF AV1 Advanced profile of [[!HEIF]], specifically for [[!AV1]] bitstreams, based on the constraints specified in [[!MIAF]] and identified by the brand MA1A.
-If the brand '[=MA1A=]'
is in the list of [=compatible_brands=]
of the [=FileTypeBox=]
, the common constraints in the section [[#brands]] shall apply.
+If the brand '[=MA1A=]'
is in the [=FileTypeBox=]
, the common constraints in the section [[#brands]] shall apply.
The following shared conditions and requirements from [[!MIAF]] shall apply:
- [=self-containment=] (subclause 8.2)
@@ -822,11 +821,11 @@ The following additional constraints apply only to [=AV1 Image Sequences=]:
- The AV1 level for High Profile shall be 5.1 or lower.
-A file containing items compliant with this profile is expected to list the following brands, in any order, in the [=compatible_brands=]
of the [=FileTypeBox=]
:
+A file containing items compliant with this profile is expected to list the following brands, in any order, in the [=FileTypeBox=]
:
avif, mif1, miaf, MA1A
-A file containing a '[=pict=]'
track compliant with this profile is expected to list the following brands, in any order, in the [=compatible_brands=]
of the [=FileTypeBox=]
:
+A file containing a '[=pict=]'
track compliant with this profile is expected to list the following brands, in any order, in the [=FileTypeBox=]
:
avis, msf1, miaf, MA1A
@@ -1325,6 +1324,7 @@ The "Version(s)" column in the following table lists the version(s) of the boxes
- EDITORIAL: Remove inconsistent dots in 9.1.2
- Change structure of optional table of boxes
- Add hidden image item recommendation
+ - Remove mentions of ftyp compatible_brands
Appendix A: (informative) Sample Transform Derived Image Item Examples
From 9c389bbca308b4e3a46bf86d5b7a0bea2ab910e6 Mon Sep 17 00:00:00 2001
From: Yannis Guyon
Date: Thu, 24 Oct 2024 09:20:37 +0000
Subject: [PATCH 62/65] Remove avio brand recommendation (#265)
---
index.bs | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/index.bs b/index.bs
index fd975a9..39ab65e 100755
--- a/index.bs
+++ b/index.bs
@@ -719,7 +719,7 @@ Files that indicate this brand in the [=FileTypeBox=]
shall comply
Files that conform with these constraints should include the brand [=AVIF Image brand/avif=]
in the [=FileTypeBox=]
.
-Additionally, the brand avio is defined. If the file indicates the brand [=avio=]
in the [=FileTypeBox=]
, then the [=primary image item=] or all the items referenced by the [=primary image item=] shall be [=AV1 image items=] made only of [=Intra Frames=]. Conversely, if the previous constraint applies, the brand [=avio=]
should be used in the [=FileTypeBox=]
.
+Additionally, the brand avio is defined. If the file indicates the brand [=avio=]
in the [=FileTypeBox=]
, then the [=primary image item=] or all the items referenced by the [=primary image item=] shall be [=AV1 image items=] made only of [=Intra Frames=].
AVIF image sequence brands
The brand to identify [=AV1 image sequences=] is avis.
@@ -1325,6 +1325,7 @@ The "Version(s)" column in the following table lists the version(s) of the boxes
- Change structure of optional table of boxes
- Add hidden image item recommendation
- Remove mentions of ftyp compatible_brands
+ - Remove avio brand recommendation
Appendix A: (informative) Sample Transform Derived Image Item Examples
From 48dc1c6f13e9a496fa7bc71f0a0a48a68a273be8 Mon Sep 17 00:00:00 2001
From: leo-barnes
Date: Fri, 25 Oct 2024 14:35:34 +0200
Subject: [PATCH 63/65] Fix use of br tags in SATO examples (#292)
Fix use of br tags in SATO examples
---
index.bs | 35 +++++++++++++++++++++++++++--------
1 file changed, 27 insertions(+), 8 deletions(-)
diff --git a/index.bs b/index.bs
index 39ab65e..307bf29 100755
--- a/index.bs
+++ b/index.bs
@@ -1326,6 +1326,7 @@ The "Version(s)" column in the following table lists the version(s) of the boxes
- Add hidden image item recommendation
- Remove mentions of ftyp compatible_brands
- Remove avio brand recommendation
+ - EDITORIAL: Fix broken lines in Sample Transform examples
Appendix A: (informative) Sample Transform Derived Image Item Examples
@@ -1340,9 +1341,13 @@ This informative appendix contains example recipes for extending base [=/AVIF=]
The following example describes how to leverage a [=Sample Transform Derived Image Item=] on top of a regular 8-bit [=MIAF image item=] to extend the decoded bit depth to 16 bits.
Consider the following:
- - A [=MIAF image item=] being a losslessly coded image item,
and its [=PixelInformationProperty=]
with [=bits_per_channel=]
=8,
- - Another [=MIAF image item=] being a lossily or losslessly coded image item with the same spatial dimensions, the same number of channels, and the same chroma subsampling (or lack thereof) as the first input image item,
and its [=PixelInformationProperty=]
with [=bits_per_channel=]
=8,
- - A [=Sample Transform Derived Image Item=] with the two items above as input in this order,
and its [=PixelInformationProperty=]
with [=bits_per_channel=]
=16,
and the following [=SampleTransform=]
fields:
+ - A [=MIAF image item=] being a losslessly coded image item,
+ and its [=PixelInformationProperty=]
with [=bits_per_channel=]
=8,
+ - Another image item being a lossily or losslessly coded image item with the same spatial dimensions, the same number of channels, and the same chroma subsampling (or lack thereof) as the first input image item,
+ and its [=PixelInformationProperty=]
with [=bits_per_channel=]
=8,
+ - A [=Sample Transform Derived Image Item=] with the two items above as input in this order,
+ and its [=PixelInformationProperty=]
with [=bits_per_channel=]
=16,
+ and the following [=SampleTransform=]
fields:
- [=sato/version=]
=0
- [=sato/bit_depth=]
=2 (signed 32-bit [=sato/constant=]
s, stack values and intermediate results)
- [=sato/token_count=]
=5
@@ -1376,15 +1381,29 @@ The following example describes how to leverage a [=Sample Transform Derived Ima
It differs from the [[#sato-example-suffix-bit-depth-extension]] by its slightly longer series of operations allowing its first input image item to be lossily encoded.
Consider the following:
- - A [=MIAF image item=] being a lossily coded image item,
and its [=PixelInformationProperty=]
with [=bits_per_channel=]
=12,
- - Another [=MIAF image item=] being a lossily or losslessly coded image item with the same spatial dimensions, the same number of channels, and the same chroma subsampling (or lack thereof) as the first input image item,
and its [=PixelInformationProperty=]
with [=bits_per_channel=]
=8,
with the following contraints:
- - For each sample position in each plane,
sampleoriginal being the value of the 16-bit original sample at that position in that plane,
sample1 being the value of the 12-bit sample of the first input image at that position in that plane,
sample2 being the value of the sample of the second input image at that position in that plane,
≈ representing similarity within compression loss range,
+ - A [=MIAF image item=] being a lossily coded image item,
+ and its [=PixelInformationProperty=]
with [=bits_per_channel=]
=12,
+ - Another image item being a lossily or losslessly coded image item with the same spatial dimensions, the same number of channels, and the same chroma subsampling (or lack thereof) as the first input image item,
+ and its [=PixelInformationProperty=]
with [=bits_per_channel=]
=8,
+ with the following contraints:
+
+ For each sample position in each plane,
+ sampleoriginal being the value of the 16-bit original sample at that position in that plane,
+ sample1 being the value of the 12-bit sample of the first input image at that position in that plane,
+ sample2 being the value of the sample of the second input image at that position in that plane,
+ ≈ representing similarity within compression loss range,
+
- sample1≈sampleoriginal24
- sample2≈sampleoriginal-24×sample1+27
- 0≤sample1<212
- 0≤sample2<28
- - 0≤24×sample1+sample2-27<216
NOTE: Files that do not respect this constraint will still decode successfully because Clause [[#sample-transform-definition]] mandates the resulting values to be each clamped to fit in the number of bits per sample as defined by the [=PixelInformationProperty=]
of the reconstructed image item.
- - A [=Sample Transform Derived Image Item=] with the two items above as input in this order,
and its [=PixelInformationProperty=]
with [=bits_per_channel=]
=16,
and the following [=SampleTransform=]
fields:
+ - 0≤24×sample1+sample2-27<216
+
+ NOTE: Files that do not respect this constraint will still decode successfully because Clause [[#sample-transform-definition]] mandates the resulting values to be each clamped to fit in the number of bits per sample as defined by the [=PixelInformationProperty=]
of the reconstructed image item.
+
+ - A [=Sample Transform Derived Image Item=] with the two items above as input in this order,
+ and its [=PixelInformationProperty=]
with [=bits_per_channel=]
=16,
+ and the following [=SampleTransform=]
fields:
- [=sato/version=]
=0
- [=sato/bit_depth=]
=2 (signed 32-bit [=sato/constant=]
s, stack values and intermediate results)
- [=sato/token_count=]
=7
From 6820e20cfbe11f42582226bee1488256de9a4f7f Mon Sep 17 00:00:00 2001
From: Leo Barnes
Date: Fri, 25 Oct 2024 14:42:18 +0200
Subject: [PATCH 64/65] Update date
---
index.bs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/index.bs b/index.bs
index 307bf29..479c8ee 100755
--- a/index.bs
+++ b/index.bs
@@ -12,7 +12,7 @@ Former Editor: Cyril Concolato, Netflix, cconcolato@netflix.com
Former Editor: Paul Kerr, Netflix, pkerr@netflix.com
Former Editor: Anders Klemets, Microsoft, Anders.Klemets@microsoft.com
Abstract: This document specifies syntax and semantics for the storage of [[!AV1]] images in the generic image file format [[!HEIF]], which is based on [[!ISOBMFF]]. While [[!HEIF]] defines general requirements, this document also specifies additional constraints to ensure higher interoperability between writers and readers when [[!HEIF]] is used with [[!AV1]] images. These constraints are based on constraints defined in the Multi-Image Application Format [[!MIAF]] and are grouped into profiles inspired by the profiles defined in [[!MIAF]].
-Date: 2024-06-25
+Date: 2024-10-25
Repository: AOMediaCodec/av1-avif
Text Macro: ADDITIONALLOGO https://aomedia.org/assets/images/avif-logo-rgb.svg
!Latest approved version: https://aomediacodec.github.io/av1-avif/latest-approved.html
From 0c0466b9b23e3f44ceb6e7893b23bfe6badb9820 Mon Sep 17 00:00:00 2001
From: Leo Barnes
Date: Fri, 25 Oct 2024 20:15:20 +0200
Subject: [PATCH 65/65] "Empty" commit to trigger a bikeshed diff to get
generated
---
index.bs | 1 +
1 file changed, 1 insertion(+)
diff --git a/index.bs b/index.bs
index 479c8ee..4f46e5a 100755
--- a/index.bs
+++ b/index.bs
@@ -21,6 +21,7 @@ Text Macro: ADDITIONALLOGO https://aomedia.org/assets/images/avif-logo-rgb.svg
Metadata Order: This version, !*, *
+
{
"AV1": {