Skip to content

Commit

Permalink
Add ColorPrimaries struct
Browse files Browse the repository at this point in the history
  • Loading branch information
quietvoid committed Jan 6, 2022
1 parent 73a6f45 commit 48ea4b1
Show file tree
Hide file tree
Showing 7 changed files with 147 additions and 132 deletions.
1 change: 1 addition & 0 deletions assets/generator_examples/full_example.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
},
{
"Level9": {
"length": 1,
"source_primary_index": 0
}
},
Expand Down
1 change: 1 addition & 0 deletions assets/generator_examples/no_duration.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
},
{
"Level9": {
"length": 1,
"source_primary_index": 0
}
}
Expand Down
69 changes: 28 additions & 41 deletions dolby_vision/src/rpu/extension_metadata/blocks/level10.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use bitvec_helpers::{bitvec_reader::BitVecReader, bitvec_writer::BitVecWriter};
#[cfg(feature = "serde_feature")]
use serde::{ser::SerializeStruct, Deserialize, Serialize, Serializer};

use super::{level6::MAX_PQ_LUMINANCE, ExtMetadataBlock, ExtMetadataBlockInfo};
use super::{level6::MAX_PQ_LUMINANCE, ColorPrimaries, ExtMetadataBlock, ExtMetadataBlockInfo};

pub const PRESET_TARGET_DISPLAYS: &[u8] = &[1, 16, 18, 21, 27, 28, 37, 38, 42, 48, 49];

Expand Down Expand Up @@ -40,14 +40,7 @@ pub struct ExtMetadataBlockLevel10 {
pub target_min_pq: u16,
pub target_primary_index: u8,

pub target_primary_red_x: u16,
pub target_primary_red_y: u16,
pub target_primary_green_x: u16,
pub target_primary_green_y: u16,
pub target_primary_blue_x: u16,
pub target_primary_blue_y: u16,
pub target_primary_white_x: u16,
pub target_primary_white_y: u16,
pub target_primaries: Option<ColorPrimaries>,
}

