mirror of
https://github.com/datarhei/core.git
synced 2025-10-22 15:39:26 +08:00
Add v16.7.2
This commit is contained in:
200
ffmpeg/ffmpeg.go
Normal file
200
ffmpeg/ffmpeg.go
Normal file
@@ -0,0 +1,200 @@
|
||||
package ffmpeg
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"time"
|
||||
|
||||
"github.com/datarhei/core/ffmpeg/parse"
|
||||
"github.com/datarhei/core/ffmpeg/probe"
|
||||
"github.com/datarhei/core/ffmpeg/skills"
|
||||
"github.com/datarhei/core/log"
|
||||
"github.com/datarhei/core/net"
|
||||
"github.com/datarhei/core/process"
|
||||
"github.com/datarhei/core/session"
|
||||
)
|
||||
|
||||
type FFmpeg interface {
|
||||
New(config ProcessConfig) (process.Process, error)
|
||||
NewProcessParser(logger log.Logger, id, reference string) parse.Parser
|
||||
NewProbeParser(logger log.Logger) probe.Parser
|
||||
ValidateInputAddress(address string) bool
|
||||
ValidateOutputAddress(address string) bool
|
||||
Skills() skills.Skills
|
||||
ReloadSkills() error
|
||||
GetPort() (int, error)
|
||||
PutPort(port int)
|
||||
States() process.States
|
||||
}
|
||||
|
||||
type ProcessConfig struct {
|
||||
Reconnect bool
|
||||
ReconnectDelay time.Duration
|
||||
StaleTimeout time.Duration
|
||||
Command []string
|
||||
Parser process.Parser
|
||||
Logger log.Logger
|
||||
OnExit func()
|
||||
OnStart func()
|
||||
OnStateChange func(from, to string)
|
||||
}
|
||||
|
||||
// Config is the configuration for ffmpeg that is part of the configuration
|
||||
// for the restreamer instance.
|
||||
type Config struct {
|
||||
Binary string
|
||||
MaxProc int64
|
||||
MaxLogLines int
|
||||
LogHistoryLength int
|
||||
ValidatorInput Validator
|
||||
ValidatorOutput Validator
|
||||
Portrange net.Portranger
|
||||
Collector session.Collector
|
||||
}
|
||||
|
||||
type ffmpeg struct {
|
||||
binary string
|
||||
validatorIn Validator
|
||||
validatorOut Validator
|
||||
portrange net.Portranger
|
||||
skills skills.Skills
|
||||
|
||||
logLines int
|
||||
historyLength int
|
||||
|
||||
collector session.Collector
|
||||
|
||||
states process.States
|
||||
}
|
||||
|
||||
func New(config Config) (FFmpeg, error) {
|
||||
f := &ffmpeg{}
|
||||
|
||||
binary, err := exec.LookPath(config.Binary)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid ffmpeg binary given: %w", err)
|
||||
}
|
||||
|
||||
f.binary = binary
|
||||
f.historyLength = config.LogHistoryLength
|
||||
f.logLines = config.MaxLogLines
|
||||
|
||||
f.portrange = config.Portrange
|
||||
if f.portrange == nil {
|
||||
f.portrange = net.NewDummyPortrange()
|
||||
}
|
||||
|
||||
f.validatorIn = config.ValidatorInput
|
||||
if f.validatorIn == nil {
|
||||
f.validatorIn, _ = NewValidator(nil, nil)
|
||||
}
|
||||
|
||||
f.validatorOut = config.ValidatorOutput
|
||||
if f.validatorOut == nil {
|
||||
f.validatorOut, _ = NewValidator(nil, nil)
|
||||
}
|
||||
|
||||
f.collector = config.Collector
|
||||
if f.collector == nil {
|
||||
f.collector = session.NewNullCollector()
|
||||
}
|
||||
|
||||
s, err := skills.New(f.binary)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid ffmpeg binary given: %w", err)
|
||||
}
|
||||
f.skills = s
|
||||
|
||||
return f, nil
|
||||
}
|
||||
|
||||
func (f *ffmpeg) New(config ProcessConfig) (process.Process, error) {
|
||||
ffmpeg, err := process.New(process.Config{
|
||||
Binary: f.binary,
|
||||
Args: config.Command,
|
||||
Reconnect: config.Reconnect,
|
||||
ReconnectDelay: config.ReconnectDelay,
|
||||
StaleTimeout: config.StaleTimeout,
|
||||
Parser: config.Parser,
|
||||
Logger: config.Logger,
|
||||
OnStart: config.OnStart,
|
||||
OnExit: config.OnExit,
|
||||
OnStateChange: func(from, to string) {
|
||||
switch to {
|
||||
case "finished":
|
||||
f.states.Finished++
|
||||
case "starting":
|
||||
f.states.Starting++
|
||||
case "running":
|
||||
f.states.Running++
|
||||
case "finishing":
|
||||
f.states.Finishing++
|
||||
case "failed":
|
||||
f.states.Failed++
|
||||
case "killed":
|
||||
f.states.Killed++
|
||||
default:
|
||||
}
|
||||
|
||||
if config.OnStateChange != nil {
|
||||
config.OnStateChange(from, to)
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
return ffmpeg, err
|
||||
}
|
||||
|
||||
func (f *ffmpeg) NewProcessParser(logger log.Logger, id, reference string) parse.Parser {
|
||||
p := parse.New(parse.Config{
|
||||
LogHistory: f.historyLength,
|
||||
LogLines: f.logLines,
|
||||
Logger: logger,
|
||||
Collector: NewWrappedCollector(id, reference, f.collector),
|
||||
})
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
func (f *ffmpeg) NewProbeParser(logger log.Logger) probe.Parser {
|
||||
p := probe.New(probe.Config{
|
||||
Logger: logger,
|
||||
})
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
func (f *ffmpeg) ValidateInputAddress(address string) bool {
|
||||
return f.validatorIn.IsValid(address)
|
||||
}
|
||||
|
||||
func (f *ffmpeg) ValidateOutputAddress(address string) bool {
|
||||
return f.validatorOut.IsValid(address)
|
||||
}
|
||||
|
||||
func (f *ffmpeg) Skills() skills.Skills {
|
||||
return f.skills
|
||||
}
|
||||
|
||||
func (f *ffmpeg) ReloadSkills() error {
|
||||
s, err := skills.New(f.binary)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid ffmpeg binary given: %w", err)
|
||||
}
|
||||
|
||||
f.skills = s
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *ffmpeg) GetPort() (int, error) {
|
||||
return f.portrange.Get()
|
||||
}
|
||||
|
||||
func (f *ffmpeg) PutPort(port int) {
|
||||
f.portrange.Put(port)
|
||||
}
|
||||
|
||||
func (f *ffmpeg) States() process.States {
|
||||
return f.states
|
||||
}
|
Reference in New Issue
Block a user