-
Notifications
You must be signed in to change notification settings - Fork 13
feat: Collects unexpected boxes during decoding #81
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This change introduces the ability to collect and retain any unexpected boxes encountered during the decoding process. Previously, the decoder would give an Error::unexpectedBox and failing the decode process. Now, these boxes are stored in a `unexpected` Vec within their parent structures (Moov, Trak, Mdia, Minf, Stbl, etc.). This allows for more robust handling of malformed or extended MP4 files, as the application can now inspect and process unexpected boxes as needed.
Adds documentation to README and library root regarding the fault-tolerant parsing feature. This explains how unexpected child boxes are handled during decoding and clarifies that they are not written back during encoding.
cargo fmt don't work for some reason.
Implements a new `fault-tolerant` feature that enables parsing of MP4 files with unexpected boxes. Updates documentation and tests to reflect the feature.
Introduces tests to verify the behavior of the fault-tolerant feature. When enabled, the feature collects unexpected boxes during decoding. When disabled, encountering unexpected boxes results in an error. Also adds tests for multiple unexpected boxes and ensures that unexpected boxes are not encoded.
|
@b01o if you have a chance, can you check that I didn't break your intent in the fixup. If no capacity, OK, just flag that. |
|
@kixelated Are you good with the fault-tolerant feature being default? |
WalkthroughAdds a new Cargo feature Pre-merge checks and finishing touches✅ Passed checks (5 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: Organization UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (4)
✅ Files skipped from review due to trivial changes (1)
🚧 Files skipped from review as they are similar to previous changes (2)
🧰 Additional context used🧠 Learnings (1)📚 Learning: 2025-08-31T04:06:57.364ZApplied to files:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/meta/iprp.rs (1)
6-22: Critical issue:unexpectedfield is decoded but never encoded, causing data loss.The
nested!macro correctly populates theunexpectedfield during decoding whenfault-tolerantis enabled (lines 204-207), but theencode_bodyfunction (lines 226-229) completely omits this field from encoding. This breaks the decode/encode symmetry required by the Atom trait and defeats the purpose of fault-tolerant mode—unexpected boxes are silently discarded when re-encoding. The macro must be updated to encode theunexpectedfield back to the buffer.src/moov/trak/mdia/minf/stbl/stsd/mp4a/mod.rs (1)
58-66:taicfield is not encoded.The
encode_bodymethod encodesaudio,esds, and optionallybtrt, but thetaicfield (line 13) is never encoded. This appears to be a pre-existing omission unrelated to the fault-tolerant changes.🔎 Proposed fix to encode taic
fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> { self.audio.encode(buf)?; self.esds.encode(buf)?; if self.btrt.is_some() { self.btrt.encode(buf)?; } + if self.taic.is_some() { + self.taic.encode(buf)?; + } Ok(()) }
🧹 Nitpick comments (1)
src/moov/trak/mdia/minf/stbl/stsd/opus.rs (1)
22-23: Consider updating the comment.The comment "Find esds in mp4a or wave" appears to be a copy-paste artifact from another file. For Opus, the loop is looking for
dOps, notesds.Suggested fix
- // Find esds in mp4a or wave + // Find dOps child box while let Some(atom) = Any::decode_maybe(buf)? {
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (43)
Cargo.tomlREADME.mdjustfilesrc/atom.rssrc/lib.rssrc/meta/iprp.rssrc/meta/mod.rssrc/moof/mod.rssrc/moof/traf/mod.rssrc/moov/mod.rssrc/moov/mvex/mod.rssrc/moov/trak/edts/mod.rssrc/moov/trak/mdia/minf/dinf/mod.rssrc/moov/trak/mdia/minf/mod.rssrc/moov/trak/mdia/minf/stbl/mod.rssrc/moov/trak/mdia/minf/stbl/stsd/ac3.rssrc/moov/trak/mdia/minf/stbl/stsd/av01.rssrc/moov/trak/mdia/minf/stbl/stsd/eac3.rssrc/moov/trak/mdia/minf/stbl/stsd/flac.rssrc/moov/trak/mdia/minf/stbl/stsd/h264/avc1.rssrc/moov/trak/mdia/minf/stbl/stsd/hevc/hev1.rssrc/moov/trak/mdia/minf/stbl/stsd/hevc/hvc1.rssrc/moov/trak/mdia/minf/stbl/stsd/hevc/hvcc.rssrc/moov/trak/mdia/minf/stbl/stsd/mod.rssrc/moov/trak/mdia/minf/stbl/stsd/mp4a/mod.rssrc/moov/trak/mdia/minf/stbl/stsd/opus.rssrc/moov/trak/mdia/minf/stbl/stsd/uncv.rssrc/moov/trak/mdia/minf/stbl/stsd/vp9/vp08.rssrc/moov/trak/mdia/minf/stbl/stsd/vp9/vp09.rssrc/moov/trak/mdia/mod.rssrc/moov/trak/mod.rssrc/moov/udta/mod.rssrc/test/av1.rssrc/test/bbb.rssrc/test/esds.rssrc/test/fault_tolerant.rssrc/test/flac.rssrc/test/h264.rssrc/test/heif.rssrc/test/hevc.rssrc/test/mod.rssrc/test/uncompressed.rssrc/test/vp9.rs
🧰 Additional context used
📓 Path-based instructions (6)
**/*.rs
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.rs: Code must be clippy-clean (cargo clippy --all-targets --all-features -- -D warnings)
Code must be formatted with rustfmt (cargo fmt) and pass formatting checks (cargo fmt -- --check)
Write unit tests inline within modules using #[cfg(test)]
Files:
src/test/mod.rssrc/moov/trak/edts/mod.rssrc/meta/iprp.rssrc/moov/trak/mdia/minf/stbl/mod.rssrc/moov/trak/mdia/minf/dinf/mod.rssrc/moov/trak/mdia/minf/stbl/stsd/opus.rssrc/atom.rssrc/moov/trak/mdia/minf/mod.rssrc/moov/trak/mdia/minf/stbl/stsd/uncv.rssrc/moov/trak/mdia/minf/stbl/stsd/ac3.rssrc/moov/trak/mdia/mod.rssrc/test/hevc.rssrc/moof/traf/mod.rssrc/moof/mod.rssrc/moov/trak/mdia/minf/stbl/stsd/flac.rssrc/moov/trak/mdia/minf/stbl/stsd/hevc/hev1.rssrc/moov/trak/mod.rssrc/moov/trak/mdia/minf/stbl/stsd/mp4a/mod.rssrc/moov/trak/mdia/minf/stbl/stsd/mod.rssrc/moov/udta/mod.rssrc/moov/trak/mdia/minf/stbl/stsd/vp9/vp08.rssrc/moov/trak/mdia/minf/stbl/stsd/vp9/vp09.rssrc/moov/trak/mdia/minf/stbl/stsd/hevc/hvc1.rssrc/test/flac.rssrc/test/fault_tolerant.rssrc/test/uncompressed.rssrc/lib.rssrc/moov/mvex/mod.rssrc/test/av1.rssrc/test/bbb.rssrc/test/esds.rssrc/moov/trak/mdia/minf/stbl/stsd/h264/avc1.rssrc/test/vp9.rssrc/moov/trak/mdia/minf/stbl/stsd/av01.rssrc/moov/trak/mdia/minf/stbl/stsd/eac3.rssrc/test/heif.rssrc/test/h264.rssrc/moov/trak/mdia/minf/stbl/stsd/hevc/hvcc.rssrc/meta/mod.rssrc/moov/mod.rs
src/**/*.rs
📄 CodeRabbit inference engine (CLAUDE.md)
src/**/*.rs: Each MP4 atom type must implement the Atom trait with KIND, decode_body(), and encode_body()
Use Header::read_from() to handle large atoms without loading entire contents into memory
All operations should return Result using custom error types defined in error.rs
Use the custom Buf/BufMut traits for contiguous byte slices instead of ad-hoc buffer handling
Files:
src/test/mod.rssrc/moov/trak/edts/mod.rssrc/meta/iprp.rssrc/moov/trak/mdia/minf/stbl/mod.rssrc/moov/trak/mdia/minf/dinf/mod.rssrc/moov/trak/mdia/minf/stbl/stsd/opus.rssrc/atom.rssrc/moov/trak/mdia/minf/mod.rssrc/moov/trak/mdia/minf/stbl/stsd/uncv.rssrc/moov/trak/mdia/minf/stbl/stsd/ac3.rssrc/moov/trak/mdia/mod.rssrc/test/hevc.rssrc/moof/traf/mod.rssrc/moof/mod.rssrc/moov/trak/mdia/minf/stbl/stsd/flac.rssrc/moov/trak/mdia/minf/stbl/stsd/hevc/hev1.rssrc/moov/trak/mod.rssrc/moov/trak/mdia/minf/stbl/stsd/mp4a/mod.rssrc/moov/trak/mdia/minf/stbl/stsd/mod.rssrc/moov/udta/mod.rssrc/moov/trak/mdia/minf/stbl/stsd/vp9/vp08.rssrc/moov/trak/mdia/minf/stbl/stsd/vp9/vp09.rssrc/moov/trak/mdia/minf/stbl/stsd/hevc/hvc1.rssrc/test/flac.rssrc/test/fault_tolerant.rssrc/test/uncompressed.rssrc/lib.rssrc/moov/mvex/mod.rssrc/test/av1.rssrc/test/bbb.rssrc/test/esds.rssrc/moov/trak/mdia/minf/stbl/stsd/h264/avc1.rssrc/test/vp9.rssrc/moov/trak/mdia/minf/stbl/stsd/av01.rssrc/moov/trak/mdia/minf/stbl/stsd/eac3.rssrc/test/heif.rssrc/test/h264.rssrc/moov/trak/mdia/minf/stbl/stsd/hevc/hvcc.rssrc/meta/mod.rssrc/moov/mod.rs
src/test/**
📄 CodeRabbit inference engine (CLAUDE.md)
Put integration tests under src/test/ with sample MP4 files for different codecs
Files:
src/test/mod.rssrc/test/hevc.rssrc/test/flac.rssrc/test/fault_tolerant.rssrc/test/uncompressed.rssrc/test/av1.rssrc/test/bbb.rssrc/test/esds.rssrc/test/vp9.rssrc/test/heif.rssrc/test/h264.rs
src/moov/**
📄 CodeRabbit inference engine (CLAUDE.md)
Place movie metadata atom implementations under src/moov/ (and its hierarchy: trak/mdia/minf/stbl/stsd)
Files:
src/moov/trak/edts/mod.rssrc/moov/trak/mdia/minf/stbl/mod.rssrc/moov/trak/mdia/minf/dinf/mod.rssrc/moov/trak/mdia/minf/stbl/stsd/opus.rssrc/moov/trak/mdia/minf/mod.rssrc/moov/trak/mdia/minf/stbl/stsd/uncv.rssrc/moov/trak/mdia/minf/stbl/stsd/ac3.rssrc/moov/trak/mdia/mod.rssrc/moov/trak/mdia/minf/stbl/stsd/flac.rssrc/moov/trak/mdia/minf/stbl/stsd/hevc/hev1.rssrc/moov/trak/mod.rssrc/moov/trak/mdia/minf/stbl/stsd/mp4a/mod.rssrc/moov/trak/mdia/minf/stbl/stsd/mod.rssrc/moov/udta/mod.rssrc/moov/trak/mdia/minf/stbl/stsd/vp9/vp08.rssrc/moov/trak/mdia/minf/stbl/stsd/vp9/vp09.rssrc/moov/trak/mdia/minf/stbl/stsd/hevc/hvc1.rssrc/moov/mvex/mod.rssrc/moov/trak/mdia/minf/stbl/stsd/h264/avc1.rssrc/moov/trak/mdia/minf/stbl/stsd/av01.rssrc/moov/trak/mdia/minf/stbl/stsd/eac3.rssrc/moov/trak/mdia/minf/stbl/stsd/hevc/hvcc.rssrc/moov/mod.rs
src/meta/**
📄 CodeRabbit inference engine (CLAUDE.md)
Place metadata (HEIF/AVIF) atom implementations under src/meta/
Files:
src/meta/iprp.rssrc/meta/mod.rs
src/moof/**
📄 CodeRabbit inference engine (CLAUDE.md)
Place movie fragment atom implementations under src/moof/
Files:
src/moof/traf/mod.rssrc/moof/mod.rs
🧠 Learnings (10)
📓 Common learnings
Learnt from: CR
Repo: kixelated/mp4-atom PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-08-31T04:06:57.364Z
Learning: Applies to src/**/*.rs : Each MP4 atom type must implement the Atom trait with KIND, decode_body(), and encode_body()
Learnt from: CR
Repo: kixelated/mp4-atom PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-08-31T04:06:57.364Z
Learning: Applies to src/any.rs : Register new atom types in the Any enum (src/any.rs) to enable flexible decoding
📚 Learning: 2025-08-31T04:06:57.364Z
Learnt from: CR
Repo: kixelated/mp4-atom PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-08-31T04:06:57.364Z
Learning: Applies to **/*.rs : Write unit tests inline within modules using #[cfg(test)]
Applied to files:
src/test/mod.rssrc/test/fault_tolerant.rs
📚 Learning: 2025-08-31T04:06:57.364Z
Learnt from: CR
Repo: kixelated/mp4-atom PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-08-31T04:06:57.364Z
Learning: Applies to src/any.rs : Register new atom types in the Any enum (src/any.rs) to enable flexible decoding
Applied to files:
src/moov/trak/edts/mod.rssrc/meta/iprp.rssrc/moov/trak/mdia/minf/stbl/mod.rssrc/moov/trak/mdia/minf/dinf/mod.rssrc/moov/trak/mdia/minf/stbl/stsd/opus.rsREADME.mdsrc/atom.rssrc/moov/trak/mdia/minf/mod.rssrc/moov/trak/mdia/minf/stbl/stsd/uncv.rssrc/moov/trak/mdia/minf/stbl/stsd/ac3.rssrc/moov/trak/mdia/mod.rssrc/moof/traf/mod.rssrc/moof/mod.rssrc/moov/trak/mdia/minf/stbl/stsd/flac.rssrc/moov/trak/mdia/minf/stbl/stsd/hevc/hev1.rssrc/moov/trak/mod.rssrc/moov/trak/mdia/minf/stbl/stsd/mp4a/mod.rssrc/moov/udta/mod.rssrc/moov/trak/mdia/minf/stbl/stsd/vp9/vp08.rssrc/moov/trak/mdia/minf/stbl/stsd/vp9/vp09.rssrc/moov/trak/mdia/minf/stbl/stsd/hevc/hvc1.rssrc/lib.rssrc/moov/mvex/mod.rssrc/moov/trak/mdia/minf/stbl/stsd/h264/avc1.rssrc/test/vp9.rssrc/moov/trak/mdia/minf/stbl/stsd/av01.rssrc/moov/trak/mdia/minf/stbl/stsd/eac3.rssrc/moov/mod.rs
📚 Learning: 2025-08-31T04:06:57.364Z
Learnt from: CR
Repo: kixelated/mp4-atom PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-08-31T04:06:57.364Z
Learning: Applies to src/**/*.rs : Each MP4 atom type must implement the Atom trait with KIND, decode_body(), and encode_body()
Applied to files:
src/moov/trak/edts/mod.rssrc/moov/trak/mdia/minf/stbl/stsd/opus.rsREADME.mdsrc/atom.rssrc/moov/trak/mdia/minf/mod.rssrc/moov/trak/mdia/minf/stbl/stsd/uncv.rssrc/moov/trak/mdia/minf/stbl/stsd/ac3.rssrc/moov/trak/mdia/mod.rssrc/test/hevc.rssrc/moof/mod.rssrc/moov/trak/mdia/minf/stbl/stsd/flac.rssrc/moov/trak/mdia/minf/stbl/stsd/hevc/hev1.rssrc/moov/trak/mod.rssrc/moov/trak/mdia/minf/stbl/stsd/mp4a/mod.rssrc/moov/trak/mdia/minf/stbl/stsd/mod.rssrc/moov/udta/mod.rssrc/moov/trak/mdia/minf/stbl/stsd/vp9/vp08.rssrc/moov/trak/mdia/minf/stbl/stsd/vp9/vp09.rssrc/moov/trak/mdia/minf/stbl/stsd/hevc/hvc1.rssrc/lib.rssrc/moov/mvex/mod.rssrc/moov/trak/mdia/minf/stbl/stsd/h264/avc1.rssrc/test/vp9.rssrc/moov/trak/mdia/minf/stbl/stsd/av01.rssrc/moov/trak/mdia/minf/stbl/stsd/eac3.rssrc/test/h264.rssrc/moov/mod.rs
📚 Learning: 2025-08-31T04:06:57.364Z
Learnt from: CR
Repo: kixelated/mp4-atom PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-08-31T04:06:57.364Z
Learning: Applies to src/**/*.rs : Use Header::read_from() to handle large atoms without loading entire contents into memory
Applied to files:
README.mdsrc/atom.rssrc/moov/trak/mdia/minf/stbl/stsd/uncv.rssrc/moov/trak/mdia/mod.rssrc/moov/trak/mdia/minf/stbl/stsd/flac.rssrc/moov/trak/mdia/minf/stbl/stsd/hevc/hev1.rssrc/moov/trak/mdia/minf/stbl/stsd/mp4a/mod.rssrc/moov/trak/mdia/minf/stbl/stsd/hevc/hvc1.rssrc/lib.rssrc/moov/trak/mdia/minf/stbl/stsd/h264/avc1.rssrc/moov/trak/mdia/minf/stbl/stsd/av01.rs
📚 Learning: 2025-08-31T04:06:57.364Z
Learnt from: CR
Repo: kixelated/mp4-atom PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-08-31T04:06:57.364Z
Learning: Applies to src/moov/** : Place movie metadata atom implementations under src/moov/ (and its hierarchy: trak/mdia/minf/stbl/stsd)
Applied to files:
src/test/hevc.rssrc/moov/trak/mdia/minf/stbl/stsd/mp4a/mod.rssrc/moov/trak/mdia/minf/stbl/stsd/h264/avc1.rssrc/test/h264.rs
📚 Learning: 2025-08-31T04:06:57.364Z
Learnt from: CR
Repo: kixelated/mp4-atom PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-08-31T04:06:57.364Z
Learning: Applies to src/moof/** : Place movie fragment atom implementations under src/moof/
Applied to files:
src/moof/mod.rs
📚 Learning: 2025-08-31T04:06:57.364Z
Learnt from: CR
Repo: kixelated/mp4-atom PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-08-31T04:06:57.364Z
Learning: Applies to **/*.rs : Code must be formatted with rustfmt (cargo fmt) and pass formatting checks (cargo fmt -- --check)
Applied to files:
justfile
📚 Learning: 2025-08-31T04:06:57.364Z
Learnt from: CR
Repo: kixelated/mp4-atom PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-08-31T04:06:57.364Z
Learning: Applies to **/*.rs : Code must be clippy-clean (cargo clippy --all-targets --all-features -- -D warnings)
Applied to files:
justfile
📚 Learning: 2025-08-31T04:06:57.364Z
Learnt from: CR
Repo: kixelated/mp4-atom PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-08-31T04:06:57.364Z
Learning: Applies to src/tokio/**/*.rs : For async IO (with the tokio feature), implement and use AsyncReadFrom and AsyncWriteTo traits
Applied to files:
Cargo.toml
🧬 Code graph analysis (7)
src/test/hevc.rs (3)
src/moov/trak/mdia/minf/stbl/stsd/mod.rs (1)
decode(115-144)src/types.rs (9)
decode(74-76)decode(97-99)decode(140-142)decode(203-208)decode(282-290)decode(321-325)new(18-20)new(189-191)new(300-302)src/moov/trak/mdia/minf/stbl/stsd/pasp.rs (1)
new(11-16)
src/moov/trak/mdia/minf/stbl/stsd/hevc/hev1.rs (1)
src/atom.rs (1)
decode_maybe(41-68)
src/moov/trak/mdia/minf/stbl/stsd/mp4a/mod.rs (1)
src/coding.rs (1)
decode_maybe(31-31)
src/moov/trak/mdia/minf/stbl/stsd/hevc/hvc1.rs (2)
src/atom.rs (1)
decode_maybe(41-68)src/coding.rs (1)
decode_maybe(31-31)
src/test/fault_tolerant.rs (1)
src/meta/mod.rs (1)
decoded(344-344)
src/moov/trak/mdia/minf/stbl/stsd/h264/avc1.rs (2)
src/atom.rs (1)
decode_maybe(41-68)src/coding.rs (1)
decode_maybe(31-31)
src/moov/trak/mdia/minf/stbl/stsd/av01.rs (1)
src/atom.rs (1)
decode_maybe(41-68)
🔇 Additional comments (71)
src/moov/mvex/mod.rs (1)
9-25: LGTM!The changes are consistent with the fault-tolerant pattern across the codebase. Removal of
Eqderive is appropriate, and theunexpectedfield is properly gated.src/meta/mod.rs (1)
161-163: LGTM!Test fixtures correctly initialize the
unexpectedfield with empty vectors when thefault-tolerantfeature is enabled, ensuring tests pass in both configurations.Also applies to: 234-236
src/moof/traf/mod.rs (1)
11-35: LGTM!The
Trafstruct correctly implements the fault-tolerant pattern with theunexpectedfield for capturing unknown child atoms during fragment decoding.src/moov/trak/mdia/minf/stbl/stsd/hevc/hvc1.rs (2)
40-46: LGTM!The fault-tolerant branching logic correctly handles unknown atoms:
- Always logs a warning for visibility
- Collects unknown atoms into
unexpectedwhenfault-tolerantis enabled- Returns
Error::UnexpectedBoxin strict modeThis matches the documented behavior where unexpected boxes are collected during decode but not re-encoded.
63-80: Confirm:unexpectedboxes are intentionally not encoded.The
encode_bodymethod correctly omits theunexpectedfield, which aligns with the PR documentation that unexpected boxes are collected during decoding but not written back during encoding. This is the expected behavior.src/test/bbb.rs (2)
221-222: LGTM!The test fixtures comprehensively initialize the
unexpectedfields across the entireMoovstructure hierarchy, ensuring proper round-trip testing with the fault-tolerant feature.Also applies to: 233-234, 241-242, 279-280
401-406: LGTM!The
MoofandTrafstructures in the test are correctly updated with theunexpectedfield initialization, maintaining test coverage for fragmented MP4 structures.Also applies to: 465-470
src/moov/trak/edts/mod.rs (1)
6-21: LGTM!The
Edtsstruct correctly implements the fault-tolerant pattern, consistent with other container atoms in the codebase.src/test/mod.rs (1)
4-4: LGTM!The new test module declaration follows the existing pattern and is properly integrated.
src/moof/mod.rs (2)
9-9: Correct removal ofEqderive.Removing
Eqis necessary because the newunexpected: Vec<Any>field may not implementEq.
14-15: LGTM! Fault-tolerant field correctly gated.The
unexpectedfield is properly feature-gated and will collect unknown boxes when fault-tolerant mode is enabled.src/moov/trak/mdia/minf/stbl/stsd/hevc/hvcc.rs (1)
172-172: Good test simplification.Using
..Default::default()makes the test more maintainable as new optional fields (likeunexpected) are added to the struct.src/moov/trak/mdia/minf/dinf/mod.rs (2)
6-6: Correct removal ofEqderive.Removing
Eqis necessary because the newunexpected: Vec<Any>field may not implementEq.
10-11: LGTM! Fault-tolerant field correctly gated.The
unexpectedfield follows the same pattern as other container atoms in this PR.justfile (2)
14-14: Good addition: testing without default features.Adding
--no-default-featurescheck ensures the codebase compiles correctly when the fault-tolerant feature is disabled.
22-23: Excellent test coverage expansion.Testing with both
--all-featuresand--no-default-featuresensures the fault-tolerant feature works correctly in both enabled and disabled states. This is critical for a feature that changes parsing behavior.src/moov/trak/mdia/minf/stbl/mod.rs (2)
29-29: Correct removal ofEqderive.Removing
Eqis necessary because the newunexpected: Vec<Any>field may not implementEq.
45-46: LGTM! Fault-tolerant field correctly gated.The
unexpectedfield follows the established pattern and will collect unknown boxes in this sample table container.src/moov/trak/mdia/mod.rs (2)
11-11: LGTM: Eq removal is correct.Removing
Eqfrom the derive list is appropriate sinceVec<Any>(used in the newunexpectedfield) may not implementEq.
17-18: LGTM: Fault-tolerant field addition.The conditional
unexpectedfield is correctly gated by thefault-tolerantfeature. Thenested!macro handles the decode/encode logic appropriately.src/test/vp9.rs (1)
159-160: LGTM: Test assertions updated correctly.The test expectations are properly updated to include the
unexpected: vec![]field under thefault-tolerantfeature flag. The empty vector is correct since the test fixtures contain no unexpected boxes.Also applies to: 198-199, 212-213, 240-241, 254-255, 266-267, 275-276, 300-301
src/moov/trak/mod.rs (1)
11-11: LGTM: Consistent fault-tolerant implementation.The changes follow the same correct pattern:
Eqremoved and theunexpectedfield added under the feature gate.Also applies to: 19-20
src/moov/trak/mdia/minf/stbl/stsd/ac3.rs (4)
5-5: LGTM: Struct changes are correct.Removing
Eqand adding the conditionalunexpectedfield aligns with the fault-tolerant feature implementation.Also applies to: 10-11
21-43: LGTM: Fault-tolerant decode logic is sound.The decode implementation correctly:
- Declares the
unexpectedvector under the feature flag (lines 21-22)- Conditionally handles unknown atoms: collecting them when fault-tolerant is enabled, or returning an error otherwise (lines 27-34)
- Includes the
unexpectedfield in the struct construction (lines 41-42)
46-50: LGTM: Encoding correctly omits unexpected boxes.As documented in the PR objectives, unexpected boxes are not written back during encoding. This implementation correctly encodes only
audioanddac3.
136-138: LGTM: Test updates are correct.Tests properly initialize the
unexpectedfield under the feature flag.Also applies to: 160-161
src/moov/trak/mdia/minf/mod.rs (1)
13-13: LGTM: Standard fault-tolerant pattern applied correctly.Also applies to: 20-21
src/test/heif.rs (1)
132-133: LGTM: Test fixtures updated correctly.The
Iprpstruct initializations properly include theunexpected: vec![]field under the fault-tolerant feature flag.Also applies to: 415-416
src/moov/udta/mod.rs (2)
7-7: LGTM: Consistent implementation.Also applies to: 11-12
31-35: LGTM: Tests properly updated.Both test cases correctly initialize the
unexpectedfield under the feature flag.Also applies to: 55-56
src/atom.rs (4)
178-179: LGTM: Unexpected vector declared under feature flag.The
unexpectedvector is correctly initialized only when thefault-tolerantfeature is enabled.
203-213: LGTM: Fault-tolerant branching is correct.The catch-all branch properly handles unexpected boxes:
- When
fault-tolerantis enabled: logs a warning and accumulates the box inunexpected- When disabled: returns
Error::UnexpectedBoxas beforeThis maintains backward compatibility while enabling lenient parsing when desired.
217-223: LGTM: Struct construction includes unexpected field.The generated struct construction correctly includes the
unexpectedfield conditionally when the feature is enabled.
226-232: LGTM: Encoding correctly omits unexpected boxes.The
encode_bodyimplementation only encodes required, optional, and multiple fields, deliberately excludingunexpected. This aligns with the documented behavior that unexpected boxes are not written back during encoding.src/moov/trak/mdia/minf/stbl/stsd/av01.rs (2)
6-17: LGTM - Fault-tolerant field addition is consistent with the pattern.The
Eqremoval is necessary sinceVec<Any>may not implementEq, and the feature-gatedunexpectedfield follows the established pattern across the codebase.
40-47: LGTM - Unknown atom handling correctly branches on feature flag.The implementation properly logs a warning, then either collects the atom (fault-tolerant) or returns an error (strict mode).
src/moov/trak/mdia/minf/stbl/stsd/flac.rs (1)
3-10: LGTM - Consistent fault-tolerant implementation for FLAC atom.The pattern matches other codec implementations with proper feature gating.
src/moov/trak/mdia/minf/stbl/stsd/mod.rs (2)
46-50: LGTM - Stsd derive update is consistent.The
Eqremoval aligns with the broader fault-tolerant changes where contained types (codecs) now may includeVec<Any>which doesn't implementEq.
53-112: LGTM - Codec enum properly handles unknown sample entries.The
Unknown(FourCC)variant correctly captures unknown codec types while the error path at line 142 appropriately rejects atoms that aren't valid sample entries.src/moov/trak/mdia/minf/stbl/stsd/uncv.rs (1)
5-16: LGTM - Fault-tolerant implementation for Uncv follows established pattern.src/test/hevc.rs (2)
214-221: LGTM - Non-fault-tolerant path correctly asserts error on unexpected box.The test properly validates that without the fault-tolerant feature, the
fielbox causes anUnexpectedBoxerror.
642-655: LGTM - Test correctly handles non-encoding of unexpected boxes.Clearing
unexpectedbeforeassert_encode_decodeis the right approach since unexpected boxes are intentionally not re-encoded.src/moov/trak/mdia/minf/stbl/stsd/opus.rs (1)
3-10: LGTM - Fault-tolerant implementation for Opus follows established pattern.src/moov/trak/mdia/minf/stbl/stsd/vp9/vp08.rs (1)
4-11: LGTM - Fault-tolerant implementation for Vp08 follows established pattern.src/test/fault_tolerant.rs (3)
1-108: LGTM - Comprehensive test for fault-tolerant behavior.The test properly exercises both feature configurations:
- With fault-tolerant: validates unexpected boxes are collected and accessible
- Without fault-tolerant: validates the appropriate error is returned
The manual construction of the moov buffer with an injected
mdatbox is a good approach for testing this edge case.
110-185: LGTM - Good coverage for multiple unexpected boxes scenario.This test validates that the implementation correctly handles and preserves multiple unexpected boxes in order.
187-226: LGTM - Important test verifying non-encoding of unexpected boxes.This test confirms the documented behavior that unexpected boxes are collected during decode but not written back during encode, which is essential for the round-trip semantics.
src/test/uncompressed.rs (1)
92-93: LGTM! Consistent fault-tolerant field additions across test expectations.The
unexpected: vec![]fields are correctly added to all nested structures (Moov, Trak, Mdia, Minf, Dinf, Stbl, Uncv codec, Udta) under the#[cfg(feature = "fault-tolerant")]gate. This aligns with the PR's design where well-formed files should decode with empty unexpected vectors.Also applies to: 117-118, 145-146, 159-160, 171-172, 180-181, 253-254, 300-301
src/test/av1.rs (1)
114-115: LGTM! Comprehensive fault-tolerant field coverage in AV1 test.The test correctly includes
unexpected: vec![]for all container structures includingMoofandTraf, ensuring the fragmented MP4 path is also covered by the fault-tolerant feature testing.Also applies to: 138-139, 150-151, 178-179, 192-193, 204-205, 213-214, 250-251, 273-274, 290-291, 294-295
src/test/flac.rs (1)
242-243: LGTM! Fault-tolerant fields correctly added to FLAC audio codec test.The test properly includes the feature-gated
unexpectedfield for theFlaccodec structure alongside the container structures.Also applies to: 266-267, 278-279, 306-307, 320-321, 325-326, 334-335, 370-371
src/moov/trak/mdia/minf/stbl/stsd/vp9/vp09.rs (2)
4-11: LGTM! Clean implementation of fault-tolerant decoding for VP09.The struct correctly:
- Removes
Eqderive (sinceVec<Any>may not implementEq)- Adds the feature-gated
unexpectedfield- Uses
Defaultderive for cleaner test initialization
20-42: Decoding logic is correct and follows the established pattern.The implementation properly:
- Initializes
unexpectedvector under feature gate- Logs a warning for unknown atoms (useful for debugging)
- Conditionally collects or errors based on feature flag
- Includes
unexpectedin the constructed structsrc/moov/trak/mdia/minf/stbl/stsd/mp4a/mod.rs (2)
7-16: LGTM! Fault-tolerant support correctly added to Mp4a.The struct properly removes
Eqand adds the feature-gatedunexpectedfield.
28-55: Decoding logic correctly implements fault-tolerant pattern.The implementation properly collects unknown atoms when the feature is enabled and returns an error otherwise.
src/moov/trak/mdia/minf/stbl/stsd/hevc/hev1.rs (3)
3-15: LGTM! Well-structured fault-tolerant implementation for HEV1.The struct correctly adds
Defaultderive alongside the feature-gatedunexpectedfield, enabling cleaner test initialization with..Default::default().
28-59: Decoding logic is correct and consistent with other codec implementations.The fault-tolerant handling follows the established pattern across the codebase.
87-104: Good test simplification using struct update syntax.Using
..Default::default()at line 103 is cleaner than explicitly setting each optional field toNoneandunexpected: vec![], and it's future-proof if new optional fields are added.src/moov/trak/mdia/minf/stbl/stsd/h264/avc1.rs (3)
3-15: LGTM! Fault-tolerant support correctly implemented for AVC1.The implementation mirrors the pattern used in other codec implementations (HEV1, VP09, etc.).
28-59: Decoding logic follows the established fault-tolerant pattern.Correctly accumulates unknown atoms when fault-tolerant is enabled and errors otherwise.
85-177: Comprehensive test coverage for AVC1 with and without optional fields.Both
test_avc1andtest_avc1_with_extrascorrectly include the feature-gatedunexpectedfield. The explicit initialization style (vs...Default::default()) is acceptable as it makes the test expectations clearer.src/test/esds.rs (1)
150-151: LGTM! Comprehensive fault-tolerant field coverage in ESDS test.The test correctly adds
unexpected: vec![]to all relevant structures across both video (AVC1) and audio (MP4A) tracks, as well as the fragmented container structures (Moof, Traf). The use of..Default::default()at strategic locations (lines 315, 318) simplifies the test while maintaining clarity.Also applies to: 162-163, 170-171, 208-209, 238-239, 254-255, 291-292, 315-316, 326-327, 330-331
src/moov/trak/mdia/minf/stbl/stsd/eac3.rs (4)
5-12: LGTM! Well-structured fault-tolerant feature implementation.The struct correctly:
- Removes
Eqderivation (sinceVec<Any>may not implementEq)- Adds the
unexpectedfield gated behind#[cfg(feature = "fault-tolerant")]- Uses public visibility to allow inspection of collected unknown boxes
21-43: Decoding logic correctly implements fault-tolerant behavior.The implementation properly:
- Logs a warning for unknown atoms in both modes (good for debugging)
- Collects unknown atoms into
unexpectedwhen the feature is enabled- Returns
Error::UnexpectedBoxwhen the feature is disabled- Conditionally includes
unexpectedin the struct construction
46-50: Encoding intentionally omits unexpected boxes.As documented in the PR objectives, unexpected boxes are not written back during encoding. This is the expected behavior - the
unexpectedfield is purely for inspection/debugging of parsed content.
196-199: Test assertions correctly include the fault-tolerant field.The use of
#[cfg(feature = "fault-tolerant")]on struct field initialization in assertions is idiomatic and ensures tests compile under both feature configurations.src/moov/mod.rs (2)
142-145: Test correctly propagates fault-tolerant fields through the hierarchy.The test comprehensively includes
unexpected: vec![]at all levels of the nested structure (Mvex, Edts, Dinf, Minf, Mdia, Trak, and Moov), ensuring the fault-tolerant feature is properly integrated throughout the module hierarchy.
21-23: Fault-tolerant field addition follows macro implementation correctly.The
nested!macro correctly handles the fault-tolerant feature: it declares and populates theunexpectedvector when the feature is enabled, collects unrecognized atoms into it during decode, and includes the field in the struct construction. The pattern is consistent across all structs using this macro.src/test/h264.rs (4)
121-122: Test correctly includes fault-tolerant field at root level.The
unexpected: vec![]field is properly placed at the top level of theMoovstruct with the appropriate cfg gate.
698-706: Moof/Traf test correctly includes fault-tolerant fields.The encrypted segment test properly includes
unexpected: vec![]for bothMoofandTrafstructures, ensuring the fault-tolerant feature works across different MP4 atom hierarchies.
409-414: Udta test construction properly includes fault-tolerant field.The explicit construction of
Udtawithunexpected: vec![]andmeta: Noneensures the test validates the fault-tolerant feature in the user data box as well.
275-276: Using..Default::default()for Avc1 is a clean pattern that reduces boilerplate.
Avc1derivesDefault, which correctly providesunexpected: vec![]when the fault-tolerant feature is enabled. This approach maintains consistency across the test without manual field initialization.
In general, anything derived from ISOBMFF is intended to allow other information in the file, and that can be ignored (see ISO/IEC 14496-12:2022 Section B.2.1). So while there are cases for strict behaviour, we should be chill where practical. Except where we are testing ourselves. Make sure that works.
905f026 to
e6b7860
Compare
|
A feature flag is not the right approach because they're meant to be additive. Enabling Also, it feels kind of gross to add I think we can instead log unknown boxes and skip them. If there's some non-standard box that users need parsed, we should parse it instead of dumping everything into |
Is the intent that this is the "always" case, or do you want some kind of option (feature flag, global configuration object, parse fn boolean, or something else) for this? |
I would turn it on globally. The application can opt-out of |
|
The only problem with Then again, they definitely won't check if every possible |
Upvote, it's always good to keep it consistent.
Due to the breakage that could introduce, we better not make it default if we were to do it.
Yes and yes, this PR is indeed too messy, and the newly added unknown variant likely won't get used. I'm wondering if there are downstream users who already depend on this fail-fast behavior. Perhaps we could make the 'log-and-continue on unknown atoms' behavior opt-in via a feature flag, rather than the default behavior? This way, we'd be more likely to receive feedback about implementation errors, and it would stay closer to the original intent of this crate: a strongly-typed, correct MP4 box implementation. |
I doubt anybody cares. I mostly decided to return an error to help catch bugs or unhandled atoms, not to be pedantic. Unit tests might be the one place I would want to error instead of log. |
|
Closed in favour of #84 |
This change introduces the ability to collect and retain any unexpected boxes encountered during the decoding process.
Previously, the decoder would give an Error::unexpectedBox when encounters an unexpected box thus failing the decode process. Now, these boxes are stored in a unexpected Vec within their parent structures (Moov, Trak, Mdia, Minf, Stbl, etc.).
This allows for more robust handling of malformed or extended MP4 files, as the application can now inspect and process unexpected boxes as needed.
closes #63
replaces #71, which it is derived from.