mirror of
https://github.com/AlexxIT/go2rtc.git
synced 2025-09-27 04:36:12 +08:00
85 lines
1.9 KiB
Go
85 lines
1.9 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 {
|
|
src := track.Codec
|
|
dst := &core.Codec{
|
|
Name: core.CodecPCML,
|
|
ClockRate: p.dev.GetRateNear(src.ClockRate),
|
|
Channels: p.dev.GetChannelsNear(src.Channels),
|
|
}
|
|
sender := core.NewSender(media, dst)
|
|
|
|
sender.Handler = func(pkt *rtp.Packet) {
|
|
if n, err := p.dev.Write(pkt.Payload); err == nil {
|
|
p.Send += n
|
|
}
|
|
}
|
|
|
|
if sender.Handler = pcm.TranscodeHandler(dst, src, sender.Handler); sender.Handler == nil {
|
|
return fmt.Errorf("alsa: can't convert %s to %s", src, dst)
|
|
}
|
|
|
|
// typical card support:
|
|
// - Formats: S16_LE, S32_LE
|
|
// - ClockRates: 8000 - 192000
|
|
// - Channels: 2 - 10
|
|
err := p.dev.SetHWParams(device.SNDRV_PCM_FORMAT_S16_LE, dst.ClockRate, byte(dst.Channels))
|
|
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()
|
|
}
|