add codec handling

This commit is contained in:
kaedwen
2023-07-21 21:08:36 +02:00
parent e738657c58
commit 1dd37c1727
7 changed files with 119 additions and 31 deletions
+2 -1
View File
@@ -16,7 +16,8 @@
"AUDIO_OUT_DEVICE": "plughw:0,1,0",
"INPUT_DEVICE": "/dev/input/event5",
"JINGLE_PATH": "${workspaceFolder}/audio",
"SONOS_TARGET": "Living Room"
"SONOS_TARGET": "Living Room",
"VIDEO_OUT_CODEC": "h264",
}
},
{
+52
View File
@@ -0,0 +1,52 @@
package common
import (
"fmt"
"strings"
"github.com/pion/webrtc/v3"
)
type StreamCodec string
const (
// video codecs
H264 StreamCodec = "H264"
VP8 StreamCodec = "VP8"
VP9 StreamCodec = "VP9"
// audio codecs
OPUS StreamCodec = "OPUS"
)
func (c *StreamCodec) UnmarshalText(text []byte) error {
switch strings.ToUpper(string(text)) {
case string(H264):
*c = H264
case string(VP8):
*c = VP8
case string(VP9):
*c = VP9
case string(OPUS):
*c = OPUS
default:
return fmt.Errorf("unsupported codec - %s", text)
}
return nil
}
func (c StreamCodec) Mime() string {
switch c {
case H264:
return webrtc.MimeTypeH264
case VP8:
return webrtc.MimeTypeVP8
case VP9:
return webrtc.MimeTypeVP9
case OPUS:
return webrtc.MimeTypeOpus
default:
return "UNKNOWN"
}
}
+12 -12
View File
@@ -47,21 +47,21 @@ type ConfigHTTP struct {
}
type ConfigVideoOutputStream struct {
Source string `arg:"--video-out-src,env:VIDEO_OUT_SRC" default:"v4l2src"`
Device string `arg:"--video-out-device,env:VIDEO_OUT_DEVICE" default:"/dev/video0"`
Codec string `arg:"--video-out-codec,env:VIDEO_OUT_CODEC" default:"vp8"`
Height uint `arg:"--video-out-height,env:VIDEO_OUT_HEIGHT" default:"480"`
Width uint `arg:"--video-out-width,env:VIDEO_OUT_WIDTH" default:"640"`
USE_QUEUE bool `arg:"--video-out-queue,env:VIDEO_OUT_QUEUE" default:"false"`
Source string `arg:"--video-out-src,env:VIDEO_OUT_SRC" default:"v4l2src"`
Device string `arg:"--video-out-device,env:VIDEO_OUT_DEVICE" default:"/dev/video0"`
Codec StreamCodec `arg:"--video-out-codec,env:VIDEO_OUT_CODEC" default:"vp8"`
Height uint `arg:"--video-out-height,env:VIDEO_OUT_HEIGHT" default:"480"`
Width uint `arg:"--video-out-width,env:VIDEO_OUT_WIDTH" default:"640"`
USE_QUEUE bool `arg:"--video-out-queue,env:VIDEO_OUT_QUEUE" default:"false"`
}
type ConfigAudioOutputStream struct {
Source string `arg:"--audio-out-src,env:AUDIO_OUT_SRC" default:"alsasrc"`
DeviceName string `arg:"--audio-out-device-name,env:AUDIO_OUT_DEVICE" default:"default"`
Device *string `arg:"--audio-out-device,env:AUDIO_OUT_DEVICE"`
Codec string `arg:"--audio-out-codec,env:AUDIO_OUT_CODEC" default:"opus"`
Channels uint `arg:"--audio-out-channels,env:AUDIO_OUT_CHANNELS" default:"1"`
USE_QUEUE bool `arg:"--audio-out-queue,env:AUDIO_OUT_QUEUE" default:"false"`
Source string `arg:"--audio-out-src,env:AUDIO_OUT_SRC" default:"alsasrc"`
DeviceName string `arg:"--audio-out-device-name,env:AUDIO_OUT_DEVICE" default:"default"`
Device *string `arg:"--audio-out-device,env:AUDIO_OUT_DEVICE"`
Codec StreamCodec `arg:"--audio-out-codec,env:AUDIO_OUT_CODEC" default:"opus"`
Channels uint `arg:"--audio-out-channels,env:AUDIO_OUT_CHANNELS" default:"1"`
USE_QUEUE bool `arg:"--audio-out-queue,env:AUDIO_OUT_QUEUE" default:"false"`
}
type ConfigAudioInputStream struct {
+4
View File
@@ -7,3 +7,7 @@ func Time[T any](runnable func() (T, error)) (time.Duration, T, error) {
res, err := runnable()
return time.Since(t), res, err
}
func Ptr[T any](v T) *T {
return &v
}
+41 -16
View File
@@ -1,6 +1,9 @@
package streamer
import (
"fmt"
"github.com/kaedwen/webrtc/pkg/common"
"github.com/pion/webrtc/v3/pkg/media"
"github.com/tinyzimmer/go-gst/gst"
"github.com/tinyzimmer/go-gst/gst/app"
@@ -80,18 +83,35 @@ func CreateVideoPipelineSink(s StreamElement) (*gst.Pipeline, <-chan media.Sampl
elems = append(elems, queue)
}
// Create the enc
enc, err := gst.NewElement("vp8enc")
if err != nil {
return nil, nil, err
}
elems = append(elems, enc)
switch s.Codec {
case common.VP8:
// Create the enc
enc, err := gst.NewElement("vp8enc")
if err != nil {
return nil, nil, err
}
elems = append(elems, enc)
enc.SetProperty("error-resilient", "partitions")
enc.SetProperty("keyframe-max-dist", 10)
enc.SetProperty("auto-alt-ref", true)
enc.SetProperty("cpu-used", 5)
enc.SetProperty("deadline", 1)
enc.SetProperty("error-resilient", "partitions")
enc.SetProperty("keyframe-max-dist", 10)
enc.SetProperty("auto-alt-ref", true)
enc.SetProperty("cpu-used", 5)
enc.SetProperty("deadline", 1)
case common.H264:
// Create the enc
enc, err := gst.NewElement("x264enc")
if err != nil {
return nil, nil, err
}
elems = append(elems, enc)
enc.SetProperty("speed-preset", "ultrafast")
enc.SetProperty("tune", "zerolatency")
enc.SetProperty("key-int-max", 2)
enc.SetProperty("bitrate", 300)
default:
return nil, nil, fmt.Errorf("unsupported video codec given - %s", s.Codec)
}
// Create the sink
appsink, err := app.NewAppSink()
@@ -158,12 +178,17 @@ func CreateAudioPipelineSink(s StreamElement) (*gst.Pipeline, <-chan media.Sampl
elems = append(elems, queue)
}
// Create the enc
enc, err := gst.NewElement("opusenc")
if err != nil {
return nil, nil, err
switch s.Codec {
case common.OPUS:
// Create the enc
enc, err := gst.NewElement("opusenc")
if err != nil {
return nil, nil, err
}
elems = append(elems, enc)
default:
return nil, nil, fmt.Errorf("unsupported audio codec given - %s", s.Codec)
}
elems = append(elems, enc)
// Create the sink
appsink, err := app.NewAppSink()
+2
View File
@@ -6,6 +6,7 @@ import (
"strings"
"time"
"github.com/kaedwen/webrtc/pkg/common"
"github.com/tinyzimmer/go-gst/gst"
"github.com/tinyzimmer/go-gst/gst/app"
"go.uber.org/zap"
@@ -28,6 +29,7 @@ type StreamElementCaps struct {
type StreamElement struct {
Kind string
Codec common.StreamCodec
Properties map[string]interface{}
Caps *StreamElementCaps
Queue bool
+6 -2
View File
@@ -22,6 +22,7 @@ const STUN_SERVER = "stun:stun.l.google.com:19302"
type WebrtcHandler struct {
lg *zap.Logger
mu *sync.Mutex
cfg *common.ConfigStream
audioPipeline *gst.Pipeline
videoPipeline *gst.Pipeline
peerHandles map[string]*PeerHandle
@@ -35,6 +36,7 @@ type PeerHandle struct {
func NewWebrtcHandler(ctx context.Context, lg *zap.Logger, cfg *common.ConfigStream, ch <-chan *server.SignalingHandle) error {
wh := WebrtcHandler{
lg: lg,
cfg: cfg,
mu: &sync.Mutex{},
peerHandles: make(map[string]*PeerHandle, 0),
}
@@ -124,6 +126,7 @@ func (wh *WebrtcHandler) handleAudioSamples(ctx context.Context, cfg *common.Con
Rate: 48000,
},
Queue: cfg.USE_QUEUE,
Codec: cfg.Codec,
}
var err error
@@ -168,6 +171,7 @@ func (wh *WebrtcHandler) handleVideoSamples(ctx context.Context, cfg *common.Con
Height: cfg.Height,
},
Queue: cfg.USE_QUEUE,
Codec: cfg.Codec,
}
var err error
@@ -299,7 +303,7 @@ func (wh *WebrtcHandler) createPeerHandle(rctx context.Context, sh *server.Signa
})
// Create a audio track
audioTrack, err := webrtc.NewTrackLocalStaticSample(webrtc.RTPCodecCapability{MimeType: "audio/opus"}, "audio", "pion1")
audioTrack, err := webrtc.NewTrackLocalStaticSample(webrtc.RTPCodecCapability{MimeType: wh.cfg.AudioOut.Codec.Mime()}, "audio", "pion1")
if err != nil {
return err
}
@@ -309,7 +313,7 @@ func (wh *WebrtcHandler) createPeerHandle(rctx context.Context, sh *server.Signa
}
// Create a video track
videoTrack, err := webrtc.NewTrackLocalStaticSample(webrtc.RTPCodecCapability{MimeType: "video/vp8"}, "video", "pion2")
videoTrack, err := webrtc.NewTrackLocalStaticSample(webrtc.RTPCodecCapability{MimeType: wh.cfg.VideoOut.Codec.Mime()}, "video", "pion2")
if err != nil {
return err
}