mirror of
https://github.com/wader/fq.git
synced 2024-11-27 14:14:58 +03:00
7b27e506f1
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
103 lines
2.3 KiB
Go
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
|
|
}
|