-
Notifications
You must be signed in to change notification settings - Fork 117
Expand file tree
/
Copy pathcolr.go
More file actions
146 lines (135 loc) · 4.37 KB
/
colr.go
File metadata and controls
146 lines (135 loc) · 4.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package mp4
import (
"encoding/hex"
"io"
"github.com/Eyevinn/mp4ff/bits"
)
const (
colrType = "colr"
ColorTypeOnScreenColors = "nclx" // on-screen colours acc. to ISO/IEC 14496-12 Sec. 12.1.5.2
ColorTypeRestrictedICCProfile = "rICC" // restricted ICC profile acc. to ISO/IEC 14496-12 Sec. 12.1.5.2
ColorTypeUnrestrictedICCTProfile = "prof" // unrestricted ICC profile acc. to ISO/IEC 14496-12 Sec. 12.1.5.2
// 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 is colr box defined in ISO/IEC 14496-12 2021 Sec. 12.1.5.
type ColrBox struct {
ColorType string
ICCProfile []byte
ColorPrimaries uint16
TransferCharacteristics uint16
MatrixCoefficients uint16
FullRangeFlag bool
UnknownPayload []byte
}
// DecodeColr decodes a ColrBox
func DecodeColr(hdr BoxHeader, startPos uint64, r io.Reader) (Box, error) {
data, err := readBoxBody(r, hdr)
if err != nil {
return nil, err
}
sr := bits.NewFixedSliceReader(data)
return DecodeColrSR(hdr, startPos, sr)
}
// DecodeColrSR decodes a ColrBox from a SliceReader
func DecodeColrSR(hdr BoxHeader, startPos uint64, sr bits.SliceReader) (Box, error) {
const colorTypeLen = 4
c := ColrBox{
ColorType: sr.ReadFixedLengthString(colorTypeLen),
}
switch c.ColorType {
case ColorTypeOnScreenColors:
c.ColorPrimaries = sr.ReadUint16()
c.TransferCharacteristics = sr.ReadUint16()
c.MatrixCoefficients = sr.ReadUint16()
b := sr.ReadUint8()
c.FullRangeFlag = (b & fullRangeBit) == fullRangeBit
case ColorTypeRestrictedICCProfile, ColorTypeUnrestrictedICCTProfile:
c.ICCProfile = sr.ReadBytes(hdr.payloadLen() - colorTypeLen)
case QuickTimeColorParameters:
c.ColorPrimaries = sr.ReadUint16()
c.TransferCharacteristics = sr.ReadUint16()
c.MatrixCoefficients = sr.ReadUint16()
default:
c.UnknownPayload = sr.RemainingBytes()
}
return &c, sr.AccError()
}
// Type returns the box type
func (c *ColrBox) Type() string {
return colrType
}
// Size returns the calculated size of the box
func (c *ColrBox) Size() uint64 {
var size uint64 = 8 + 4
switch c.ColorType {
case ColorTypeOnScreenColors:
size += 7
case ColorTypeRestrictedICCProfile, ColorTypeUnrestrictedICCTProfile:
size += uint64(len(c.ICCProfile))
case QuickTimeColorParameters:
size += 6
default:
size += uint64(len(c.UnknownPayload))
}
return size
}
// Encode writes box to w
func (c *ColrBox) Encode(w io.Writer) error {
sw := bits.NewFixedSliceWriter(int(c.Size()))
err := c.EncodeSW(sw)
if err != nil {
return err
}
_, err = w.Write(sw.Bytes())
return err
}
// EncodeSW writes box to sw
func (c *ColrBox) EncodeSW(sw bits.SliceWriter) error {
err := EncodeHeaderSW(c, sw)
if err != nil {
return err
}
sw.WriteString(c.ColorType, false)
switch c.ColorType {
case ColorTypeOnScreenColors:
sw.WriteUint16(c.ColorPrimaries)
sw.WriteUint16(c.TransferCharacteristics)
sw.WriteUint16(c.MatrixCoefficients)
b := byte(0)
if c.FullRangeFlag {
b = fullRangeBit
}
sw.WriteUint8(b)
case ColorTypeRestrictedICCProfile, ColorTypeUnrestrictedICCTProfile:
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()
}
// Info writes box information
func (c *ColrBox) Info(w io.Writer, specificBoxLevels, indent, indentStep string) (err error) {
bd := newInfoDumper(w, indent, c, -1, 0)
bd.write(" - colorType: %s", c.ColorType)
switch c.ColorType {
case ColorTypeOnScreenColors:
bd.write(" - ColorPrimaries: %d, TransferCharacteristics: %d, MatrixCoefficients: %d, FullRange: %t",
c.ColorPrimaries, c.TransferCharacteristics, c.MatrixCoefficients, c.FullRangeFlag)
case ColorTypeRestrictedICCProfile, ColorTypeUnrestrictedICCTProfile:
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
}