Skip to content

Commit

Permalink
Fix level3/4 metadata blocks
Browse files Browse the repository at this point in the history
  • Loading branch information
quietvoid committed Dec 9, 2021
1 parent 57d2cfd commit 8f5bf22
Show file tree
Hide file tree
Showing 17 changed files with 241 additions and 76 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file added assets/tests/st2094_10_level3.bin
Binary file not shown.
8 changes: 8 additions & 0 deletions dolby_vision/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## 1.4.0

Fixed L3/L4 metadata block sizes.

Renamed `ExtMetadataBlock` functions:
- `length` -> `length_bytes`
- `bits` -> `length_bits`

## 1.3.1

Conditional initializations of `Vec`s in `RpuDataMapping` and `RpuDataNlq` structs.
Expand Down
2 changes: 1 addition & 1 deletion dolby_vision/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "dolby_vision"
version = "1.3.2"
version = "1.4.0"
authors = ["quietvoid"]
edition = "2018"
rust-version = "1.55.0"
Expand Down
7 changes: 7 additions & 0 deletions dolby_vision/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
/// Dolby Vision RPU (as found in HEVC type 62 NALUs) module
pub mod rpu;

/// SMPTE ST2094-10 metadata module
pub mod st2094_10;

/// Various utils
/// cbindgen:ignore
pub mod utils;

/// Dolby Vision XML metadata module
#[cfg(feature = "xml")]
pub mod xml;

/// C API module
#[cfg(any(cargo_c, feature = "capi"))]
pub mod capi;

/// Structs used and exposed in the C API
#[cfg(any(cargo_c, feature = "capi"))]
pub mod c_structs;
16 changes: 15 additions & 1 deletion dolby_vision/src/st2094_10/metadata_blocks/level1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use bitvec_helpers::{bitvec_reader::BitVecReader, bitvec_writer::BitVecWriter};
#[cfg(feature = "serde_feature")]
use serde::Serialize;

use super::ExtMetadataBlock;
use super::{ExtMetadataBlock, ExtMetadataBlockInfo};

/// Statistical analysis of the frame: min, max, avg brightness.
#[repr(C)]
Expand All @@ -30,3 +30,17 @@ impl ExtMetadataBlockLevel1 {
writer.write_n(&self.avg_pq.to_be_bytes(), 12);
}
}

impl ExtMetadataBlockInfo for ExtMetadataBlockLevel1 {
fn level(&self) -> u8 {
1
}

fn bytes_size(&self) -> u64 {
5
}

fn required_bits(&self) -> u64 {
36
}
}
20 changes: 19 additions & 1 deletion dolby_vision/src/st2094_10/metadata_blocks/level2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use bitvec_helpers::{bitvec_reader::BitVecReader, bitvec_writer::BitVecWriter};
#[cfg(feature = "serde_feature")]
use serde::Serialize;

use super::ExtMetadataBlock;
use super::{ExtMetadataBlock, ExtMetadataBlockInfo};

/// Creative intent trim passes per target display peak brightness
#[repr(C)]
Expand Down Expand Up @@ -42,3 +42,21 @@ impl ExtMetadataBlockLevel2 {
writer.write_n(&self.ms_weight.to_be_bytes(), 13);
}
}

impl ExtMetadataBlockInfo for ExtMetadataBlockLevel2 {
fn level(&self) -> u8 {
2
}

fn bytes_size(&self) -> u64 {
11
}

fn required_bits(&self) -> u64 {
85
}

fn sort_key(&self) -> (u8, u16) {
(self.level(), self.target_max_pq)
}
}
16 changes: 15 additions & 1 deletion dolby_vision/src/st2094_10/metadata_blocks/level3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use bitvec_helpers::{bitvec_reader::BitVecReader, bitvec_writer::BitVecWriter};
#[cfg(feature = "serde_feature")]
use serde::Serialize;

use super::ExtMetadataBlock;
use super::{ExtMetadataBlock, ExtMetadataBlockInfo};

/// Level 1 offsets.
#[repr(C)]
Expand All @@ -30,3 +30,17 @@ impl ExtMetadataBlockLevel3 {
writer.write_n(&self.avg_pq_offset.to_be_bytes(), 12);
}
}

impl ExtMetadataBlockInfo for ExtMetadataBlockLevel3 {
fn level(&self) -> u8 {
3
}

fn bytes_size(&self) -> u64 {
5
}

fn required_bits(&self) -> u64 {
36
}
}
17 changes: 16 additions & 1 deletion dolby_vision/src/st2094_10/metadata_blocks/level4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ use bitvec_helpers::{bitvec_reader::BitVecReader, bitvec_writer::BitVecWriter};
#[cfg(feature = "serde_feature")]
use serde::Serialize;

use super::ExtMetadataBlock;
use super::{ExtMetadataBlock, ExtMetadataBlockInfo};

