Skip to content

Commit 257ecde

Browse files
committed
fixing suggestions.
1 parent 0b4b8a3 commit 257ecde

7 files changed

Lines changed: 82 additions & 61 deletions

File tree

examples/typed_sample_tables.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ fn main() -> anyhow::Result<()> {
1919
println!("Analyzing sample tables in: {}", path);
2020
analyze_sample_tables(&boxes, 0);
2121

22+
// Also test the direct parsing example
23+
println!("\nTesting direct parsing example:");
24+
example_direct_parsing()?;
25+
2226
Ok(())
2327
}
2428

@@ -91,15 +95,14 @@ fn analyze_sample_tables(boxes: &[mp4box::Box], depth: usize) {
9195
}
9296

9397
/// Example of how you would access structured data directly from the registry
94-
#[allow(dead_code)]
9598
fn example_direct_parsing() -> anyhow::Result<()> {
9699
use mp4box::boxes::{BoxHeader, FourCC};
97100
use mp4box::registry::{BoxDecoder, SttsDecoder};
98101
use std::io::Cursor;
99102

100103
// Example: Create a mock STTS box data
104+
// Note: version/flags are handled by the main parser, decoder receives only payload
101105
let mock_stts_data = vec![
102-
0, 0, 0, 0, // version + flags
103106
0, 0, 0, 2, // entry_count = 2
104107
0, 0, 0, 100, // sample_count = 100
105108
0, 0, 4, 0, // sample_delta = 1024
@@ -111,13 +114,13 @@ fn example_direct_parsing() -> anyhow::Result<()> {
111114
let header = BoxHeader {
112115
typ: FourCC(*b"stts"),
113116
uuid: None,
114-
size: 32,
117+
size: 28, // 20 bytes data + 8 bytes header
115118
header_size: 8,
116119
start: 0,
117120
};
118121

119122
let decoder = SttsDecoder;
120-
let result = decoder.decode(&mut cursor, &header)?;
123+
let result = decoder.decode(&mut cursor, &header, Some(0), Some(0))?;
121124

122125
match result {
123126
BoxValue::Structured(StructuredData::DecodingTimeToSample(stts_data)) => {

src/api.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,13 @@ fn decode_value<R: Read + Seek>(
193193
}
194194
let mut limited = r.take(len);
195195

196-
if let Some(res) = reg.decode(&key, &mut limited, &b.hdr) {
196+
// Extract version and flags from the box if it's a FullBox
197+
let (version, flags) = match &b.kind {
198+
crate::boxes::NodeKind::FullBox { version, flags, .. } => (Some(*version), Some(*flags)),
199+
_ => (None, None),
200+
};
201+
202+
if let Some(res) = reg.decode(&key, &mut limited, &b.hdr, version, flags) {
197203
match res {
198204
Ok(BoxValue::Text(s)) => (Some(s), None),
199205
Ok(BoxValue::Bytes(bytes)) => (Some(format!("{} bytes", bytes.len())), None),

src/bin/mp4dump.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,13 @@ fn decode_value(f: &mut File, b: &BoxRef, reg: &Registry) -> Option<String> {
235235
}
236236
let mut limited = f.take(len);
237237

238-
if let Some(res) = reg.decode(&key, &mut limited, &b.hdr) {
238+
// Extract version and flags from the box if it's a FullBox
239+
let (version, flags) = match &b.kind {
240+
mp4box::boxes::NodeKind::FullBox { version, flags, .. } => (Some(*version), Some(*flags)),
241+
_ => (None, None),
242+
};
243+
244+
if let Some(res) = reg.decode(&key, &mut limited, &b.hdr, version, flags) {
239245
match res {
240246
Ok(BoxValue::Text(s)) => Some(s),
241247
Ok(BoxValue::Bytes(bytes)) => Some(format!("{} bytes", bytes.len())),

src/registry.rs

Lines changed: 37 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ pub struct HdlrData {
165165
/// A decoder is responsible for interpreting the payload of a specific box
166166
/// (identified by a [`BoxKey`]) and returning a [`BoxValue`].
167167
pub trait BoxDecoder: Send + Sync {
168-
fn decode(&self, r: &mut dyn Read, hdr: &BoxHeader) -> anyhow::Result<BoxValue>;
168+
fn decode(&self, r: &mut dyn Read, hdr: &BoxHeader, version: Option<u8>, flags: Option<u32>) -> anyhow::Result<BoxValue>;
169169
}
170170

171171
/// Registry of decoders keyed by `BoxKey` (4CC or UUID).
@@ -211,8 +211,10 @@ impl Registry {
211211
key: &BoxKey,
212212
r: &mut dyn Read,
213213
hdr: &BoxHeader,
214+
version: Option<u8>,
215+
flags: Option<u32>,
214216
) -> Option<anyhow::Result<BoxValue>> {
215-
self.map.get(key).map(|d| d.inner.decode(r, hdr))
217+
self.map.get(key).map(|d| d.inner.decode(r, hdr, version, flags))
216218
}
217219
}
218220

@@ -246,7 +248,7 @@ fn lang_from_u16(code: u16) -> String {
246248
pub struct FtypDecoder;
247249

248250
impl BoxDecoder for FtypDecoder {
249-
fn decode(&self, r: &mut dyn Read, _hdr: &BoxHeader) -> anyhow::Result<BoxValue> {
251+
fn decode(&self, r: &mut dyn Read, _hdr: &BoxHeader, _version: Option<u8>, _flags: Option<u32>) -> anyhow::Result<BoxValue> {
250252
let buf = read_all(r)?;
251253
if buf.len() < 8 {
252254
return Ok(BoxValue::Text(format!(
@@ -280,7 +282,7 @@ impl BoxDecoder for FtypDecoder {
280282
pub struct MvhdDecoder;
281283

282284
impl BoxDecoder for MvhdDecoder {
283-
fn decode(&self, r: &mut dyn Read, _hdr: &BoxHeader) -> anyhow::Result<BoxValue> {
285+
fn decode(&self, r: &mut dyn Read, _hdr: &BoxHeader, _version: Option<u8>, _flags: Option<u32>) -> anyhow::Result<BoxValue> {
284286
let buf = read_all(r)?;
285287
let mut cur = Cursor::new(&buf);
286288

@@ -316,7 +318,7 @@ impl BoxDecoder for MvhdDecoder {
316318
pub struct TkhdDecoder;
317319

318320
impl BoxDecoder for TkhdDecoder {
319-
fn decode(&self, r: &mut dyn Read, _hdr: &BoxHeader) -> anyhow::Result<BoxValue> {
321+
fn decode(&self, r: &mut dyn Read, _hdr: &BoxHeader, _version: Option<u8>, _flags: Option<u32>) -> anyhow::Result<BoxValue> {
320322
let buf = read_all(r)?;
321323
if buf.len() < 4 {
322324
return Ok(BoxValue::Text(format!(
@@ -426,7 +428,7 @@ impl BoxDecoder for TkhdDecoder {
426428
pub struct MdhdDecoder;
427429

428430
impl BoxDecoder for MdhdDecoder {
429-
fn decode(&self, r: &mut dyn Read, _hdr: &BoxHeader) -> anyhow::Result<BoxValue> {
431+
fn decode(&self, r: &mut dyn Read, _hdr: &BoxHeader, version: Option<u8>, flags: Option<u32>) -> anyhow::Result<BoxValue> {
430432
let creation_time = r.read_u32::<BigEndian>()?;
431433
let modification_time = r.read_u32::<BigEndian>()?;
432434
let timescale = r.read_u32::<BigEndian>()?;
@@ -437,8 +439,8 @@ impl BoxDecoder for MdhdDecoder {
437439
let lang = lang_from_u16(language_code);
438440

439441
let data = MdhdData {
440-
version: 0, // Version/flags are handled by the FullBox parsing layer
441-
flags: 0,
442+
version: version.unwrap_or(0),
443+
flags: flags.unwrap_or(0),
442444
creation_time,
443445
modification_time,
444446
timescale,
@@ -454,7 +456,7 @@ impl BoxDecoder for MdhdDecoder {
454456
pub struct HdlrDecoder;
455457

456458
impl BoxDecoder for HdlrDecoder {
457-
fn decode(&self, r: &mut dyn Read, _hdr: &BoxHeader) -> anyhow::Result<BoxValue> {
459+
fn decode(&self, r: &mut dyn Read, _hdr: &BoxHeader, version: Option<u8>, flags: Option<u32>) -> anyhow::Result<BoxValue> {
458460
use byteorder::{BigEndian, ReadBytesExt};
459461

460462
// pre_defined (4 bytes) + handler_type (4 bytes)
@@ -478,8 +480,8 @@ impl BoxDecoder for HdlrDecoder {
478480
let handler_str = std::str::from_utf8(&handler_type).unwrap_or("????");
479481

480482
let data = HdlrData {
481-
version: 0, // Version/flags are handled by the FullBox parsing layer
482-
flags: 0,
483+
version: version.unwrap_or(0),
484+
flags: flags.unwrap_or(0),
483485
handler_type: handler_str.to_string(),
484486
name,
485487
};
@@ -492,7 +494,7 @@ impl BoxDecoder for HdlrDecoder {
492494
pub struct SidxDecoder;
493495

494496
impl BoxDecoder for SidxDecoder {
495-
fn decode(&self, r: &mut dyn Read, _hdr: &BoxHeader) -> anyhow::Result<BoxValue> {
497+
fn decode(&self, r: &mut dyn Read, _hdr: &BoxHeader, _version: Option<u8>, _flags: Option<u32>) -> anyhow::Result<BoxValue> {
496498
let buf = read_all(r)?;
497499
let mut cur = Cursor::new(&buf);
498500

@@ -531,7 +533,7 @@ impl BoxDecoder for SidxDecoder {
531533
pub struct StsdDecoder;
532534

533535
impl BoxDecoder for StsdDecoder {
534-
fn decode(&self, r: &mut dyn Read, _hdr: &BoxHeader) -> anyhow::Result<BoxValue> {
536+
fn decode(&self, r: &mut dyn Read, _hdr: &BoxHeader, _version: Option<u8>, _flags: Option<u32>) -> anyhow::Result<BoxValue> {
535537
use byteorder::{BigEndian, ReadBytesExt};
536538

537539
// stsd is a FullBox; our reader is already positioned at payload:
@@ -613,7 +615,7 @@ impl BoxDecoder for StsdDecoder {
613615
pub struct SttsDecoder;
614616

615617
impl BoxDecoder for SttsDecoder {
616-
fn decode(&self, r: &mut dyn Read, _hdr: &BoxHeader) -> anyhow::Result<BoxValue> {
618+
fn decode(&self, r: &mut dyn Read, _hdr: &BoxHeader, version: Option<u8>, flags: Option<u32>) -> anyhow::Result<BoxValue> {
617619
let buf = read_all(r)?;
618620
let mut cur = Cursor::new(&buf);
619621

@@ -631,11 +633,9 @@ impl BoxDecoder for SttsDecoder {
631633
});
632634
}
633635

634-
// Note: We don't have access to the actual version/flags here since they're
635-
// parsed separately. We use placeholder values.
636636
let data = SttsData {
637-
version: 0, // Placeholder - actual version parsed separately
638-
flags: 0, // Placeholder - actual flags parsed separately
637+
version: version.unwrap_or(0),
638+
flags: flags.unwrap_or(0),
639639
entry_count,
640640
entries,
641641
};
@@ -650,7 +650,7 @@ impl BoxDecoder for SttsDecoder {
650650
pub struct StssDecoder;
651651

652652
impl BoxDecoder for StssDecoder {
653-
fn decode(&self, r: &mut dyn Read, _hdr: &BoxHeader) -> anyhow::Result<BoxValue> {
653+
fn decode(&self, r: &mut dyn Read, _hdr: &BoxHeader, version: Option<u8>, flags: Option<u32>) -> anyhow::Result<BoxValue> {
654654
let buf = read_all(r)?;
655655
let mut cur = Cursor::new(&buf);
656656

@@ -663,8 +663,8 @@ impl BoxDecoder for StssDecoder {
663663
}
664664

665665
let data = StssData {
666-
version: 0, // Placeholder - actual version parsed separately
667-
flags: 0, // Placeholder - actual flags parsed separately
666+
version: version.unwrap_or(0),
667+
flags: flags.unwrap_or(0),
668668
entry_count,
669669
sample_numbers,
670670
};
@@ -677,7 +677,7 @@ impl BoxDecoder for StssDecoder {
677677
pub struct CttsDecoder;
678678

679679
impl BoxDecoder for CttsDecoder {
680-
fn decode(&self, r: &mut dyn Read, _hdr: &BoxHeader) -> anyhow::Result<BoxValue> {
680+
fn decode(&self, r: &mut dyn Read, _hdr: &BoxHeader, version: Option<u8>, flags: Option<u32>) -> anyhow::Result<BoxValue> {
681681
let buf = read_all(r)?;
682682
let mut cur = Cursor::new(&buf);
683683

@@ -697,8 +697,8 @@ impl BoxDecoder for CttsDecoder {
697697
}
698698

699699
let data = CttsData {
700-
version: 0, // Placeholder - actual version parsed separately
701-
flags: 0, // Placeholder - actual flags parsed separately
700+
version: version.unwrap_or(0),
701+
flags: flags.unwrap_or(0),
702702
entry_count,
703703
entries,
704704
};
@@ -713,7 +713,7 @@ impl BoxDecoder for CttsDecoder {
713713
pub struct StscDecoder;
714714

715715
impl BoxDecoder for StscDecoder {
716-
fn decode(&self, r: &mut dyn Read, _hdr: &BoxHeader) -> anyhow::Result<BoxValue> {
716+
fn decode(&self, r: &mut dyn Read, _hdr: &BoxHeader, version: Option<u8>, flags: Option<u32>) -> anyhow::Result<BoxValue> {
717717
let buf = read_all(r)?;
718718
let mut cur = Cursor::new(&buf);
719719

@@ -733,8 +733,8 @@ impl BoxDecoder for StscDecoder {
733733
}
734734

735735
let data = StscData {
736-
version: 0, // Placeholder - actual version parsed separately
737-
flags: 0, // Placeholder - actual flags parsed separately
736+
version: version.unwrap_or(0),
737+
flags: flags.unwrap_or(0),
738738
entry_count,
739739
entries,
740740
};
@@ -747,7 +747,7 @@ impl BoxDecoder for StscDecoder {
747747
pub struct StszDecoder;
748748

749749
impl BoxDecoder for StszDecoder {
750-
fn decode(&self, r: &mut dyn Read, _hdr: &BoxHeader) -> anyhow::Result<BoxValue> {
750+
fn decode(&self, r: &mut dyn Read, _hdr: &BoxHeader, version: Option<u8>, flags: Option<u32>) -> anyhow::Result<BoxValue> {
751751
let buf = read_all(r)?;
752752
let mut cur = Cursor::new(&buf);
753753

@@ -764,8 +764,8 @@ impl BoxDecoder for StszDecoder {
764764
}
765765

766766
let data = StszData {
767-
version: 0, // Placeholder - actual version parsed separately
768-
flags: 0, // Placeholder - actual flags parsed separately
767+
version: version.unwrap_or(0),
768+
flags: flags.unwrap_or(0),
769769
sample_size,
770770
sample_count,
771771
sample_sizes,
@@ -779,7 +779,7 @@ impl BoxDecoder for StszDecoder {
779779
pub struct StcoDecoder;
780780

781781
impl BoxDecoder for StcoDecoder {
782-
fn decode(&self, r: &mut dyn Read, _hdr: &BoxHeader) -> anyhow::Result<BoxValue> {
782+
fn decode(&self, r: &mut dyn Read, _hdr: &BoxHeader, version: Option<u8>, flags: Option<u32>) -> anyhow::Result<BoxValue> {
783783
let buf = read_all(r)?;
784784
let mut cur = Cursor::new(&buf);
785785

@@ -792,8 +792,8 @@ impl BoxDecoder for StcoDecoder {
792792
}
793793

794794
let data = StcoData {
795-
version: 0, // Placeholder - actual version parsed separately
796-
flags: 0, // Placeholder - actual flags parsed separately
795+
version: version.unwrap_or(0),
796+
flags: flags.unwrap_or(0),
797797
entry_count,
798798
chunk_offsets,
799799
};
@@ -806,7 +806,7 @@ impl BoxDecoder for StcoDecoder {
806806
pub struct Co64Decoder;
807807

808808
impl BoxDecoder for Co64Decoder {
809-
fn decode(&self, r: &mut dyn Read, _hdr: &BoxHeader) -> anyhow::Result<BoxValue> {
809+
fn decode(&self, r: &mut dyn Read, _hdr: &BoxHeader, version: Option<u8>, flags: Option<u32>) -> anyhow::Result<BoxValue> {
810810
let buf = read_all(r)?;
811811
let mut cur = Cursor::new(&buf);
812812

@@ -819,8 +819,8 @@ impl BoxDecoder for Co64Decoder {
819819
}
820820

821821
let data = Co64Data {
822-
version: 0, // Placeholder - actual version parsed separately
823-
flags: 0, // Placeholder - actual flags parsed separately
822+
version: version.unwrap_or(0),
823+
flags: flags.unwrap_or(0),
824824
entry_count,
825825
chunk_offsets,
826826
};
@@ -833,7 +833,7 @@ impl BoxDecoder for Co64Decoder {
833833
pub struct ElstDecoder;
834834

835835
impl BoxDecoder for ElstDecoder {
836-
fn decode(&self, r: &mut dyn Read, _hdr: &BoxHeader) -> anyhow::Result<BoxValue> {
836+
fn decode(&self, r: &mut dyn Read, _hdr: &BoxHeader, _version: Option<u8>, _flags: Option<u32>) -> anyhow::Result<BoxValue> {
837837
let buf = read_all(r)?;
838838
if buf.len() < 8 {
839839
return Ok(BoxValue::Text(format!(

src/samples.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -614,17 +614,19 @@ fn get_sample_file_offset(tables: &SampleTables, sample_index: u32) -> u64 {
614614

615615
samples_per_chunk = entry.samples_per_chunk;
616616
let chunks_with_this_config = next_first_chunk - entry.first_chunk;
617-
let samples_in_this_range = chunks_with_this_config * samples_per_chunk;
617+
let samples_in_this_range = (chunks_with_this_config as u64)
618+
.saturating_mul(samples_per_chunk as u64);
618619

619-
if current_sample + samples_in_this_range > target_sample {
620+
if (current_sample as u64) + samples_in_this_range > target_sample as u64 {
620621
// Target sample is in this range
622+
// First, find the chunk containing the sample within this range
621623
let sample_offset_in_range = target_sample - current_sample;
622-
chunk_index = (entry.first_chunk - 1) as usize
623-
+ (sample_offset_in_range / samples_per_chunk) as usize;
624+
let chunk_offset_in_range = sample_offset_in_range / samples_per_chunk;
625+
chunk_index = (entry.first_chunk - 1) as usize + chunk_offset_in_range as usize;
624626
break;
625627
}
626628

627-
current_sample += samples_in_this_range;
629+
current_sample = (current_sample as u64 + samples_in_this_range).min(u32::MAX as u64) as u32;
628630
}
629631

630632
if chunk_index >= chunk_offsets.len() {
@@ -635,11 +637,15 @@ fn get_sample_file_offset(tables: &SampleTables, sample_index: u32) -> u64 {
635637
let chunk_offset = chunk_offsets[chunk_index];
636638

637639
// Calculate which sample within the chunk we want
638-
let sample_in_chunk = ((target_sample - current_sample) % samples_per_chunk) as usize;
640+
// Need to recalculate since we need the offset within the specific chunk
641+
let sample_offset_in_range = target_sample - current_sample;
642+
let chunk_offset_in_range = sample_offset_in_range / samples_per_chunk;
643+
let sample_in_chunk = (sample_offset_in_range % samples_per_chunk) as usize;
639644

640645
// Sum up the sizes of preceding samples in this chunk to get the offset within chunk
641646
let mut offset_in_chunk = 0u64;
642-
let chunk_start_sample = current_sample as usize;
647+
// The chunk_start_sample is the first sample in this specific chunk (0-based for array indexing)
648+
let chunk_start_sample = (current_sample - 1 + chunk_offset_in_range * samples_per_chunk) as usize;
643649

644650
// Handle both fixed and variable sample sizes
645651
if stsz.sample_size > 0 {

tests/registry_ftyp.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::io::Read;
55
struct DummyDecoder;
66

77
impl BoxDecoder for DummyDecoder {
8-
fn decode(&self, r: &mut dyn Read, _hdr: &BoxHeader) -> anyhow::Result<BoxValue> {
8+
fn decode(&self, r: &mut dyn Read, _hdr: &BoxHeader, _version: Option<u8>, _flags: Option<u32>) -> anyhow::Result<BoxValue> {
99
let mut buf = Vec::new();
1010
r.read_to_end(&mut buf)?;
1111
Ok(BoxValue::Bytes(buf))
@@ -31,7 +31,7 @@ fn registry_invokes_decoder() {
3131
let payload = &[1u8, 2, 3, 4];
3232
let mut cursor = std::io::Cursor::new(payload.to_vec());
3333

34-
let res = reg.decode(&BoxKey::FourCC(FourCC(*b"test")), &mut cursor, &hdr);
34+
let res = reg.decode(&BoxKey::FourCC(FourCC(*b"test")), &mut cursor, &hdr, None, None);
3535
assert!(res.is_some());
3636

3737
match res.unwrap().unwrap() {

0 commit comments

Comments
 (0)