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.
This commit is contained in:
Alex Gustafsson
2022-03-22 11:30:36 +01:00
parent 98a5c5c30b
commit 205828f3ee
2 changed files with 26 additions and 4 deletions

View File

@@ -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

23
run.go
View File

@@ -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()
}