Files
go2rtc/pkg/alsa/playback_linux.go
2025-04-21 20:18:28 +03:00

95 lines
2.0 KiB
Go

package alsa
import (
"fmt"
"github.com/AlexxIT/go2rtc/pkg/alsa/device"
"github.com/AlexxIT/go2rtc/pkg/core"
"github.com/AlexxIT/go2rtc/pkg/pcm"
"github.com/pion/rtp"
)
type Playback struct {
core.Connection
dev *device.Device
closed core.Waiter
}
func newPlayback(dev *device.Device) (*Playback, error) {
medias := []*core.Media{
{
Kind: core.KindAudio,
Direction: core.DirectionSendonly,
Codecs: []*core.Codec{
{Name: core.CodecPCML}, // support ffmpeg producer (auto transcode)
{Name: core.CodecPCMA, ClockRate: 8000}, // support webrtc producer
},
},
}
return &Playback{
Connection: core.Connection{
ID: core.NewID(),
FormatName: "alsa",
Medias: medias,
Transport: dev,
},
dev: dev,
}, nil
}
func (p *Playback) GetTrack(media *core.Media, codec *core.Codec) (*core.Receiver, error) {
return nil, core.ErrCantGetTrack
}
func (p *Playback) AddTrack(media *core.Media, codec *core.Codec, track *core.Receiver) error {
in := track.Codec
// support probe
if in.Name == core.CodecAny {
in = &core.Codec{
Name: core.CodecPCML,
ClockRate: 16000,
Channels: 2,
}
}
out := &core.Codec{
Name: core.CodecPCML,
ClockRate: in.ClockRate,
Channels: 2,
}
sender := core.NewSender(media, out)
sender.Handler = func(pkt *rtp.Packet) {
if n, err := p.dev.Write(pkt.Payload); err == nil {
p.Send += n
}
}
if sender.Handler = pcm.Convert(in, out, sender.Handler); sender.Handler == nil {
return fmt.Errorf("alsa: can't convert %s to %s", in, out)
}
// typical card support:
// - Formats: S16_LE, S32_LE
// - ClockRates: 8000 - 192000
// - Channels: 2 - 10
err := p.dev.SetHWParams(device.SNDRV_PCM_FORMAT_S16_LE, out.ClockRate, 2)
if err != nil {
return err
}
sender.HandleRTP(track)
p.Senders = append(p.Senders, sender)
return nil
}
func (p *Playback) Start() (err error) {
return p.closed.Wait()
}
func (p *Playback) Stop() error {
p.closed.Done(nil)
return p.Connection.Stop()
}