use audio and video bitrate.

This commit is contained in:
m1k1o 2021-02-14 21:07:56 +01:00
parent 34954d1a54
commit 61eed9ca98
3 changed files with 40 additions and 42 deletions

View File

@ -9,7 +9,6 @@ package gst
import "C" import "C"
import ( import (
"fmt" "fmt"
"strconv"
"sync" "sync"
"time" "time"
"unsafe" "unsafe"
@ -76,7 +75,7 @@ func CreateRTMPPipeline(pipelineDevice string, pipelineDisplay string, pipelineS
} }
// CreateAppPipeline creates a GStreamer Pipeline // CreateAppPipeline creates a GStreamer Pipeline
func CreateAppPipeline(codecName string, pipelineDevice string, pipelineSrc string, bitrate int) (*Pipeline, error) { func CreateAppPipeline(codecName string, pipelineDevice string, pipelineSrc string, bitrate uint) (*Pipeline, error) {
pipelineStr := " ! appsink name=appsink" pipelineStr := " ! appsink name=appsink"
switch codecName { switch codecName {
@ -91,7 +90,7 @@ func CreateAppPipeline(codecName string, pipelineDevice string, pipelineSrc stri
if pipelineSrc != "" { if pipelineSrc != "" {
pipelineStr = fmt.Sprintf(pipelineSrc+pipelineStr, pipelineDevice) pipelineStr = fmt.Sprintf(pipelineSrc+pipelineStr, pipelineDevice)
} else { } else {
pipelineStr = fmt.Sprintf(videoSrc+"vp8enc cpu-used=-5 threads=4 deadline=1 error-resilient=partitions keyframe-max-dist=30 auto-alt-ref=true"+pipelineStr, pipelineDevice) pipelineStr = fmt.Sprintf(videoSrc+"vp8enc target-bitrate=%d cpu-used=-5 threads=4 deadline=1 error-resilient=partitions keyframe-max-dist=30 auto-alt-ref=true"+pipelineStr, pipelineDevice, bitrate*1000)
} }
case "VP9": case "VP9":
// https://gstreamer.freedesktop.org/documentation/vpx/vp9enc.html?gi-language=c // https://gstreamer.freedesktop.org/documentation/vpx/vp9enc.html?gi-language=c
@ -105,41 +104,34 @@ func CreateAppPipeline(codecName string, pipelineDevice string, pipelineSrc stri
if pipelineSrc != "" { if pipelineSrc != "" {
pipelineStr = fmt.Sprintf(pipelineSrc+pipelineStr, pipelineDevice) pipelineStr = fmt.Sprintf(pipelineSrc+pipelineStr, pipelineDevice)
} else { } else {
pipelineStr = fmt.Sprintf(videoSrc+"vp9enc"+pipelineStr, pipelineDevice) pipelineStr = fmt.Sprintf(videoSrc+"vp9enc target-bitrate=%d cpu-used=-5 threads=4 deadline=1 keyframe-max-dist=30 auto-alt-ref=true"+pipelineStr, pipelineDevice, bitrate*1000)
} }
case "H264": case "H264":
// https://gstreamer.freedesktop.org/documentation/openh264/openh264enc.html?gi-language=c#openh264enc
// gstreamer1.0-plugins-bad
// openh264enc multi-thread=4 complexity=high bitrate=3072000 max-bitrate=4096000
if err := CheckPlugins([]string{"ximagesrc"}); err != nil { if err := CheckPlugins([]string{"ximagesrc"}); err != nil {
return nil, err return nil, err
} }
if pipelineSrc != "" { if pipelineSrc != "" {
pipelineStr = fmt.Sprintf(pipelineSrc+pipelineStr, pipelineDevice) pipelineStr = fmt.Sprintf(pipelineSrc+pipelineStr, pipelineDevice)
} else { break
var h264Str string }
h264Str = "openh264enc multi-thread=4 complexity=high bitrate=3072000 max-bitrate=4096000 ! video/x-h264,stream-format=byte-stream"
if bitrate > 0 { // https://gstreamer.freedesktop.org/documentation/openh264/openh264enc.html?gi-language=c#openh264enc
h264Str = "openh264enc multi-thread=4 complexity=high bitrate=" + strconv.Itoa(bitrate) + "000 max-bitrate=" + strconv.Itoa(bitrate) + "999 ! video/x-h264,stream-format=byte-stream" // gstreamer1.0-plugins-bad
// openh264enc multi-thread=4 complexity=high bitrate=3072000 max-bitrate=4096000
if err := CheckPlugins([]string{"openh264"}); err == nil {
pipelineStr = fmt.Sprintf(videoSrc+"openh264enc multi-thread=4 complexity=high bitrate=%d max-bitrate=%d ! video/x-h264,stream-format=byte-stream"+pipelineStr, pipelineDevice, bitrate*1000, (bitrate+1024)*1000)
break
} }
// https://gstreamer.freedesktop.org/documentation/x264/index.html?gi-language=c // https://gstreamer.freedesktop.org/documentation/x264/index.html?gi-language=c
// gstreamer1.0-plugins-ugly // gstreamer1.0-plugins-ugly
// video/x-raw,format=I420 ! x264enc bframes=0 key-int-max=60 byte-stream=true tune=zerolatency speed-preset=veryfast ! video/x-h264,stream-format=byte-stream // video/x-raw,format=I420 ! x264enc bframes=0 key-int-max=60 byte-stream=true tune=zerolatency speed-preset=veryfast ! video/x-h264,stream-format=byte-stream
if err := CheckPlugins([]string{"openh264"}); err != nil {
h264Str = "video/x-raw,format=I420 ! x264enc threads=4 byte-stream=true tune=zerolatency speed-preset=veryfast ! video/x-h264,stream-format=byte-stream"
if bitrate > 0 {
h264Str = "video/x-raw,format=I420 ! x264enc threads=4 bitrate=" + strconv.Itoa(bitrate) + " byte-stream=true tune=zerolatency speed-preset=veryfast ! video/x-h264,stream-format=byte-stream"
}
if err := CheckPlugins([]string{"x264"}); err != nil { if err := CheckPlugins([]string{"x264"}); err != nil {
return nil, err return nil, err
} }
}
pipelineStr = fmt.Sprintf(videoSrc+h264Str+pipelineStr, pipelineDevice) pipelineStr = fmt.Sprintf(videoSrc+"video/x-raw,format=I420 ! x264enc threads=4 bitrate=%d byte-stream=true tune=zerolatency speed-preset=veryfast ! video/x-h264,stream-format=byte-stream"+pipelineStr, pipelineDevice, bitrate)
}
case "Opus": case "Opus":
// https://gstreamer.freedesktop.org/documentation/opus/opusenc.html // https://gstreamer.freedesktop.org/documentation/opus/opusenc.html
// gstreamer1.0-plugins-base // gstreamer1.0-plugins-base
@ -151,7 +143,7 @@ func CreateAppPipeline(codecName string, pipelineDevice string, pipelineSrc stri
if pipelineSrc != "" { if pipelineSrc != "" {
pipelineStr = fmt.Sprintf(pipelineSrc+pipelineStr, pipelineDevice) pipelineStr = fmt.Sprintf(pipelineSrc+pipelineStr, pipelineDevice)
} else { } else {
pipelineStr = fmt.Sprintf(audioSrc+"opusenc"+pipelineStr, pipelineDevice) pipelineStr = fmt.Sprintf(audioSrc+"opusenc bitrate=%d"+pipelineStr, pipelineDevice, bitrate*1000)
} }
case "G722": case "G722":
// https://gstreamer.freedesktop.org/documentation/libav/avenc_g722.html?gi-language=c // https://gstreamer.freedesktop.org/documentation/libav/avenc_g722.html?gi-language=c
@ -164,7 +156,7 @@ func CreateAppPipeline(codecName string, pipelineDevice string, pipelineSrc stri
if pipelineSrc != "" { if pipelineSrc != "" {
pipelineStr = fmt.Sprintf(pipelineSrc+pipelineStr, pipelineDevice) pipelineStr = fmt.Sprintf(pipelineSrc+pipelineStr, pipelineDevice)
} else { } else {
pipelineStr = fmt.Sprintf(audioSrc+"avenc_g722"+pipelineStr, pipelineDevice) pipelineStr = fmt.Sprintf(audioSrc+"avenc_g722 bitrate=%d"+pipelineStr, pipelineDevice, bitrate*1000)
} }
case "PCMU": case "PCMU":
// https://gstreamer.freedesktop.org/documentation/mulaw/mulawenc.html?gi-language=c // https://gstreamer.freedesktop.org/documentation/mulaw/mulawenc.html?gi-language=c

View File

@ -135,7 +135,7 @@ func (manager *RemoteManager) createPipelines() {
manager.config.VideoCodec, manager.config.VideoCodec,
manager.config.Display, manager.config.Display,
manager.config.VideoParams, manager.config.VideoParams,
manager.config.Bitrate, manager.config.VideoBitrate,
) )
if err != nil { if err != nil {
manager.logger.Panic().Err(err).Msg("unable to create video pipeline") manager.logger.Panic().Err(err).Msg("unable to create video pipeline")
@ -145,7 +145,7 @@ func (manager *RemoteManager) createPipelines() {
manager.config.AudioCodec, manager.config.AudioCodec,
manager.config.Device, manager.config.Device,
manager.config.AudioParams, manager.config.AudioParams,
0, manager.config.AudioBitrate,
) )
if err != nil { if err != nil {
manager.logger.Panic().Err(err).Msg("unable to create audio pipeline") manager.logger.Panic().Err(err).Msg("unable to create audio pipeline")
@ -176,7 +176,7 @@ func (manager *RemoteManager) ChangeResolution(width int, height int, rate int)
manager.config.VideoCodec, manager.config.VideoCodec,
manager.config.Display, manager.config.Display,
manager.config.VideoParams, manager.config.VideoParams,
manager.config.Bitrate, manager.config.VideoBitrate,
) )
if err != nil { if err != nil {
manager.logger.Panic().Err(err).Msg("unable to create new video pipeline") manager.logger.Panic().Err(err).Msg("unable to create new video pipeline")

View File

@ -13,12 +13,13 @@ type Remote struct {
Device string Device string
AudioCodec string AudioCodec string
AudioParams string AudioParams string
AudioBitrate uint
VideoCodec string VideoCodec string
VideoParams string VideoParams string
VideoBitrate uint
ScreenWidth int ScreenWidth int
ScreenHeight int ScreenHeight int
ScreenRate int ScreenRate int
Bitrate int
} }
func (Remote) Init(cmd *cobra.Command) error { func (Remote) Init(cmd *cobra.Command) error {
@ -37,22 +38,26 @@ func (Remote) Init(cmd *cobra.Command) error {
return err return err
} }
cmd.PersistentFlags().Int("audio_bitrate", 128, "audio bitrate in kbit/s")
if err := viper.BindPFlag("audio_bitrate", cmd.PersistentFlags().Lookup("audio_bitrate")); err != nil {
return err
}
cmd.PersistentFlags().String("video", "", "video codec parameters to use for streaming") cmd.PersistentFlags().String("video", "", "video codec parameters to use for streaming")
if err := viper.BindPFlag("video", cmd.PersistentFlags().Lookup("video")); err != nil { if err := viper.BindPFlag("video", cmd.PersistentFlags().Lookup("video")); err != nil {
return err return err
} }
cmd.PersistentFlags().Int("video_bitrate", 3072, "video bitrate in kbit/s")
if err := viper.BindPFlag("video_bitrate", cmd.PersistentFlags().Lookup("video_bitrate")); err != nil {
return err
}
cmd.PersistentFlags().String("screen", "1280x720@30", "default screen resolution and framerate") cmd.PersistentFlags().String("screen", "1280x720@30", "default screen resolution and framerate")
if err := viper.BindPFlag("screen", cmd.PersistentFlags().Lookup("screen")); err != nil { if err := viper.BindPFlag("screen", cmd.PersistentFlags().Lookup("screen")); err != nil {
return err return err
} }
cmd.PersistentFlags().Int("bitrate", 0, "set this video bitrate when possible")
if err := viper.BindPFlag("bitrate", cmd.PersistentFlags().Lookup("bitrate")); err != nil {
return err
}
// video codecs // video codecs
cmd.PersistentFlags().Bool("vp8", false, "use VP8 video codec") cmd.PersistentFlags().Bool("vp8", false, "use VP8 video codec")
if err := viper.BindPFlag("vp8", cmd.PersistentFlags().Lookup("vp8")); err != nil { if err := viper.BindPFlag("vp8", cmd.PersistentFlags().Lookup("vp8")); err != nil {
@ -117,10 +122,11 @@ func (s *Remote) Set() {
s.Device = viper.GetString("device") s.Device = viper.GetString("device")
s.AudioCodec = audioCodec s.AudioCodec = audioCodec
s.AudioParams = viper.GetString("audio") s.AudioParams = viper.GetString("audio")
s.AudioBitrate = viper.GetUint("audio_bitrate")
s.Display = viper.GetString("display") s.Display = viper.GetString("display")
s.VideoCodec = videoCodec s.VideoCodec = videoCodec
s.VideoParams = viper.GetString("video") s.VideoParams = viper.GetString("video")
s.Bitrate = viper.GetInt("bitrate") s.VideoBitrate = viper.GetUint("video_bitrate")
s.ScreenWidth = 1280 s.ScreenWidth = 1280
s.ScreenHeight = 720 s.ScreenHeight = 720