mirror of
https://github.com/asticode/go-astiav.git
synced 2025-10-05 16:16:50 +08:00
Removed FilterLink and added BuffersinkFilterContext and BuffersrcFilterContext
This commit is contained in:
4
BREAKING_CHANGES.md
Normal file
4
BREAKING_CHANGES.md
Normal 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
|
@@ -58,3 +58,7 @@ 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).
|
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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)
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fc *FilterContext) Outputs() (ls []*FilterLink) {
|
func (bfc *BuffersinkFilterContext) ColorRange() ColorRange {
|
||||||
lcs := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.AVFilterLink)(nil))](*C.AVFilterLink))(unsafe.Pointer(fc.c.outputs))
|
return ColorRange(C.av_buffersink_get_color_range(bfc.fc.c))
|
||||||
for i := 0; i < fc.NbOutputs(); i++ {
|
|
||||||
ls = append(ls, newFilterLinkFromC(lcs[i]))
|
|
||||||
}
|
}
|
||||||
return
|
|
||||||
|
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 newError(C.av_buffersink_get_frame_flags(bfc.fc.c, cf, C.int(fs)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bfc *BuffersinkFilterContext) Height() int {
|
||||||
|
return int(C.av_buffersink_get_h(bfc.fc.c))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bfc *BuffersinkFilterContext) MediaType() MediaType {
|
||||||
|
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
|
||||||
}
|
}
|
||||||
|
@@ -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))
|
||||||
|
@@ -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,10 +46,12 @@ 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
|
||||||
@@ -56,19 +59,19 @@ func TestFilterGraph(t *testing.T) {
|
|||||||
}
|
}
|
||||||
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,15 +100,15 @@ 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{
|
||||||
@@ -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())
|
||||||
|
@@ -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)
|
|
||||||
}
|
|
Reference in New Issue
Block a user