Skip to content

Commit

Permalink
mkv: parse Dolby Vision configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
sscobici committed Oct 24, 2024
1 parent 1713adf commit 2a74330
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 0 deletions.
6 changes: 6 additions & 0 deletions symphonia-format-mkv/src/codecs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,12 @@ fn make_video_codec_params(
codec_params.add_extra_data(VideoExtraData { id: extra_data_id, data: codec_private });
}

for block in track.block_addition_mappings {
if let Some(extra_data) = block.extra_data {
codec_params.add_extra_data(extra_data);
}
}

Ok(Some(CodecParameters::Video(codec_params)))
}

Expand Down
6 changes: 6 additions & 0 deletions symphonia-format-mkv/src/element_ids.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ pub enum ElementType {
BlockAdditions,
BlockMore,
BlockAddId,
BlockAddIdType,
BlockAdditional,
BlockAdditionMapping,
BlockDuration,
ReferenceBlock,
DiscardPadding,
Expand Down Expand Up @@ -93,6 +95,7 @@ pub enum ElementType {
DisplayHeight,
DisplayUnit,
AspectRatioType,
DolbyVisionConfiguration,
Audio,
SamplingFrequency,
OutputSamplingFrequency,
Expand Down Expand Up @@ -218,7 +221,9 @@ lazy_static! {
elems.insert(0x75A1, (Type::Master, ElementType::BlockAdditions));
elems.insert(0xA6, (Type::Master, ElementType::BlockMore));
elems.insert(0xEE, (Type::Unsigned, ElementType::BlockAddId));
elems.insert(0x41E7, (Type::String, ElementType::BlockAddIdType));
elems.insert(0xA5, (Type::Binary, ElementType::BlockAdditional));
elems.insert(0x41E4, (Type::Binary, ElementType::BlockAdditionMapping));
elems.insert(0x9B, (Type::Unsigned, ElementType::BlockDuration));
elems.insert(0xFB, (Type::Signed, ElementType::ReferenceBlock));
elems.insert(0x75A2, (Type::Signed, ElementType::DiscardPadding));
Expand Down Expand Up @@ -258,6 +263,7 @@ lazy_static! {
elems.insert(0x54BA, (Type::Unsigned, ElementType::DisplayHeight));
elems.insert(0x54B2, (Type::Unsigned, ElementType::DisplayUnit));
elems.insert(0x54B3, (Type::Unsigned, ElementType::AspectRatioType));
elems.insert(0x41ED, (Type::Binary, ElementType::DolbyVisionConfiguration));
elems.insert(0xE1, (Type::Master, ElementType::Audio));
elems.insert(0xB5, (Type::Float, ElementType::SamplingFrequency));
elems.insert(0x78B5, (Type::Float, ElementType::OutputSamplingFrequency));
Expand Down
55 changes: 55 additions & 0 deletions symphonia-format-mkv/src/segment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
// 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, VIDEO_EXTRA_DATA_ID_DOLBY_VISION_EL_HEVC,
};
use symphonia_core::codecs::video::VideoExtraData;
use symphonia_core::errors::{Error, Result};
use symphonia_core::io::{BufReader, ReadBytes};
use symphonia_core::meta::{MetadataBuilder, MetadataRevision, Tag, Value};
Expand All @@ -21,6 +25,7 @@ pub(crate) struct TrackElement {
pub(crate) language: Option<String>,
pub(crate) codec_id: String,
pub(crate) codec_private: Option<Box<[u8]>>,
pub(crate) block_addition_mappings: Vec<BlockAdditionMappingElement>,
pub(crate) audio: Option<AudioElement>,
pub(crate) video: Option<VideoElement>,
pub(crate) default_duration: Option<u64>,
Expand All @@ -36,6 +41,7 @@ impl Element for TrackElement {
let mut audio = None;
let mut video = None;
let mut codec_private = None;
let mut block_addition_mappings = Vec::new();
let mut codec_id = None;
let mut default_duration = None;

Expand Down Expand Up @@ -63,6 +69,9 @@ impl Element for TrackElement {
ElementType::Video => {
video = Some(it.read_element_data()?);
}
ElementType::BlockAdditionMapping => {
block_addition_mappings.push(it.read_element_data()?);
}
ElementType::DefaultDuration => {
default_duration = Some(it.read_u64()?);
}
Expand All @@ -78,6 +87,7 @@ impl Element for TrackElement {
language,
codec_id: codec_id.ok_or(Error::DecodeError("mkv: missing codec id"))?,
codec_private,
block_addition_mappings,
audio,
video,
default_duration,
Expand Down Expand Up @@ -166,6 +176,51 @@ impl Element for VideoElement {
}
}

#[derive(Debug)]
pub(crate) struct BlockAdditionMappingElement {
pub(crate) extra_data: Option<VideoExtraData>,
}

impl Element for BlockAdditionMappingElement {
const ID: ElementType = ElementType::BlockAdditionMapping;

fn read<B: ReadBytes>(reader: &mut B, header: ElementHeader) -> Result<Self> {
// There can be many BlockAdditionMapping elements with DolbyVisionConfiguration in a single track
// BlockAddIdType FourCC string allows to determine the type of DolbyVisionConfiguration extra data
let mut extra_data = None;
let mut block_add_id_type = String::new();

let mut it = header.children(reader);
while let Some(header) = it.read_header()? {
match header.etype {
ElementType::BlockAddIdType => {
block_add_id_type = it.read_string()?;
}
ElementType::DolbyVisionConfiguration => match block_add_id_type.as_str() {
"dvcC" | "dvvC" => {
extra_data = Some(VideoExtraData {
id: VIDEO_EXTRA_DATA_ID_DOLBY_VISION_CONFIG,
data: it.read_boxed_slice()?,
});
}
"hvcE" => {
extra_data = Some(VideoExtraData {
id: VIDEO_EXTRA_DATA_ID_DOLBY_VISION_EL_HEVC,
data: it.read_boxed_slice()?,
});
}
_ => {}
},
other => {
log::debug!("ignored element {:?}", other);
}
}
}

Ok(Self { extra_data })
}
}

#[derive(Debug)]
pub(crate) struct SeekHeadElement {
pub(crate) seeks: Box<[SeekElement]>,
Expand Down

0 comments on commit 2a74330

Please sign in to comment.