Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added assets/tests/l15_to_l18.bin
Binary file not shown.
36 changes: 36 additions & 0 deletions dolby_vision/src/c_structs/extension_metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ pub struct DmData {
level9: *const ExtMetadataBlockLevel9,
level10: Level10BlockList,
level11: *const ExtMetadataBlockLevel11,
level15: *const ExtMetadataBlockLevel15,
level16: *const ExtMetadataBlockLevel16,
level17: *const ExtMetadataBlockLevel17,
level18: *const ExtMetadataBlockLevel18,
level254: *const ExtMetadataBlockLevel254,
level255: *const ExtMetadataBlockLevel255,
}
Expand Down Expand Up @@ -106,6 +110,22 @@ impl DmData {
self.level11 =
Box::into_raw(Box::new(b.clone())) as *const ExtMetadataBlockLevel11
}
ExtMetadataBlock::Level15(b) => {
self.level15 =
Box::into_raw(Box::new(b.clone())) as *const ExtMetadataBlockLevel15
}
ExtMetadataBlock::Level16(b) => {
self.level16 =
Box::into_raw(Box::new(b.clone())) as *const ExtMetadataBlockLevel16
}
ExtMetadataBlock::Level17(b) => {
self.level17 =
Box::into_raw(Box::new(b.clone())) as *const ExtMetadataBlockLevel17
}
ExtMetadataBlock::Level18(b) => {
self.level18 =
Box::into_raw(Box::new(b.clone())) as *const ExtMetadataBlockLevel18
}
ExtMetadataBlock::Level254(b) => {
self.level254 =
Box::into_raw(Box::new(b.clone())) as *const ExtMetadataBlockLevel254
Expand Down Expand Up @@ -156,6 +176,18 @@ impl DmData {
if !self.level11.is_null() {
drop(Box::from_raw(self.level11 as *mut ExtMetadataBlockLevel11));
}
if !self.level15.is_null() {
drop(Box::from_raw(self.level15 as *mut ExtMetadataBlockLevel15));
}
if !self.level16.is_null() {
drop(Box::from_raw(self.level16 as *mut ExtMetadataBlockLevel16));
}
if !self.level17.is_null() {
drop(Box::from_raw(self.level17 as *mut ExtMetadataBlockLevel17));
}
if !self.level18.is_null() {
drop(Box::from_raw(self.level18 as *mut ExtMetadataBlockLevel18));
}
if !self.level254.is_null() {
drop(Box::from_raw(
self.level254 as *mut ExtMetadataBlockLevel254,
Expand Down Expand Up @@ -184,6 +216,10 @@ impl Default for DmData {
level9: null(),
level10: Default::default(),
level11: null(),
level15: null(),
level16: null(),
level17: null(),
level18: null(),
level254: null(),
level255: null(),
}
Expand Down
20 changes: 19 additions & 1 deletion dolby_vision/src/rpu/extension_metadata/blocks/level11.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ pub struct ExtMetadataBlockLevel11 {

#[cfg_attr(feature = "serde", serde(default))]
pub reserved_byte2: u8,
/// Byte 3 of the L11 block. In DV2 this carries Authentic Motion /
/// FRC metadata (see Dolby Vision Metadata Spec v1.5.1 §6, HDMI
/// Transmission Spec v5.1.1 PB[13]): bits [3:0] = `frc_strength`,
/// bit 4 = `frc_type` (0 = De-judder, 1 = Smoothness). Stored as a
/// raw byte for round-trip fidelity; decoded via [`Self::frc_strength`]
/// and [`Self::frc_type`].
#[cfg_attr(feature = "serde", serde(default))]
pub reserved_byte3: u8,
}
Expand Down Expand Up @@ -51,11 +57,23 @@ impl ExtMetadataBlockLevel11 {
pub fn validate(&self) -> Result<()> {
ensure!(self.content_type <= 15);
ensure!(self.whitepoint <= 15);
ensure!(self.reserved_byte3 == 0);

Ok(())
}

/// FRC strength (Authentic Motion), bits [3:0] of byte 3.
/// Range 0..=15. Only meaningful when `DV2_Motion_Control` is set
/// (byte 1, bit 5); otherwise this is expected to be 0.
pub const fn frc_strength(&self) -> u8 {
self.reserved_byte3 & 0x0F
}

/// FRC type (Authentic Motion), bit 4 of byte 3.
/// `false` (0) = De-judder (<=30fps film), `true` (1) = Smoothness (>=50fps sports).
pub const fn frc_type(&self) -> bool {
(self.reserved_byte3 >> 4) & 0x01 == 1
}

/// Cinema, D65 whitepoint
pub const fn default_cinema() -> Self {
Self {
Expand Down
92 changes: 92 additions & 0 deletions dolby_vision/src/rpu/extension_metadata/blocks/level15.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
use anyhow::{Result, ensure};
use bitvec_helpers::{
bitstream_io_reader::BsIoSliceReader, bitstream_io_writer::BitstreamIoWriter,
};

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

use super::{ExtMetadataBlock, ExtMetadataBlockInfo};

/// Consumer look metadata, Precision Rendering/Detail
#[repr(C)]
#[derive(Debug, Default, Clone)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
pub struct ExtMetadataBlockLevel15 {
pub confidence: u8,
pub precision_rendering_strength: u8,
pub d_local_contrast: u8,
pub d_brightness: u8,
pub d_saturation_plus_one: u8,
pub d_contrast_plus_one: u8,

pub confidence_no_pr: u8,
pub d_brightness_no_pr: u8,
pub d_saturation_plus_one_no_pr: u8,
pub d_contrast_plus_one_no_pr: u8,

/// 4 bits
pub revision: u8,
/// 4 bits
pub reserved: u8,
}

impl ExtMetadataBlockLevel15 {
pub(crate) fn parse(reader: &mut BsIoSliceReader) -> Result<ExtMetadataBlock> {
let block = Self {
confidence: reader.read::<8, u8>()?,
precision_rendering_strength: reader.read::<8, u8>()?,
d_local_contrast: reader.read::<8, u8>()?,
d_brightness: reader.read::<8, u8>()?,
d_saturation_plus_one: reader.read::<8, u8>()?,
d_contrast_plus_one: reader.read::<8, u8>()?,
confidence_no_pr: reader.read::<8, u8>()?,
d_brightness_no_pr: reader.read::<8, u8>()?,
d_saturation_plus_one_no_pr: reader.read::<8, u8>()?,
d_contrast_plus_one_no_pr: reader.read::<8, u8>()?,
revision: reader.read::<4, u8>()?,
reserved: reader.read::<4, u8>()?,
};

Ok(ExtMetadataBlock::Level15(block))
}

pub fn write(&self, writer: &mut BitstreamIoWriter) -> Result<()> {
self.validate()?;

writer.write::<8, u8>(self.confidence)?;
writer.write::<8, u8>(self.precision_rendering_strength)?;
writer.write::<8, u8>(self.d_local_contrast)?;
writer.write::<8, u8>(self.d_brightness)?;
writer.write::<8, u8>(self.d_saturation_plus_one)?;
writer.write::<8, u8>(self.d_contrast_plus_one)?;
writer.write::<8, u8>(self.confidence_no_pr)?;
writer.write::<8, u8>(self.d_brightness_no_pr)?;
writer.write::<8, u8>(self.d_saturation_plus_one_no_pr)?;
writer.write::<8, u8>(self.d_contrast_plus_one_no_pr)?;
writer.write::<4, u8>(self.revision)?;
writer.write::<4, u8>(self.reserved)?;

Ok(())
}

pub fn validate(&self) -> Result<()> {
ensure!(self.reserved == 0);

Ok(())
}
}

impl ExtMetadataBlockInfo for ExtMetadataBlockLevel15 {
fn level(&self) -> u8 {
15
}

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

fn required_bits(&self) -> u64 {
88
}
}
92 changes: 92 additions & 0 deletions dolby_vision/src/rpu/extension_metadata/blocks/level16.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
use anyhow::{Result, ensure};
use bitvec_helpers::{
bitstream_io_reader::BsIoSliceReader, bitstream_io_writer::BitstreamIoWriter,
};

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

use super::{ExtMetadataBlock, ExtMetadataBlockInfo};

/// Local tone mapping metadata
#[repr(C)]
#[derive(Debug, Default, Clone)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
pub struct ExtMetadataBlockLevel16 {
pub revision: u8,
pub count: usize,

pub params: Vec<Level16Params>,
}

#[repr(C)]
#[derive(Debug, Default, Clone)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
pub struct Level16Params {
pub contrast_target: u8,
pub precision_rendering_strength: u8,
pub d_local_contrast: u8,
pub max_d_brightness: u8,
pub max_d_saturation_plus_one: u8,
}

impl ExtMetadataBlockLevel16 {
pub(crate) fn parse(reader: &mut BsIoSliceReader) -> Result<ExtMetadataBlock> {
let mut block = Self {
revision: reader.read::<4, u8>()?,
count: reader.read::<4, u8>()? as usize,
..Default::default()
};

block.params.reserve(block.count);

for _ in 0..block.count {
block.params.push(Level16Params {
contrast_target: reader.read::<8, u8>()?,
precision_rendering_strength: reader.read::<8, u8>()?,
d_local_contrast: reader.read::<8, u8>()?,
max_d_brightness: reader.read::<8, u8>()?,
max_d_saturation_plus_one: reader.read::<8, u8>()?,
});
}

Ok(ExtMetadataBlock::Level16(block))
}

pub fn write(&self, writer: &mut BitstreamIoWriter) -> Result<()> {
self.validate()?;

writer.write::<4, u8>(self.revision)?;
writer.write::<4, u8>(self.count as u8)?;

for params in &self.params {
writer.write::<8, u8>(params.contrast_target)?;
writer.write::<8, u8>(params.precision_rendering_strength)?;
writer.write::<8, u8>(params.d_local_contrast)?;
writer.write::<8, u8>(params.max_d_brightness)?;
writer.write::<8, u8>(params.max_d_saturation_plus_one)?;
}

Ok(())
}

pub fn validate(&self) -> Result<()> {
ensure!(self.count == self.params.len());

Ok(())
}
}

impl ExtMetadataBlockInfo for ExtMetadataBlockLevel16 {
fn level(&self) -> u8 {
16
}

fn bytes_size(&self) -> u64 {
1 + (self.count as u64 * 5)
}

fn required_bits(&self) -> u64 {
self.bytes_size() * 8
}
}
85 changes: 85 additions & 0 deletions dolby_vision/src/rpu/extension_metadata/blocks/level17.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
use anyhow::Result;
use bitvec_helpers::{
bitstream_io_reader::BsIoSliceReader, bitstream_io_writer::BitstreamIoWriter,
};

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

use super::{ExtMetadataBlock, ExtMetadataBlockInfo};

/// Up mapping metadata
#[repr(C)]
#[derive(Debug, Default, Clone)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
pub struct ExtMetadataBlockLevel17 {
pub mid_boost: u8,
pub highlight_stretch: u8,
pub shadow_drop: u8,
pub contrast_boost: u8,
pub saturation_boost: u8,
pub detail_boost: u8,
pub chroma_indicator: u8,

/// 12 bits
pub intensity_indicator_pq: u16,

/// 4 bits
pub revision: u8,

pub chroma_lift: u8,
}

impl ExtMetadataBlockLevel17 {
pub(crate) fn parse(reader: &mut BsIoSliceReader) -> Result<ExtMetadataBlock> {
let block = Self {
mid_boost: reader.read::<8, u8>()?,
highlight_stretch: reader.read::<8, u8>()?,
shadow_drop: reader.read::<8, u8>()?,
contrast_boost: reader.read::<8, u8>()?,
saturation_boost: reader.read::<8, u8>()?,
detail_boost: reader.read::<8, u8>()?,
chroma_indicator: reader.read::<8, u8>()?,
intensity_indicator_pq: reader.read::<12, u16>()?,
revision: reader.read::<4, u8>()?,
chroma_lift: reader.read::<8, u8>()?,
};

Ok(ExtMetadataBlock::Level17(block))
}

pub fn write(&self, writer: &mut BitstreamIoWriter) -> Result<()> {
self.validate()?;

writer.write::<8, u8>(self.mid_boost)?;
writer.write::<8, u8>(self.highlight_stretch)?;
writer.write::<8, u8>(self.shadow_drop)?;
writer.write::<8, u8>(self.contrast_boost)?;
writer.write::<8, u8>(self.saturation_boost)?;
writer.write::<8, u8>(self.detail_boost)?;
writer.write::<8, u8>(self.chroma_indicator)?;
writer.write::<12, u16>(self.intensity_indicator_pq)?;
writer.write::<4, u8>(self.revision)?;
writer.write::<8, u8>(self.chroma_lift)?;

Ok(())
}

pub fn validate(&self) -> Result<()> {
Ok(())
}
}

impl ExtMetadataBlockInfo for ExtMetadataBlockLevel17 {
fn level(&self) -> u8 {
17
}

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

fn required_bits(&self) -> u64 {
80
}
}
Loading