/// Something about temporal stability
#[repr(C)]
#[derive(Debug, Default, Clone)]
#[cfg_attr(feature = "serde_feature", derive(Serialize))]
Expand All @@ -26,3 +27,17 @@ impl ExtMetadataBlockLevel4 {
writer.write_n(&self.anchor_power.to_be_bytes(), 12);
}
}

impl ExtMetadataBlockInfo for ExtMetadataBlockLevel4 {
fn level(&self) -> u8 {
4
}

fn bytes_size(&self) -> u64 {
3
}

fn required_bits(&self) -> u64 {
24
}
}
16 changes: 15 additions & 1 deletion dolby_vision/src/st2094_10/metadata_blocks/level5.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use bitvec_helpers::{bitvec_reader::BitVecReader, bitvec_writer::BitVecWriter};
#[cfg(feature = "serde_feature")]
use serde::Serialize;

use super::ExtMetadataBlock;
use super::{ExtMetadataBlock, ExtMetadataBlockInfo};

/// Active area of the picture (letterbox, aspect ratio)
#[repr(C)]
Expand Down Expand Up @@ -65,3 +65,17 @@ impl ExtMetadataBlockLevel5 {
self.active_area_bottom_offset = 0;
}
}

impl ExtMetadataBlockInfo for ExtMetadataBlockLevel5 {
fn level(&self) -> u8 {
5
}

fn bytes_size(&self) -> u64 {
7
}

fn required_bits(&self) -> u64 {
52
}
}
16 changes: 15 additions & 1 deletion dolby_vision/src/st2094_10/metadata_blocks/level6.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use serde::Serialize;

use crate::st2094_10::generate::Level6Metadata;

use super::ExtMetadataBlock;
use super::{ExtMetadataBlock, ExtMetadataBlockInfo};

/// ST2086 metadata fallback
#[repr(C)]
Expand Down Expand Up @@ -42,3 +42,17 @@ impl ExtMetadataBlockLevel6 {
self.max_frame_average_light_level = meta.max_frame_average_light_level;
}
}

impl ExtMetadataBlockInfo for ExtMetadataBlockLevel6 {
fn level(&self) -> u8 {
6
}

fn bytes_size(&self) -> u64 {
8
}

fn required_bits(&self) -> u64 {
64
}
}
136 changes: 72 additions & 64 deletions dolby_vision/src/st2094_10/metadata_blocks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,44 +24,31 @@ pub enum ExtMetadataBlock {
Reserved(reserved::ReservedExtMetadataBlock),
}

pub trait ExtMetadataBlockInfo {
fn level(&self) -> u8;
fn bytes_size(&self) -> u64;
fn required_bits(&self) -> u64;

fn bits_size(&self) -> u64 {
self.bytes_size() * 8
}

fn sort_key(&self) -> (u8, u16) {
(self.level(), 0)
}
}

