add codec handling
This commit is contained in:
Vendored
+2
-1
@@ -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",
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -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
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user