-
Notifications
You must be signed in to change notification settings - Fork 0
/
box.go
130 lines (108 loc) · 2.19 KB
/
box.go
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
package bmff
import (
"bytes"
"encoding/binary"
"io"
"io/ioutil"
"log"
"github.com/pkg/errors"
)
const boxHeaderSize = 8
func newBox(src io.Reader) (*box, error) {
b := &box{}
if err := b.decode(src); err != nil {
return nil, err
}
return b, nil
}
type box struct {
boxtype string
size uint32
largesize uint64
raw []byte
}
func (b *box) decode(src io.Reader) error {
header := make([]byte, 8)
if _, err := io.ReadFull(src, header); err != nil {
return errors.Wrapf(err, "error reading box header: %x", header)
}
b.size = binary.BigEndian.Uint32(header[0:4])
b.boxtype = string(header[4:8])
if b.size == 1 {
if err := binary.Read(src, binary.BigEndian, &b.largesize); err != nil {
return errors.Wrap(err, "failure to read largesize field")
}
}
if b.size == 0 {
data, err := ioutil.ReadAll(src)
if err != nil {
return errors.Wrap(err, "failure reading box to EOF")
}
b.raw = data
} else {
size := b.size - boxHeaderSize
if b.largesize != 0 {
size -= 8
}
b.raw = make([]byte, size)
if _, err := io.ReadFull(src, b.raw); err != nil {
return errors.Wrapf(err, "bad read for box(%s) body", b.boxtype)
}
}
return nil
}
func (b *box) Size() uint64 {
if b == nil {
return 0
}
if b.size == 1 {
return b.largesize
}
return uint64(b.size)
}
func (b *box) Type() string {
return b.boxtype
}
func (b *box) Raw() []byte {
return b.raw
}
type fullbox struct {
*box
version uint8
flags uint32
}
func (b *fullbox) Version() int {
return int(b.version)
}
func (b *fullbox) decode() error {
if len(b.raw) < 4 {
return errors.Errorf("failed decode of fullbox type %s, missing data", b.box.boxtype)
}
b.version = uint8(b.raw[0])
b.flags = binary.BigEndian.Uint32([]byte{0x00, b.raw[1], b.raw[2], b.raw[3]})
b.raw = b.raw[4:]
return nil
}
func readBoxes(buf []byte) <-chan *box {
boxes := make(chan *box)
r := bytes.NewReader(buf)
go func() {
for eof := false; !eof; {
b, err := newBox(r)
if err != nil {
switch errors.Cause(err) {
case io.EOF:
eof = true
default:
log.Fatal(err)
}
}
if b != nil {
log.Println("newBox - " + b.boxtype)
boxes <- b
}
}
close(boxes)
}()
return boxes
}