EBML: Start parsing segment.Info

Signed-off-by: Serial <69764315+Serial-ATA@users.noreply.github.com>
This commit is contained in:
Serial 2023-11-26 12:02:37 -05:00
parent eb5253ba50
commit 131049cd4b
No known key found for this signature in database
GPG key ID: DA95198DC17C4568
5 changed files with 81 additions and 5 deletions

View file

@ -224,6 +224,11 @@ where
self.ctx.max_size_length = len
}
fn store_previous_master(&mut self) {
self.ctx.previous_master = self.ctx.current_master;
self.ctx.previous_master_length = self.ctx.master_length;
}
fn next_master(&mut self) -> Result<ElementReaderYield> {
let header = ElementHeader::read(
&mut self.reader,
@ -235,8 +240,7 @@ where
return Ok(ElementReaderYield::Unknown(header));
};
self.ctx.previous_master = self.ctx.current_master;
self.ctx.previous_master_length = self.ctx.master_length;
self.store_previous_master();
self.ctx.current_master = Some(*master);
self.ctx.master_length = header.size.value();
Ok(ElementReaderYield::Master((
@ -288,6 +292,7 @@ where
};
if child.data_type == ElementDataType::Master {
self.store_previous_master();
self.ctx.current_master = Some(
*MASTER_ELEMENTS
.get(&header.id)

View file

@ -17,11 +17,19 @@ pub struct EbmlExtension {
pub(crate) version: u64,
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct SegmentInfo {
pub(crate) timecode_scale: u64,
pub(crate) muxing_app: String,
pub(crate) writing_app: String,
}
/// EBML audio properties
#[derive(Debug, Clone, PartialEq, Default)]
pub struct EbmlProperties {
pub(crate) header: EbmlHeaderProperties,
pub(crate) extensions: Vec<EbmlExtension>,
pub(crate) segment_info: SegmentInfo,
}
impl From<EbmlProperties> for FileProperties {

View file

@ -1,4 +1,5 @@
mod segment;
mod segment_info;
use super::EbmlFile;
use crate::ebml::element_reader::{ElementHeader, ElementIdent, ElementReader, ElementReaderYield};

View file

@ -1,3 +1,4 @@
use super::segment_info;
use crate::ebml::element_reader::{ElementIdent, ElementReader, ElementReaderYield};
use crate::ebml::properties::EbmlProperties;
use crate::ebml::tag::EbmlTag;
@ -9,8 +10,8 @@ use std::io::{Read, Seek};
pub(super) fn read_from<R>(
element_reader: &mut ElementReader<R>,
_parse_options: ParseOptions,
_properties: &mut EbmlProperties,
parse_options: ParseOptions,
properties: &mut EbmlProperties,
) -> Result<Option<EbmlTag>>
where
R: Read + Seek,
@ -23,7 +24,9 @@ where
let res = element_reader.next()?;
match res {
ElementReaderYield::Master((id, size)) => match id {
ElementIdent::Info => todo!("Support segment.Info"),
ElementIdent::Info => {
segment_info::read_from(element_reader, parse_options, properties)?
},
ElementIdent::Cluster => todo!("Support segment.Cluster"),
ElementIdent::Tracks => todo!("Support segment.Tracks"),
ElementIdent::Tags => todo!("Support segment.Tags"),

View file

@ -0,0 +1,59 @@
use crate::ebml::element_reader::{ElementIdent, ElementReader, ElementReaderYield};
use crate::ebml::properties::EbmlProperties;
use crate::error::Result;
use crate::probe::ParseOptions;
use std::io::{Read, Seek};
pub(super) fn read_from<R>(
element_reader: &mut ElementReader<R>,
_parse_options: ParseOptions,
_properties: &mut EbmlProperties,
) -> Result<()>
where
R: Read + Seek,
{
element_reader.lock();
loop {
let res = element_reader.next()?;
match res {
ElementReaderYield::Master((id, size)) => {
// We do not end up using information from any of the nested master
// elements, so we can just skip them.
log::debug!("Skipping EBML master element: {:?}", id);
element_reader.skip(size)?;
element_reader.goto_previous_master()?;
continue;
},
ElementReaderYield::Child((child, size)) => {
match child.ident {
ElementIdent::TimecodeScale => todo!("Support segment.Info.TimecodeScale"),
ElementIdent::MuxingApp => todo!("Support segment.Info.MuxingApp"),
ElementIdent::WritingApp => todo!("Support segment.Info.WritingApp"),
_ => {
// We do not end up using information from all of the segment
// elements, so we can just skip any useless ones.
log::debug!("Skipping EBML child element: {:?}", child);
element_reader.skip(size)?;
continue;
},
}
},
ElementReaderYield::Unknown(element) => {
log::debug!("Skipping unknown EBML element: {:X}", element.id.0);
element_reader.skip(element.size.value())?;
continue;
},
ElementReaderYield::Eof => {
element_reader.unlock();
break;
},
}
}
element_reader.goto_previous_master()?;
Ok(())
}