mirror of
https://github.com/Serial-ATA/lofty-rs
synced 2024-12-14 22:52:32 +00:00
MP4: Make AtomReader act relatively
This commit is contained in:
parent
2271266dd4
commit
f422444848
1 changed files with 31 additions and 19 deletions
|
@ -5,6 +5,7 @@ use super::Mp4File;
|
||||||
use crate::error::{ErrorKind, LoftyError, Result};
|
use crate::error::{ErrorKind, LoftyError, Result};
|
||||||
use crate::macros::{decode_err, err};
|
use crate::macros::{decode_err, err};
|
||||||
use crate::probe::ParseOptions;
|
use crate::probe::ParseOptions;
|
||||||
|
use crate::traits::SeekStreamLen;
|
||||||
|
|
||||||
use std::io::{Read, Seek, SeekFrom};
|
use std::io::{Read, Seek, SeekFrom};
|
||||||
|
|
||||||
|
@ -15,6 +16,7 @@ where
|
||||||
R: Read + Seek,
|
R: Read + Seek,
|
||||||
{
|
{
|
||||||
reader: R,
|
reader: R,
|
||||||
|
start: u64,
|
||||||
remaining_size: u64,
|
remaining_size: u64,
|
||||||
len: u64,
|
len: u64,
|
||||||
}
|
}
|
||||||
|
@ -24,18 +26,18 @@ where
|
||||||
R: Read + Seek,
|
R: Read + Seek,
|
||||||
{
|
{
|
||||||
pub(super) fn new(mut reader: R) -> Result<Self> {
|
pub(super) fn new(mut reader: R) -> Result<Self> {
|
||||||
use crate::traits::SeekStreamLen;
|
|
||||||
|
|
||||||
#[allow(unstable_name_collisions)]
|
#[allow(unstable_name_collisions)]
|
||||||
let len = reader.stream_len()?;
|
let len = reader.stream_len()?;
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
reader,
|
reader,
|
||||||
|
start: 0,
|
||||||
remaining_size: len,
|
remaining_size: len,
|
||||||
len,
|
len,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn reset_length(&mut self, len: u64) {
|
pub(super) fn reset_bounds(&mut self, start_position: u64, len: u64) {
|
||||||
|
self.start = start_position;
|
||||||
self.remaining_size = len;
|
self.remaining_size = len;
|
||||||
self.len = len;
|
self.len = len;
|
||||||
}
|
}
|
||||||
|
@ -84,13 +86,30 @@ where
|
||||||
{
|
{
|
||||||
fn seek(&mut self, pos: SeekFrom) -> std::io::Result<u64> {
|
fn seek(&mut self, pos: SeekFrom) -> std::io::Result<u64> {
|
||||||
match pos {
|
match pos {
|
||||||
SeekFrom::Start(_) | SeekFrom::End(_) => {
|
SeekFrom::Start(s) => {
|
||||||
let ret = self.reader.seek(pos)?;
|
if s > self.len {
|
||||||
let new_rem = self.len.saturating_sub(ret);
|
self.remaining_size = 0;
|
||||||
|
|
||||||
self.remaining_size = new_rem;
|
let bound_end = self.start + self.len;
|
||||||
|
return self.reader.seek(SeekFrom::Start(bound_end));
|
||||||
|
}
|
||||||
|
|
||||||
|
let ret = self.reader.seek(SeekFrom::Start(self.start + s))?;
|
||||||
|
self.remaining_size = self.len.saturating_sub(ret);
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
},
|
},
|
||||||
|
SeekFrom::End(s) => {
|
||||||
|
if s.is_positive() || s == 0 {
|
||||||
|
self.remaining_size = 0;
|
||||||
|
return self.reader.seek(SeekFrom::Start(self.start + self.len));
|
||||||
|
}
|
||||||
|
|
||||||
|
let bound_end = self.start + self.len;
|
||||||
|
let relative_seek_count = core::cmp::min(self.len, s.unsigned_abs());
|
||||||
|
self.reader.seek(SeekFrom::Start(
|
||||||
|
bound_end.saturating_sub(relative_seek_count),
|
||||||
|
))
|
||||||
|
},
|
||||||
SeekFrom::Current(s) => {
|
SeekFrom::Current(s) => {
|
||||||
if s.is_negative() {
|
if s.is_negative() {
|
||||||
self.remaining_size = self.remaining_size.saturating_add(s.unsigned_abs());
|
self.remaining_size = self.remaining_size.saturating_add(s.unsigned_abs());
|
||||||
|
@ -102,10 +121,6 @@ where
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stream_position(&mut self) -> std::io::Result<u64> {
|
|
||||||
self.position()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R> Read for AtomReader<R>
|
impl<R> Read for AtomReader<R>
|
||||||
|
@ -154,23 +169,22 @@ where
|
||||||
R: Read + Seek,
|
R: Read + Seek,
|
||||||
{
|
{
|
||||||
let mut reader = AtomReader::new(data)?;
|
let mut reader = AtomReader::new(data)?;
|
||||||
|
let file_length = reader.stream_len()?;
|
||||||
|
|
||||||
let ftyp = verify_mp4(&mut reader)?;
|
let ftyp = verify_mp4(&mut reader)?;
|
||||||
|
|
||||||
// Find the `moov` atom and restrict the reader to its length
|
// Find the `moov` atom and restrict the reader to its length
|
||||||
let moov_info = Moov::find(&mut reader)?;
|
let moov_info = Moov::find(&mut reader)?;
|
||||||
reader.reset_length(moov_info.len - 8);
|
reader.reset_bounds(moov_info.start + 8, moov_info.len - 8);
|
||||||
|
|
||||||
let moov = Moov::parse(&mut reader, parse_options.read_properties)?;
|
let moov = Moov::parse(&mut reader, parse_options.read_properties)?;
|
||||||
|
|
||||||
let file_length = reader.seek(SeekFrom::End(0))?;
|
|
||||||
|
|
||||||
Ok(Mp4File {
|
Ok(Mp4File {
|
||||||
ftyp,
|
ftyp,
|
||||||
ilst_tag: moov.meta,
|
ilst_tag: moov.meta,
|
||||||
properties: if parse_options.read_properties {
|
properties: if parse_options.read_properties {
|
||||||
// Remove the length restriction
|
// Remove the length restriction
|
||||||
reader.reset_length(file_length);
|
reader.reset_bounds(0, file_length);
|
||||||
super::properties::read_properties(&mut reader, &moov.traks, file_length)?
|
super::properties::read_properties(&mut reader, &moov.traks, file_length)?
|
||||||
} else {
|
} else {
|
||||||
Mp4Properties::default()
|
Mp4Properties::default()
|
||||||
|
@ -265,8 +279,6 @@ pub(super) fn meta_is_full<R>(reader: &mut R) -> Result<bool>
|
||||||
where
|
where
|
||||||
R: Read + Seek,
|
R: Read + Seek,
|
||||||
{
|
{
|
||||||
let meta_pos = reader.stream_position()?;
|
|
||||||
|
|
||||||
// A full `meta` atom should have the following:
|
// A full `meta` atom should have the following:
|
||||||
//
|
//
|
||||||
// Version (1)
|
// Version (1)
|
||||||
|
@ -282,11 +294,11 @@ where
|
||||||
|
|
||||||
match &possible_ident {
|
match &possible_ident {
|
||||||
b"hdlr" | b"ilst" | b"mhdr" | b"ctry" | b"lang" => {
|
b"hdlr" | b"ilst" | b"mhdr" | b"ctry" | b"lang" => {
|
||||||
reader.seek(SeekFrom::Start(meta_pos))?;
|
reader.seek(SeekFrom::Current(-8))?;
|
||||||
Ok(false)
|
Ok(false)
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
reader.seek(SeekFrom::Start(meta_pos + 4))?;
|
reader.seek(SeekFrom::Current(-4))?;
|
||||||
Ok(true)
|
Ok(true)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue