From 4b35c9a741f5aa61d405d0911005cae5220e1337 Mon Sep 17 00:00:00 2001 From: Quentin Renard Date: Thu, 19 Dec 2024 16:20:19 +0100 Subject: [PATCH] Removed args from NewXXXFilterContext() --- BREAKING_CHANGES.md | 5 + buffersrc_filter_context.go | 5 + buffersrc_filter_context_parameters.go | 111 +++++++++++++++++++ buffersrc_filter_context_parameters_test.go | 34 ++++++ class_test.go | 6 +- examples/filtering/main.go | 31 ++++-- examples/hardware_decoding_filtering/main.go | 35 +++--- examples/transcoding/main.go | 43 ++++--- filter_graph.go | 46 +++----- filter_graph_test.go | 59 +++++++--- 10 files changed, 286 insertions(+), 89 deletions(-) create mode 100644 buffersrc_filter_context_parameters_test.go diff --git a/BREAKING_CHANGES.md b/BREAKING_CHANGES.md index fc796c2..7f3a15a 100644 --- a/BREAKING_CHANGES.md +++ b/BREAKING_CHANGES.md @@ -1,3 +1,8 @@ +# v0.29.0 + +- `NewFilterContext` has been removed, use `NewBuffersinkFilterContext` or `NewBuffersrcFilterContext` instead +- `args` has been removed from `NewBuffersinkFilterContext` and `NewBuffersrcFilterContext`. Instead, after calling `NewBuffersrcFilterContext`, you need to use `BuffersrcFilterContext`.`SetParameters` then `BuffersrcFilterContext`.`Initialize`. You don't need to use anything else after calling `NewBuffersinkFilterContext` + # v0.27.0 - make sure to call the `IOInterrupter`.`Free` method after using `NewIOInterrupter` diff --git a/buffersrc_filter_context.go b/buffersrc_filter_context.go index b59f9ba..131722f 100644 --- a/buffersrc_filter_context.go +++ b/buffersrc_filter_context.go @@ -24,6 +24,11 @@ func (bfc *BuffersrcFilterContext) FilterContext() *FilterContext { return bfc.fc } +// https://ffmpeg.org/doxygen/7.0/group__lavfi.html#ga8c15af28902395399fe455f6f8236848 +func (bfc *BuffersrcFilterContext) Initialize() error { + return newError(C.avfilter_init_dict(bfc.fc.c, nil)) +} + // https://ffmpeg.org/doxygen/7.0/group__lavfi__buffersrc.html#ga398cd2a84f8b4a588197ab9d90135048 func (bfc *BuffersrcFilterContext) SetParameters(bfcp *BuffersrcFilterContextParameters) error { return newError(C.av_buffersrc_parameters_set(bfc.fc.c, bfcp.c)) diff --git a/buffersrc_filter_context_parameters.go b/buffersrc_filter_context_parameters.go index bfd52d7..a219d7b 100644 --- a/buffersrc_filter_context_parameters.go +++ b/buffersrc_filter_context_parameters.go @@ -30,6 +30,47 @@ func (bfcp *BuffersrcFilterContextParameters) Free() { } } +// https://ffmpeg.org/doxygen/7.0/structAVBufferSrcParameters.html#a5267368bf88b4f2a65a5e06ac3f9ecd4 +func (bfcp *BuffersrcFilterContextParameters) ChannelLayout() ChannelLayout { + l, _ := newChannelLayoutFromC(&bfcp.c.ch_layout).clone() + return l +} + +// https://ffmpeg.org/doxygen/7.0/structAVBufferSrcParameters.html#a5267368bf88b4f2a65a5e06ac3f9ecd4 +func (bfcp *BuffersrcFilterContextParameters) SetChannelLayout(l ChannelLayout) { + l.copy(&bfcp.c.ch_layout) //nolint: errcheck +} + +// https://ffmpeg.org/doxygen/7.0/structAVBufferSrcParameters.html#a442add2b039f416dd7c92ccf1ccd0d3b +func (bfcp *BuffersrcFilterContextParameters) ColorRange() ColorRange { + return ColorRange(bfcp.c.color_range) +} + +// https://ffmpeg.org/doxygen/7.0/structAVBufferSrcParameters.html#a442add2b039f416dd7c92ccf1ccd0d3b +func (bfcp *BuffersrcFilterContextParameters) SetColorRange(r ColorRange) { + bfcp.c.color_range = C.enum_AVColorRange(r) +} + +// https://ffmpeg.org/doxygen/7.0/structAVBufferSrcParameters.html#a700226626af70f787c930d7506554757 +func (bfcp *BuffersrcFilterContextParameters) ColorSpace() ColorSpace { + return ColorSpace(bfcp.c.color_space) +} + +// https://ffmpeg.org/doxygen/7.0/structAVBufferSrcParameters.html#a700226626af70f787c930d7506554757 +func (bfcp *BuffersrcFilterContextParameters) SetColorSpace(s ColorSpace) { + bfcp.c.color_space = C.enum_AVColorSpace(s) +} + +// https://ffmpeg.org/doxygen/7.0/structAVBufferSrcParameters.html#a032a202496206e18449c66233058647a +func (bfcp *BuffersrcFilterContextParameters) Framerate() Rational { + return newRationalFromC(bfcp.c.frame_rate) +} + +// https://ffmpeg.org/doxygen/7.0/structAVBufferSrcParameters.html#a032a202496206e18449c66233058647a +func (bfcp *BuffersrcFilterContextParameters) SetFramerate(f Rational) { + bfcp.c.frame_rate = f.c +} + // https://ffmpeg.org/doxygen/7.0/structAVBufferSrcParameters.html#a86c49b4202433037c9e2b0b6ae541534 func (bfcp *BuffersrcFilterContextParameters) SetHardwareFrameContext(hfc *HardwareFrameContext) { if bfcp.c.hw_frames_ctx != nil { @@ -41,3 +82,73 @@ func (bfcp *BuffersrcFilterContextParameters) SetHardwareFrameContext(hfc *Hardw bfcp.c.hw_frames_ctx = nil } } + +// https://ffmpeg.org/doxygen/7.0/structAVBufferSrcParameters.html#a89783d603b84908fb1998bbbea981b70 +func (bfcp *BuffersrcFilterContextParameters) Height() int { + return int(bfcp.c.height) +} + +// https://ffmpeg.org/doxygen/7.0/structAVBufferSrcParameters.html#a89783d603b84908fb1998bbbea981b70 +func (bfcp *BuffersrcFilterContextParameters) SetHeight(height int) { + bfcp.c.height = C.int(height) +} + +// https://ffmpeg.org/doxygen/7.0/structAVBufferSrcParameters.html#a56f28f81f1a86cecc39a8d61674912b8 +func (bfcp *BuffersrcFilterContextParameters) PixelFormat() PixelFormat { + return PixelFormat(bfcp.c.format) +} + +// https://ffmpeg.org/doxygen/7.0/structAVBufferSrcParameters.html#a56f28f81f1a86cecc39a8d61674912b8 +func (bfcp *BuffersrcFilterContextParameters) SetPixelFormat(f PixelFormat) { + bfcp.c.format = C.int(f) +} + +// https://ffmpeg.org/doxygen/7.0/structAVBufferSrcParameters.html#ae47c141ea7a7770351613242229f951a +func (bfcp *BuffersrcFilterContextParameters) SampleAspectRatio() Rational { + return newRationalFromC(bfcp.c.sample_aspect_ratio) +} + +// https://ffmpeg.org/doxygen/7.0/structAVBufferSrcParameters.html#ae47c141ea7a7770351613242229f951a +func (bfcp *BuffersrcFilterContextParameters) SetSampleAspectRatio(r Rational) { + bfcp.c.sample_aspect_ratio = r.c +} + +// https://ffmpeg.org/doxygen/7.0/structAVBufferSrcParameters.html#a56f28f81f1a86cecc39a8d61674912b8 +func (bfcp *BuffersrcFilterContextParameters) SampleFormat() SampleFormat { + return SampleFormat(bfcp.c.format) +} + +// https://ffmpeg.org/doxygen/7.0/structAVBufferSrcParameters.html#a56f28f81f1a86cecc39a8d61674912b8 +func (bfcp *BuffersrcFilterContextParameters) SetSampleFormat(f SampleFormat) { + bfcp.c.format = C.int(f) +} + +// https://ffmpeg.org/doxygen/7.0/structAVBufferSrcParameters.html#a34a1613f1e80f8520c159fac59e29834 +func (bfcp *BuffersrcFilterContextParameters) SampleRate() int { + return int(bfcp.c.sample_rate) +} + +// https://ffmpeg.org/doxygen/7.0/structAVBufferSrcParameters.html#a34a1613f1e80f8520c159fac59e29834 +func (bfcp *BuffersrcFilterContextParameters) SetSampleRate(sampleRate int) { + bfcp.c.sample_rate = C.int(sampleRate) +} + +// https://ffmpeg.org/doxygen/7.0/structAVBufferSrcParameters.html#a7767325c1259942a33586f05c90e38b0 +func (bfcp *BuffersrcFilterContextParameters) TimeBase() Rational { + return newRationalFromC(bfcp.c.time_base) +} + +// https://ffmpeg.org/doxygen/7.0/structAVBufferSrcParameters.html#a7767325c1259942a33586f05c90e38b0 +func (bfcp *BuffersrcFilterContextParameters) SetTimeBase(r Rational) { + bfcp.c.time_base = r.c +} + +// https://ffmpeg.org/doxygen/7.0/structAVBufferSrcParameters.html#a6c6f3d9ed8b427070e9055e7ac61263f +func (bfcp *BuffersrcFilterContextParameters) Width() int { + return int(bfcp.c.width) +} + +// https://ffmpeg.org/doxygen/7.0/structAVBufferSrcParameters.html#a6c6f3d9ed8b427070e9055e7ac61263f +func (bfcp *BuffersrcFilterContextParameters) SetWidth(width int) { + bfcp.c.width = C.int(width) +} diff --git a/buffersrc_filter_context_parameters_test.go b/buffersrc_filter_context_parameters_test.go new file mode 100644 index 0000000..f130d35 --- /dev/null +++ b/buffersrc_filter_context_parameters_test.go @@ -0,0 +1,34 @@ +package astiav + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestBuffersrcFilterContextParameters(t *testing.T) { + p := AllocBuffersrcFilterContextParameters() + defer p.Free() + p.SetChannelLayout(ChannelLayoutStereo) + require.Equal(t, ChannelLayoutStereo, p.ChannelLayout()) + p.SetColorRange(ColorRangeMpeg) + require.Equal(t, ColorRangeMpeg, p.ColorRange()) + p.SetColorSpace(ColorSpaceBt470Bg) + require.Equal(t, ColorSpaceBt470Bg, p.ColorSpace()) + p.SetFramerate(NewRational(1, 2)) + require.Equal(t, NewRational(1, 2), p.Framerate()) + p.SetHeight(1) + require.Equal(t, 1, p.Height()) + p.SetPixelFormat(PixelFormatRgba) + require.Equal(t, PixelFormatRgba, p.PixelFormat()) + p.SetSampleAspectRatio(NewRational(3, 4)) + require.Equal(t, NewRational(3, 4), p.SampleAspectRatio()) + p.SetSampleFormat(SampleFormatDblp) + require.Equal(t, SampleFormatDblp, p.SampleFormat()) + p.SetSampleRate(2) + require.Equal(t, 2, p.SampleRate()) + p.SetTimeBase(NewRational(5, 6)) + require.Equal(t, NewRational(5, 6), p.TimeBase()) + p.SetWidth(3) + require.Equal(t, 3, p.Width()) +} diff --git a/class_test.go b/class_test.go index 3b3f320..99e4524 100644 --- a/class_test.go +++ b/class_test.go @@ -40,9 +40,9 @@ func TestClassers(t *testing.T) { require.NotNil(t, cc) bufferSink := FindFilterByName("buffersink") require.NotNil(t, bufferSink) - fc1, err := f1.NewFilterContext(bufferSink, "filter_out", nil) + bfc1, err := f1.NewBuffersinkFilterContext(bufferSink, "filter_out") require.NoError(t, err) - _, err = f2.NewFilterContext(bufferSink, "filter_out", nil) + _, err = f2.NewBuffersinkFilterContext(bufferSink, "filter_out") require.NoError(t, err) fmc1 := AllocFormatContext() fmc2 := AllocFormatContext() @@ -64,7 +64,7 @@ func TestClassers(t *testing.T) { bfc.Free() cc.Free() - fc1.Free() + bfc1.FilterContext().Free() f1.Free() f2.Free() fmc1.Free() diff --git a/examples/filtering/main.go b/examples/filtering/main.go index 227ba1f..cbf57f8 100644 --- a/examples/filtering/main.go +++ b/examples/filtering/main.go @@ -5,7 +5,6 @@ import ( "flag" "fmt" "log" - "strconv" "strings" "github.com/asticode/go-astiav" @@ -250,20 +249,36 @@ func initFilter() (err error) { } // Create filter contexts - if s.buffersrcContext, err = s.filterGraph.NewBuffersrcFilterContext(buffersrc, "in", astiav.FilterArgs{ - "pix_fmt": strconv.Itoa(int(s.decCodecContext.PixelFormat())), - "pixel_aspect": s.decCodecContext.SampleAspectRatio().String(), - "time_base": s.inputStream.TimeBase().String(), - "video_size": strconv.Itoa(s.decCodecContext.Width()) + "x" + strconv.Itoa(s.decCodecContext.Height()), - }); err != nil { + if s.buffersrcContext, err = s.filterGraph.NewBuffersrcFilterContext(buffersrc, "in"); err != nil { err = fmt.Errorf("main: creating buffersrc context failed: %w", err) return } - if s.buffersinkContext, err = s.filterGraph.NewBuffersinkFilterContext(buffersink, "in", nil); err != nil { + if s.buffersinkContext, err = s.filterGraph.NewBuffersinkFilterContext(buffersink, "in"); err != nil { err = fmt.Errorf("main: creating buffersink context failed: %w", err) return } + // Create buffersrc context parameters + buffersrcContextParameters := astiav.AllocBuffersrcFilterContextParameters() + defer buffersrcContextParameters.Free() + buffersrcContextParameters.SetHeight(s.decCodecContext.Height()) + buffersrcContextParameters.SetPixelFormat(s.decCodecContext.PixelFormat()) + buffersrcContextParameters.SetSampleAspectRatio(s.decCodecContext.SampleAspectRatio()) + buffersrcContextParameters.SetTimeBase(s.inputStream.TimeBase()) + buffersrcContextParameters.SetWidth(s.decCodecContext.Width()) + + // Set buffersrc context parameters + if err = s.buffersrcContext.SetParameters(buffersrcContextParameters); err != nil { + err = fmt.Errorf("main: setting buffersrc context parameters failed: %w", err) + return + } + + // Initialize buffersrc context + if err = s.buffersrcContext.Initialize(); err != nil { + err = fmt.Errorf("main: initializing buffersrc context failed: %w", err) + return + } + // Update outputs outputs.SetName("in") outputs.SetFilterContext(s.buffersrcContext.FilterContext()) diff --git a/examples/hardware_decoding_filtering/main.go b/examples/hardware_decoding_filtering/main.go index 9c7c716..ee3b55d 100644 --- a/examples/hardware_decoding_filtering/main.go +++ b/examples/hardware_decoding_filtering/main.go @@ -5,7 +5,6 @@ import ( "flag" "fmt" "log" - "strconv" "strings" "github.com/asticode/go-astiav" @@ -294,28 +293,34 @@ func initFilter() (err error) { } // Create filter contexts - if buffersrcContext, err = filterGraph.NewBuffersrcFilterContext(buffersrc, "in", astiav.FilterArgs{ - "pix_fmt": strconv.Itoa(int(decCodecContext.PixelFormat())), - "pixel_aspect": decCodecContext.SampleAspectRatio().String(), - "time_base": inputStream.TimeBase().String(), - "video_size": strconv.Itoa(decCodecContext.Width()) + "x" + strconv.Itoa(decCodecContext.Height()), - }); err != nil { + if buffersrcContext, err = filterGraph.NewBuffersrcFilterContext(buffersrc, "in"); err != nil { err = fmt.Errorf("main: creating buffersrc context failed: %w", err) return } - if buffersinkContext, err = filterGraph.NewBuffersinkFilterContext(buffersink, "in", nil); err != nil { + if buffersinkContext, err = filterGraph.NewBuffersinkFilterContext(buffersink, "in"); err != nil { err = fmt.Errorf("main: creating buffersink context failed: %w", err) return } - // Create buffersrc parameters - bfcp := astiav.AllocBuffersrcFilterContextParameters() - defer bfcp.Free() - bfcp.SetHardwareFrameContext(decCodecContext.HardwareFrameContext()) + // Create buffersrc context parameters + buffersrcContextParameters := astiav.AllocBuffersrcFilterContextParameters() + defer buffersrcContextParameters.Free() + buffersrcContextParameters.SetHardwareFrameContext(decCodecContext.HardwareFrameContext()) + buffersrcContextParameters.SetHeight(decCodecContext.Height()) + buffersrcContextParameters.SetPixelFormat(decCodecContext.PixelFormat()) + buffersrcContextParameters.SetSampleAspectRatio(decCodecContext.SampleAspectRatio()) + buffersrcContextParameters.SetTimeBase(inputStream.TimeBase()) + buffersrcContextParameters.SetWidth(decCodecContext.Width()) + + // Set buffersrc context parameters + if err = buffersrcContext.SetParameters(buffersrcContextParameters); err != nil { + err = fmt.Errorf("main: setting buffersrc context parameters failed: %w", err) + return + } - // Set buffersrc parameters - if err = buffersrcContext.SetParameters(bfcp); err != nil { - err = fmt.Errorf("main: setting buffersrc parameters failed: %w", err) + // Initialize buffersrc context + if err = buffersrcContext.Initialize(); err != nil { + err = fmt.Errorf("main: initializing buffersrc context failed: %w", err) return } diff --git a/examples/transcoding/main.go b/examples/transcoding/main.go index aa805cb..0576388 100644 --- a/examples/transcoding/main.go +++ b/examples/transcoding/main.go @@ -5,7 +5,6 @@ import ( "flag" "fmt" "log" - "strconv" "strings" "github.com/asticode/go-astiav" @@ -378,29 +377,29 @@ func initFilters() (err error) { } c.Add(inputs.Free) + // Create buffersrc context parameters + buffersrcContextParameters := astiav.AllocBuffersrcFilterContextParameters() + defer buffersrcContextParameters.Free() + // Switch on media type - var args astiav.FilterArgs var buffersrc, buffersink *astiav.Filter var content string switch s.decCodecContext.MediaType() { case astiav.MediaTypeAudio: - args = astiav.FilterArgs{ - "channel_layout": s.decCodecContext.ChannelLayout().String(), - "sample_fmt": s.decCodecContext.SampleFormat().Name(), - "sample_rate": strconv.Itoa(s.decCodecContext.SampleRate()), - "time_base": s.decCodecContext.TimeBase().String(), - } buffersrc = astiav.FindFilterByName("abuffer") + buffersrcContextParameters.SetChannelLayout(s.decCodecContext.ChannelLayout()) + buffersrcContextParameters.SetSampleFormat(s.decCodecContext.SampleFormat()) + buffersrcContextParameters.SetSampleRate(s.decCodecContext.SampleRate()) + buffersrcContextParameters.SetTimeBase(s.decCodecContext.TimeBase()) buffersink = astiav.FindFilterByName("abuffersink") content = fmt.Sprintf("aformat=sample_fmts=%s:channel_layouts=%s", s.encCodecContext.SampleFormat().Name(), s.encCodecContext.ChannelLayout().String()) default: - args = astiav.FilterArgs{ - "pix_fmt": strconv.Itoa(int(s.decCodecContext.PixelFormat())), - "pixel_aspect": s.decCodecContext.SampleAspectRatio().String(), - "time_base": s.inputStream.TimeBase().String(), - "video_size": strconv.Itoa(s.decCodecContext.Width()) + "x" + strconv.Itoa(s.decCodecContext.Height()), - } buffersrc = astiav.FindFilterByName("buffer") + buffersrcContextParameters.SetHeight(s.decCodecContext.Height()) + buffersrcContextParameters.SetPixelFormat(s.decCodecContext.PixelFormat()) + buffersrcContextParameters.SetSampleAspectRatio(s.decCodecContext.SampleAspectRatio()) + buffersrcContextParameters.SetTimeBase(s.inputStream.TimeBase()) + buffersrcContextParameters.SetWidth(s.decCodecContext.Width()) buffersink = astiav.FindFilterByName("buffersink") content = fmt.Sprintf("format=pix_fmts=%s", s.encCodecContext.PixelFormat().Name()) } @@ -416,15 +415,27 @@ func initFilters() (err error) { } // Create filter contexts - if s.buffersrcContext, err = s.filterGraph.NewBuffersrcFilterContext(buffersrc, "in", args); err != nil { + if s.buffersrcContext, err = s.filterGraph.NewBuffersrcFilterContext(buffersrc, "in"); err != nil { err = fmt.Errorf("main: creating buffersrc context failed: %w", err) return } - if s.buffersinkContext, err = s.filterGraph.NewBuffersinkFilterContext(buffersink, "out", nil); err != nil { + if s.buffersinkContext, err = s.filterGraph.NewBuffersinkFilterContext(buffersink, "out"); err != nil { err = fmt.Errorf("main: creating buffersink context failed: %w", err) return } + // Set buffersrc context parameters + if err = s.buffersrcContext.SetParameters(buffersrcContextParameters); err != nil { + err = fmt.Errorf("main: setting buffersrc context parameters failed: %w", err) + return + } + + // Initialize buffersrc context + if err = s.buffersrcContext.Initialize(); err != nil { + err = fmt.Errorf("main: initializing buffersrc context failed: %w", err) + return + } + // Update outputs outputs.SetName("in") outputs.SetFilterContext(s.buffersrcContext.FilterContext()) diff --git a/filter_graph.go b/filter_graph.go index 57fc972..46ec6a2 100644 --- a/filter_graph.go +++ b/filter_graph.go @@ -3,7 +3,7 @@ package astiav //#include import "C" import ( - "strings" + "errors" "unsafe" ) @@ -84,47 +84,29 @@ func (g *FilterGraph) SetThreadType(t ThreadType) { g.c.thread_type = C.int(t) } -type FilterArgs map[string]string - -func (args FilterArgs) String() string { - var ss []string - for k, v := range args { - ss = append(ss, k+"="+v) - } - return strings.Join(ss, ":") -} - // https://ffmpeg.org/doxygen/7.0/group__lavfi.html#gac0788a9ab6966dba9318b5d5c7524fea -func (g *FilterGraph) NewFilterContext(f *Filter, name string, args FilterArgs) (*FilterContext, error) { - ca := (*C.char)(nil) - if len(args) > 0 { - ca = C.CString(args.String()) - defer C.free(unsafe.Pointer(ca)) - } - cn := C.CString(name) - defer C.free(unsafe.Pointer(cn)) +func (g *FilterGraph) NewBuffersinkFilterContext(f *Filter, name string) (*BuffersinkFilterContext, error) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) var c *C.AVFilterContext - if err := newError(C.avfilter_graph_create_filter(&c, f.c, cn, ca, nil, g.c)); err != nil { + if err := newError(C.avfilter_graph_create_filter(&c, f.c, cname, nil, nil, g.c)); err != nil { return nil, err } fc := newFilterContext(c) g.fcs = append(g.fcs, fc) - return fc, nil -} - -func (g *FilterGraph) NewBuffersinkFilterContext(f *Filter, name string, args FilterArgs) (*BuffersinkFilterContext, error) { - fc, err := g.NewFilterContext(f, name, args) - if err != nil { - return nil, err - } return newBuffersinkFilterContext(fc), nil } -func (g *FilterGraph) NewBuffersrcFilterContext(f *Filter, name string, args FilterArgs) (*BuffersrcFilterContext, error) { - fc, err := g.NewFilterContext(f, name, args) - if err != nil { - return nil, err +// https://ffmpeg.org/doxygen/7.0/group__lavfi.html#gaa9af17ecf4c5c87307b57cf08411088b +func (g *FilterGraph) NewBuffersrcFilterContext(f *Filter, name string) (*BuffersrcFilterContext, error) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + c := C.avfilter_graph_alloc_filter(g.c, f.c, cname) + if c == nil { + return nil, errors.New("astiav: allocating filter context failed") } + fc := newFilterContext(c) + g.fcs = append(g.fcs, fc) return newBuffersrcFilterContext(fc), nil } diff --git a/filter_graph_test.go b/filter_graph_test.go index 8f4bd5f..8e728f8 100644 --- a/filter_graph_test.go +++ b/filter_graph_test.go @@ -5,7 +5,6 @@ package astiav import ( "fmt" - "strconv" "testing" "github.com/stretchr/testify/require" @@ -49,13 +48,24 @@ func TestFilterGraph(t *testing.T) { type buffersrc struct { name string } + type buffersrcParameters struct { + channelLayout ChannelLayout + height int + mediaType MediaType + pixelFormat PixelFormat + sampleAspectRatio Rational + sampleFormat SampleFormat + sampleRate int + timeBase Rational + width int + } type graph struct { buffersink buffersink buffersrc buffersrc commands []command content string s string - sources []FilterArgs + sources []buffersrcParameters } for _, v := range []graph{ { @@ -89,13 +99,14 @@ func TestFilterGraph(t *testing.T) { }, content: "[input_1]scale=4x8,settb=1/4,fps=fps=4/1,format=pix_fmts=yuv420p,setsar=2/1", s: " +--------------+\nParsed_setsar_4:default--[4x8 2:1 yuv420p]--default| filter_out |\n | (buffersink) |\n +--------------+\n\n+-------------+\n| filter_in_1 |default--[2x4 1:2 rgba]--Parsed_scale_0:default\n| (buffer) |\n+-------------+\n\n +----------------+\nfilter_in_1:default--[2x4 1:2 rgba]--default| Parsed_scale_0 |default--[4x8 1:2 yuv420p]--Parsed_settb_1:default\n | (scale) |\n +----------------+\n\n +----------------+\nParsed_scale_0:default--[4x8 1:2 yuv420p]--default| Parsed_settb_1 |default--[4x8 1:2 yuv420p]--Parsed_fps_2:default\n | (settb) |\n +----------------+\n\n +--------------+\nParsed_settb_1:default--[4x8 1:2 yuv420p]--default| Parsed_fps_2 |default--[4x8 1:2 yuv420p]--Parsed_format_3:default\n | (fps) |\n +--------------+\n\n +-----------------+\nParsed_fps_2:default--[4x8 1:2 yuv420p]--default| Parsed_format_3 |default--[4x8 1:2 yuv420p]--Parsed_setsar_4:default\n | (format) |\n +-----------------+\n\n +-----------------+\nParsed_format_3:default--[4x8 1:2 yuv420p]--default| Parsed_setsar_4 |default--[4x8 2:1 yuv420p]--filter_out:default\n | (setsar) |\n +-----------------+\n\n", - sources: []FilterArgs{ + sources: []buffersrcParameters{ { - "height": "4", - "pix_fmt": strconv.Itoa(int(PixelFormatRgba)), - "sar": "1/2", - "time_base": "1/2", - "width": "2", + height: 4, + mediaType: MediaTypeVideo, + pixelFormat: PixelFormatRgba, + sampleAspectRatio: NewRational(1, 2), + timeBase: NewRational(1, 2), + width: 2, }, }, }, @@ -111,12 +122,13 @@ func TestFilterGraph(t *testing.T) { buffersrc: buffersrc{name: "abuffer"}, content: "[input_1]aformat=sample_fmts=s16:channel_layouts=stereo:sample_rates=3,asettb=1/4", s: " +---------------+\nParsed_asettb_1:default--[3Hz s16:stereo]--default| filter_out |\n | (abuffersink) |\n +---------------+\n\n+-------------+\n| filter_in_1 |default--[2Hz fltp:mono]--auto_aresample_0:default\n| (abuffer) |\n+-------------+\n\n +------------------+\nauto_aresample_0:default--[3Hz s16:stereo]--default| Parsed_aformat_0 |default--[3Hz s16:stereo]--Parsed_asettb_1:default\n | (aformat) |\n +------------------+\n\n +-----------------+\nParsed_aformat_0:default--[3Hz s16:stereo]--default| Parsed_asettb_1 |default--[3Hz s16:stereo]--filter_out:default\n | (asettb) |\n +-----------------+\n\n +------------------+\nfilter_in_1:default--[2Hz fltp:mono]--default| auto_aresample_0 |default--[3Hz s16:stereo]--Parsed_aformat_0:default\n | (aresample) |\n +------------------+\n\n", - sources: []FilterArgs{ + sources: []buffersrcParameters{ { - "channel_layout": ChannelLayoutMono.String(), - "sample_fmt": strconv.Itoa(int(SampleFormatFltp)), - "sample_rate": "2", - "time_base": "1/2", + channelLayout: ChannelLayoutMono, + mediaType: MediaTypeAudio, + sampleFormat: SampleFormatFltp, + sampleRate: 2, + timeBase: NewRational(1, 2), }, }, }, @@ -130,7 +142,7 @@ func TestFilterGraph(t *testing.T) { buffersink := FindFilterByName(v.buffersink.name) require.NotNil(t, buffersink) - buffersinkContext, err := fg.NewBuffersinkFilterContext(buffersink, "filter_out", nil) + buffersinkContext, err := fg.NewBuffersinkFilterContext(buffersink, "filter_out") require.NoError(t, err) cl = buffersinkContext.FilterContext().Class() require.NotNil(t, cl) @@ -152,8 +164,25 @@ func TestFilterGraph(t *testing.T) { var buffersrcContexts []*BuffersrcFilterContext for idx, src := range v.sources { - buffersrcContext, err := fg.NewBuffersrcFilterContext(buffersrc, fmt.Sprintf("filter_in_%d", idx+1), src) + buffersrcContext, err := fg.NewBuffersrcFilterContext(buffersrc, fmt.Sprintf("filter_in_%d", idx+1)) require.NoError(t, err) + buffersrcContextParameters := AllocBuffersrcFilterContextParameters() + defer buffersrcContextParameters.Free() + switch src.mediaType { + case MediaTypeAudio: + buffersrcContextParameters.SetChannelLayout(src.channelLayout) + buffersrcContextParameters.SetSampleFormat(src.sampleFormat) + buffersrcContextParameters.SetSampleRate(src.sampleRate) + buffersrcContextParameters.SetTimeBase(src.timeBase) + default: + buffersrcContextParameters.SetHeight(src.height) + buffersrcContextParameters.SetPixelFormat(src.pixelFormat) + buffersrcContextParameters.SetSampleAspectRatio(src.sampleAspectRatio) + buffersrcContextParameters.SetTimeBase(src.timeBase) + buffersrcContextParameters.SetWidth(src.width) + } + buffersrcContext.SetParameters(buffersrcContextParameters) + require.NoError(t, buffersrcContext.Initialize()) buffersrcContexts = append(buffersrcContexts, buffersrcContext) o := AllocFilterInOut()