2022-09-03 14:20:40 +00:00
|
|
|
package aps1
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"encoding/binary"
|
|
|
|
"encoding/json"
|
|
|
|
"errors"
|
|
|
|
"git.gammaspectra.live/S.O.N.G/Kirika/audio/packetizer"
|
|
|
|
"git.gammaspectra.live/S.O.N.G/MeteorLight/listener"
|
|
|
|
"git.gammaspectra.live/S.O.N.G/MeteorLight/queue/metadata"
|
|
|
|
"sync/atomic"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Listener struct {
|
|
|
|
information listener.Information
|
|
|
|
started atomic.Bool
|
|
|
|
streamStartOffset int64
|
|
|
|
streamSamplesBuffer int64
|
|
|
|
|
2022-10-02 13:19:51 +00:00
|
|
|
writer listener.WriterFunc
|
|
|
|
waiter chan struct{}
|
2022-09-03 14:20:40 +00:00
|
|
|
offsetStart bool
|
|
|
|
headerBytes []byte
|
|
|
|
}
|
|
|
|
|
2022-10-02 13:19:51 +00:00
|
|
|
func NewListener(info listener.Information, writer listener.WriterFunc, samplesToBuffer int64, offsetStart bool, channels, sampleRate int, mimeType string) (*Listener, map[string]string) {
|
2022-09-03 14:20:40 +00:00
|
|
|
headers := make(map[string]string)
|
|
|
|
headers["x-audio-packet-stream"] = "1"
|
|
|
|
headers["content-type"] = "application/x-audio-packet-stream"
|
|
|
|
|
|
|
|
headerBytes := new(bytes.Buffer)
|
|
|
|
|
2022-10-03 09:56:54 +00:00
|
|
|
_ = binary.Write(headerBytes, binary.LittleEndian, int64(channels))
|
|
|
|
_ = binary.Write(headerBytes, binary.LittleEndian, int64(sampleRate))
|
|
|
|
_ = binary.Write(headerBytes, binary.LittleEndian, int32(len(mimeType)))
|
2022-09-03 14:20:40 +00:00
|
|
|
headerBytes.Write([]byte(mimeType))
|
|
|
|
|
|
|
|
return &Listener{
|
|
|
|
information: info,
|
2022-10-02 13:19:51 +00:00
|
|
|
writer: writer,
|
2022-09-03 14:20:40 +00:00
|
|
|
offsetStart: offsetStart,
|
|
|
|
streamSamplesBuffer: samplesToBuffer,
|
|
|
|
streamStartOffset: -1,
|
|
|
|
headerBytes: headerBytes.Bytes(),
|
2022-10-02 13:19:51 +00:00
|
|
|
waiter: make(chan struct{}),
|
2022-09-03 14:20:40 +00:00
|
|
|
}, headers
|
|
|
|
}
|
|
|
|
|
2022-10-02 13:19:51 +00:00
|
|
|
func (l *Listener) Wait() {
|
|
|
|
<-l.waiter
|
|
|
|
}
|
|
|
|
|
2022-09-03 14:20:40 +00:00
|
|
|
func (l *Listener) Identifier() string {
|
|
|
|
return l.information.Identifier
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *Listener) Information() *listener.Information {
|
|
|
|
return &l.information
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *Listener) HasStarted() bool {
|
|
|
|
return l.started.Load()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *Listener) Start(packets []packetizer.Packet) error {
|
|
|
|
if l.started.Swap(true) {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-10-02 13:19:51 +00:00
|
|
|
if err := l.writer((&packetStreamFrame{
|
2022-09-03 14:20:40 +00:00
|
|
|
Type: Header,
|
|
|
|
Category: 0,
|
|
|
|
StartSampleNumber: 0,
|
|
|
|
DurationInSamples: 0,
|
|
|
|
Data: l.headerBytes,
|
2022-10-02 13:19:51 +00:00
|
|
|
}).Encode()); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2022-09-03 14:20:40 +00:00
|
|
|
|
|
|
|
if len(packets) > 0 {
|
|
|
|
sampleBufferMin := packets[len(packets)-1].GetStartSampleNumber() - l.streamSamplesBuffer
|
|
|
|
for _, p := range packets {
|
|
|
|
if p.KeepMode() != packetizer.Discard || p.GetEndSampleNumber() >= sampleBufferMin {
|
|
|
|
if err := l.Write(p); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *Listener) Write(packet packetizer.Packet) error {
|
|
|
|
if metadataPacket, ok := packet.(*metadata.Packet); ok {
|
|
|
|
|
|
|
|
queueInfoBuf := make([]byte, binary.MaxVarintLen64)
|
2022-09-05 15:11:49 +00:00
|
|
|
n := binary.PutVarint(queueInfoBuf, int64(metadataPacket.TrackEntry.Identifier))
|
2022-09-03 14:20:40 +00:00
|
|
|
|
2022-10-02 13:19:51 +00:00
|
|
|
if err := l.writer((&packetStreamFrame{
|
2022-09-03 14:20:40 +00:00
|
|
|
Type: TrackIdentifier,
|
|
|
|
Category: packet.Category(),
|
|
|
|
StartSampleNumber: packet.GetStartSampleNumber(),
|
|
|
|
DurationInSamples: packet.GetEndSampleNumber() - packet.GetStartSampleNumber(),
|
|
|
|
Data: queueInfoBuf[:n],
|
2022-10-02 13:19:51 +00:00
|
|
|
}).Encode()); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2022-09-03 14:20:40 +00:00
|
|
|
|
|
|
|
if metadataBytes, err := json.Marshal(metadataPacket.TrackEntry.Metadata); err == nil {
|
|
|
|
|
2022-10-02 13:19:51 +00:00
|
|
|
if err := l.writer((&packetStreamFrame{
|
2022-09-03 14:20:40 +00:00
|
|
|
Type: TrackMetadata,
|
|
|
|
Category: packet.Category(),
|
|
|
|
StartSampleNumber: packet.GetStartSampleNumber(),
|
|
|
|
DurationInSamples: packet.GetEndSampleNumber() - packet.GetStartSampleNumber(),
|
|
|
|
Data: metadataBytes,
|
2022-10-02 13:19:51 +00:00
|
|
|
}).Encode()); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2022-09-03 14:20:40 +00:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
var frameType PacketStreamType
|
|
|
|
switch packet.KeepMode() {
|
|
|
|
case packetizer.KeepLast:
|
|
|
|
frameType = DataKeepLast
|
|
|
|
case packetizer.Keep:
|
|
|
|
frameType = DataKeep
|
|
|
|
case packetizer.GroupKeep:
|
|
|
|
frameType = DataGroupKeep
|
|
|
|
case packetizer.GroupDiscard:
|
|
|
|
frameType = DataGroupDiscard
|
|
|
|
case packetizer.Discard:
|
|
|
|
frameType = DataDiscard
|
|
|
|
default:
|
|
|
|
return errors.New("unknown KeepMode")
|
|
|
|
}
|
|
|
|
|
2022-10-02 13:19:51 +00:00
|
|
|
return l.writer((&packetStreamFrame{
|
2022-09-03 14:20:40 +00:00
|
|
|
Type: frameType,
|
|
|
|
Category: packet.Category(),
|
|
|
|
StartSampleNumber: packet.GetStartSampleNumber(),
|
|
|
|
DurationInSamples: packet.GetEndSampleNumber() - packet.GetStartSampleNumber(),
|
|
|
|
Data: packet.GetData(),
|
2022-10-02 13:19:51 +00:00
|
|
|
}).Encode())
|
2022-09-03 14:20:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (l *Listener) Close() {
|
2022-10-03 09:56:54 +00:00
|
|
|
_ = l.writer(nil)
|
2022-10-02 13:19:51 +00:00
|
|
|
close(l.waiter)
|
2022-09-03 14:20:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type PacketStreamType uint64
|
|
|
|
|
|
|
|
// PacketStreamType The order of these fields is important and set on-wire protocol
|
|
|
|
const (
|
|
|
|
Header = PacketStreamType(iota)
|
|
|
|
DataKeepLast
|
|
|
|
DataKeep
|
|
|
|
DataGroupKeep
|
|
|
|
DataGroupDiscard
|
|
|
|
DataDiscard
|
|
|
|
TrackIdentifier
|
|
|
|
TrackMetadata
|
|
|
|
)
|
|
|
|
|
|
|
|
type packetStreamFrame struct {
|
|
|
|
Type PacketStreamType
|
|
|
|
Category int64
|
|
|
|
StartSampleNumber int64
|
|
|
|
DurationInSamples int64
|
|
|
|
//automatically filled based on Data
|
|
|
|
//Size uint64
|
|
|
|
Data []byte
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *packetStreamFrame) Encode() []byte {
|
|
|
|
buf := new(bytes.Buffer)
|
|
|
|
|
|
|
|
varBuf := make([]byte, binary.MaxVarintLen64)
|
|
|
|
|
|
|
|
n := binary.PutUvarint(varBuf, uint64(p.Type))
|
|
|
|
buf.Write(varBuf[:n])
|
|
|
|
|
|
|
|
n = binary.PutUvarint(varBuf, uint64(p.Category))
|
|
|
|
buf.Write(varBuf[:n])
|
|
|
|
|
|
|
|
n = binary.PutVarint(varBuf, p.StartSampleNumber)
|
|
|
|
buf.Write(varBuf[:n])
|
|
|
|
|
|
|
|
n = binary.PutVarint(varBuf, p.DurationInSamples)
|
|
|
|
buf.Write(varBuf[:n])
|
|
|
|
|
|
|
|
n = binary.PutUvarint(varBuf, uint64(len(p.Data)))
|
|
|
|
buf.Write(varBuf[:n])
|
|
|
|
|
|
|
|
buf.Write(p.Data)
|
|
|
|
|
|
|
|
return buf.Bytes()
|
|
|
|
}
|