Repository navigation
Fix unmarshalling of sgpd RollDistancesL - #188
Merged
Kubo, Ryosuke (sunfish-shogi) merged 1 commit intoOct 23, 2026
Merged
Kubo, Ryosuke (sunfish-shogi) merged 1 commit into
Kubo, Ryosuke (sunfish-shogi) merged 1 commit into
Conversation
A version 1 sgpd box with grouping_type 'roll' or 'prol' and default_length 0 has a 32-bit description_length before each 16-bit roll_distance (ISO/IEC 14496-12, 8.9.3.2), which go-mp4 models as RollDistancesL []RollDistanceWithLength. The field was tagged size=16, the size of a bare roll_distance. unmarshalStructInternal requires a struct element to consume exactly size bits, so each 48-bit element failed with "invalid alignment". Marshal ignores the size for struct elements, so such a box could be written but not read back. Tag the field len=dynamic,opt=dynamic like AlternativeStartupEntriesL, VisualRandomAccessEntriesL and TemporalLevelEntriesL. Sgpd's GetFieldLength already returns EntryCount for RollDistancesL. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Kubo, Ryosuke (sunfish-shogi)
self-requested a review
October 23, 2026 01:46
Contributor
|
Thanks! |
Kubo, Ryosuke (sunfish-shogi)
approved these changes
Oct 23, 2026
Kubo, Ryosuke (sunfish-shogi)
merged commit Oct 23, 2026
0f35e18
into
abema:master
19 of 21 checks passed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Kubo, Ryosuke (@sunfish-shogi)
A version 1
sgpdbox with grouping typerollorprolanddefault_length0 cannot be unmarshalled. ISO/IEC 14496-12 §8.9.3.2 starts each entry of such a box withif (default_length==0) { unsigned int(32) description_length; }, and aroll/prolentry is a singlesigned int(16) roll_distance, so each element is 48 bits. go-mp4 models this asRollDistancesL []RollDistanceWithLength(DescriptionLength32 bits,RollDistance16 bits), butbox_types_iso14496_12.go:1557tags the fieldsize=16, the size of a bareroll_distanceinRollDistanceson the line above.unmarshalStructInternal(marshaller.go:366-378) requires a struct element to consume exactlysizebits, so the first 48-bit element makesUnmarshalreturninvalid alignment.Marshaldoes not use the size for struct elements, so such a box can be written but not read back, andmp4tool dumpstops with the same error because it parses everysgpd. The tag has been like this since 68a2dc0 added the field, and no test covered it.The fix tags the field
len=dynamic,opt=dynamic, likeAlternativeStartupEntriesL,VisualRandomAccessEntriesLandTemporalLevelEntriesL.Sgpd.GetFieldLengthalready returnsEntryCountforRollDistancesL, so nothing else changes.size=48would also parse, butlen=dynamicmatches the sibling fields and uses that existing case.The new case
sgpd: version 1 roll no-default-lengthinTestBoxTypesISO14496_12has two entries withdescription_length2. I wrote its bytes andString()output by hand following the neighbouringsgpdcases and checked the bytes with a small Python encoder written from the §8.9.3.2 syntax, which also reproduces the existingroll,proland version 2 vectors.I had no Go toolchain available, so this change has not been compiled or run with
go test; CI will be its first real run. As a stand-in I ported the parts offield.go,marshaller.go,string.goandinternal/bitiothatSgpdreaches to Python and ran everysgpdcase ofTestBoxTypesISO14496_12through Marshal, Unmarshal and Stringify. The eight existing cases pass with either tag; the new case fails at Unmarshal withinvalid alignmentundersize=16and passes underlen=dynamic. The runtime behaviour described above comes from reading the code and from that port, not from a Go run.🤖 Generated with Claude Code