Packetize FLAC using libFLAC for faster parsing
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
e899166ec4
commit
44d93971c5
20
README.md
20
README.md
|
@ -27,15 +27,15 @@ Collection of audio utilities for decoding/encoding files and streams.
|
|||
|
||||
Only output from Kirika's own encoders is supported.
|
||||
|
||||
| Container | Packetizer | Keep Mode | Sample Numbers | Offset | Notes |
|
||||
|:---------:|:----------:|:---------:|:--------------:|:------:|:---------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| **FLAC** | ✅ | ✅ | ✅ | ❌ | Uses [mewkiz/flac](https://github.com/mewkiz/flac) for parsing streams. |
|
||||
| **TTA** | ❌ | - | - | - | |
|
||||
| **MP3** | ✅ | ✅ | ✅ | ✅ | Uses [sssgun/mp3](https://github.com/sssgun/mp3) as a frame parser. |
|
||||
| **Ogg** | ✅ | ✅ | ✅* | ✅ | *Sample numbers (absolute granule position in Ogg) depend on underlying codec implementing it.<br/>Has been tested as working for Opus |
|
||||
| **ADTS** | ✅ | ✅ | ✅ | ✅ | Uses [edgeware/mp4ff](https://github.com/edgeware/mp4ff) for its ADTS frame parser. |
|
||||
| **MP4** | ❌ | - | - | - | |
|
||||
| **ADIF** | ❌ | - | - | - | |
|
||||
| Container | Packetizer | Keep Mode | Sample Numbers | Offset | Notes |
|
||||
|:---------:|:----------:|:---------:|:--------------:|:------:|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| **FLAC** | ✅ | ✅ | ✅ | ❌ | Uses [libFLAC](https://github.com/xiph/flac) via [goflac](https://git.gammaspectra.live/S.O.N.G/goflac) for parsing streams.<br/>If not available, [mewkiz/flac](https://github.com/mewkiz/flac) will be used. |
|
||||
| **TTA** | ❌ | - | - | - | |
|
||||
| **MP3** | ✅ | ✅ | ✅ | ✅ | Uses [sssgun/mp3](https://github.com/sssgun/mp3) as a frame parser. |
|
||||
| **Ogg** | ✅ | ✅ | ✅* | ✅ | *Sample numbers (absolute granule position in Ogg) depend on underlying codec implementing it.<br/>Has been tested as working for Opus |
|
||||
| **ADTS** | ✅ | ✅ | ✅ | ✅ | Uses [edgeware/mp4ff](https://github.com/edgeware/mp4ff) for its ADTS frame parser. |
|
||||
| **MP4** | ❌ | - | - | - | |
|
||||
| **ADIF** | ❌ | - | - | - | |
|
||||
|
||||
## Dependencies
|
||||
### Go >= 1.18
|
||||
|
@ -136,7 +136,7 @@ If this tag is enabled, yet `aac` support remains enabled, an AAC encoder (but n
|
|||
|
||||
|
||||
### disable_codec_libflac
|
||||
This tag disables the [libFLAC](https://gitlab.xiph.org/xiph/flac) support for decoding/encoding FLAC.
|
||||
This tag disables the [libFLAC](https://gitlab.xiph.org/xiph/flac) support for decoding/encoding/packetizing FLAC.
|
||||
|
||||
If this tag is enabled, yet `flac` support remains enabled, [mewkiz/flac](https://github.com/mewkiz/flac) FLAC decoder (but not encoder) will be used.
|
||||
|
||||
|
|
|
@ -2,19 +2,9 @@ package packetizer
|
|||
|
||||
import (
|
||||
"bufio"
|
||||
flac_parser "github.com/mewkiz/flac"
|
||||
"io"
|
||||
)
|
||||
|
||||
type FLACPacketizer struct {
|
||||
reader io.Reader
|
||||
stream *flac_parser.Stream
|
||||
offset int64
|
||||
samples int64
|
||||
bytesRead int64
|
||||
buffer []byte
|
||||
}
|
||||
|
||||
type FLACPacket struct {
|
||||
mode KeepMode
|
||||
sampleNumber int64
|
||||
|
@ -47,8 +37,8 @@ func NewFLACPacketizer(reader io.Reader) *FLACPacketizer {
|
|||
}
|
||||
|
||||
func (o *FLACPacketizer) Read(p []byte) (n int, err error) {
|
||||
n, err = io.ReadFull(o.reader, p)
|
||||
if err == nil {
|
||||
n, err = o.reader.Read(p)
|
||||
if n > 0 {
|
||||
o.buffer = append(o.buffer, p[:n]...)
|
||||
}
|
||||
o.bytesRead += int64(n)
|
||||
|
@ -62,45 +52,13 @@ func (o *FLACPacketizer) Seek(offset int64, whence int) (int64, error) {
|
|||
return 0, io.ErrNoProgress
|
||||
}
|
||||
|
||||
func (o *FLACPacketizer) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *FLACPacketizer) getBuffer() (buf []byte) {
|
||||
buf = make([]byte, len(o.buffer))
|
||||
copy(buf, o.buffer)
|
||||
o.buffer = o.buffer[:0]
|
||||
return
|
||||
}
|
||||
|
||||
func (o *FLACPacketizer) GetPacket() (packet Packet) {
|
||||
var err error
|
||||
if o.stream == nil {
|
||||
o.stream, err = flac_parser.NewSeek(o)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
packet = &FLACPacket{
|
||||
mode: Keep,
|
||||
sampleNumber: 0,
|
||||
endSampleNumber: 0,
|
||||
data: o.getBuffer(),
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
frame, err := o.stream.ParseNext()
|
||||
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
sampleNumber := int64(frame.Num)
|
||||
if frame.HasFixedBlockSize {
|
||||
sampleNumber *= int64(frame.BlockSize)
|
||||
}
|
||||
packet = &FLACPacket{
|
||||
mode: Discard,
|
||||
sampleNumber: sampleNumber,
|
||||
endSampleNumber: sampleNumber + int64(frame.Subframes[0].NSamples),
|
||||
data: o.getBuffer(),
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
|
50
audio/packetizer/flac_cgo.go
Normal file
50
audio/packetizer/flac_cgo.go
Normal file
|
@ -0,0 +1,50 @@
|
|||
//go:build !disable_format_flac && !disable_codec_libflac && cgo
|
||||
|
||||
package packetizer
|
||||
|
||||
import (
|
||||
libflac "git.gammaspectra.live/S.O.N.G/goflac"
|
||||
"io"
|
||||
)
|
||||
|
||||
type FLACPacketizer struct {
|
||||
reader io.Reader
|
||||
stream *libflac.Decoder
|
||||
offset int64
|
||||
samples int64
|
||||
bytesRead int64
|
||||
buffer []byte
|
||||
}
|
||||
|
||||
func (o *FLACPacketizer) GetPacket() Packet {
|
||||
var err error
|
||||
if o.stream == nil {
|
||||
o.stream, err = libflac.NewDecoderReader(o)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return &FLACPacket{
|
||||
mode: Keep,
|
||||
sampleNumber: 0,
|
||||
endSampleNumber: 0,
|
||||
data: o.getBuffer(),
|
||||
}
|
||||
}
|
||||
|
||||
frame, err := o.stream.ReadFrame()
|
||||
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
sampleNumber := o.samples
|
||||
nsamples := int64(len(frame.Buffer)) / int64(frame.Channels)
|
||||
o.samples += nsamples
|
||||
|
||||
return &FLACPacket{
|
||||
mode: Discard,
|
||||
sampleNumber: sampleNumber,
|
||||
endSampleNumber: sampleNumber + nsamples,
|
||||
data: o.getBuffer(),
|
||||
}
|
||||
}
|
50
audio/packetizer/flac_nocgo.go
Normal file
50
audio/packetizer/flac_nocgo.go
Normal file
|
@ -0,0 +1,50 @@
|
|||
//go:build disable_format_flac || disable_codec_libflac || !cgo
|
||||
|
||||
package packetizer
|
||||
|
||||
import (
|
||||
flac_parser "github.com/mewkiz/flac"
|
||||
"io"
|
||||
)
|
||||
|
||||
type FLACPacketizer struct {
|
||||
reader io.Reader
|
||||
stream *flac_parser.Stream
|
||||
offset int64
|
||||
samples int64
|
||||
bytesRead int64
|
||||
buffer []byte
|
||||
}
|
||||
|
||||
func (o *FLACPacketizer) GetPacket() Packet {
|
||||
var err error
|
||||
if o.stream == nil {
|
||||
o.stream, err = flac_parser.NewSeek(o)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return &FLACPacket{
|
||||
mode: Keep,
|
||||
sampleNumber: 0,
|
||||
endSampleNumber: 0,
|
||||
data: o.getBuffer(),
|
||||
}
|
||||
}
|
||||
|
||||
frame, err := o.stream.ParseNext()
|
||||
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
sampleNumber := int64(frame.Num)
|
||||
if frame.HasFixedBlockSize {
|
||||
sampleNumber *= int64(frame.BlockSize)
|
||||
}
|
||||
return &FLACPacket{
|
||||
mode: Discard,
|
||||
sampleNumber: sampleNumber,
|
||||
endSampleNumber: sampleNumber + int64(frame.Subframes[0].NSamples),
|
||||
data: o.getBuffer(),
|
||||
}
|
||||
}
|
|
@ -87,7 +87,9 @@ func TestPacketizeOggOffset(t *testing.T) {
|
|||
break
|
||||
}
|
||||
packetCount++
|
||||
packetBytes += len(packet.GetDataOffset(1000))
|
||||
if offsetablePacket, ok := packet.(OffsetablePacket); ok {
|
||||
packetBytes += len(offsetablePacket.GetDataOffset(1000))
|
||||
}
|
||||
}
|
||||
if packetCount != 395 {
|
||||
t.Errorf("Wrong Packet Count %d != %d", packetCount, 395)
|
||||
|
|
Loading…
Reference in a new issue