go-alac/mp4.go

127 lines
2.7 KiB
Go

package go_alac
import (
"github.com/edgeware/mp4ff/bits"
"github.com/edgeware/mp4ff/mp4"
"io"
"time"
)
type FormatEncoder struct {
encoder *FrameEncoder
writer io.Writer
buffer []byte
segmentDuration int64
trackId uint32
seqNumber uint32
}
type alacBox struct {
cookie []byte
}
func (b *alacBox) Type() string {
return "alac"
}
// Size - calculated size of box
func (b *alacBox) Size() uint64 {
return uint64(12 + len(b.cookie))
}
// Encode - write box to w
func (b *alacBox) Encode(w io.Writer) error {
sw := bits.NewFixedSliceWriter(int(b.Size()))
err := b.EncodeSW(sw)
if err != nil {
return err
}
_, err = w.Write(sw.Bytes())
return err
}
func (b *alacBox) EncodeSW(sw bits.SliceWriter) error {
err := mp4.EncodeHeaderSW(b, sw)
if err != nil {
return err
}
sw.WriteUint32(0) //version
sw.WriteBytes(b.cookie)
return sw.AccError()
}
func (b *alacBox) Info(w io.Writer, specificBoxLevels, indent, indentStep string) error {
return nil
}
func NewFormatEncoder(writer io.Writer, sampleRate, channels, bitDepth int, fastMode bool, segmentDuration time.Duration) *FormatEncoder {
e := &FormatEncoder{
encoder: NewFrameEncoder(sampleRate, channels, bitDepth, fastMode),
writer: writer,
segmentDuration: segmentDuration.Milliseconds(),
}
if e.encoder == nil {
return nil
}
init := mp4.CreateEmptyInit()
init.AddEmptyTrack(uint32(sampleRate), "audio", "en")
e.trackId = init.Moov.Mvhd.NextTrackID - 1
trak := init.Moov.Trak
stsd := trak.Mdia.Minf.Stbl.Stsd
//TODO: this does not work with 96kHz freq etc.
mp4a := mp4.CreateAudioSampleEntryBox("alac", uint16(channels), uint16(bitDepth), uint16(sampleRate), &alacBox{
cookie: e.encoder.GetMagicCookie(),
})
stsd.AddChild(mp4a)
init.Encode(writer)
return e
}
func (e *FormatEncoder) outputPacket(packet []byte) {
//TODO: more frames
seg := mp4.NewMediaSegment()
frag, _ := mp4.CreateFragment(e.seqNumber, e.trackId)
seg.AddFragment(frag)
frag.AddFullSampleToTrack(mp4.FullSample{
Sample: mp4.Sample{
Dur: 4096, //TODO
Size: uint32(len(packet)),
},
DecodeTime: uint64(4096 * e.seqNumber),
Data: packet,
}, e.trackId)
seg.Encode(e.writer)
e.seqNumber++
}
func (e *FormatEncoder) Write(pcm []byte) {
if e.encoder == nil {
return
}
e.buffer = append(e.buffer, pcm...)
inputSize := e.encoder.GetInputSize()
for len(e.buffer) >= inputSize {
e.outputPacket(e.encoder.WritePacket(e.buffer[:inputSize]))
e.buffer = e.buffer[inputSize:]
}
}
func (e *FormatEncoder) Flush() {
if e.encoder == nil {
return
}
if len(e.buffer) > 0 {
e.outputPacket(e.encoder.WritePacket(e.buffer))
e.buffer = nil
}
//TODO: flush end
}