From 205828f3ee4991eea97e2ce60753712bbaaff2b8 Mon Sep 17 00:00:00 2001 From: Alex Gustafsson Date: Tue, 22 Mar 2022 11:30:36 +0100 Subject: [PATCH] Add support for compilation options Add options to the Compile function, and in turn, the Run function in order to modify the compiled command instance before executing it. This is helpful to, for example, specify that the command should be run in a separate process group in order for ffmpeg not to react on SIGINTs sent to the parent proces. --- ffmpeg_test.go | 7 +++++++ run.go | 23 +++++++++++++++++++---- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/ffmpeg_test.go b/ffmpeg_test.go index 4b1fb39..749bcae 100644 --- a/ffmpeg_test.go +++ b/ffmpeg_test.go @@ -277,6 +277,13 @@ func TestCompile(t *testing.T) { assert.Equal(t, out.Compile().Args, []string{"ffmpeg", "-i", "dummy.mp4", "dummy2.mp4"}) } +func TestCompileWithOptions(t *testing.T) { + out := Input("dummy.mp4").Output("dummy2.mp4") + cmd := out.Compile(SeparateProcessGroup()) + assert.Equal(t, cmd.SysProcAttr.Pgid, 0) + assert.True(t, cmd.SysProcAttr.Setpgid) +} + func TestPipe(t *testing.T) { width, height := 32, 32 diff --git a/run.go b/run.go index f657d67..6d386bb 100644 --- a/run.go +++ b/run.go @@ -9,6 +9,7 @@ import ( "os/exec" "sort" "strings" + "syscall" "time" ) @@ -91,7 +92,7 @@ func _allocateFilterStreamNames(nodes []*Node, outOutingEdgeMaps map[int]map[Lab // todo sort for _, l := range _getAllLabelsSorted(om) { if len(om[l]) > 1 { - panic(fmt.Sprintf(`encountered %s with multiple outgoing edges + panic(fmt.Sprintf(`encountered %s with multiple outgoing edges with same upstream label %s; a 'split'' filter is probably required`, n.name, l)) } streamNameMap[fmt.Sprintf("%d%s", n.Hash(), l)] = fmt.Sprintf("s%d", sc) @@ -236,8 +237,19 @@ func (s *Stream) ErrorToStdOut() *Stream { return s.WithErrorOutput(os.Stdout) } +type CompilationOption func(s *Stream, cmd *exec.Cmd) + +// SeparateProcessGroup ensures that the command is run in a separate process +// group. This is useful to enable handling of signals such as SIGINT without +// propagating them to the ffmpeg process. +func SeparateProcessGroup() CompilationOption { + return func(s *Stream, cmd *exec.Cmd) { + cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true, Pgid: 0} + } +} + // for test -func (s *Stream) Compile() *exec.Cmd { +func (s *Stream) Compile(options ...CompilationOption) *exec.Cmd { args := s.GetArgs() cmd := exec.CommandContext(s.Context, "ffmpeg", args...) if a, ok := s.Context.Value("Stdin").(io.Reader); ok { @@ -249,11 +261,14 @@ func (s *Stream) Compile() *exec.Cmd { if a, ok := s.Context.Value("Stderr").(io.Writer); ok { cmd.Stderr = a } + for _, option := range options { + option(s, cmd) + } log.Printf("compiled command: ffmpeg %s\n", strings.Join(args, " ")) return cmd } -func (s *Stream) Run() error { +func (s *Stream) Run(options ...CompilationOption) error { if s.Context.Value("run_hook") != nil { hook := s.Context.Value("run_hook").(*RunHook) go hook.f() @@ -264,5 +279,5 @@ func (s *Stream) Run() error { <-hook.done }() } - return s.Compile().Run() + return s.Compile(options...).Run() }