Skip to content

Commit

Permalink
Fix parsing Level5
Browse files Browse the repository at this point in the history
Choose most common per-shot image aspect ratio as global image aspect ratio
  • Loading branch information
saindriches committed Aug 7, 2023
1 parent 220ef2c commit 4aecd2b
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 73 deletions.
57 changes: 6 additions & 51 deletions src/functions/convert.rs
Expand Up @@ -4,7 +4,6 @@ use std::io::{BufWriter, Write};

use anyhow::{bail, ensure, Result};
use dolby_vision::rpu::utils::parse_rpu_file;
use itertools::{Itertools, MinMaxResult};
use quick_xml::events::Event;
use quick_xml::se::Serializer;
use quick_xml::{Reader, Writer};
Expand All @@ -15,9 +14,7 @@ use crate::commands::convert::ConvertArgs;
use crate::metadata::levels::Level11;
use crate::metadata::levels::Level5;
use crate::MDFType::{CMV29, CMV40};
use crate::{
cmv40, display, IntoCMV29, Level254, Level6, UHD_AR, UHD_HEIGHT, UHD_WIDTH, XML_PREFIX,
};
use crate::{cmv40, display, IntoCMV29, Level254, Level6, XML_PREFIX};

#[derive(Debug, Default)]
pub struct Converter {
Expand Down Expand Up @@ -195,7 +192,9 @@ impl Converter {
*level11_map.entry(&shot.plugin_node.level11).or_insert(0) += 1_usize;
});

converter.level5 = Some(Self::get_global_ar(level5_map, canvas));
// converter.level5 = Some(Self::get_global_ar(level5_map, canvas));
converter.level5 =
Self::get_common(level5_map).or_else(|| Some(Level5::with_canvas(None, canvas)));

// Choose the most common level11 as track-level metadata,
converter.level11 = Self::get_common(level11_map);
Expand Down Expand Up @@ -257,57 +256,13 @@ impl Converter {
}

/// None: Standard UHD
fn parse_canvas_ar(vec: Vec<usize>) -> Result<Option<(usize, usize)>> {
fn parse_canvas_ar(vec: Vec<usize>) -> Result<(usize, usize)> {
ensure!(
vec.len() == 2,
"Invalid canvas size. Use 'x' as delimiter, like 3840x2160"
);
ensure!(vec[0] != 0 && vec[1] != 0, "Invalid canvas size.");
let canvas = (vec[0], vec[1]);
let canvas = if canvas == (UHD_WIDTH, UHD_HEIGHT) {
None
} else {
Some(canvas)
};

// stdout().flush().ok();

Ok(canvas)
}

fn get_global_ar(
map: HashMap<&Option<Level5>, usize>,
canvas: Option<(usize, usize)>,
) -> Level5 {
let canvas_ar = match canvas {
Some((width, height)) => width as f32 / height as f32,
None => UHD_AR,
};

let minmax = map
.into_iter()
.filter(|(value, _)| value.is_some())
.map(|(value, _)| value.clone().unwrap())
.minmax();

match minmax {
MinMaxResult::NoElements => Level5::from(canvas_ar),
MinMaxResult::OneElement(b) => b,
MinMaxResult::MinMax(b_min, b_max) => {
let b_canvas = Level5::from(canvas_ar);
// if b_min > b_canvas {
// // all letterbox types are up/bottom
// b_min
// } else if b_max < b_canvas {
// // all letterbox types are left/right
// b_max
// } else {
// // Mixed type, or no letterbox
// b_canvas
// }
b_canvas.clamp(b_min, b_max)
}
}
Ok((vec[0], vec[1]))
}

fn get_common<K, V>(map: HashMap<&Option<K>, V>) -> Option<K>
Expand Down
27 changes: 14 additions & 13 deletions src/metadata/cmv40/shot.rs
Expand Up @@ -37,7 +37,7 @@ impl Shot {
}
}

