diff --git a/CHANGELOG.md b/CHANGELOG.md index 2728e6a..6da3c37 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,12 +12,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - InitSegment.TweakSingleTrakLive changes an init segment to fit live streaming - Made bits.Mask() function public - New counter methods added to bits.Reader +- colr box support for nclc and unknown colour_type ### Changed - All readers and writers in bits package now stop working at first error and provides the first error as AccError() - Renamed bits.AccErrReader, bits.AccErrEBSPReader, bits.AccErrWriter to corresponiding names without AccErr - Renamed bits.SliceWriterError to bits.ErrSliceWrite +- colr box supports unknown colrType ## [0.42.0] - 2024-01-26 diff --git a/mp4/colr.go b/mp4/colr.go index a37daad..7ecf76c 100644 --- a/mp4/colr.go +++ b/mp4/colr.go @@ -2,7 +2,6 @@ package mp4 import ( "encoding/hex" - "fmt" "io" "github.com/Eyevinn/mp4ff/bits" @@ -13,10 +12,14 @@ const ( onScreenColors = "nclx" restrictedICCType = "rICC" unrestrictedICCType = "prof" - fullRangeBit = 0x80 + // quickTimeColorParameters defined in [nclc] + // + // [nclc]: https://developer.apple.com/library/archive/technotes/tn2162/_index.html#//apple_ref/doc/uid/DTS40013070-CH1-TNTAG10 + quickTimeColorParameters = "nclc" + fullRangeBit = 0x80 ) -// ColrBox i colr box defined in ISO/IEC 14496-2 2021 12.1.5 +// ColrBox is colr box defined in ISO/IEC 14496-2 2021 12.1.5. type ColrBox struct { ColorType string ICCProfile []byte @@ -24,6 +27,7 @@ type ColrBox struct { TransferCharacteristics uint16 MatrixCoefficients uint16 FullRangeFlag bool + UnknownPayload []byte } // DecodeColr decodes a ColrBox @@ -50,8 +54,12 @@ func DecodeColrSR(hdr BoxHeader, startPos uint64, sr bits.SliceReader) (Box, err c.FullRangeFlag = (b & fullRangeBit) == fullRangeBit case restrictedICCType, unrestrictedICCType: c.ICCProfile = sr.RemainingBytes() + case quickTimeColorParameters: + c.ColorPrimaries = sr.ReadUint16() + c.TransferCharacteristics = sr.ReadUint16() + c.MatrixCoefficients = sr.ReadUint16() default: - return nil, fmt.Errorf("unknown color type %q", c.ColorType) + c.UnknownPayload = sr.RemainingBytes() } return &c, sr.AccError() } @@ -69,6 +77,10 @@ func (c *ColrBox) Size() uint64 { size += 7 case restrictedICCType, unrestrictedICCType: size += uint64(len(c.ICCProfile)) + case quickTimeColorParameters: + size += 6 + default: + size += uint64(len(c.UnknownPayload)) } return size } @@ -101,8 +113,14 @@ func (c *ColrBox) EncodeSW(sw bits.SliceWriter) error { b = fullRangeBit } sw.WriteUint8(b) - default: + case restrictedICCType, unrestrictedICCType: sw.WriteBytes(c.ICCProfile) + case quickTimeColorParameters: + sw.WriteUint16(c.ColorPrimaries) + sw.WriteUint16(c.TransferCharacteristics) + sw.WriteUint16(c.MatrixCoefficients) + default: + sw.WriteBytes(c.UnknownPayload) } return sw.AccError() } @@ -115,9 +133,13 @@ func (c *ColrBox) Info(w io.Writer, specificBoxLevels, indent, indentStep string case onScreenColors: bd.write(" - ColorPrimaries: %d, TransferCharacteristics: %d, MatrixCoefficients: %d, FullRange: %t", c.ColorPrimaries, c.TransferCharacteristics, c.MatrixCoefficients, c.FullRangeFlag) - default: + case restrictedICCType, unrestrictedICCType: bd.write(" - ICCProfile: %s", hex.EncodeToString(c.ICCProfile)) - + case quickTimeColorParameters: + bd.write(" - ColorPrimaries: %d, TransferCharacteristics: %d, MatrixCoefficients: %d", + c.ColorPrimaries, c.TransferCharacteristics, c.MatrixCoefficients) + default: + bd.write(" - Payload: %s", hex.EncodeToString(c.UnknownPayload)) } return bd.err } diff --git a/mp4/colr_test.go b/mp4/colr_test.go index 3ed8c31..91f758d 100644 --- a/mp4/colr_test.go +++ b/mp4/colr_test.go @@ -29,6 +29,16 @@ func TestColrEncodeDecode(t *testing.T) { ColorType: unrestrictedICCType, ICCProfile: []byte{1, 2, 2, 43, 4, 5}, }, + { + ColorType: quickTimeColorParameters, + ColorPrimaries: 1, + TransferCharacteristics: 1, + MatrixCoefficients: 1, + }, + { + ColorType: "xyzd", + UnknownPayload: []byte{0x0, 0x1, 0x0, 0x1}, + }, } for _, tc := range cases { boxDiffAfterEncodeAndDecode(t, &tc)