diff --git a/filter_context.go b/filter_context.go index c911a40..6fe2248 100644 --- a/filter_context.go +++ b/filter_context.go @@ -39,3 +39,15 @@ func (fc *FilterContext) Free() { func (fc *FilterContext) Class() *Class { return newClassFromC(unsafe.Pointer(fc.c)) } + +// https://ffmpeg.org/doxygen/7.0/structAVFilterContext.html#addd946fbe5af506a2b19f9ad7cb97c35 +func (fc *FilterContext) SetHardwareDeviceContext(hdc *HardwareDeviceContext) { + if fc.c.hw_device_ctx != nil { + C.av_buffer_unref(&fc.c.hw_device_ctx) + } + if hdc != nil { + fc.c.hw_device_ctx = hdc.c + } else { + fc.c.hw_device_ctx = nil + } +} diff --git a/filter_graph.go b/filter_graph.go index 46ec6a2..bd26739 100644 --- a/filter_graph.go +++ b/filter_graph.go @@ -4,6 +4,7 @@ package astiav import "C" import ( "errors" + "math" "unsafe" ) @@ -154,3 +155,17 @@ func (g *FilterGraph) SendCommand(target, cmd, args string, f FilterCommandFlags }) return } + +// https://ffmpeg.org/doxygen/7.0/structAVFilterGraph.html#a0ba5c820c760788ea5f8e40c476f9704 +func (g *FilterGraph) NbFilters() int { + return int(g.c.nb_filters) +} + +// https://ffmpeg.org/doxygen/7.0/structAVFilterGraph.html#a1dafd3d239f7c2f5e3ac109578ef926d +func (g *FilterGraph) Filters() (fs []*FilterContext) { + fcs := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.AVFilterContext)(nil))](*C.AVFilterContext))(unsafe.Pointer(g.c.filters)) + for i := 0; i < g.NbFilters(); i++ { + fs = append(fs, newFilterContext(fcs[i])) + } + return +} diff --git a/filter_graph_test.go b/filter_graph_test.go index 9e5d11d..0f1b533 100644 --- a/filter_graph_test.go +++ b/filter_graph_test.go @@ -247,6 +247,43 @@ func TestFilterGraph(t *testing.T) { require.Equal(t, 1, len(os)) require.Equal(t, MediaTypeAudio, os[0].MediaType()) + fg3 := AllocFilterGraph() + require.NotNil(t, fg3) + defer fg3.Free() + outputs := AllocFilterInOut() + br := FindFilterByName("buffer") + brCtx, err := fg3.NewBuffersrcFilterContext(br, "in") + require.NoError(t, err) + brCtxParameters := AllocBuffersrcFilterContextParameters() + brCtxParameters.SetPixelFormat(PixelFormatYuv420P) + brCtxParameters.SetSampleAspectRatio(NewRational(1, 1)) + brCtxParameters.SetWidth(1080) + brCtxParameters.SetHeight(720) + brCtxParameters.SetTimeBase(NewRational(1, 30)) + err = brCtx.SetParameters(brCtxParameters) + require.NoError(t, err) + err = brCtx.Initialize(nil) + require.NoError(t, err) + outputs.SetName("in") + outputs.SetFilterContext(brCtx.FilterContext()) + outputs.SetPadIdx(0) + outputs.SetNext(nil) + inputs := AllocFilterInOut() + bs := FindFilterByName("buffersink") + bsCtx, err := fg3.NewBuffersinkFilterContext(bs, "out") + require.NoError(t, err) + inputs.SetName("out") + inputs.SetFilterContext(bsCtx.FilterContext()) + inputs.SetPadIdx(0) + inputs.SetNext(nil) + err = fg3.Parse("movie=filename=testdata/video.mp4[mv];[in][mv]overlay=x=100:y=100[ol];[ol]scale=w=1080:h=720[out]", outputs, inputs) + require.NoError(t, err) + var filterNames string + for _, filterContext := range fg3.Filters() { + filterNames += fmt.Sprintf("[%s]", filterContext.Class().ItemName()) + } + require.Equal(t, "[in][out][Parsed_movie_0][Parsed_overlay_1][Parsed_scale_2]", filterNames) + // TODO Test BuffersrcAddFrame // TODO Test BuffersinkGetFrame }