pub fn with_canvas(vdr: &VdrDmData, canvas: Option<(usize, usize)>) -> Self {
pub fn with_canvas(vdr: &VdrDmData, canvas: (usize, usize)) -> Self {
Self {
unique_id: UUIDv4::new(),
record: Default::default(),
Expand Down Expand Up @@ -67,7 +67,7 @@ impl Shot {

impl From<&VdrDmData> for Shot {
fn from(vdr: &VdrDmData) -> Self {
Self::with_canvas(vdr, None)
Self::with_canvas(vdr, UHD_CANVAS)
}
}

Expand All @@ -94,7 +94,7 @@ pub struct ShotPluginNode {
}

impl ShotPluginNode {
fn with_canvas(vdr: &VdrDmData, canvas: Option<(usize, usize)>) -> Self {
fn with_canvas(vdr: &VdrDmData, canvas: (usize, usize)) -> Self {
let level11 = vdr.get_block(11).and_then(|b| match b {
ExtMetadataBlock::Level11(b) => Some(Level11::from(b)),
_ => None,
Expand All @@ -109,7 +109,7 @@ impl ShotPluginNode {

impl From<&VdrDmData> for ShotPluginNode {
fn from(vdr: &VdrDmData) -> Self {
Self::with_canvas(vdr, None)
Self::with_canvas(vdr, UHD_CANVAS)
}
}

Expand All @@ -135,7 +135,7 @@ pub struct DVDynamicData {
}

impl DVDynamicData {
pub fn with_canvas(vdr: &VdrDmData, canvas: Option<(usize, usize)>) -> Self {
pub fn with_canvas(vdr: &VdrDmData, canvas: (usize, usize)) -> Self {
let level1 = if let Some(ExtMetadataBlock::Level1(block)) = vdr.get_block(1) {
Level1::from(block)
} else {
Expand Down Expand Up @@ -165,13 +165,14 @@ impl DVDynamicData {
_ => None,
});

let level5 = vdr.get_block(5).and_then(|b| match b {
ExtMetadataBlock::Level5(b) => match canvas {
Some(canvas) => Some(Level5::with_canvas(b, canvas)),
None => Some(Level5::from(b)),
},
_ => None,
});
let level5 = {
let b = vdr.get_block(5).and_then(|b| match b {
ExtMetadataBlock::Level5(b) => Some(b),
_ => None,
});

Some(Level5::with_canvas(b, canvas))
};

let level8 = vdr
.level_blocks_iter(8)
Expand All @@ -194,7 +195,7 @@ impl DVDynamicData {

impl From<&VdrDmData> for DVDynamicData {
fn from(vdr: &VdrDmData) -> Self {
Self::with_canvas(vdr, None)
Self::with_canvas(vdr, UHD_CANVAS)
}
}

Expand Down
23 changes: 14 additions & 9 deletions src/metadata/levels/level5.rs
Expand Up @@ -2,8 +2,9 @@ use dolby_vision::rpu::extension_metadata::blocks::ExtMetadataBlockLevel5;
use serde::Serialize;
use std::cmp::Ordering;

use crate::metadata::levels::UHD_CANVAS;
use crate::MDFType::CMV40;
use crate::{IntoCMV29, MDFType, UHD_HEIGHT, UHD_WIDTH};
use crate::{IntoCMV29, MDFType};

use super::AspectRatio;

Expand All @@ -26,7 +27,7 @@ impl Level5 {
// For convenience, it assumes the canvas is standard UHD
impl From<&ExtMetadataBlockLevel5> for Level5 {
fn from(block: &ExtMetadataBlockLevel5) -> Self {
Self::with_canvas(block, (UHD_WIDTH, UHD_HEIGHT))
Self::with_canvas(Some(block), UHD_CANVAS)
}
}

Expand All @@ -49,18 +50,22 @@ impl IntoCMV29<Self> for Level5 {
}

impl Level5 {
pub fn with_canvas(block: &ExtMetadataBlockLevel5, canvas: (usize, usize)) -> Self {
pub fn with_canvas(block: Option<&ExtMetadataBlockLevel5>, canvas: (usize, usize)) -> Self {
let (width, height) = canvas;
let canvas_ar = width as f32 / height as f32;

let horizontal_crop = block.active_area_left_offset + block.active_area_right_offset;
let vertical_crop = block.active_area_top_offset + block.active_area_bottom_offset;
let image_ar = if let Some(block) = block {
let horizontal_crop = block.active_area_left_offset + block.active_area_right_offset;
let vertical_crop = block.active_area_top_offset + block.active_area_bottom_offset;

let image_ar = if horizontal_crop > 0 {
(width as f32 - horizontal_crop as f32) / height as f32
if horizontal_crop > 0 {
(width as f32 - horizontal_crop as f32) / height as f32
} else {
// Ok because only one of the crop types will be 0
width as f32 / (height as f32 - vertical_crop as f32)
}
} else {
// Ok because only one of the crop types will be 0
width as f32 / (height as f32 - vertical_crop as f32)
canvas_ar
};

Self {
Expand Down
1 change: 1 addition & 0 deletions src/metadata/levels/mod.rs
Expand Up @@ -33,6 +33,7 @@ pub const RPU_U8_BIAS: f32 = 128.0;
pub const RPU_U12_BIAS: f32 = 2048.0;
pub const UHD_WIDTH: usize = 3840;
pub const UHD_HEIGHT: usize = 2160;
pub const UHD_CANVAS: (usize, usize) = (UHD_WIDTH, UHD_HEIGHT);
pub const UHD_AR: f32 = 16.0 / 9.0;

pub fn f32_from_rpu_u12_with_bias(u: u16) -> f32 {
Expand Down

0 comments on commit 4aecd2b

Please sign in to comment.