impl ExtMetadataBlockLevel10 {
Expand All @@ -62,14 +55,7 @@ impl ExtMetadataBlockLevel10 {
};

if length > 5 {
block.target_primary_red_x = reader.get_n(16);
block.target_primary_red_y = reader.get_n(16);
block.target_primary_green_x = reader.get_n(16);
block.target_primary_green_y = reader.get_n(16);
block.target_primary_blue_x = reader.get_n(16);
block.target_primary_blue_y = reader.get_n(16);
block.target_primary_white_x = reader.get_n(16);
block.target_primary_white_y = reader.get_n(16);
block.target_primaries = Some(ColorPrimaries::parse(reader));
}

ExtMetadataBlock::Level10(block)
Expand All @@ -84,14 +70,9 @@ impl ExtMetadataBlockLevel10 {
writer.write_n(&self.target_primary_index.to_be_bytes(), 8);

if self.length > 5 {
writer.write_n(&self.target_primary_red_x.to_be_bytes(), 16);
writer.write_n(&self.target_primary_red_y.to_be_bytes(), 16);
writer.write_n(&self.target_primary_green_x.to_be_bytes(), 16);
writer.write_n(&self.target_primary_green_y.to_be_bytes(), 16);
writer.write_n(&self.target_primary_blue_x.to_be_bytes(), 16);
writer.write_n(&self.target_primary_blue_y.to_be_bytes(), 16);
writer.write_n(&self.target_primary_white_x.to_be_bytes(), 16);
writer.write_n(&self.target_primary_white_y.to_be_bytes(), 16);
if let Some(primaries) = &self.target_primaries {
primaries.write(writer);
}
}

Ok(())
Expand All @@ -102,6 +83,17 @@ impl ExtMetadataBlockLevel10 {
ensure!(self.target_max_pq <= MAX_PQ_LUMINANCE);
ensure!(self.target_min_pq <= MAX_PQ_LUMINANCE);

if self.length > 5 {
ensure!(self.target_primary_index == 255);
ensure!(self.target_primaries.is_some());

if let Some(primaries) = &self.target_primaries {
primaries.validate()?;
}
} else {
ensure!(self.target_primary_index != 255);
}

Ok(())
}
}
Expand Down Expand Up @@ -136,14 +128,7 @@ impl Default for ExtMetadataBlockLevel10 {
target_max_pq: 2081,
target_min_pq: 0,
target_primary_index: 2,
target_primary_red_x: 0,
target_primary_red_y: 0,
target_primary_green_x: 0,
target_primary_green_y: 0,
target_primary_blue_x: 0,
target_primary_blue_y: 0,
target_primary_white_x: 0,
target_primary_white_y: 0,
target_primaries: None,
}
}
}
Expand All @@ -169,14 +154,16 @@ impl Serialize for ExtMetadataBlockLevel10 {
state.serialize_field("target_primary_index", &self.target_primary_index)?;

if self.length > 5 {
state.serialize_field("target_primary_red_x", &self.target_primary_red_x)?;
state.serialize_field("target_primary_red_y", &self.target_primary_white_y)?;
state.serialize_field("target_primary_green_x", &self.target_primary_green_x)?;
state.serialize_field("target_primary_green_y", &self.target_primary_green_y)?;
state.serialize_field("target_primary_blue_x", &self.target_primary_blue_x)?;
state.serialize_field("target_primary_blue_y", &self.target_primary_blue_y)?;
state.serialize_field("target_primary_white_x", &self.target_primary_white_x)?;
state.serialize_field("target_primary_white_y", &self.target_primary_white_y)?;
if let Some(primaries) = &self.target_primaries {
state.serialize_field("target_primary_red_x", &primaries.red_x)?;
state.serialize_field("target_primary_red_y", &primaries.white_y)?;
state.serialize_field("target_primary_green_x", &primaries.green_x)?;
state.serialize_field("target_primary_green_y", &primaries.green_y)?;
state.serialize_field("target_primary_blue_x", &primaries.blue_x)?;
state.serialize_field("target_primary_blue_y", &primaries.blue_y)?;
state.serialize_field("target_primary_white_x", &primaries.white_x)?;
state.serialize_field("target_primary_white_y", &primaries.white_y)?;
}
}

state.end()
Expand Down
73 changes: 23 additions & 50 deletions dolby_vision/src/rpu/extension_metadata/blocks/level9.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use bitvec_helpers::{bitvec_reader::BitVecReader, bitvec_writer::BitVecWriter};
#[cfg(feature = "serde_feature")]
use serde::{ser::SerializeStruct, Deserialize, Serialize, Serializer};

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

pub const PREDEFINED_COLORSPACE_PRIMARIES: &[[f64; 8]] = &[
[0.68, 0.32, 0.265, 0.69, 0.15, 0.06, 0.3127, 0.329], // 0, DCI-P3 D65
Expand All @@ -26,14 +26,7 @@ pub struct ExtMetadataBlockLevel9 {
pub length: u64,
pub source_primary_index: u8,

pub source_primary_red_x: u16,
pub source_primary_red_y: u16,
pub source_primary_green_x: u16,
pub source_primary_green_y: u16,
pub source_primary_blue_x: u16,
pub source_primary_blue_y: u16,
pub source_primary_white_x: u16,
pub source_primary_white_y: u16,
pub source_primaries: Option<ColorPrimaries>,
}

impl ExtMetadataBlockLevel9 {
Expand All @@ -45,14 +38,7 @@ impl ExtMetadataBlockLevel9 {
};

if length > 1 {
block.source_primary_red_x = reader.get_n(16);
block.source_primary_red_y = reader.get_n(16);
block.source_primary_green_x = reader.get_n(16);
block.source_primary_green_y = reader.get_n(16);
block.source_primary_blue_x = reader.get_n(16);
block.source_primary_blue_y = reader.get_n(16);
block.source_primary_white_x = reader.get_n(16);
block.source_primary_white_y = reader.get_n(16);
block.source_primaries = Some(ColorPrimaries::parse(reader));
}

ExtMetadataBlock::Level9(block)
Expand All @@ -64,31 +50,23 @@ impl ExtMetadataBlockLevel9 {
writer.write_n(&self.source_primary_index.to_be_bytes(), 8);

if self.length > 1 {
writer.write_n(&self.source_primary_red_x.to_be_bytes(), 16);
writer.write_n(&self.source_primary_red_y.to_be_bytes(), 16);
writer.write_n(&self.source_primary_green_x.to_be_bytes(), 16);
writer.write_n(&self.source_primary_green_y.to_be_bytes(), 16);
writer.write_n(&self.source_primary_blue_x.to_be_bytes(), 16);
writer.write_n(&self.source_primary_blue_y.to_be_bytes(), 16);
writer.write_n(&self.source_primary_white_x.to_be_bytes(), 16);
writer.write_n(&self.source_primary_white_y.to_be_bytes(), 16);
if let Some(primaries) = &self.source_primaries {
primaries.write(writer);
}
}

Ok(())
}

pub fn validate(&self) -> Result<()> {
if self.length > 1 {
// Custom primaries
// Custom primaries required
ensure!(self.source_primary_index == 255);
ensure!(self.source_primary_red_x > 0);
ensure!(self.source_primary_red_y > 0);
ensure!(self.source_primary_green_x > 0);
ensure!(self.source_primary_green_y > 0);
ensure!(self.source_primary_blue_x > 0);
ensure!(self.source_primary_blue_y > 0);
ensure!(self.source_primary_white_x > 0);
ensure!(self.source_primary_white_y > 0);
ensure!(self.source_primaries.is_some());

if let Some(primaries) = &self.source_primaries {
primaries.validate()?;
}
} else {
// Should be a preset primary between 0-8?
// But not custom primaries
Expand Down Expand Up @@ -127,14 +105,7 @@ impl Default for ExtMetadataBlockLevel9 {
Self {
length: 1,
source_primary_index: 0,
source_primary_red_x: 0,
source_primary_red_y: 0,
source_primary_green_x: 0,
source_primary_green_y: 0,
source_primary_blue_x: 0,
source_primary_blue_y: 0,
source_primary_white_x: 0,
source_primary_white_y: 0,
source_primaries: None,
}
}
}
Expand All @@ -156,14 +127,16 @@ impl Serialize for ExtMetadataBlockLevel9 {
state.serialize_field("source_primary_index", &self.source_primary_index)?;

if self.length > 1 {
state.serialize_field("source_primary_red_x", &self.source_primary_red_x)?;
state.serialize_field("source_primary_red_y", &self.source_primary_white_y)?;
state.serialize_field("source_primary_green_x", &self.source_primary_green_x)?;
state.serialize_field("source_primary_green_y", &self.source_primary_green_y)?;
state.serialize_field("source_primary_blue_x", &self.source_primary_blue_x)?;
state.serialize_field("source_primary_blue_y", &self.source_primary_blue_y)?;
state.serialize_field("source_primary_white_x", &self.source_primary_white_x)?;
state.serialize_field("source_primary_white_y", &self.source_primary_white_y)?;
if let Some(primaries) = &self.source_primaries {
state.serialize_field("source_primary_red_x", &primaries.red_x)?;
state.serialize_field("source_primary_red_y", &primaries.white_y)?;
state.serialize_field("source_primary_green_x", &primaries.green_x)?;
state.serialize_field("source_primary_green_y", &primaries.green_y)?;
state.serialize_field("source_primary_blue_x", &primaries.blue_x)?;
state.serialize_field("source_primary_blue_y", &primaries.blue_y)?;
state.serialize_field("source_primary_white_x", &primaries.white_x)?;
state.serialize_field("source_primary_white_y", &primaries.white_y)?;
}
}

state.end()
Expand Down
75 changes: 75 additions & 0 deletions dolby_vision/src/rpu/extension_metadata/blocks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,26 @@ pub use level8::ExtMetadataBlockLevel8;
pub use level9::ExtMetadataBlockLevel9;
pub use reserved::ReservedExtMetadataBlock;

use crate::utils::f64_to_integer_primaries;

use super::WithExtMetadataBlocks;

/// cbindgen:ignore
pub const MAX_12_BIT_VALUE: u16 = 4095;

#[derive(Debug, Default, Clone)]
#[cfg_attr(feature = "serde_feature", derive(Deserialize, Serialize))]
pub struct ColorPrimaries {
pub red_x: u16,
pub red_y: u16,
pub green_x: u16,
pub green_y: u16,
pub blue_x: u16,
pub blue_y: u16,
pub white_x: u16,
pub white_y: u16,
}

#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde_feature", derive(Deserialize, Serialize))]
pub enum ExtMetadataBlock {
Expand Down Expand Up @@ -213,3 +228,63 @@ impl ExtMetadataBlock {
Ok(())
}
}

impl ColorPrimaries {
pub fn parse(reader: &mut BitVecReader) -> ColorPrimaries {
Self {
red_x: reader.get_n(16),
red_y: reader.get_n(16),
green_x: reader.get_n(16),
green_y: reader.get_n(16),
blue_x: reader.get_n(16),
blue_y: reader.get_n(16),
white_x: reader.get_n(16),
white_y: reader.get_n(16),
}
}

pub fn write(&self, writer: &mut BitVecWriter) {
writer.write_n(&self.red_x.to_be_bytes(), 16);
writer.write_n(&self.red_y.to_be_bytes(), 16);
writer.write_n(&self.green_x.to_be_bytes(), 16);
writer.write_n(&self.green_y.to_be_bytes(), 16);
writer.write_n(&self.blue_x.to_be_bytes(), 16);
writer.write_n(&self.blue_y.to_be_bytes(), 16);
writer.write_n(&self.white_x.to_be_bytes(), 16);
writer.write_n(&self.white_y.to_be_bytes(), 16);
}

/// Primaries only make sense if all coordinates are set
pub fn validate(&self) -> Result<()> {
ensure!(self.red_x > 0);
ensure!(self.red_y > 0);
ensure!(self.green_x > 0);
ensure!(self.green_y > 0);
ensure!(self.blue_x > 0);
ensure!(self.blue_y > 0);
ensure!(self.white_x > 0);
ensure!(self.white_y > 0);

Ok(())
}

pub fn from_array_int(primaries: &[u16; 8]) -> ColorPrimaries {
Self {
red_x: primaries[0],
red_y: primaries[1],
green_x: primaries[2],
green_y: primaries[3],
blue_x: primaries[4],
blue_y: primaries[5],
white_x: primaries[6],
white_y: primaries[7],
}
}

pub fn from_array_float(primaries: &[f64; 8]) -> ColorPrimaries {
// Float to integer primaries
let primaries_int = f64_to_integer_primaries(primaries);

Self::from_array_int(&primaries_int)
}
}
Loading

0 comments on commit 48ea4b1

Please sign in to comment.