Removed FilterLink and added BuffersinkFilterContext and BuffersrcFilterContext

This commit is contained in:
Quentin Renard
2024-10-18 14:57:22 +02:00
parent c8b4cbec66
commit cd2a16de95
8 changed files with 162 additions and 163 deletions

4
BREAKING_CHANGES.md Normal file
View File

@@ -0,0 +1,4 @@
# v0.24.0
- use `FilterGraph`.`NewBuffersinkFilterContext` and `FilterGraph`.`NewBuffersrcFilterContext` instead of `FilterGraph`.`NewFilterContext` when creating `buffersink` and `buffersrc` filter contexts and use `BuffersinkFilterContext`.`GetFrame` and `BuffersrcFilterContext`.`AddFrame` to manipulate them. Use `BuffersinkFilterContext`.`FilterContext` and `BuffersrcFilterContext`.`FilterContext` in `FilterInOut`.`SetFilterContext`.
- `FilterLink` has been removed and methods like `BuffersinkFilterContext`.`ChannelLayout` have been added instead

View File

@@ -57,4 +57,8 @@ export PKG_CONFIG_PATH="{{ path to your working directory }}/tmp/n7.0/lib/pkgcon
# Why astiav? # Why astiav?
After maintaining for several years the most starred [fork](https://github.com/asticode/goav) of [goav](https://github.com/giorgisio/goav), I've decided to write from scratch my own C bindings to fix most of the problems I still encountered using `goav`. After maintaining for several years the most starred [fork](https://github.com/asticode/goav) of [goav](https://github.com/giorgisio/goav), I've decided to write from scratch my own C bindings to fix most of the problems I still encountered using `goav`.
# Breaking changes
You can see the list of breaking changes [here](BREAKING_CHANGES.md).

View File

@@ -23,8 +23,8 @@ var (
) )
type stream struct { type stream struct {
buffersinkContext *astiav.FilterContext buffersinkContext *astiav.BuffersinkFilterContext
buffersrcContext *astiav.FilterContext buffersrcContext *astiav.BuffersrcFilterContext
decCodec *astiav.Codec decCodec *astiav.Codec
decCodecContext *astiav.CodecContext decCodecContext *astiav.CodecContext
decFrame *astiav.Frame decFrame *astiav.Frame
@@ -232,7 +232,7 @@ func initFilter() (err error) {
} }
// Create filter contexts // Create filter contexts
if s.buffersrcContext, err = s.filterGraph.NewFilterContext(buffersrc, "in", astiav.FilterArgs{ if s.buffersrcContext, err = s.filterGraph.NewBuffersrcFilterContext(buffersrc, "in", astiav.FilterArgs{
"pix_fmt": strconv.Itoa(int(s.decCodecContext.PixelFormat())), "pix_fmt": strconv.Itoa(int(s.decCodecContext.PixelFormat())),
"pixel_aspect": s.decCodecContext.SampleAspectRatio().String(), "pixel_aspect": s.decCodecContext.SampleAspectRatio().String(),
"time_base": s.inputStream.TimeBase().String(), "time_base": s.inputStream.TimeBase().String(),
@@ -241,20 +241,20 @@ func initFilter() (err error) {
err = fmt.Errorf("main: creating buffersrc context failed: %w", err) err = fmt.Errorf("main: creating buffersrc context failed: %w", err)
return return
} }
if s.buffersinkContext, err = s.filterGraph.NewFilterContext(buffersink, "in", nil); err != nil { if s.buffersinkContext, err = s.filterGraph.NewBuffersinkFilterContext(buffersink, "in", nil); err != nil {
err = fmt.Errorf("main: creating buffersink context failed: %w", err) err = fmt.Errorf("main: creating buffersink context failed: %w", err)
return return
} }
// Update outputs // Update outputs
outputs.SetName("in") outputs.SetName("in")
outputs.SetFilterContext(s.buffersrcContext) outputs.SetFilterContext(s.buffersrcContext.FilterContext())
outputs.SetPadIdx(0) outputs.SetPadIdx(0)
outputs.SetNext(nil) outputs.SetNext(nil)
// Update inputs // Update inputs
inputs.SetName("out") inputs.SetName("out")
inputs.SetFilterContext(s.buffersinkContext) inputs.SetFilterContext(s.buffersinkContext.FilterContext())
inputs.SetPadIdx(0) inputs.SetPadIdx(0)
inputs.SetNext(nil) inputs.SetNext(nil)
@@ -278,7 +278,7 @@ func initFilter() (err error) {
func filterFrame(f *astiav.Frame, s *stream) (err error) { func filterFrame(f *astiav.Frame, s *stream) (err error) {
// Add frame // Add frame
if err = s.buffersrcContext.BuffersrcAddFrame(f, astiav.NewBuffersrcFlags(astiav.BuffersrcFlagKeepRef)); err != nil { if err = s.buffersrcContext.AddFrame(f, astiav.NewBuffersrcFlags(astiav.BuffersrcFlagKeepRef)); err != nil {
err = fmt.Errorf("main: adding frame failed: %w", err) err = fmt.Errorf("main: adding frame failed: %w", err)
return return
} }
@@ -289,7 +289,7 @@ func filterFrame(f *astiav.Frame, s *stream) (err error) {
s.filterFrame.Unref() s.filterFrame.Unref()
// Get frame // Get frame
if err = s.buffersinkContext.BuffersinkGetFrame(s.filterFrame, astiav.NewBuffersinkFlags()); err != nil { if err = s.buffersinkContext.GetFrame(s.filterFrame, astiav.NewBuffersinkFlags()); err != nil {
if errors.Is(err, astiav.ErrEof) || errors.Is(err, astiav.ErrEagain) { if errors.Is(err, astiav.ErrEof) || errors.Is(err, astiav.ErrEagain) {
err = nil err = nil
break break

View File

@@ -25,8 +25,8 @@ var (
) )
type stream struct { type stream struct {
buffersinkContext *astiav.FilterContext buffersinkContext *astiav.BuffersinkFilterContext
buffersrcContext *astiav.FilterContext buffersrcContext *astiav.BuffersrcFilterContext
decCodec *astiav.Codec decCodec *astiav.Codec
decCodecContext *astiav.CodecContext decCodecContext *astiav.CodecContext
decFrame *astiav.Frame decFrame *astiav.Frame
@@ -395,24 +395,24 @@ func initFilters() (err error) {
} }
// Create filter contexts // Create filter contexts
if s.buffersrcContext, err = s.filterGraph.NewFilterContext(buffersrc, "in", args); err != nil { if s.buffersrcContext, err = s.filterGraph.NewBuffersrcFilterContext(buffersrc, "in", args); err != nil {
err = fmt.Errorf("main: creating buffersrc context failed: %w", err) err = fmt.Errorf("main: creating buffersrc context failed: %w", err)
return return
} }
if s.buffersinkContext, err = s.filterGraph.NewFilterContext(buffersink, "out", nil); err != nil { if s.buffersinkContext, err = s.filterGraph.NewBuffersinkFilterContext(buffersink, "out", nil); err != nil {
err = fmt.Errorf("main: creating buffersink context failed: %w", err) err = fmt.Errorf("main: creating buffersink context failed: %w", err)
return return
} }
// Update outputs // Update outputs
outputs.SetName("in") outputs.SetName("in")
outputs.SetFilterContext(s.buffersrcContext) outputs.SetFilterContext(s.buffersrcContext.FilterContext())
outputs.SetPadIdx(0) outputs.SetPadIdx(0)
outputs.SetNext(nil) outputs.SetNext(nil)
// Update inputs // Update inputs
inputs.SetName("out") inputs.SetName("out")
inputs.SetFilterContext(s.buffersinkContext) inputs.SetFilterContext(s.buffersinkContext.FilterContext())
inputs.SetPadIdx(0) inputs.SetPadIdx(0)
inputs.SetNext(nil) inputs.SetNext(nil)
@@ -441,7 +441,7 @@ func initFilters() (err error) {
func filterEncodeWriteFrame(f *astiav.Frame, s *stream) (err error) { func filterEncodeWriteFrame(f *astiav.Frame, s *stream) (err error) {
// Add frame // Add frame
if err = s.buffersrcContext.BuffersrcAddFrame(f, astiav.NewBuffersrcFlags(astiav.BuffersrcFlagKeepRef)); err != nil { if err = s.buffersrcContext.AddFrame(f, astiav.NewBuffersrcFlags(astiav.BuffersrcFlagKeepRef)); err != nil {
err = fmt.Errorf("main: adding frame failed: %w", err) err = fmt.Errorf("main: adding frame failed: %w", err)
return return
} }
@@ -452,7 +452,7 @@ func filterEncodeWriteFrame(f *astiav.Frame, s *stream) (err error) {
s.filterFrame.Unref() s.filterFrame.Unref()
// Get frame // Get frame
if err = s.buffersinkContext.BuffersinkGetFrame(s.filterFrame, astiav.NewBuffersinkFlags()); err != nil { if err = s.buffersinkContext.GetFrame(s.filterFrame, astiav.NewBuffersinkFlags()); err != nil {
if errors.Is(err, astiav.ErrEof) || errors.Is(err, astiav.ErrEagain) { if errors.Is(err, astiav.ErrEof) || errors.Is(err, astiav.ErrEagain) {
err = nil err = nil
break break

View File

@@ -6,7 +6,6 @@ package astiav
//#include <libavutil/frame.h> //#include <libavutil/frame.h>
import "C" import "C"
import ( import (
"math"
"unsafe" "unsafe"
) )
@@ -38,46 +37,96 @@ func (fc *FilterContext) Free() {
} }
} }
func (fc *FilterContext) BuffersrcAddFrame(f *Frame, fs BuffersrcFlags) error {
var cf *C.AVFrame
if f != nil {
cf = f.c
}
return newError(C.av_buffersrc_add_frame_flags(fc.c, cf, C.int(fs)))
}
func (fc *FilterContext) BuffersinkGetFrame(f *Frame, fs BuffersinkFlags) error {
var cf *C.AVFrame
if f != nil {
cf = f.c
}
return newError(C.av_buffersink_get_frame_flags(fc.c, cf, C.int(fs)))
}
func (fc *FilterContext) Class() *Class { func (fc *FilterContext) Class() *Class {
return newClassFromC(unsafe.Pointer(fc.c)) return newClassFromC(unsafe.Pointer(fc.c))
} }
func (fc *FilterContext) NbInputs() int { type BuffersinkFilterContext struct {
return int(fc.c.nb_inputs) fc *FilterContext
} }
func (fc *FilterContext) NbOutputs() int { func newBuffersinkFilterContext(fc *FilterContext) *BuffersinkFilterContext {
return int(fc.c.nb_outputs) return &BuffersinkFilterContext{fc: fc}
} }
func (fc *FilterContext) Inputs() (ls []*FilterLink) { func (bfc *BuffersinkFilterContext) ChannelLayout() ChannelLayout {
lcs := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.AVFilterLink)(nil))](*C.AVFilterLink))(unsafe.Pointer(fc.c.inputs)) var cl C.AVChannelLayout
for i := 0; i < fc.NbInputs(); i++ { C.av_buffersink_get_ch_layout(bfc.fc.c, &cl)
ls = append(ls, newFilterLinkFromC(lcs[i])) return newChannelLayoutFromC(&cl)
}
func (bfc *BuffersinkFilterContext) ColorRange() ColorRange {
return ColorRange(C.av_buffersink_get_color_range(bfc.fc.c))
}
func (bfc *BuffersinkFilterContext) ColorSpace() ColorSpace {
return ColorSpace(C.av_buffersink_get_colorspace(bfc.fc.c))
}
func (bfc *BuffersinkFilterContext) FilterContext() *FilterContext {
return bfc.fc
}
func (bfc *BuffersinkFilterContext) FrameRate() Rational {
return newRationalFromC(C.av_buffersink_get_frame_rate(bfc.fc.c))
}
func (bfc *BuffersinkFilterContext) GetFrame(f *Frame, fs BuffersinkFlags) error {
var cf *C.AVFrame
if f != nil {
cf = f.c
} }
return return newError(C.av_buffersink_get_frame_flags(bfc.fc.c, cf, C.int(fs)))
} }
func (fc *FilterContext) Outputs() (ls []*FilterLink) { func (bfc *BuffersinkFilterContext) Height() int {
lcs := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.AVFilterLink)(nil))](*C.AVFilterLink))(unsafe.Pointer(fc.c.outputs)) return int(C.av_buffersink_get_h(bfc.fc.c))
for i := 0; i < fc.NbOutputs(); i++ { }
ls = append(ls, newFilterLinkFromC(lcs[i]))
} func (bfc *BuffersinkFilterContext) MediaType() MediaType {
return return MediaType(C.av_buffersink_get_type(bfc.fc.c))
}
func (bfc *BuffersinkFilterContext) PixelFormat() PixelFormat {
return PixelFormat(C.av_buffersink_get_format(bfc.fc.c))
}
func (bfc *BuffersinkFilterContext) SampleAspectRatio() Rational {
return newRationalFromC(C.av_buffersink_get_sample_aspect_ratio(bfc.fc.c))
}
func (bfc *BuffersinkFilterContext) SampleFormat() SampleFormat {
return SampleFormat(C.av_buffersink_get_format(bfc.fc.c))
}
func (bfc *BuffersinkFilterContext) SampleRate() int {
return int(C.av_buffersink_get_sample_rate(bfc.fc.c))
}
func (bfc *BuffersinkFilterContext) TimeBase() Rational {
return newRationalFromC(C.av_buffersink_get_time_base(bfc.fc.c))
}
func (bfc *BuffersinkFilterContext) Width() int {
return int(C.av_buffersink_get_w(bfc.fc.c))
}
type BuffersrcFilterContext struct {
fc *FilterContext
}
func newBuffersrcFilterContext(fc *FilterContext) *BuffersrcFilterContext {
return &BuffersrcFilterContext{fc: fc}
}
func (bfc *BuffersrcFilterContext) AddFrame(f *Frame, fs BuffersrcFlags) error {
var cf *C.AVFrame
if f != nil {
cf = f.c
}
return newError(C.av_buffersrc_add_frame_flags(bfc.fc.c, cf, C.int(fs)))
}
func (bfc *BuffersrcFilterContext) FilterContext() *FilterContext {
return bfc.fc
} }

View File

@@ -103,6 +103,22 @@ func (g *FilterGraph) NewFilterContext(f *Filter, name string, args FilterArgs)
return fc, nil 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
}
return newBuffersrcFilterContext(fc), nil
}
func (g *FilterGraph) Parse(content string, inputs, outputs *FilterInOut) error { func (g *FilterGraph) Parse(content string, inputs, outputs *FilterInOut) error {
cc := C.CString(content) cc := C.CString(content)
defer C.free(unsafe.Pointer(cc)) defer C.free(unsafe.Pointer(cc))

View File

@@ -31,13 +31,14 @@ func TestFilterGraph(t *testing.T) {
target string target string
withError bool withError bool
} }
type link struct { type buffersink struct {
channelLayout ChannelLayout channelLayout ChannelLayout
colorRange ColorRange colorRange ColorRange
colorSpace ColorSpace colorSpace ColorSpace
frameRate Rational frameRate Rational
height int height int
mediaType MediaType mediaType MediaType
name string
pixelFormat PixelFormat pixelFormat PixelFormat
sampleAspectRatio Rational sampleAspectRatio Rational
sampleFormat SampleFormat sampleFormat SampleFormat
@@ -45,30 +46,32 @@ func TestFilterGraph(t *testing.T) {
timeBase Rational timeBase Rational
width int width int
} }
type buffersrc struct {
name string
}
type graph struct { type graph struct {
buffersinkExpectedInput link buffersink buffersink
buffersinkName string buffersrc buffersrc
buffersrcName string commands []command
commands []command content string
content string s string
s string sources []FilterArgs
sources []FilterArgs
} }
for _, v := range []graph{ for _, v := range []graph{
{ {
buffersinkExpectedInput: link{ buffersink: buffersink{
colorRange: ColorRangeUnspecified, colorRange: ColorRangeUnspecified,
colorSpace: ColorSpaceUnspecified, colorSpace: ColorSpaceUnspecified,
frameRate: NewRational(4, 1), frameRate: NewRational(4, 1),
height: 8, height: 8,
mediaType: MediaTypeVideo, mediaType: MediaTypeVideo,
name: "buffersink",
pixelFormat: PixelFormatYuv420P, pixelFormat: PixelFormatYuv420P,
sampleAspectRatio: NewRational(2, 1), sampleAspectRatio: NewRational(2, 1),
timeBase: NewRational(1, 4), timeBase: NewRational(1, 4),
width: 4, width: 4,
}, },
buffersinkName: "buffersink", buffersrc: buffersrc{name: "buffer"},
buffersrcName: "buffer",
commands: []command{ commands: []command{
{ {
args: "a", args: "a",
@@ -97,17 +100,17 @@ func TestFilterGraph(t *testing.T) {
}, },
}, },
{ {
buffersinkExpectedInput: link{ buffersink: buffersink{
channelLayout: ChannelLayoutStereo, channelLayout: ChannelLayoutStereo,
mediaType: MediaTypeAudio, mediaType: MediaTypeAudio,
name: "abuffersink",
sampleFormat: SampleFormatS16, sampleFormat: SampleFormatS16,
sampleRate: 3, sampleRate: 3,
timeBase: NewRational(1, 4), timeBase: NewRational(1, 4),
}, },
buffersinkName: "abuffersink", buffersrc: buffersrc{name: "abuffer"},
buffersrcName: "abuffer", content: "[input_1]aformat=sample_fmts=s16:channel_layouts=stereo:sample_rates=3,asettb=1/4",
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",
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: []FilterArgs{
{ {
"channel_layout": ChannelLayoutMono.String(), "channel_layout": ChannelLayoutMono.String(),
@@ -122,21 +125,21 @@ func TestFilterGraph(t *testing.T) {
require.NotNil(t, fg) require.NotNil(t, fg)
defer fg.Free() defer fg.Free()
buffersrc := FindFilterByName(v.buffersrcName) buffersrc := FindFilterByName(v.buffersrc.name)
require.NotNil(t, buffersrc) require.NotNil(t, buffersrc)
buffersink := FindFilterByName(v.buffersinkName) buffersink := FindFilterByName(v.buffersink.name)
require.NotNil(t, buffersink) require.NotNil(t, buffersink)
buffersinkContext, err := fg.NewFilterContext(buffersink, "filter_out", nil) buffersinkContext, err := fg.NewBuffersinkFilterContext(buffersink, "filter_out", nil)
require.NoError(t, err) require.NoError(t, err)
cl = buffersinkContext.Class() cl = buffersinkContext.FilterContext().Class()
require.NotNil(t, cl) require.NotNil(t, cl)
require.Equal(t, "AVFilter", cl.Name()) require.Equal(t, "AVFilter", cl.Name())
inputs := AllocFilterInOut() inputs := AllocFilterInOut()
defer inputs.Free() defer inputs.Free()
inputs.SetName("out") inputs.SetName("out")
inputs.SetFilterContext(buffersinkContext) inputs.SetFilterContext(buffersinkContext.FilterContext())
inputs.SetPadIdx(0) inputs.SetPadIdx(0)
inputs.SetNext(nil) inputs.SetNext(nil)
@@ -147,15 +150,15 @@ func TestFilterGraph(t *testing.T) {
} }
}() }()
var buffersrcContexts []*FilterContext var buffersrcContexts []*BuffersrcFilterContext
for idx, src := range v.sources { for idx, src := range v.sources {
buffersrcContext, err := fg.NewFilterContext(buffersrc, fmt.Sprintf("filter_in_%d", idx+1), src) buffersrcContext, err := fg.NewBuffersrcFilterContext(buffersrc, fmt.Sprintf("filter_in_%d", idx+1), src)
require.NoError(t, err) require.NoError(t, err)
buffersrcContexts = append(buffersrcContexts, buffersrcContext) buffersrcContexts = append(buffersrcContexts, buffersrcContext)
o := AllocFilterInOut() o := AllocFilterInOut()
o.SetName(fmt.Sprintf("input_%d", idx+1)) o.SetName(fmt.Sprintf("input_%d", idx+1))
o.SetFilterContext(buffersrcContext) o.SetFilterContext(buffersrcContext.FilterContext())
o.SetPadIdx(0) o.SetPadIdx(0)
o.SetNext(outputs) o.SetNext(outputs)
@@ -165,33 +168,21 @@ func TestFilterGraph(t *testing.T) {
require.NoError(t, fg.Parse(v.content, inputs, outputs)) require.NoError(t, fg.Parse(v.content, inputs, outputs))
require.NoError(t, fg.Configure()) require.NoError(t, fg.Configure())
require.Equal(t, 1, buffersinkContext.NbInputs()) require.Equal(t, v.buffersink.frameRate, buffersinkContext.FrameRate())
links := buffersinkContext.Inputs() require.Equal(t, v.buffersink.mediaType, buffersinkContext.MediaType())
require.Equal(t, 1, len(links)) require.Equal(t, v.buffersink.timeBase, buffersinkContext.TimeBase())
e, g := v.buffersinkExpectedInput, links[0] switch v.buffersink.mediaType {
require.Equal(t, e.frameRate, g.FrameRate())
require.Equal(t, e.mediaType, g.MediaType())
require.Equal(t, e.timeBase, g.TimeBase())
switch e.mediaType {
case MediaTypeAudio: case MediaTypeAudio:
require.True(t, e.channelLayout.Equal(g.ChannelLayout())) require.True(t, v.buffersink.channelLayout.Equal(buffersinkContext.ChannelLayout()))
require.Equal(t, e.sampleFormat, g.SampleFormat()) require.Equal(t, v.buffersink.sampleFormat, buffersinkContext.SampleFormat())
require.Equal(t, e.sampleRate, g.SampleRate()) require.Equal(t, v.buffersink.sampleRate, buffersinkContext.SampleRate())
default: default:
require.Equal(t, e.colorRange, g.ColorRange()) require.Equal(t, v.buffersink.colorRange, buffersinkContext.ColorRange())
require.Equal(t, e.colorSpace, g.ColorSpace()) require.Equal(t, v.buffersink.colorSpace, buffersinkContext.ColorSpace())
require.Equal(t, e.height, g.Height()) require.Equal(t, v.buffersink.height, buffersinkContext.Height())
require.Equal(t, e.pixelFormat, g.PixelFormat()) require.Equal(t, v.buffersink.pixelFormat, buffersinkContext.PixelFormat())
require.Equal(t, e.sampleAspectRatio, g.SampleAspectRatio()) require.Equal(t, v.buffersink.sampleAspectRatio, buffersinkContext.SampleAspectRatio())
require.Equal(t, e.width, g.Width()) require.Equal(t, v.buffersink.width, buffersinkContext.Width())
}
for _, buffersrcContext := range buffersrcContexts {
require.Equal(t, 0, buffersrcContext.NbInputs())
require.Equal(t, 1, buffersrcContext.NbOutputs())
links := buffersrcContext.Outputs()
require.Equal(t, 1, len(links))
require.Equal(t, v.buffersinkExpectedInput.mediaType, links[0].MediaType())
} }
require.Equal(t, v.s, fg.String()) require.Equal(t, v.s, fg.String())

View File

@@ -1,65 +0,0 @@
package astiav
//#include <libavfilter/avfilter.h>
import "C"
// https://github.com/FFmpeg/FFmpeg/blob/n5.0/libavfilter/avfilter.h#L471
type FilterLink struct {
c *C.AVFilterLink
}
func newFilterLinkFromC(c *C.AVFilterLink) *FilterLink {
if c == nil {
return nil
}
return &FilterLink{c: c}
}
func (l *FilterLink) ChannelLayout() ChannelLayout {
v, _ := newChannelLayoutFromC(&l.c.ch_layout).clone()
return v
}
func (l *FilterLink) ColorRange() ColorRange {
return ColorRange(l.c.color_range)
}
func (l *FilterLink) ColorSpace() ColorSpace {
return ColorSpace(l.c.colorspace)
}
func (l *FilterLink) FrameRate() Rational {
return newRationalFromC(l.c.frame_rate)
}
func (l *FilterLink) Height() int {
return int(l.c.h)
}
func (l *FilterLink) MediaType() MediaType {
return MediaType(l.c._type)
}
func (l *FilterLink) PixelFormat() PixelFormat {
return PixelFormat(l.c.format)
}
func (l *FilterLink) SampleAspectRatio() Rational {
return newRationalFromC(l.c.sample_aspect_ratio)
}
func (l *FilterLink) SampleFormat() SampleFormat {
return SampleFormat(l.c.format)
}
func (l *FilterLink) SampleRate() int {
return int(l.c.sample_rate)
}
func (l *FilterLink) TimeBase() Rational {
return newRationalFromC(l.c.time_base)
}
func (l *FilterLink) Width() int {
return int(l.c.w)
}