video backend CLI flag
This commit is contained in:
+32
-5
@@ -43,11 +43,12 @@ type appArgs struct {
|
|||||||
overlayY int
|
overlayY int
|
||||||
overlayPos string
|
overlayPos string
|
||||||
|
|
||||||
videoWidth uint
|
videoWidth uint
|
||||||
videoHeight uint
|
videoHeight uint
|
||||||
videoFPS string
|
videoFPS string
|
||||||
videoUUID string
|
videoUUID string
|
||||||
noVideo bool
|
noVideo bool
|
||||||
|
videoBackend string
|
||||||
|
|
||||||
audioChannels uint8
|
audioChannels uint8
|
||||||
audioSamplingFreq string
|
audioSamplingFreq string
|
||||||
@@ -136,6 +137,9 @@ func validateVideoArgs(args *appArgs) error {
|
|||||||
if args.noVideo {
|
if args.noVideo {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
if _, err := parseVideoBackend(args.videoBackend); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if !video.HasPattern(args.pattern) {
|
if !video.HasPattern(args.pattern) {
|
||||||
return fmt.Errorf("unknown video pattern %q (use --list-patterns to see available patterns)", args.pattern)
|
return fmt.Errorf("unknown video pattern %q (use --list-patterns to see available patterns)", args.pattern)
|
||||||
}
|
}
|
||||||
@@ -284,6 +288,7 @@ func addFlags(fs *pflag.FlagSet, args *appArgs) {
|
|||||||
fs.StringVar(&args.videoFPS, "fps", "25", "Video pattern FPS")
|
fs.StringVar(&args.videoFPS, "fps", "25", "Video pattern FPS")
|
||||||
fs.StringVar(&args.videoUUID, "video-id", "", "Video UUID. Will be created, if not provided")
|
fs.StringVar(&args.videoUUID, "video-id", "", "Video UUID. Will be created, if not provided")
|
||||||
fs.BoolVar(&args.noVideo, "no-video", false, "Disable video generation; audio must be enabled")
|
fs.BoolVar(&args.noVideo, "no-video", false, "Disable video generation; audio must be enabled")
|
||||||
|
fs.StringVar(&args.videoBackend, "backend", string(video.BackendAuto), "Video generator backend: auto, gpu or cpu")
|
||||||
// Audio pattern flags
|
// Audio pattern flags
|
||||||
fs.Uint8VarP(&args.audioChannels, "channel", "c", 0, "Amount of audio channels. Each channel: num * 1kHz")
|
fs.Uint8VarP(&args.audioChannels, "channel", "c", 0, "Amount of audio channels. Each channel: num * 1kHz")
|
||||||
fs.StringVarP(&args.audioSamplingFreq, "freq", "f", "48", "Sampling frequency of test audio feed in kHz")
|
fs.StringVarP(&args.audioSamplingFreq, "freq", "f", "48", "Sampling frequency of test audio feed in kHz")
|
||||||
@@ -319,6 +324,22 @@ func parseArgs(argv []string, stdout, stderr io.Writer) (parseResult, error) {
|
|||||||
return parseResult{args: args, shouldRun: true}, nil
|
return parseResult{args: args, shouldRun: true}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseVideoBackend(value string) (video.Backend, error) {
|
||||||
|
if value == "" {
|
||||||
|
return video.BackendAuto, nil
|
||||||
|
}
|
||||||
|
backend := video.Backend(value)
|
||||||
|
switch backend {
|
||||||
|
case video.BackendAuto, video.BackendGPU, video.BackendCPU:
|
||||||
|
return backend, nil
|
||||||
|
default:
|
||||||
|
return "", fmt.Errorf(
|
||||||
|
"unsupported video backend %q (supported: auto, gpu, cpu)",
|
||||||
|
value,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func buildVideoConfig(args appArgs) (*video.Config, error) {
|
func buildVideoConfig(args appArgs) (*video.Config, error) {
|
||||||
if args.noVideo {
|
if args.noVideo {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@@ -370,6 +391,11 @@ func buildVideoConfig(args appArgs) (*video.Config, error) {
|
|||||||
return nil, fmt.Errorf("unknown video pattern %q", args.pattern)
|
return nil, fmt.Errorf("unknown video pattern %q", args.pattern)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
backend, err := parseVideoBackend(args.videoBackend)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return &video.Config{
|
return &video.Config{
|
||||||
Definition: definition,
|
Definition: definition,
|
||||||
Pattern: args.pattern,
|
Pattern: args.pattern,
|
||||||
@@ -379,6 +405,7 @@ func buildVideoConfig(args appArgs) (*video.Config, error) {
|
|||||||
Y: args.overlayY,
|
Y: args.overlayY,
|
||||||
Position: args.overlayPos,
|
Position: args.overlayPos,
|
||||||
},
|
},
|
||||||
|
Backend: backend,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
|
|
||||||
"mxl-pattern-generator/internal/audio"
|
"mxl-pattern-generator/internal/audio"
|
||||||
"mxl-pattern-generator/internal/flowdef"
|
"mxl-pattern-generator/internal/flowdef"
|
||||||
|
"mxl-pattern-generator/internal/video"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestParseArgsHelpStopsBeforeValidation(t *testing.T) {
|
func TestParseArgsHelpStopsBeforeValidation(t *testing.T) {
|
||||||
@@ -112,6 +113,46 @@ func TestValidateVideoArgsSkipsDisabledVideo(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestParseVideoBackend(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
value string
|
||||||
|
want video.Backend
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{name: "zero value defaults to auto", want: video.BackendAuto},
|
||||||
|
{name: "auto", value: "auto", want: video.BackendAuto},
|
||||||
|
{name: "gpu", value: "gpu", want: video.BackendGPU},
|
||||||
|
{name: "cpu", value: "cpu", want: video.BackendCPU},
|
||||||
|
{name: "unknown", value: "other", wantErr: true},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range tests {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
got, err := parseVideoBackend(tc.value)
|
||||||
|
if tc.wantErr {
|
||||||
|
if err == nil || !strings.Contains(err.Error(), "unsupported video backend") {
|
||||||
|
t.Fatalf("error = %v, want unsupported backend error", err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("parseVideoBackend: %v", err)
|
||||||
|
}
|
||||||
|
if got != tc.want {
|
||||||
|
t.Fatalf("backend = %q, want %q", got, tc.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValidateVideoArgsRejectsUnknownBackend(t *testing.T) {
|
||||||
|
args := appArgs{videoBackend: "other"}
|
||||||
|
if err := validateVideoArgs(&args); err == nil || !strings.Contains(err.Error(), "unsupported video backend") {
|
||||||
|
t.Fatalf("error = %v, want unsupported backend error", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestValidateMediaSelection(t *testing.T) {
|
func TestValidateMediaSelection(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
@@ -187,6 +228,30 @@ func TestBuildVideoConfigFromArgs(t *testing.T) {
|
|||||||
if cfg.Rate().Num != 30000 || cfg.Rate().Den != 1001 {
|
if cfg.Rate().Num != 30000 || cfg.Rate().Den != 1001 {
|
||||||
t.Fatalf("rate = %d/%d, want 30000/1001", cfg.Rate().Num, cfg.Rate().Den)
|
t.Fatalf("rate = %d/%d, want 30000/1001", cfg.Rate().Num, cfg.Rate().Den)
|
||||||
}
|
}
|
||||||
|
if cfg.Backend != video.BackendAuto {
|
||||||
|
t.Fatalf("backend = %q, want %q", cfg.Backend, video.BackendAuto)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBuildVideoConfigBackends(t *testing.T) {
|
||||||
|
for _, backend := range []video.Backend{video.BackendGPU, video.BackendCPU} {
|
||||||
|
t.Run(string(backend), func(t *testing.T) {
|
||||||
|
cfg, err := buildVideoConfig(appArgs{
|
||||||
|
videoUUID: "5fbec3b1-1b0f-417d-9059-8b94a47197ed",
|
||||||
|
videoWidth: 1920,
|
||||||
|
videoHeight: 1080,
|
||||||
|
videoFPS: "25",
|
||||||
|
pattern: "ebu75",
|
||||||
|
videoBackend: string(backend),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("buildVideoConfig: %v", err)
|
||||||
|
}
|
||||||
|
if cfg.Backend != backend {
|
||||||
|
t.Fatalf("backend = %q, want %q", cfg.Backend, backend)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBuildVideoConfigDisabled(t *testing.T) {
|
func TestBuildVideoConfigDisabled(t *testing.T) {
|
||||||
|
|||||||
@@ -6,10 +6,19 @@ import (
|
|||||||
"github.com/qvest-digital/go-mxl/mxl"
|
"github.com/qvest-digital/go-mxl/mxl"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Backend string
|
||||||
|
|
||||||
|
const (
|
||||||
|
BackendAuto Backend = "auto"
|
||||||
|
BackendGPU Backend = "gpu"
|
||||||
|
BackendCPU Backend = "cpu"
|
||||||
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Definition flowdef.Video
|
Definition flowdef.Video
|
||||||
Pattern string
|
Pattern string
|
||||||
Overlay OverlayConfig
|
Overlay OverlayConfig
|
||||||
|
Backend Backend
|
||||||
}
|
}
|
||||||
|
|
||||||
type OverlayConfig struct {
|
type OverlayConfig struct {
|
||||||
|
|||||||
Reference in New Issue
Block a user