diff options
Diffstat (limited to 'vendor/github.com/abema/go-mp4/bitio')
-rw-r--r-- | vendor/github.com/abema/go-mp4/bitio/bitio.go | 8 | ||||
-rw-r--r-- | vendor/github.com/abema/go-mp4/bitio/read.go | 97 | ||||
-rw-r--r-- | vendor/github.com/abema/go-mp4/bitio/write.go | 61 |
3 files changed, 166 insertions, 0 deletions
diff --git a/vendor/github.com/abema/go-mp4/bitio/bitio.go b/vendor/github.com/abema/go-mp4/bitio/bitio.go new file mode 100644 index 000000000..404fd1b82 --- /dev/null +++ b/vendor/github.com/abema/go-mp4/bitio/bitio.go @@ -0,0 +1,8 @@ +package bitio + +import "errors" + +var ( + ErrInvalidAlignment = errors.New("invalid alignment") + ErrDiscouragedReader = errors.New("discouraged reader implementation") +) diff --git a/vendor/github.com/abema/go-mp4/bitio/read.go b/vendor/github.com/abema/go-mp4/bitio/read.go new file mode 100644 index 000000000..4da76eae6 --- /dev/null +++ b/vendor/github.com/abema/go-mp4/bitio/read.go @@ -0,0 +1,97 @@ +package bitio + +import "io" + +type Reader interface { + io.Reader + + // alignment: + // |-1-byte-block-|--------------|--------------|--------------| + // |<-offset->|<-------------------width---------------------->| + ReadBits(width uint) (data []byte, err error) + + ReadBit() (bit bool, err error) +} + +type ReadSeeker interface { + Reader + io.Seeker +} + +type reader struct { + reader io.Reader + octet byte + width uint +} + +func NewReader(r io.Reader) Reader { + return &reader{reader: r} +} + +func (r *reader) Read(p []byte) (n int, err error) { + if r.width != 0 { + return 0, ErrInvalidAlignment + } + return r.reader.Read(p) +} + +func (r *reader) ReadBits(size uint) ([]byte, error) { + bytes := (size + 7) / 8 + data := make([]byte, bytes) + offset := (bytes * 8) - (size) + + for i := uint(0); i < size; i++ { + bit, err := r.ReadBit() + if err != nil { + return nil, err + } + + byteIdx := (offset + i) / 8 + bitIdx := 7 - (offset+i)%8 + if bit { + data[byteIdx] |= 0x1 << bitIdx + } + } + + return data, nil +} + +func (r *reader) ReadBit() (bool, error) { + if r.width == 0 { + buf := make([]byte, 1) + if n, err := r.reader.Read(buf); err != nil { + return false, err + } else if n != 1 { + return false, ErrDiscouragedReader + } + r.octet = buf[0] + r.width = 8 + } + + r.width-- + return (r.octet>>r.width)&0x01 != 0, nil +} + +type readSeeker struct { + reader + seeker io.Seeker +} + +func NewReadSeeker(r io.ReadSeeker) ReadSeeker { + return &readSeeker{ + reader: reader{reader: r}, + seeker: r, + } +} + +func (r *readSeeker) Seek(offset int64, whence int) (int64, error) { + if whence == io.SeekCurrent && r.reader.width != 0 { + return 0, ErrInvalidAlignment + } + n, err := r.seeker.Seek(offset, whence) + if err != nil { + return n, err + } + r.reader.width = 0 + return n, nil +} diff --git a/vendor/github.com/abema/go-mp4/bitio/write.go b/vendor/github.com/abema/go-mp4/bitio/write.go new file mode 100644 index 000000000..5f63dd2d2 --- /dev/null +++ b/vendor/github.com/abema/go-mp4/bitio/write.go @@ -0,0 +1,61 @@ +package bitio + +import ( + "io" +) + +type Writer interface { + io.Writer + + // alignment: + // |-1-byte-block-|--------------|--------------|--------------| + // |<-offset->|<-------------------width---------------------->| + WriteBits(data []byte, width uint) error + + WriteBit(bit bool) error +} + +type writer struct { + writer io.Writer + octet byte + width uint +} + +func NewWriter(w io.Writer) Writer { + return &writer{writer: w} +} + +func (w *writer) Write(p []byte) (n int, err error) { + if w.width != 0 { + return 0, ErrInvalidAlignment + } + return w.writer.Write(p) +} + +func (w *writer) WriteBits(data []byte, width uint) error { + length := uint(len(data)) * 8 + offset := length - width + for i := offset; i < length; i++ { + oi := i / 8 + if err := w.WriteBit((data[oi]>>(7-i%8))&0x01 != 0); err != nil { + return err + } + } + return nil +} + +func (w *writer) WriteBit(bit bool) error { + if bit { + w.octet |= 0x1 << (7 - w.width) + } + w.width++ + + if w.width == 8 { + if _, err := w.writer.Write([]byte{w.octet}); err != nil { + return err + } + w.octet = 0x00 + w.width = 0 + } + return nil +} |