mirror of
https://github.com/m1k1o/neko.git
synced 2024-07-24 14:40:50 +12:00
format Go source code.
This commit is contained in:
@ -2,8 +2,8 @@ package capture
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
@ -12,20 +12,20 @@ import (
|
||||
)
|
||||
|
||||
type BroacastManagerCtx struct {
|
||||
logger zerolog.Logger
|
||||
mu sync.Mutex
|
||||
pipelineStr string
|
||||
pipeline *gst.Pipeline
|
||||
started bool
|
||||
url string
|
||||
logger zerolog.Logger
|
||||
mu sync.Mutex
|
||||
pipelineStr string
|
||||
pipeline *gst.Pipeline
|
||||
started bool
|
||||
url string
|
||||
}
|
||||
|
||||
func broadcastNew(pipelineStr string) *BroacastManagerCtx {
|
||||
return &BroacastManagerCtx{
|
||||
logger: log.With().Str("module", "capture").Str("submodule", "broadcast").Logger(),
|
||||
pipelineStr: pipelineStr,
|
||||
started: false,
|
||||
url: "",
|
||||
logger: log.With().Str("module", "capture").Str("submodule", "broadcast").Logger(),
|
||||
pipelineStr: pipelineStr,
|
||||
started: false,
|
||||
url: "",
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,18 +8,18 @@ package gst
|
||||
import "C"
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"sync"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"demodesk/neko/internal/types"
|
||||
)
|
||||
|
||||
type Pipeline struct {
|
||||
Pipeline *C.GstElement
|
||||
Sample chan types.Sample
|
||||
Src string
|
||||
id int
|
||||
Pipeline *C.GstElement
|
||||
Sample chan types.Sample
|
||||
Src string
|
||||
id int
|
||||
}
|
||||
|
||||
var pipelines = make(map[int]*Pipeline)
|
||||
@ -45,14 +45,14 @@ func CreatePipeline(pipelineStr string) (*Pipeline, error) {
|
||||
|
||||
if gstError != nil {
|
||||
defer C.g_error_free(gstError)
|
||||
return nil, fmt.Errorf("(pipeline error) %s", C.GoString(gstError.message))
|
||||
return nil, fmt.Errorf("(pipeline error) %s", C.GoString(gstError.message))
|
||||
}
|
||||
|
||||
p := &Pipeline{
|
||||
Pipeline: gstPipeline,
|
||||
Sample: make(chan types.Sample),
|
||||
Src: pipelineStr,
|
||||
id: len(pipelines),
|
||||
Pipeline: gstPipeline,
|
||||
Sample: make(chan types.Sample),
|
||||
Src: pipelineStr,
|
||||
id: len(pipelines),
|
||||
}
|
||||
|
||||
pipelines[p.id] = p
|
||||
@ -96,7 +96,7 @@ func goHandlePipelineBuffer(buffer unsafe.Pointer, bufferLen C.int, duration C.i
|
||||
|
||||
if ok {
|
||||
pipeline.Sample <- types.Sample{
|
||||
Data: C.GoBytes(buffer, bufferLen),
|
||||
Data: C.GoBytes(buffer, bufferLen),
|
||||
Duration: time.Duration(duration),
|
||||
}
|
||||
} else {
|
||||
|
@ -7,20 +7,20 @@ import (
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
|
||||
"demodesk/neko/internal/config"
|
||||
"demodesk/neko/internal/types"
|
||||
"demodesk/neko/internal/types/codec"
|
||||
"demodesk/neko/internal/config"
|
||||
)
|
||||
|
||||
type CaptureManagerCtx struct {
|
||||
logger zerolog.Logger
|
||||
desktop types.DesktopManager
|
||||
streaming bool
|
||||
broadcast *BroacastManagerCtx
|
||||
screencast *ScreencastManagerCtx
|
||||
audio *StreamManagerCtx
|
||||
videos map[string]*StreamManagerCtx
|
||||
videoIDs []string
|
||||
logger zerolog.Logger
|
||||
desktop types.DesktopManager
|
||||
streaming bool
|
||||
broadcast *BroacastManagerCtx
|
||||
screencast *ScreencastManagerCtx
|
||||
audio *StreamManagerCtx
|
||||
videos map[string]*StreamManagerCtx
|
||||
videoIDs []string
|
||||
}
|
||||
|
||||
func New(desktop types.DesktopManager, config *config.Capture) *CaptureManagerCtx {
|
||||
@ -29,124 +29,124 @@ func New(desktop types.DesktopManager, config *config.Capture) *CaptureManagerCt
|
||||
broadcastPipeline := config.BroadcastPipeline
|
||||
if broadcastPipeline == "" {
|
||||
broadcastPipeline = fmt.Sprintf(
|
||||
"flvmux name=mux ! rtmpsink location='{url} live=1' " +
|
||||
"pulsesrc device=%s " +
|
||||
"! audio/x-raw,channels=2 " +
|
||||
"! audioconvert " +
|
||||
"! queue " +
|
||||
"! voaacenc " +
|
||||
"! mux. " +
|
||||
"ximagesrc display-name=%s show-pointer=true use-damage=false " +
|
||||
"! video/x-raw " +
|
||||
"! videoconvert " +
|
||||
"! queue " +
|
||||
"! x264enc threads=4 bitrate=4096 key-int-max=15 byte-stream=true byte-stream=true tune=zerolatency speed-preset=veryfast " +
|
||||
"! mux.", config.Device, config.Display,
|
||||
"flvmux name=mux ! rtmpsink location='{url} live=1' "+
|
||||
"pulsesrc device=%s "+
|
||||
"! audio/x-raw,channels=2 "+
|
||||
"! audioconvert "+
|
||||
"! queue "+
|
||||
"! voaacenc "+
|
||||
"! mux. "+
|
||||
"ximagesrc display-name=%s show-pointer=true use-damage=false "+
|
||||
"! video/x-raw "+
|
||||
"! videoconvert "+
|
||||
"! queue "+
|
||||
"! x264enc threads=4 bitrate=4096 key-int-max=15 byte-stream=true byte-stream=true tune=zerolatency speed-preset=veryfast "+
|
||||
"! mux.", config.Device, config.Display,
|
||||
)
|
||||
}
|
||||
|
||||
screencastPipeline := config.ScreencastPipeline
|
||||
if screencastPipeline == "" {
|
||||
screencastPipeline = fmt.Sprintf(
|
||||
"ximagesrc display-name=%s show-pointer=true use-damage=false " +
|
||||
"! video/x-raw,framerate=%s " +
|
||||
"! videoconvert " +
|
||||
"! queue " +
|
||||
"! jpegenc quality=%s " +
|
||||
"ximagesrc display-name=%s show-pointer=true use-damage=false "+
|
||||
"! video/x-raw,framerate=%s "+
|
||||
"! videoconvert "+
|
||||
"! queue "+
|
||||
"! jpegenc quality=%s "+
|
||||
"! appsink name=appsink", config.Display, config.ScreencastRate, config.ScreencastQuality,
|
||||
)
|
||||
}
|
||||
|
||||
return &CaptureManagerCtx{
|
||||
logger: logger,
|
||||
desktop: desktop,
|
||||
streaming: false,
|
||||
broadcast: broadcastNew(broadcastPipeline),
|
||||
screencast: screencastNew(config.Screencast, screencastPipeline),
|
||||
audio: streamNew(config.AudioCodec, func() string {
|
||||
logger: logger,
|
||||
desktop: desktop,
|
||||
streaming: false,
|
||||
broadcast: broadcastNew(broadcastPipeline),
|
||||
screencast: screencastNew(config.Screencast, screencastPipeline),
|
||||
audio: streamNew(config.AudioCodec, func() string {
|
||||
if config.AudioPipeline != "" {
|
||||
return config.AudioPipeline
|
||||
}
|
||||
|
||||
return fmt.Sprintf(
|
||||
"pulsesrc device=%s " +
|
||||
"! audio/x-raw,channels=2 " +
|
||||
"! audioconvert " +
|
||||
"! queue " +
|
||||
"! %s " +
|
||||
"pulsesrc device=%s "+
|
||||
"! audio/x-raw,channels=2 "+
|
||||
"! audioconvert "+
|
||||
"! queue "+
|
||||
"! %s "+
|
||||
"! appsink name=appsink", config.Device, config.AudioCodec.Pipeline,
|
||||
)
|
||||
}),
|
||||
videos: map[string]*StreamManagerCtx{
|
||||
videos: map[string]*StreamManagerCtx{
|
||||
"hd": streamNew(codec.VP8(), func() string {
|
||||
screen := desktop.GetScreenSize()
|
||||
screen := desktop.GetScreenSize()
|
||||
bitrate := screen.Width * screen.Height * 12
|
||||
|
||||
return fmt.Sprintf(
|
||||
"ximagesrc display-name=%s show-pointer=false use-damage=false " +
|
||||
"! video/x-raw,framerate=25/1 " +
|
||||
"! videoconvert " +
|
||||
"! queue " +
|
||||
"! vp8enc target-bitrate=%d cpu-used=16 threads=4 deadline=100000 error-resilient=partitions keyframe-max-dist=15 auto-alt-ref=true min-quantizer=6 max-quantizer=12 " +
|
||||
"ximagesrc display-name=%s show-pointer=false use-damage=false "+
|
||||
"! video/x-raw,framerate=25/1 "+
|
||||
"! videoconvert "+
|
||||
"! queue "+
|
||||
"! vp8enc target-bitrate=%d cpu-used=16 threads=4 deadline=100000 error-resilient=partitions keyframe-max-dist=15 auto-alt-ref=true min-quantizer=6 max-quantizer=12 "+
|
||||
"! appsink name=appsink", config.Display, bitrate,
|
||||
)
|
||||
}),
|
||||
"hq": streamNew(codec.VP8(), func() string {
|
||||
screen := desktop.GetScreenSize()
|
||||
width := int(math.Ceil(float64(screen.Width) / 6) * 5)
|
||||
height := int(math.Ceil(float64(screen.Height) / 6) * 5)
|
||||
screen := desktop.GetScreenSize()
|
||||
width := int(math.Ceil(float64(screen.Width)/6) * 5)
|
||||
height := int(math.Ceil(float64(screen.Height)/6) * 5)
|
||||
bitrate := width * height * 12
|
||||
|
||||
return fmt.Sprintf(
|
||||
"ximagesrc display-name=%s show-pointer=false use-damage=false " +
|
||||
"! video/x-raw,framerate=25/1 " +
|
||||
"! videoconvert " +
|
||||
"! queue " +
|
||||
"! videoscale " +
|
||||
"! video/x-raw,width=%d,height=%d " +
|
||||
"! queue " +
|
||||
"! vp8enc target-bitrate=%d cpu-used=16 threads=4 deadline=100000 error-resilient=partitions keyframe-max-dist=15 auto-alt-ref=true min-quantizer=6 max-quantizer=12 " +
|
||||
"ximagesrc display-name=%s show-pointer=false use-damage=false "+
|
||||
"! video/x-raw,framerate=25/1 "+
|
||||
"! videoconvert "+
|
||||
"! queue "+
|
||||
"! videoscale "+
|
||||
"! video/x-raw,width=%d,height=%d "+
|
||||
"! queue "+
|
||||
"! vp8enc target-bitrate=%d cpu-used=16 threads=4 deadline=100000 error-resilient=partitions keyframe-max-dist=15 auto-alt-ref=true min-quantizer=6 max-quantizer=12 "+
|
||||
"! appsink name=appsink", config.Display, width, height, bitrate,
|
||||
)
|
||||
}),
|
||||
"mq": streamNew(codec.VP8(), func() string {
|
||||
screen := desktop.GetScreenSize()
|
||||
width := int(math.Ceil(float64(screen.Width) / 6) * 4)
|
||||
height := int(math.Ceil(float64(screen.Height) / 6) * 4)
|
||||
screen := desktop.GetScreenSize()
|
||||
width := int(math.Ceil(float64(screen.Width)/6) * 4)
|
||||
height := int(math.Ceil(float64(screen.Height)/6) * 4)
|
||||
bitrate := width * height * 8
|
||||
|
||||
return fmt.Sprintf(
|
||||
"ximagesrc display-name=%s show-pointer=false use-damage=false " +
|
||||
"! video/x-raw,framerate=125/10 " +
|
||||
"! videoconvert " +
|
||||
"! queue " +
|
||||
"! videoscale " +
|
||||
"! video/x-raw,width=%d,height=%d " +
|
||||
"! queue " +
|
||||
"! vp8enc target-bitrate=%d cpu-used=16 threads=4 deadline=100000 error-resilient=partitions keyframe-max-dist=15 auto-alt-ref=true min-quantizer=12 max-quantizer=24 " +
|
||||
"ximagesrc display-name=%s show-pointer=false use-damage=false "+
|
||||
"! video/x-raw,framerate=125/10 "+
|
||||
"! videoconvert "+
|
||||
"! queue "+
|
||||
"! videoscale "+
|
||||
"! video/x-raw,width=%d,height=%d "+
|
||||
"! queue "+
|
||||
"! vp8enc target-bitrate=%d cpu-used=16 threads=4 deadline=100000 error-resilient=partitions keyframe-max-dist=15 auto-alt-ref=true min-quantizer=12 max-quantizer=24 "+
|
||||
"! appsink name=appsink", config.Display, width, height, bitrate,
|
||||
)
|
||||
}),
|
||||
"lq": streamNew(codec.VP8(), func() string {
|
||||
screen := desktop.GetScreenSize()
|
||||
width := int(math.Ceil(float64(screen.Width) / 6) * 3)
|
||||
height := int(math.Ceil(float64(screen.Height) / 6) * 3)
|
||||
screen := desktop.GetScreenSize()
|
||||
width := int(math.Ceil(float64(screen.Width)/6) * 3)
|
||||
height := int(math.Ceil(float64(screen.Height)/6) * 3)
|
||||
bitrate := width * height * 4
|
||||
|
||||
return fmt.Sprintf(
|
||||
"ximagesrc display-name=%s show-pointer=false use-damage=false " +
|
||||
"! video/x-raw,framerate=125/10 " +
|
||||
"! videoconvert " +
|
||||
"! queue " +
|
||||
"! videoscale " +
|
||||
"! video/x-raw,width=%d,height=%d " +
|
||||
"! queue " +
|
||||
"! vp8enc target-bitrate=%d cpu-used=16 threads=4 deadline=100000 error-resilient=partitions keyframe-max-dist=15 auto-alt-ref=true min-quantizer=12 max-quantizer=24 " +
|
||||
"ximagesrc display-name=%s show-pointer=false use-damage=false "+
|
||||
"! video/x-raw,framerate=125/10 "+
|
||||
"! videoconvert "+
|
||||
"! queue "+
|
||||
"! videoscale "+
|
||||
"! video/x-raw,width=%d,height=%d "+
|
||||
"! queue "+
|
||||
"! vp8enc target-bitrate=%d cpu-used=16 threads=4 deadline=100000 error-resilient=partitions keyframe-max-dist=15 auto-alt-ref=true min-quantizer=12 max-quantizer=24 "+
|
||||
"! appsink name=appsink", config.Display, width, height, bitrate,
|
||||
)
|
||||
}),
|
||||
},
|
||||
videoIDs: []string{ "hd", "hq", "mq", "lq" },
|
||||
videoIDs: []string{"hd", "hq", "mq", "lq"},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,41 +2,41 @@ package capture
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
|
||||
"demodesk/neko/internal/types"
|
||||
"demodesk/neko/internal/capture/gst"
|
||||
"demodesk/neko/internal/types"
|
||||
)
|
||||
|
||||
type ScreencastManagerCtx struct {
|
||||
logger zerolog.Logger
|
||||
mu sync.Mutex
|
||||
pipelineStr string
|
||||
pipeline *gst.Pipeline
|
||||
enabled bool
|
||||
started bool
|
||||
emitStop chan bool
|
||||
emitUpdate chan bool
|
||||
expired int32
|
||||
sample chan types.Sample
|
||||
image types.Sample
|
||||
logger zerolog.Logger
|
||||
mu sync.Mutex
|
||||
pipelineStr string
|
||||
pipeline *gst.Pipeline
|
||||
enabled bool
|
||||
started bool
|
||||
emitStop chan bool
|
||||
emitUpdate chan bool
|
||||
expired int32
|
||||
sample chan types.Sample
|
||||
image types.Sample
|
||||
}
|
||||
|
||||
const screencastTimeout = 5 * time.Second
|
||||
|
||||
func screencastNew(enabled bool, pipelineStr string) *ScreencastManagerCtx {
|
||||
manager := &ScreencastManagerCtx{
|
||||
logger: log.With().Str("module", "capture").Str("submodule", "screencast").Logger(),
|
||||
pipelineStr: pipelineStr,
|
||||
enabled: enabled,
|
||||
started: false,
|
||||
emitStop: make(chan bool),
|
||||
emitUpdate: make(chan bool),
|
||||
logger: log.With().Str("module", "capture").Str("submodule", "screencast").Logger(),
|
||||
pipelineStr: pipelineStr,
|
||||
enabled: enabled,
|
||||
started: false,
|
||||
emitStop: make(chan bool),
|
||||
emitUpdate: make(chan bool),
|
||||
}
|
||||
|
||||
go func() {
|
||||
@ -146,7 +146,7 @@ func (manager *ScreencastManagerCtx) createPipeline() error {
|
||||
|
||||
manager.pipeline.Start()
|
||||
manager.sample = manager.pipeline.Sample
|
||||
manager.emitUpdate <-true
|
||||
manager.emitUpdate <- true
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -2,40 +2,40 @@ package capture
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
|
||||
"demodesk/neko/internal/capture/gst"
|
||||
"demodesk/neko/internal/types"
|
||||
"demodesk/neko/internal/types/codec"
|
||||
"demodesk/neko/internal/capture/gst"
|
||||
)
|
||||
|
||||
type StreamManagerCtx struct {
|
||||
logger zerolog.Logger
|
||||
mu sync.Mutex
|
||||
codec codec.RTPCodec
|
||||
pipelineStr func() string
|
||||
pipeline *gst.Pipeline
|
||||
sample chan types.Sample
|
||||
listeners map[uintptr]*func(sample types.Sample)
|
||||
emitMu sync.Mutex
|
||||
emitUpdate chan bool
|
||||
emitStop chan bool
|
||||
started bool
|
||||
logger zerolog.Logger
|
||||
mu sync.Mutex
|
||||
codec codec.RTPCodec
|
||||
pipelineStr func() string
|
||||
pipeline *gst.Pipeline
|
||||
sample chan types.Sample
|
||||
listeners map[uintptr]*func(sample types.Sample)
|
||||
emitMu sync.Mutex
|
||||
emitUpdate chan bool
|
||||
emitStop chan bool
|
||||
started bool
|
||||
}
|
||||
|
||||
func streamNew(codec codec.RTPCodec, pipelineStr func() string) *StreamManagerCtx {
|
||||
manager := &StreamManagerCtx{
|
||||
logger: log.With().Str("module", "capture").Str("submodule", "stream").Logger(),
|
||||
codec: codec,
|
||||
pipelineStr: pipelineStr,
|
||||
listeners: map[uintptr]*func(sample types.Sample){},
|
||||
emitUpdate: make(chan bool),
|
||||
emitStop: make(chan bool),
|
||||
started: false,
|
||||
logger: log.With().Str("module", "capture").Str("submodule", "stream").Logger(),
|
||||
codec: codec,
|
||||
pipelineStr: pipelineStr,
|
||||
listeners: map[uintptr]*func(sample types.Sample){},
|
||||
emitUpdate: make(chan bool),
|
||||
emitStop: make(chan bool),
|
||||
started: false,
|
||||
}
|
||||
|
||||
go func() {
|
||||
@ -146,7 +146,7 @@ func (manager *StreamManagerCtx) createPipeline() error {
|
||||
manager.pipeline.Start()
|
||||
|
||||
manager.sample = manager.pipeline.Sample
|
||||
manager.emitUpdate <-true
|
||||
manager.emitUpdate <- true
|
||||
return nil
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user