Decrease memory usage of AAC decoding, use int16 sample format

This commit is contained in:
DataHoarder 2022-07-21 10:02:35 +02:00
parent 386837a4f7
commit 84c6c3b064
Signed by: DataHoarder
SSH key fingerprint: SHA256:OLTRf6Fl87G52SiR7sWLGNzlJt4WOX+tfI2yxo0z7xk

View file

@ -131,7 +131,7 @@ func (f Format) Open(r io.ReadSeekCloser) (audio.Source, error) {
return nil, err
}
source := audio.NewFloat32Source(decoder.SampleRate(), decoder.NumChannels())
source := audio.NewInt16Source(16, decoder.SampleRate(), decoder.NumChannels())
go func() {
defer source.Close()
@ -169,7 +169,7 @@ func (f Format) Open(r io.ReadSeekCloser) (audio.Source, error) {
return nil, err
}
source := audio.NewFloat32Source(decoder.SampleRate(), decoder.NumChannels())
source := audio.NewInt16Source(16, decoder.SampleRate(), decoder.NumChannels())
go func() {
defer source.Close()
@ -315,6 +315,74 @@ func (f Format) Encode(source audio.Source, writer io.WriteCloser, options map[s
frameSize := encoder.FrameSize() * encoder.Channels()
encodeSource := func(source audio.Source, writeCallback func(frame []byte) error) error {
buffer := make([]int16, 0, frameSize)
for block := range source.ToInt16().GetBlocks() {
buffer = append(buffer, block...)
tempBuffer := buffer[:]
for len(tempBuffer) >= frameSize {
sl := tempBuffer[:frameSize]
frameBuffer, err := encoder.Encode(unsafe.Slice((*byte)(unsafe.Pointer(&sl[0])), len(sl)*2))
if err != nil {
return err
}
if len(frameBuffer) > 0 {
if err = writeCallback(frameBuffer); err != nil {
return err
}
}
tempBuffer = tempBuffer[frameSize:]
}
if len(tempBuffer) > 0 {
copy(buffer, tempBuffer)
}
buffer = buffer[:len(tempBuffer)]
}
if len(buffer) > 0 {
//pad
buffer = append(buffer, make([]int16, frameSize-len(buffer))...)
frameBuffer, err := encoder.Encode(unsafe.Slice((*byte)(unsafe.Pointer(&buffer[0])), len(buffer)*2))
if err != nil {
return err
}
if len(frameBuffer) > 0 {
if err = writeCallback(frameBuffer); err != nil {
return err
}
}
}
//Do flush
for {
frameBuffer, err := encoder.Flush()
if err != nil {
return err
}
if len(frameBuffer) > 0 {
if err = writeCallback(frameBuffer); err != nil {
return err
}
} else {
break
}
}
return nil
}
if format == "mp4" {
init := mp4.CreateEmptyInit()
init.AddEmptyTrack(uint32(source.GetSampleRate()), "audio", "en")
@ -392,126 +460,28 @@ func (f Format) Encode(source audio.Source, writer io.WriteCloser, options map[s
outputBuffer = nil
}
outputPacket := func(packet []byte) {
outputBuffer = append(outputBuffer, packet)
if err := encodeSource(source, func(frame []byte) error {
outputBuffer = append(outputBuffer, frame)
if time.Duration(float64(time.Second)*(float64(frameSize*len(outputBuffer))/float64(source.GetSampleRate()))) >= segmentDuration {
outputSegment()
}
}
var buffer []int16
for block := range source.ToInt16().GetBlocks() {
buffer = append(buffer, block...)
for len(buffer) >= frameSize {
sl := buffer[:frameSize]
buf, err := encoder.Encode(unsafe.Slice((*byte)(unsafe.Pointer(&sl[0])), len(sl)*2))
if err != nil {
return err
}
if len(buf) > 0 {
outputPacket(buf)
}
buffer = buffer[frameSize:]
}
}
if len(buffer) > 0 {
//pad
buffer = append(buffer, make([]int16, frameSize-len(buffer))...)
buf, err := encoder.Encode(unsafe.Slice((*byte)(unsafe.Pointer(&buffer[0])), len(buffer)*2))
if err != nil {
return err
}
if len(buf) > 0 {
outputPacket(buf)
}
}
//Do flush
for {
buf, err := encoder.Flush()
if err != nil {
return err
}
if len(buf) > 0 {
outputPacket(buf)
} else {
break
}
return nil
}); err != nil {
return err
}
if len(outputBuffer) > 0 {
outputSegment()
}
} else {
var buffer []int16
for block := range source.ToInt16().GetBlocks() {
buffer = append(buffer, block...)
for len(buffer) >= frameSize {
sl := buffer[:frameSize]
buf, err := encoder.Encode(unsafe.Slice((*byte)(unsafe.Pointer(&sl[0])), len(sl)*2))
if err != nil {
return err
}
if len(buf) > 0 {
_, err = writer.Write(buf)
if err != nil {
return err
}
}
buffer = buffer[frameSize:]
}
}
if len(buffer) > 0 {
//pad
buffer = append(buffer, make([]int16, frameSize-len(buffer))...)
buf, err := encoder.Encode(unsafe.Slice((*byte)(unsafe.Pointer(&buffer[0])), len(buffer)*2))
if err := encodeSource(source, func(frame []byte) error {
_, err := writer.Write(frame)
if err != nil {
return err
}
if len(buf) > 0 {
_, err = writer.Write(buf)
if err != nil {
return err
}
}
}
//Do flush
for {
buf, err := encoder.Flush()
if err != nil {
return err
}
if len(buf) > 0 {
_, err = writer.Write(buf)
if err != nil {
return err
}
} else {
break
}
return nil
}); err != nil {
return err
}
}