mirror of
https://github.com/wader/fq.git
synced 2024-12-26 15:02:28 +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
130 lines
2.4 KiB
Go
130 lines
2.4 KiB
Go
package bitio
|
|
|
|
import (
|
|
"errors"
|
|
"io"
|
|
)
|
|
|
|
// TODO: smarter, track index?
|
|
|
|
func endPos(rs Seeker) (int64, error) {
|
|
c, err := rs.SeekBits(0, io.SeekCurrent)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
e, err := rs.SeekBits(0, io.SeekEnd)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
_, err = rs.SeekBits(c, io.SeekStart)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return e, nil
|
|
}
|
|
|
|
// MultiReader is a bitio.ReaderAtSeeker concatinating multiple bitio.ReadAtSeeker:s.
|
|
// Similar to io.MultiReader.
|
|
type MultiReader struct {
|
|
pos int64
|
|
readers []ReadAtSeeker
|
|
readerEnds []int64
|
|
}
|
|
|
|
// NewMultiReader returns a new bitio.MultiReader.
|
|
func NewMultiReader(rs ...ReadAtSeeker) (*MultiReader, error) {
|
|
readerEnds := make([]int64, len(rs))
|
|
var esSum int64
|
|
for i, r := range rs {
|
|
e, err := endPos(r)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
esSum += e
|
|
readerEnds[i] = esSum
|
|
}
|
|
return &MultiReader{readers: rs, readerEnds: readerEnds}, nil
|
|
}
|
|
|
|
func (m *MultiReader) ReadBitsAt(p []byte, nBits int64, bitOff int64) (n int64, err error) {
|
|
var end int64
|
|
if len(m.readers) > 0 {
|
|
end = m.readerEnds[len(m.readers)-1]
|
|
}
|
|
if end <= bitOff {
|
|
return 0, io.EOF
|
|
}
|
|
|
|
prevAtEnd := int64(0)
|
|
readerAt := m.readers[0]
|
|
for i, end := range m.readerEnds {
|
|
if bitOff < end {
|
|
readerAt = m.readers[i]
|
|
break
|
|
}
|
|
prevAtEnd = end
|
|
}
|
|
|
|
rBits, err := readerAt.ReadBitsAt(p, nBits, bitOff-prevAtEnd)
|
|
|
|
if errors.Is(err, io.EOF) {
|
|
if bitOff+rBits < end {
|
|
err = nil
|
|
}
|
|
}
|
|
|
|
return rBits, err
|
|
}
|
|
|
|
func (m *MultiReader) ReadBits(p []byte, nBits int64) (n int64, err error) {
|
|
n, err = m.ReadBitsAt(p, nBits, m.pos)
|
|
m.pos += n
|
|
return n, err
|
|
}
|
|
|
|
func (m *MultiReader) SeekBits(bitOff int64, whence int) (int64, error) {
|
|
var p int64
|
|
var end int64
|
|
if len(m.readers) > 0 {
|
|
end = m.readerEnds[len(m.readers)-1]
|
|
}
|
|
|
|
switch whence {
|
|
case io.SeekStart:
|
|
p = bitOff
|
|
case io.SeekCurrent:
|
|
p = m.pos + bitOff
|
|
case io.SeekEnd:
|
|
p = end + bitOff
|
|
default:
|
|
panic("unknown whence")
|
|
}
|
|
if p < 0 || p > end {
|
|
return 0, ErrOffset
|
|
}
|
|
|
|
m.pos = p
|
|
|
|
return p, nil
|
|
}
|
|
|
|
func (m *MultiReader) CloneReader() (Reader, error) {
|
|
return m.CloneReaderAtSeeker()
|
|
}
|
|
|
|
func (m *MultiReader) CloneReadSeeker() (ReadSeeker, error) {
|
|
return m.CloneReaderAtSeeker()
|
|
}
|
|
|
|
func (m *MultiReader) CloneReadAtSeeker() (ReadAtSeeker, error) {
|
|
return m.CloneReaderAtSeeker()
|
|
}
|
|
|
|
func (m *MultiReader) CloneReaderAtSeeker() (ReaderAtSeeker, error) {
|
|
return &MultiReader{
|
|
pos: 0,
|
|
readers: m.readers,
|
|
readerEnds: m.readerEnds,
|
|
}, nil
|
|
}
|