Skip to content

Commit

Permalink
Fix CM v2.9 Level 2 parsing & support more custom display cases
Browse files Browse the repository at this point in the history
  • Loading branch information
saindriches committed Nov 2, 2022
1 parent 65a9c74 commit 49a06c1
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 21 deletions.
4 changes: 2 additions & 2 deletions README.md
Expand Up @@ -62,9 +62,9 @@ Currently, the only available subcommand is **`convert`**
```console
dovi_meta convert RPU.bin metadata.xml --skip 24 --rate 30000/1001 --size 1920x1080
```
The default color space of mastering display is **BT.2020**, the default EOTF is **PQ**.
The default color encoding is **BT.2020 PQ 16-bit RGB Full Range**.

The default color space of target display (except the anchor target) is **P3 D65** for CM v2.9 XML, also for CM v4.0 XML when it can't be determined by input.
The default color space of mastering display and target displays (except the anchor target) is **P3 D65** for CM v2.9 XML, also for CM v4.0 XML when it can't be determined by input.


## **Notes**
Expand Down
64 changes: 55 additions & 9 deletions src/metadata/display/characteristics.rs
Expand Up @@ -109,10 +109,10 @@ impl Characteristics {
}
}

fn get_primary_target(block: &ExtMetadataBlockLevel2, primary: Primaries) -> Option<Self> {
fn get_primary_target(block: &ExtMetadataBlockLevel2, primary: Primaries) -> Self {
let max_luminance = Self::max_u16_from_rpu_pq_u12(block.target_max_pq);

let primary = if let Some(primary) = primary.get_index() {
let primary_index = if let Some(primary) = primary.get_index() {
if max_luminance == 100 {
1
} else {
Expand All @@ -122,7 +122,24 @@ impl Characteristics {
0
};

Self::get_display(PREDEFINED_TARGET_DISPLAYS, max_luminance, primary)
if let Some(target) =
Self::get_display(PREDEFINED_TARGET_DISPLAYS, max_luminance, primary_index)
{
target
} else {
let mut target = Self {
id: block.target_max_pq as usize,
primary_index,
primaries: primary,
peak_brightness: max_luminance,
minimum_brightness: 0.0,
eotf: Eotf::Pq,
..Default::default()
};

target.update_name();
target
}
}

fn get_target(block: &ExtMetadataBlockLevel8) -> Option<Self> {
Expand Down Expand Up @@ -156,9 +173,7 @@ impl Characteristics {

vdr.level_blocks_iter(2).for_each(|b| {
if let ExtMetadataBlock::Level2(b) = b {
if let Some(d) = Self::get_primary_target(b, primary) {
targets.push(d)
}
targets.push(Self::get_primary_target(b, primary))
}
});

Expand All @@ -181,16 +196,47 @@ impl Characteristics {
}

pub fn get_source_or_default(vdr: &VdrDmData) -> Self {
let primary = Primaries::from(vdr).get_index().unwrap_or(0);
let primary = Primaries::from(vdr);
let primary_index = primary.get_index().unwrap_or(0);

// Prefer level 6 metadata
let max_luminance = match vdr.get_block(6) {
Some(ExtMetadataBlock::Level6(b)) => b.max_display_mastering_luminance as usize,
_ => Characteristics::max_u16_from_rpu_pq_u12(vdr.source_max_pq),
};

Self::get_display(PREDEFINED_MASTERING_DISPLAYS, max_luminance, primary)
.unwrap_or_else(Self::default_source)
if let Some(source) =
Self::get_display(PREDEFINED_MASTERING_DISPLAYS, max_luminance, primary_index)
{
source
} else {
let mut source = Self::default_source();

if vdr.get_block(254).is_some() {
// Custom mastering display for CM v4.0
// For convenience, use source_max_pq as custom mastering display id
source.id = vdr.source_max_pq as usize;
source.primaries = primary;

source.primary_index = if primary.get_index().is_none() {
// Random invalid value
255
} else {
primary_index
};

// BT.709 BT.1886
if primary_index == 1 {
source.eotf = Eotf::GammaBT1886;
source.peak_brightness = 100;
// Default source (4000-nit) min_brightness is 0.005-nit
}

source.update_name();
}

source
}
}

/*pub fn update_luminance_range_with_l6_block(&mut self, block: &ExtMetadataBlockLevel6) {
Expand Down
6 changes: 3 additions & 3 deletions src/metadata/display/mod.rs
Expand Up @@ -58,7 +58,7 @@ pub const PREDEFINED_TARGET_DISPLAYS: &[[usize; 6]] = &[
[ 38, 2, 2000, 0, 0, 0],
[ 48, 0, 1000, 0, 0, 0],
[ 49, 2, 1000, 0, 0, 0],
[9003, 1, 600, 7, 2, 0], // BETA
// [9003, 1, 600, 7, 2, 0], // BETA
];

// pub const CMV29_TARGET_DISPLAYS_LIST: &[u8] = &[1, 27, 28, 37, 38, 48, 49];
Expand All @@ -78,8 +78,8 @@ pub fn pq2l(pq: f32) -> f32 {
y * ST2084_Y_MAX
}

pub fn find_target_id(max: usize, primary: usize) -> usize {
get_display_id(PREDEFINED_TARGET_DISPLAYS, max, primary).unwrap_or(0)
pub fn find_target_id(max: usize, primary: usize) -> Option<usize> {
get_display_id(PREDEFINED_TARGET_DISPLAYS, max, primary)
}

fn get_display_id(list: &[[usize; 6]], max_luminance: usize, primary: usize) -> Option<usize> {
Expand Down
16 changes: 9 additions & 7 deletions src/metadata/levels/level2.rs
Expand Up @@ -13,10 +13,8 @@ use super::TrimSixField;
#[derive(Debug, Clone, PartialEq, Default)]
pub struct Level2 {
pub level: u8,
// #[serde(rename = "$unflatten=TID")]
pub tid: u8,
pub tid: usize,
// Format: 0 0 0 f32 f32 f32 f32 f32 f32
// #[serde(rename = "$unflatten=Trim")]
pub trim: MDFType<TrimSixField>,
}

Expand Down Expand Up @@ -55,7 +53,7 @@ impl IntoCMV29<Self> for Level2 {

impl Level2 {
pub fn with_primary_index(block: &ExtMetadataBlockLevel2, primary: Option<usize>) -> Self {
// Actually the only possible value is -1
// identical definition for all negative values, use -1 for v2.0.5+
let ms_weight = if block.ms_weight < 0 {
-1.0
} else {
Expand All @@ -66,9 +64,13 @@ impl Level2 {
let primary = if luminance == 100 {
1
} else {
primary.unwrap_or(2)
// P3 D65
primary.unwrap_or(0)
};

// For convenience, use target_max_pq as Level2 custom target display id
let tid = find_target_id(luminance, primary).unwrap_or(block.target_max_pq as usize);

let mut trim = TrimSixField([
f32_from_rpu_u12_with_bias(block.trim_slope),
f32_from_rpu_u12_with_bias(block.trim_offset),
Expand All @@ -82,15 +84,15 @@ impl Level2 {

Self {
level: 2,
tid: find_target_id(luminance, primary) as u8,
tid,
trim: CMV40(trim),
}
}
}

impl From<&ExtMetadataBlockLevel2> for Level2 {
fn from(block: &ExtMetadataBlockLevel2) -> Self {
// BT.2020
// P3 D65
Self::with_primary_index(block, None)
}
}

0 comments on commit 49a06c1

Please sign in to comment.