pub fn ext_metadata_block(reader: &mut BitVecReader) -> Result<ExtMetadataBlock> {
let ext_block_length = reader.get_ue()?;
let ext_block_level = reader.get_n(8);

let ext_metadata_block = match ext_block_level {
1 => {
ensure!(ext_block_length == 5, "level 1 block should have length 5");

level1::ExtMetadataBlockLevel1::parse(reader)
}
2 => {
ensure!(
ext_block_length == 11,
"level 2 block should have length 11"
);

level2::ExtMetadataBlockLevel2::parse(reader)
}
3 => {
ensure!(ext_block_length == 2, "level 3 block should have length 2");

level3::ExtMetadataBlockLevel3::parse(reader)
}
4 => {
ensure!(ext_block_length == 3, "level 4 block should have length 4");

level4::ExtMetadataBlockLevel4::parse(reader)
}
5 => {
ensure!(ext_block_length == 7, "level 5 block should have length 7");

level5::ExtMetadataBlockLevel5::parse(reader)
}
6 => {
ensure!(ext_block_length == 8, "level 6 block should have length 8");

level6::ExtMetadataBlockLevel6::parse(reader)
}
1 => level1::ExtMetadataBlockLevel1::parse(reader),
2 => level2::ExtMetadataBlockLevel2::parse(reader),
3 => level3::ExtMetadataBlockLevel3::parse(reader),
4 => level4::ExtMetadataBlockLevel4::parse(reader),
5 => level5::ExtMetadataBlockLevel5::parse(reader),
6 => level6::ExtMetadataBlockLevel6::parse(reader),
_ => {
ensure!(
false,
Expand All @@ -72,7 +59,16 @@ pub fn ext_metadata_block(reader: &mut BitVecReader) -> Result<ExtMetadataBlock>
}
};

let ext_block_use_bits = (8 * ext_block_length) - ext_metadata_block.bits();
ensure!(
ext_block_length == ext_metadata_block.length_bytes(),
format!(
"level {} block should have length {}",
ext_block_level,
ext_metadata_block.length_bytes()
)
);

let ext_block_use_bits = ext_metadata_block.length_bits() - ext_metadata_block.required_bits();

for _ in 0..ext_block_use_bits {
ensure!(!reader.get()?, "ext_dm_alignment_zero_bit != 0");
Expand All @@ -82,51 +78,63 @@ pub fn ext_metadata_block(reader: &mut BitVecReader) -> Result<ExtMetadataBlock>
}

impl ExtMetadataBlock {
pub fn length(&self) -> u64 {
pub fn length_bytes(&self) -> u64 {
match self {
ExtMetadataBlock::Level1(b) => b.bytes_size(),
ExtMetadataBlock::Level2(b) => b.bytes_size(),
ExtMetadataBlock::Level3(b) => b.bytes_size(),
ExtMetadataBlock::Level4(b) => b.bytes_size(),
ExtMetadataBlock::Level5(b) => b.bytes_size(),
ExtMetadataBlock::Level6(b) => b.bytes_size(),
ExtMetadataBlock::Reserved(b) => b.bytes_size(),
}
}

pub fn length_bits(&self) -> u64 {
match self {
ExtMetadataBlock::Level1(_) => 5,
ExtMetadataBlock::Level2(_) => 11,
ExtMetadataBlock::Level3(_) => 2,
ExtMetadataBlock::Level4(_) => 3,
ExtMetadataBlock::Level5(_) => 7,
ExtMetadataBlock::Level6(_) => 8,
ExtMetadataBlock::Reserved(b) => b.ext_block_length,
ExtMetadataBlock::Level1(b) => b.bits_size(),
ExtMetadataBlock::Level2(b) => b.bits_size(),
ExtMetadataBlock::Level3(b) => b.bits_size(),
ExtMetadataBlock::Level4(b) => b.bits_size(),
ExtMetadataBlock::Level5(b) => b.bits_size(),
ExtMetadataBlock::Level6(b) => b.bits_size(),
ExtMetadataBlock::Reserved(b) => b.bits_size(),
}
}

pub fn bits(&self) -> u64 {
pub fn required_bits(&self) -> u64 {
match self {
ExtMetadataBlock::Level1(_) => 36,
ExtMetadataBlock::Level2(_) => 85,
ExtMetadataBlock::Level3(_) => 36,
ExtMetadataBlock::Level4(_) => 24,
ExtMetadataBlock::Level5(_) => 52,
ExtMetadataBlock::Level6(_) => 64,
ExtMetadataBlock::Reserved(b) => b.data.len() as u64,
ExtMetadataBlock::Level1(b) => b.required_bits(),
ExtMetadataBlock::Level2(b) => b.required_bits(),
ExtMetadataBlock::Level3(b) => b.required_bits(),
ExtMetadataBlock::Level4(b) => b.required_bits(),
ExtMetadataBlock::Level5(b) => b.required_bits(),
ExtMetadataBlock::Level6(b) => b.required_bits(),
ExtMetadataBlock::Reserved(b) => b.required_bits(),
}
}

pub fn level(&self) -> u8 {
match self {
ExtMetadataBlock::Level1(_) => 1,
ExtMetadataBlock::Level2(_) => 2,
ExtMetadataBlock::Level3(_) => 3,
ExtMetadataBlock::Level4(_) => 4,
ExtMetadataBlock::Level5(_) => 5,
ExtMetadataBlock::Level6(_) => 6,
ExtMetadataBlock::Reserved(_) => 255,
ExtMetadataBlock::Level1(b) => b.level(),
ExtMetadataBlock::Level2(b) => b.level(),
ExtMetadataBlock::Level3(b) => b.level(),
ExtMetadataBlock::Level4(b) => b.level(),
ExtMetadataBlock::Level5(b) => b.level(),
ExtMetadataBlock::Level6(b) => b.level(),
ExtMetadataBlock::Reserved(b) => b.level(),
}
}

pub fn sort_key(&self) -> (u8, u16) {
match self {
ExtMetadataBlock::Level1(_) => (1, 0),
ExtMetadataBlock::Level2(b) => (2, b.target_max_pq),
ExtMetadataBlock::Level3(_) => (3, 0),
ExtMetadataBlock::Level4(_) => (4, 0),
ExtMetadataBlock::Level5(_) => (5, 0),
ExtMetadataBlock::Level6(_) => (6, 0),
ExtMetadataBlock::Reserved(_) => (255, 0),
ExtMetadataBlock::Level1(b) => b.sort_key(),
ExtMetadataBlock::Level2(b) => b.sort_key(),
ExtMetadataBlock::Level3(b) => b.sort_key(),
ExtMetadataBlock::Level4(b) => b.sort_key(),
ExtMetadataBlock::Level5(b) => b.sort_key(),
ExtMetadataBlock::Level6(b) => b.sort_key(),
ExtMetadataBlock::Reserved(b) => b.sort_key(),
}
}

Expand Down
Loading

0 comments on commit 8f5bf22

Please sign in to comment.