1
1
mirror of https://github.com/wader/fq.git synced 2024-11-27 14:14:58 +03:00
fq/pkg/bitio/iobitreadseeker.go
Mattias Wadman 7b27e506f1 mp4,bitio: Fix broken pssh decoding and add proper reader cloning to bitio
PSSH decoding probably got broken in some refactoring. system id is 16 bytes,
also scalar mapper should use cloned reader to not affect reader which in the case
broke reading system id bytes.

Add test with playread and widevine pssh boxes

Related to #282
2022-05-28 13:42:38 +02:00

103 lines
2.3 KiB
Go

package bitio
import (
"errors"
"io"
)
// IOBitReadSeeker is a bitio.ReadAtSeeker reading from a io.ReadSeeker.
type IOBitReadSeeker struct {
bitPos int64
rs io.ReadSeeker
buf []byte
}
// NewIOBitReadSeeker returns a new bitio.IOBitReadSeeker
func NewIOBitReadSeeker(rs io.ReadSeeker) *IOBitReadSeeker {
return &IOBitReadSeeker{
bitPos: 0,
rs: rs,
}
}
func (r *IOBitReadSeeker) ReadBitsAt(p []byte, nBits int64, bitOffset int64) (int64, error) {
if nBits < 0 {
return 0, ErrNegativeNBits
}
readBytePos := bitOffset / 8
readSkipBits := bitOffset % 8
wantReadBits := readSkipBits + nBits
wantReadBytes := int(BitsByteCount(wantReadBits))
if wantReadBytes > len(r.buf) {
// TODO: use append somehow?
r.buf = make([]byte, wantReadBytes)
}
_, err := r.rs.Seek(readBytePos, io.SeekStart)
if err != nil {
return 0, err
}
// TODO: nBits should be available
readBytes, err := io.ReadFull(r.rs, r.buf[0:wantReadBytes])
if err != nil && !errors.Is(err, io.ErrUnexpectedEOF) {
return 0, err
} else if errors.Is(err, io.ErrUnexpectedEOF) {
nBits = int64(readBytes) * 8
err = io.EOF
}
if readSkipBits == 0 && nBits%8 == 0 {
copy(p[0:readBytes], r.buf[0:readBytes])
return nBits, err
}
nBytes := nBits / 8
restBits := nBits % 8
// TODO: copy smartness if many bytes
for i := int64(0); i < nBytes; i++ {
p[i] = byte(Read64(r.buf, readSkipBits+i*8, 8))
}
if restBits != 0 {
p[nBytes] = byte(Read64(r.buf, readSkipBits+nBytes*8, restBits)) << (8 - restBits)
}
return nBits, err
}
func (r *IOBitReadSeeker) ReadBits(p []byte, nBits int64) (n int64, err error) {
rBits, err := r.ReadBitsAt(p, nBits, r.bitPos)
r.bitPos += rBits
return rBits, err
}
func (r *IOBitReadSeeker) SeekBits(bitOff int64, whence int) (int64, error) {
seekBytesPos, err := r.rs.Seek(bitOff/8, whence)
if err != nil {
return 0, err
}
seekBitPos := seekBytesPos*8 + bitOff%8
r.bitPos = seekBitPos
return seekBitPos, nil
}
func (r *IOBitReadSeeker) CloneReader() (Reader, error) {
return r.CloneReaderAtSeeker()
}
func (r *IOBitReadSeeker) CloneReadSeeker() (ReadSeeker, error) {
return r.CloneReaderAtSeeker()
}
func (r *IOBitReadSeeker) CloneReadAtSeeker() (ReadAtSeeker, error) {
return r.CloneReaderAtSeeker()
}
func (r *IOBitReadSeeker) CloneReaderAtSeeker() (ReaderAtSeeker, error) {
return NewIOBitReadSeeker(r.rs), nil
}