remove go-events
This commit is contained in:
committed by
Miroslav Šedivý
parent
cfc6bd417f
commit
5690a849e2
@ -51,6 +51,7 @@ func CreatePipeline(pipelineStr string) (*Pipeline, error) {
|
||||
|
||||
if gstError != nil {
|
||||
defer C.g_error_free(gstError)
|
||||
fmt.Printf("(pipeline error) %s", C.GoString(gstError.message))
|
||||
return nil, fmt.Errorf("(pipeline error) %s", C.GoString(gstError.message))
|
||||
}
|
||||
|
||||
@ -177,6 +178,7 @@ func goHandlePipelineBuffer(buffer unsafe.Pointer, bufferLen C.int, duration C.i
|
||||
if ok {
|
||||
pipeline.Sample <- types.Sample{
|
||||
Data: C.GoBytes(buffer, bufferLen),
|
||||
Timestamp: time.Now(),
|
||||
Duration: time.Duration(duration),
|
||||
}
|
||||
} else {
|
||||
|
@ -18,12 +18,12 @@ type CaptureManagerCtx struct {
|
||||
broadcast *BroacastManagerCtx
|
||||
audio *StreamSinkManagerCtx
|
||||
video *StreamSinkManagerCtx
|
||||
|
||||
}
|
||||
|
||||
func New(desktop types.DesktopManager, config *config.Capture) *CaptureManagerCtx {
|
||||
logger := log.With().Str("module", "capture").Logger()
|
||||
|
||||
return &CaptureManagerCtx{
|
||||
manager := &CaptureManagerCtx{
|
||||
logger: logger,
|
||||
desktop: desktop,
|
||||
|
||||
@ -38,6 +38,10 @@ func New(desktop types.DesktopManager, config *config.Capture) *CaptureManagerCt
|
||||
return NewVideoPipeline(config.VideoCodec, config.Display, config.VideoPipeline, config.VideoMaxFPS, config.VideoBitrate, config.VideoHWEnc)
|
||||
}, "video"),
|
||||
}
|
||||
|
||||
manager.Video().SetAdaptiveFramerate(config.VideoAdaptiveFramerate)
|
||||
|
||||
return manager
|
||||
}
|
||||
|
||||
func (manager *CaptureManagerCtx) Start() {
|
||||
@ -47,31 +51,38 @@ func (manager *CaptureManagerCtx) Start() {
|
||||
}
|
||||
}
|
||||
|
||||
manager.desktop.OnBeforeScreenSizeChange(func() {
|
||||
if manager.video.Started() {
|
||||
manager.video.destroyPipeline()
|
||||
}
|
||||
go func() {
|
||||
for {
|
||||
_ = <- manager.desktop.GetBeforeScreenSizeChangeChannel()
|
||||
if manager.video.Started() {
|
||||
manager.video.destroyPipeline()
|
||||
}
|
||||
|
||||
if manager.broadcast.Started() {
|
||||
manager.broadcast.destroyPipeline()
|
||||
}
|
||||
})
|
||||
|
||||
manager.desktop.OnAfterScreenSizeChange(func() {
|
||||
if manager.video.Started() {
|
||||
err := manager.video.createPipeline()
|
||||
if err != nil && !errors.Is(err, types.ErrCapturePipelineAlreadyExists) {
|
||||
manager.logger.Panic().Err(err).Msg("unable to recreate video pipeline")
|
||||
if manager.broadcast.Started() {
|
||||
manager.broadcast.destroyPipeline()
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
if manager.broadcast.Started() {
|
||||
err := manager.broadcast.createPipeline()
|
||||
if err != nil && !errors.Is(err, types.ErrCapturePipelineAlreadyExists) {
|
||||
manager.logger.Panic().Err(err).Msg("unable to recreate broadcast pipeline")
|
||||
go func() {
|
||||
for {
|
||||
framerate := <- manager.desktop.GetAfterScreenSizeChangeChannel();
|
||||
if manager.video.Started() {
|
||||
manager.video.SetChangeFramerate(framerate)
|
||||
err := manager.video.createPipeline()
|
||||
if err != nil && !errors.Is(err, types.ErrCapturePipelineAlreadyExists) {
|
||||
manager.logger.Panic().Err(err).Msg("unable to recreate video pipeline")
|
||||
}
|
||||
}
|
||||
|
||||
if manager.broadcast.Started() {
|
||||
err := manager.broadcast.createPipeline()
|
||||
if err != nil && !errors.Is(err, types.ErrCapturePipelineAlreadyExists) {
|
||||
manager.logger.Panic().Err(err).Msg("unable to recreate broadcast pipeline")
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}()
|
||||
}
|
||||
|
||||
func (manager *CaptureManagerCtx) Shutdown() error {
|
||||
|
@ -53,7 +53,7 @@ func NewBroadcastPipeline(device string, display string, pipelineSrc string, url
|
||||
}
|
||||
|
||||
func NewVideoPipeline(rtpCodec codec.RTPCodec, display string, pipelineSrc string, fps int16, bitrate uint, hwenc string) (string, error) {
|
||||
pipelineStr := " ! appsink name=appsink"
|
||||
pipelineStr := " ! appsink name=appsinkvideo"
|
||||
|
||||
// if using custom pipeline
|
||||
if pipelineSrc != "" {
|
||||
@ -106,6 +106,27 @@ func NewVideoPipeline(rtpCodec codec.RTPCodec, display string, pipelineSrc strin
|
||||
}
|
||||
|
||||
pipelineStr = fmt.Sprintf(videoSrc+"vp9enc target-bitrate=%d cpu-used=-5 threads=4 deadline=1 keyframe-max-dist=30 auto-alt-ref=true"+pipelineStr, display, fps, bitrate*1000)
|
||||
case codec.AV1().Name:
|
||||
// https://gstreamer.freedesktop.org/documentation/aom/av1enc.html?gi-language=c
|
||||
// gstreamer1.0-plugins-bad
|
||||
// av1enc usage-profile=1
|
||||
if err := gst.CheckPlugins([]string{"ximagesrc", "vpx"}); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
pipelineStr = strings.Join([]string{
|
||||
fmt.Sprintf(videoSrc, display, fps),
|
||||
"av1enc",
|
||||
fmt.Sprintf("target-bitrate=%d", bitrate*650),
|
||||
"cpu-used=4",
|
||||
"end-usage=cbr",
|
||||
// "usage-profile=realtime",
|
||||
"undershoot=95",
|
||||
"keyframe-max-dist=25",
|
||||
"min-quantizer=4",
|
||||
"max-quantizer=20",
|
||||
pipelineStr,
|
||||
}, " ")
|
||||
case codec.H264().Name:
|
||||
if err := gst.CheckPlugins([]string{"ximagesrc"}); err != nil {
|
||||
return "", err
|
||||
@ -149,7 +170,7 @@ func NewVideoPipeline(rtpCodec codec.RTPCodec, display string, pipelineSrc strin
|
||||
}
|
||||
|
||||
func NewAudioPipeline(rtpCodec codec.RTPCodec, device string, pipelineSrc string, bitrate uint) (string, error) {
|
||||
pipelineStr := " ! appsink name=appsink"
|
||||
pipelineStr := " ! appsink name=appsinkaudio"
|
||||
|
||||
// if using custom pipeline
|
||||
if pipelineSrc != "" {
|
||||
|
@ -3,6 +3,8 @@ package capture
|
||||
import (
|
||||
"errors"
|
||||
"sync"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
@ -17,15 +19,17 @@ type StreamSinkManagerCtx struct {
|
||||
mu sync.Mutex
|
||||
wg sync.WaitGroup
|
||||
|
||||
codec codec.RTPCodec
|
||||
pipeline *gst.Pipeline
|
||||
pipelineMu sync.Mutex
|
||||
pipelineFn func() (string, error)
|
||||
codec codec.RTPCodec
|
||||
pipeline *gst.Pipeline
|
||||
pipelineMu sync.Mutex
|
||||
pipelineFn func() (string, error)
|
||||
adaptiveFramerate bool
|
||||
|
||||
listeners int
|
||||
listenersMu sync.Mutex
|
||||
|
||||
sampleFn func(sample types.Sample)
|
||||
changeFramerate int16
|
||||
sampleChannel chan types.Sample
|
||||
}
|
||||
|
||||
func streamSinkNew(codec codec.RTPCodec, pipelineFn func() (string, error), video_id string) *StreamSinkManagerCtx {
|
||||
@ -35,9 +39,12 @@ func streamSinkNew(codec codec.RTPCodec, pipelineFn func() (string, error), vide
|
||||
Str("video_id", video_id).Logger()
|
||||
|
||||
manager := &StreamSinkManagerCtx{
|
||||
logger: logger,
|
||||
codec: codec,
|
||||
pipelineFn: pipelineFn,
|
||||
logger: logger,
|
||||
codec: codec,
|
||||
pipelineFn: pipelineFn,
|
||||
changeFramerate: 0,
|
||||
adaptiveFramerate: false,
|
||||
sampleChannel: make(chan types.Sample, 100),
|
||||
}
|
||||
|
||||
return manager
|
||||
@ -50,10 +57,6 @@ func (manager *StreamSinkManagerCtx) shutdown() {
|
||||
manager.wg.Wait()
|
||||
}
|
||||
|
||||
func (manager *StreamSinkManagerCtx) OnSample(listener func(sample types.Sample)) {
|
||||
manager.sampleFn = listener
|
||||
}
|
||||
|
||||
func (manager *StreamSinkManagerCtx) Codec() codec.RTPCodec {
|
||||
return manager.codec
|
||||
}
|
||||
@ -142,6 +145,11 @@ func (manager *StreamSinkManagerCtx) createPipeline() error {
|
||||
return err
|
||||
}
|
||||
|
||||
if manager.changeFramerate > 0 && manager.adaptiveFramerate {
|
||||
m1 := regexp.MustCompile(`framerate=\d+/1`)
|
||||
pipelineStr = m1.ReplaceAllString(pipelineStr, "framerate=" + strconv.FormatInt(int64(manager.changeFramerate), 10) + "/1")
|
||||
}
|
||||
|
||||
manager.logger.Info().
|
||||
Str("codec", manager.codec.Name).
|
||||
Str("src", pipelineStr).
|
||||
@ -152,7 +160,12 @@ func (manager *StreamSinkManagerCtx) createPipeline() error {
|
||||
return err
|
||||
}
|
||||
|
||||
manager.pipeline.AttachAppsink("appsink")
|
||||
appsinkSubfix := "audio"
|
||||
if codec.IsVideo(manager.codec.Type) {
|
||||
appsinkSubfix = "video"
|
||||
}
|
||||
|
||||
manager.pipeline.AttachAppsink("appsink" + appsinkSubfix)
|
||||
manager.pipeline.Play()
|
||||
|
||||
manager.wg.Add(1)
|
||||
@ -169,7 +182,7 @@ func (manager *StreamSinkManagerCtx) createPipeline() error {
|
||||
return
|
||||
}
|
||||
|
||||
manager.sampleFn(sample)
|
||||
manager.sampleChannel <- sample
|
||||
}
|
||||
}()
|
||||
|
||||
@ -188,3 +201,15 @@ func (manager *StreamSinkManagerCtx) destroyPipeline() {
|
||||
manager.logger.Info().Msgf("destroying pipeline")
|
||||
manager.pipeline = nil
|
||||
}
|
||||
|
||||
func (manager *StreamSinkManagerCtx) GetSampleChannel() (chan types.Sample) {
|
||||
return manager.sampleChannel
|
||||
}
|
||||
|
||||
func (manager *StreamSinkManagerCtx) SetChangeFramerate(rate int16) {
|
||||
manager.changeFramerate = rate
|
||||
}
|
||||
|
||||
func (manager *StreamSinkManagerCtx) SetAdaptiveFramerate(allow bool) {
|
||||
manager.adaptiveFramerate = allow
|
||||
}
|
||||
|
Reference in New Issue
Block a user