From 761d505bcdeacba1223ce181b62d3783a5d392cb Mon Sep 17 00:00:00 2001 From: sscobici Date: Mon, 14 Oct 2024 23:05:08 +0300 Subject: [PATCH] isomp4: parse Dolby Vision configuration --- symphonia-common/src/mpeg/video/mod.rs | 34 ++++++++++++++++++ symphonia-format-isomp4/src/atoms/dovi.rs | 43 +++++++++++++++++++++++ symphonia-format-isomp4/src/atoms/mod.rs | 4 +++ symphonia-format-isomp4/src/atoms/stsd.rs | 5 +++ 4 files changed, 86 insertions(+) create mode 100644 symphonia-format-isomp4/src/atoms/dovi.rs diff --git a/symphonia-common/src/mpeg/video/mod.rs b/symphonia-common/src/mpeg/video/mod.rs index ae873500..7978114a 100644 --- a/symphonia-common/src/mpeg/video/mod.rs +++ b/symphonia-common/src/mpeg/video/mod.rs @@ -76,3 +76,37 @@ impl HEVCDecoderConfigurationRecord { }) } } + +#[derive(Debug, Default)] +pub struct DOVIDecoderConfigurationRecord { + pub dv_version_major: u8, + pub dv_version_minor: u8, + pub dv_profile: u8, + pub dv_level: u8, + pub rpu_present_flag: bool, + pub el_present_flag: bool, + pub bl_present_flag: bool, + pub dv_bl_signal_compatibility_id: u8, +} + +impl DOVIDecoderConfigurationRecord { + pub fn read(buf: &[u8]) -> Result { + let mut br = BitReaderLtr::new(buf); + + // Parse the DOVIDecoderConfigurationRecord, point 3.2 from + // https://professional.dolby.com/siteassets/content-creation/dolby-vision-for-content-creators/dolby_vision_bitstreams_within_the_iso_base_media_file_format_dec2017.pdf + + let config = DOVIDecoderConfigurationRecord { + dv_version_major: br.read_bits_leq32(8)? as u8, + dv_version_minor: br.read_bits_leq32(8)? as u8, + dv_profile: br.read_bits_leq32(7)? as u8, + dv_level: br.read_bits_leq32(6)? as u8, + rpu_present_flag: br.read_bit()? != 0, + el_present_flag: br.read_bit()? != 0, + bl_present_flag: br.read_bit()? != 0, + dv_bl_signal_compatibility_id: br.read_bits_leq32(4)? as u8, + }; + + Ok(config) + } +} diff --git a/symphonia-format-isomp4/src/atoms/dovi.rs b/symphonia-format-isomp4/src/atoms/dovi.rs new file mode 100644 index 00000000..94b99ca6 --- /dev/null +++ b/symphonia-format-isomp4/src/atoms/dovi.rs @@ -0,0 +1,43 @@ +// Symphonia +// Copyright (c) 2019-2022 The Project Symphonia Developers. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +use symphonia_core::codecs::video::well_known::extra_data::VIDEO_EXTRA_DATA_ID_DOLBY_VISION_CONFIG; +use symphonia_core::codecs::video::VideoExtraData; +use symphonia_core::errors::{Error, Result}; +use symphonia_core::io::ReadBytes; + +use crate::atoms::{Atom, AtomHeader}; + +use super::stsd::VisualSampleEntry; + +#[allow(dead_code)] +#[derive(Debug)] +pub struct DoviAtom { + extra_data: VideoExtraData, +} + +impl Atom for DoviAtom { + fn read(reader: &mut B, header: AtomHeader) -> Result { + // The Dolby Vision Configuration atom payload (dvvC and dvcC) + let len = header + .data_len() + .ok_or_else(|| Error::DecodeError("isomp4 (dovi): expected atom size to be known"))?; + + let dovi_data = VideoExtraData { + id: VIDEO_EXTRA_DATA_ID_DOLBY_VISION_CONFIG, + data: reader.read_boxed_slice_exact(len as usize)?, + }; + + Ok(Self { extra_data: dovi_data }) + } +} + +impl DoviAtom { + pub fn fill_video_sample_entry(&self, entry: &mut VisualSampleEntry) { + entry.extra_data.push(self.extra_data.clone()); + } +} diff --git a/symphonia-format-isomp4/src/atoms/mod.rs b/symphonia-format-isomp4/src/atoms/mod.rs index f19942f5..2bcd08a1 100644 --- a/symphonia-format-isomp4/src/atoms/mod.rs +++ b/symphonia-format-isomp4/src/atoms/mod.rs @@ -16,6 +16,7 @@ pub(crate) mod co64; pub(crate) mod ctts; pub(crate) mod dac3; pub(crate) mod dec3; +pub(crate) mod dovi; pub(crate) mod edts; pub(crate) mod elst; pub(crate) mod esds; @@ -141,6 +142,7 @@ pub enum AtomType { DateTag, DescriptionTag, DiskNumberTag, + DolbyVisionConfiguration, Eac3Config, Edit, EditList, @@ -250,8 +252,10 @@ impl From<[u8; 4]> for AtomType { b"data" => AtomType::MetaTagData, b"dfLa" => AtomType::FlacDsConfig, b"dOps" => AtomType::OpusDsConfig, + b"dvcC" => AtomType::DolbyVisionConfiguration, b"dvh1" => AtomType::VisualSampleEntryDvh1, b"dvhe" => AtomType::VisualSampleEntryDvhe, + b"dvvC" => AtomType::DolbyVisionConfiguration, b"edts" => AtomType::Edit, b"elst" => AtomType::EditList, b"esds" => AtomType::Esds, diff --git a/symphonia-format-isomp4/src/atoms/stsd.rs b/symphonia-format-isomp4/src/atoms/stsd.rs index ffb12ef9..a42ff046 100644 --- a/symphonia-format-isomp4/src/atoms/stsd.rs +++ b/symphonia-format-isomp4/src/atoms/stsd.rs @@ -35,6 +35,7 @@ use crate::atoms::{ }; use crate::fp::FpU16; +use super::dovi::DoviAtom; use super::{AtomIterator, AvcCAtom, HvcCAtom}; /// Sample description atom. @@ -552,6 +553,10 @@ fn read_visual_sample_entry( let atom = iter.read_atom::()?; atom.fill_video_sample_entry(&mut entry); } + AtomType::DolbyVisionConfiguration => { + let atom = iter.read_atom::()?; + atom.fill_video_sample_entry(&mut entry); + } _ => { debug!("unknown visual sample entry sub-atom: {:?}.", entry_header.atom_type()); }