Use caching reader to packetize FLAC efficiently
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
DataHoarder 2022-08-01 17:31:01 +02:00
parent a7d06f5eea
commit 3dbf436742
Signed by: DataHoarder
SSH key fingerprint: SHA256:OLTRf6Fl87G52SiR7sWLGNzlJt4WOX+tfI2yxo0z7xk

View file

@ -9,10 +9,6 @@ import (
"io" "io"
) )
func NewFLACPacketizer(reader io.Reader) *FLACPacketizer {
return &FLACPacketizer{br: bitio.NewReader(bufio.NewReaderSize(reader, 4096))}
}
type FLACHeaderPacket struct { type FLACHeaderPacket struct {
Capture [4]byte Capture [4]byte
MinimumBlockSize uint16 MinimumBlockSize uint16
@ -137,7 +133,7 @@ func readFlacHeader(br *bitio.Reader) *FLACHeaderPacket {
return hdr return hdr
} }
func readFlacFrame(hdr *FLACHeaderPacket, br *bitio.Reader) *FLACPacket { func readFlacFrame(hdr *FLACHeaderPacket, br *bitio.Reader, bfr *cachedBitReader) *FLACPacket {
if sync, err := br.ReadBits(14); err != nil || sync != 0b11111111111110 { if sync, err := br.ReadBits(14); err != nil || sync != 0b11111111111110 {
return nil return nil
} }
@ -336,11 +332,9 @@ func readFlacFrame(hdr *FLACHeaderPacket, br *bitio.Reader) *FLACPacket {
blockSize := int(p.getBlockSize()) blockSize := int(p.getBlockSize())
buf := bytes.NewBuffer(hdr.buf[:0]) bfr.ResetBuffer()
bw := bitio.NewWriter(buf) var subframeType, wastedBitsFlag, wastedBits uint64
var padding, subframeType, wastedBitsFlag, wastedBits uint64
//TODO: remove error checking here, given we get proper input and a check will happen later //TODO: remove error checking here, given we get proper input and a check will happen later
for channelNumber := 0; channelNumber < channelCount; channelNumber++ { for channelNumber := 0; channelNumber < channelCount; channelNumber++ {
bps := p.getBitsPerSample() bps := p.getBitsPerSample()
@ -351,7 +345,8 @@ func readFlacFrame(hdr *FLACHeaderPacket, br *bitio.Reader) *FLACPacket {
bps++ bps++
} }
if padding, err = br.ReadBits(1); err != nil { //var padding uint64
if _, err = br.ReadBits(1); err != nil {
return nil return nil
} }
if subframeType, err = br.ReadBits(6); err != nil { if subframeType, err = br.ReadBits(6); err != nil {
@ -370,11 +365,11 @@ func readFlacFrame(hdr *FLACHeaderPacket, br *bitio.Reader) *FLACPacket {
wastedBits = 0 wastedBits = 0
} }
_ = bw.WriteBits(padding, 1) //_ = bw.WriteBits(padding, 1)
_ = bw.WriteBits(subframeType, 6) //_ = bw.WriteBits(subframeType, 6)
_ = bw.WriteBits(wastedBitsFlag, 1) //_ = bw.WriteBits(wastedBitsFlag, 1)
if wastedBitsFlag == 1 { if wastedBitsFlag == 1 {
_ = writeUnary(bw, wastedBits) //_ = writeUnary(bw, wastedBits)
bps -= uint8(wastedBits) + 1 bps -= uint8(wastedBits) + 1
} }
@ -382,17 +377,17 @@ func readFlacFrame(hdr *FLACHeaderPacket, br *bitio.Reader) *FLACPacket {
switch { switch {
case subframeType == 0: //Constant case subframeType == 0: //Constant
var constantSample uint64 //var constantSample uint64
if constantSample, err = br.ReadBits(bps); err != nil { if _, err = br.ReadBits(bps); err != nil {
return nil return nil
} }
_ = bw.WriteBits(constantSample, bps) //_ = bw.WriteBits(constantSample, bps)
case subframeType == 1: //Verbatim case subframeType == 1: //Verbatim
var verbatimData []byte //var verbatimData []byte
if verbatimData, err = readManyBits(br, blockSize*int(bps)); err != nil { if _, err = readManyBits(br, blockSize*int(bps)); err != nil {
return nil return nil
} }
_ = writeManyBits(bw, verbatimData, blockSize*int(bps)) //_ = writeManyBits(bw, verbatimData, blockSize*int(bps))
case subframeType < 8: //reserved case subframeType < 8: //reserved
return nil return nil
case subframeType < 16: //Fixed case subframeType < 16: //Fixed
@ -402,30 +397,30 @@ func readFlacFrame(hdr *FLACHeaderPacket, br *bitio.Reader) *FLACPacket {
return nil return nil
} }
var warmupData []byte //var warmupData []byte
if warmupData, err = readManyBits(br, order*int(bps)); err != nil { if _, err = readManyBits(br, order*int(bps)); err != nil {
return nil return nil
} }
_ = writeManyBits(bw, warmupData, order*int(bps)) //_ = writeManyBits(bw, warmupData, order*int(bps))
if err = decodeResidual(br, bw, blockSize, order); err != nil { if err = decodeResidual(br, blockSize, order); err != nil {
return nil return nil
} }
case subframeType < 32: //reserved case subframeType < 32: //reserved
return nil return nil
default: //FIR default: //FIR
order := int(subframeType&0x1F) + 1 order := int(subframeType&0x1F) + 1
var warmupData []byte //var warmupData []byte
if warmupData, err = readManyBits(br, order*int(bps)); err != nil { if _, err = readManyBits(br, order*int(bps)); err != nil {
return nil return nil
} }
_ = writeManyBits(bw, warmupData, order*int(bps)) //_ = writeManyBits(bw, warmupData, order*int(bps))
var coefficientPrecisionLen, quantizationLevel uint64 var coefficientPrecisionLen uint64
if coefficientPrecisionLen, err = br.ReadBits(4); err != nil { if coefficientPrecisionLen, err = br.ReadBits(4); err != nil {
return nil return nil
} }
_ = bw.WriteBits(coefficientPrecisionLen, 4) //_ = bw.WriteBits(coefficientPrecisionLen, 4)
if coefficientPrecisionLen == 0xF { if coefficientPrecisionLen == 0xF {
return nil return nil
@ -433,35 +428,30 @@ func readFlacFrame(hdr *FLACHeaderPacket, br *bitio.Reader) *FLACPacket {
precision := int(coefficientPrecisionLen) + 1 precision := int(coefficientPrecisionLen) + 1
if quantizationLevel, err = br.ReadBits(5); err != nil { //var quantizationLevel uint64
if _, err = br.ReadBits(5); err != nil {
return nil return nil
} }
_ = bw.WriteBits(quantizationLevel, 5) //_ = bw.WriteBits(quantizationLevel, 5)
var coefficientData []byte //var coefficientData []byte
if coefficientData, err = readManyBits(br, order*precision); err != nil { if _, err = readManyBits(br, order*precision); err != nil {
return nil return nil
} }
_ = writeManyBits(bw, coefficientData, order*precision) //_ = writeManyBits(bw, coefficientData, order*precision)
if err = decodeResidual(br, bw, blockSize, order); err != nil { if err = decodeResidual(br, blockSize, order); err != nil {
return nil return nil
} }
} }
} }
if n := br.Align(); n > 0 { br.Align()
_ = bw.WriteBits(0, n)
if n, err = bw.Align(); err != nil || n != 0 {
//Alignment mismatch!
return nil
}
}
_ = bw.Close() buf := bfr.GetBuffer()
p.FrameData = make([]byte, buf.Len()) p.FrameData = make([]byte, len(buf))
copy(p.FrameData, buf.Bytes()) copy(p.FrameData, buf)
if p.CRC16, err = br.ReadBits(16); err != nil { if p.CRC16, err = br.ReadBits(16); err != nil {
return nil return nil
@ -470,12 +460,12 @@ func readFlacFrame(hdr *FLACHeaderPacket, br *bitio.Reader) *FLACPacket {
return p return p
} }
func decodeResidual(br *bitio.Reader, bw *bitio.Writer, blockSize, predictorOrder int) (err error) { func decodeResidual(br *bitio.Reader, blockSize, predictorOrder int) (err error) {
var entropyCodingMethod, partitionOrder uint64 var entropyCodingMethod, partitionOrder uint64
if entropyCodingMethod, err = br.ReadBits(2); err != nil { if entropyCodingMethod, err = br.ReadBits(2); err != nil {
return err return err
} }
_ = bw.WriteBits(entropyCodingMethod, 2) //_ = bw.WriteBits(entropyCodingMethod, 2)
paramSize := 0 paramSize := 0
@ -491,7 +481,7 @@ func decodeResidual(br *bitio.Reader, bw *bitio.Writer, blockSize, predictorOrde
if partitionOrder, err = br.ReadBits(4); err != nil { if partitionOrder, err = br.ReadBits(4); err != nil {
return err return err
} }
_ = bw.WriteBits(partitionOrder, 4) //_ = bw.WriteBits(partitionOrder, 4)
partitions := 1 << partitionOrder partitions := 1 << partitionOrder
@ -500,7 +490,7 @@ func decodeResidual(br *bitio.Reader, bw *bitio.Writer, blockSize, predictorOrde
if riceParameter, err = br.ReadBits(uint8(paramSize)); err != nil { if riceParameter, err = br.ReadBits(uint8(paramSize)); err != nil {
return err return err
} }
_ = bw.WriteBitsUnsafe(riceParameter, uint8(paramSize)) //_ = bw.WriteBitsUnsafe(riceParameter, uint8(paramSize))
var nsamples int var nsamples int
if partition != 0 { if partition != 0 {
@ -517,36 +507,36 @@ func decodeResidual(br *bitio.Reader, bw *bitio.Writer, blockSize, predictorOrde
if riceParameter2, err = br.ReadBits(5); err != nil { if riceParameter2, err = br.ReadBits(5); err != nil {
return err return err
} }
_ = bw.WriteBitsUnsafe(riceParameter2, 5) //_ = bw.WriteBitsUnsafe(riceParameter2, 5)
if riceParameter2 > 0 { if riceParameter2 > 0 {
var sampleData []byte //var sampleData []byte
if sampleData, err = readManyBits(br, nsamples*int(riceParameter2)); err != nil { if _, err = readManyBits(br, nsamples*int(riceParameter2)); err != nil {
return err return err
} }
_ = writeManyBits(bw, sampleData, nsamples*int(riceParameter2)) //_ = writeManyBits(bw, sampleData, nsamples*int(riceParameter2))
} }
} else { } else {
//TODO: optimize this! //TODO: optimize this!
var high, low uint64 //var high, low uint64
if riceParameter == 0 { if riceParameter == 0 {
for j := 0; j < nsamples; j++ { for j := 0; j < nsamples; j++ {
if high, err = readUnary(br); err != nil { if _, err = readUnary(br); err != nil {
return err return err
} }
_ = writeUnary(bw, high) //_ = writeUnary(bw, high)
} }
} else { } else {
for j := 0; j < nsamples; j++ { for j := 0; j < nsamples; j++ {
if high, err = readUnary(br); err != nil { if _, err = readUnary(br); err != nil {
return err return err
} }
_ = writeUnary(bw, high) //_ = writeUnary(bw, high)
if low, err = br.ReadBits(uint8(riceParameter)); err != nil { if _, err = br.ReadBits(uint8(riceParameter)); err != nil {
return err return err
} }
_ = bw.WriteBitsUnsafe(low, uint8(riceParameter)) //_ = bw.WriteBitsUnsafe(low, uint8(riceParameter))
} }
} }
} }
@ -934,12 +924,64 @@ func (p *FLACPacket) GetDataOffset(offset int64) []byte {
return buf.Bytes() return buf.Bytes()
} }
type cachedBitReader struct {
r *bufio.Reader
originalBuf []byte
buf []byte
byteBuf []byte
}
func newCachedBitReader(reader io.Reader, bufSize int) *cachedBitReader {
r := &cachedBitReader{
r: bufio.NewReaderSize(reader, bufSize),
buf: make([]byte, 0, bufSize),
byteBuf: make([]byte, 1),
}
r.originalBuf = r.buf[:]
return r
}
func (r *cachedBitReader) Read(p []byte) (n int, err error) {
n, err = r.r.Read(p)
if n > 0 {
r.buf = append(r.buf, p[:n]...)
}
return
}
func (r *cachedBitReader) ReadByte() (byte, error) {
n, err := r.r.Read(r.byteBuf)
if n > 0 {
r.buf = append(r.buf, r.byteBuf[0])
}
return r.byteBuf[0], err
}
func (r *cachedBitReader) GetBuffer() []byte {
return r.buf
}
func (r *cachedBitReader) ResetBuffer() {
r.buf = r.originalBuf
}
type FLACPacketizer struct { type FLACPacketizer struct {
bfr *cachedBitReader
br *bitio.Reader br *bitio.Reader
hdr *FLACHeaderPacket hdr *FLACHeaderPacket
} }
func NewFLACPacketizer(reader io.Reader) *FLACPacketizer {
p := &FLACPacketizer{
bfr: newCachedBitReader(reader, 1024*32),
}
p.br = bitio.NewReader(p.bfr)
return p
}
func (o *FLACPacketizer) GetPacket() Packet { func (o *FLACPacketizer) GetPacket() Packet {
o.bfr.ResetBuffer()
if o.hdr == nil { if o.hdr == nil {
o.hdr = readFlacHeader(o.br) o.hdr = readFlacHeader(o.br)
if o.hdr == nil { if o.hdr == nil {
@ -948,7 +990,7 @@ func (o *FLACPacketizer) GetPacket() Packet {
return o.hdr return o.hdr
} }
packet := readFlacFrame(o.hdr, o.br) packet := readFlacFrame(o.hdr, o.br, o.bfr)
if packet == nil { if packet == nil {
return nil return nil
} }