diff --git a/CHANGELOG.md b/CHANGELOG.md index 9973ecf6..e8c40f86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Renamed bits.SliceWriterError to bits.ErrSliceWrite - colr box supports unknown colrType +### Fixed + +- kind box full-box header + ## [0.42.0] - 2024-01-26 ### Fixed diff --git a/mp4/kind.go b/mp4/kind.go index 8f89ff59..4f11ed8c 100644 --- a/mp4/kind.go +++ b/mp4/kind.go @@ -9,6 +9,8 @@ import ( // KindBox - Track Kind Box type KindBox struct { + Version byte + Flags uint32 SchemeURI string Value string } @@ -25,14 +27,17 @@ func DecodeKind(hdr BoxHeader, startPos uint64, r io.Reader) (Box, error) { // DecodeKindSR - box-specific decode func DecodeKindSR(hdr BoxHeader, startPos uint64, sr bits.SliceReader) (Box, error) { - maxLen := hdr.payloadLen() - 1 + versionAndFlags := sr.ReadUint32() + maxLen := hdr.payloadLen() - 4 - 1 schemeURI := sr.ReadZeroTerminatedString(maxLen) - maxLen = hdr.payloadLen() - 1 + maxLen = hdr.payloadLen() - 4 - len(schemeURI) - 1 value := sr.ReadZeroTerminatedString(maxLen) if err := sr.AccError(); err != nil { return nil, fmt.Errorf("decode kind: %w", err) } b := KindBox{ + Version: byte(versionAndFlags >> 24), + Flags: versionAndFlags & flagsMask, SchemeURI: schemeURI, Value: value, } @@ -46,7 +51,7 @@ func (b *KindBox) Type() string { // Size - calculated size of box func (b *KindBox) Size() uint64 { - return uint64(boxHeaderSize + len(b.SchemeURI) + 1 + len(b.Value) + 1) + return uint64(boxHeaderSize + 4 + len(b.SchemeURI) + 1 + len(b.Value) + 1) } // Encode - write box to w @@ -66,6 +71,8 @@ func (b *KindBox) EncodeSW(sw bits.SliceWriter) error { if err != nil { return err } + versionAndFlags := (uint32(b.Version) << 24) + b.Flags + sw.WriteUint32(versionAndFlags) sw.WriteString(b.SchemeURI, true) sw.WriteString(b.Value, true) return sw.AccError() @@ -73,7 +80,7 @@ func (b *KindBox) EncodeSW(sw bits.SliceWriter) error { // Info - write box-specific information func (b *KindBox) Info(w io.Writer, specificBoxLevels, indent, indentStep string) error { - bd := newInfoDumper(w, indent, b, -1, 0) + bd := newInfoDumper(w, indent, b, int(b.Version), b.Flags) bd.write(" - schemeURI: %s", b.SchemeURI) bd.write(" - value: %s", b.Value) return bd.err diff --git a/mp4/kind_test.go b/mp4/kind_test.go index e62b7cb7..2530e3cb 100644 --- a/mp4/kind_test.go +++ b/mp4/kind_test.go @@ -1,10 +1,35 @@ package mp4 import ( + "bytes" + "encoding/hex" "testing" ) func TestKind(t *testing.T) { - kind := &KindBox{SchemeURI: "urn:mpeg:dash:role:2011", Value: "forced-subtitle"} - boxDiffAfterEncodeAndDecode(t, kind) + t.Run("encode and decode", func(t *testing.T) { + kind := &KindBox{SchemeURI: "urn:mpeg:dash:role:2011", Value: "forced-subtitle"} + boxDiffAfterEncodeAndDecode(t, kind) + }) + t.Run("decode with full box header", func(t *testing.T) { + rawHex := ("000000296b696e64" + + "0000000075726e3a6d7065673a646173" + + "683a726f6c653a32303131006d61696e00") + rawBytes, err := hex.DecodeString(rawHex) + if err != nil { + t.Error(err) + } + buffer := bytes.NewReader(rawBytes) + box, err := DecodeBox(0, buffer) + if err != nil { + t.Errorf("Error decoding kind box: %v", err) + } + kind := box.(*KindBox) + if kind.SchemeURI != "urn:mpeg:dash:role:2011" { + t.Errorf("Expected scheme URI 'urn:mpeg:dash:role:2011', got '%s'", kind.SchemeURI) + } + if kind.Value != "main" { + t.Errorf("Expected value 'main', got '%s'", kind.Value) + } + }) }