mirror of
https://github.com/asticode/go-astiav.git
synced 2025-10-08 09:30:23 +08:00
Added filter ParseSegment()
This commit is contained in:
26
filter.go
26
filter.go
@@ -2,7 +2,9 @@ package astiav
|
|||||||
|
|
||||||
//#include <libavfilter/avfilter.h>
|
//#include <libavfilter/avfilter.h>
|
||||||
import "C"
|
import "C"
|
||||||
import "unsafe"
|
import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
// https://github.com/FFmpeg/FFmpeg/blob/n5.0/libavfilter/avfilter.h#L165
|
// https://github.com/FFmpeg/FFmpeg/blob/n5.0/libavfilter/avfilter.h#L165
|
||||||
type Filter struct {
|
type Filter struct {
|
||||||
@@ -29,3 +31,25 @@ func (f *Filter) Name() string {
|
|||||||
func (f *Filter) String() string {
|
func (f *Filter) String() string {
|
||||||
return f.Name()
|
return f.Name()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *Filter) NbInputs() int {
|
||||||
|
return int(f.c.nb_inputs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Filter) NbOutputs() int {
|
||||||
|
return int(f.c.nb_outputs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Filter) Inputs() (ps []*FilterPad) {
|
||||||
|
for idx := 0; idx < f.NbInputs(); idx++ {
|
||||||
|
ps = append(ps, newFilterPad(MediaType(C.avfilter_pad_get_type(f.c.inputs, C.int(idx)))))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Filter) Outputs() (ps []*FilterPad) {
|
||||||
|
for idx := 0; idx < f.NbOutputs(); idx++ {
|
||||||
|
ps = append(ps, newFilterPad(MediaType(C.avfilter_pad_get_type(f.c.outputs, C.int(idx)))))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
32
filter_chain.go
Normal file
32
filter_chain.go
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package astiav
|
||||||
|
|
||||||
|
//#include <libavfilter/avfilter.h>
|
||||||
|
import "C"
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// https://github.com/FFmpeg/FFmpeg/blob/n7.0/libavfilter/avfilter.h#L1142
|
||||||
|
type FilterChain struct {
|
||||||
|
c *C.AVFilterChain
|
||||||
|
}
|
||||||
|
|
||||||
|
func newFilterChainFromC(c *C.AVFilterChain) *FilterChain {
|
||||||
|
if c == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &FilterChain{c: c}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fc *FilterChain) Filters() (fs []*FilterParams) {
|
||||||
|
fcs := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.AVFilterParams)(nil))](*C.AVFilterParams))(unsafe.Pointer(fc.c.filters))
|
||||||
|
for i := 0; i < fc.NbFilters(); i++ {
|
||||||
|
fs = append(fs, newFilterParamsFromC(fcs[i]))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fc *FilterChain) NbFilters() int {
|
||||||
|
return int(fc.c.nb_filters)
|
||||||
|
}
|
@@ -97,6 +97,16 @@ func (g *FilterGraph) Parse(content string, inputs, outputs *FilterInOut) error
|
|||||||
return newError(C.avfilter_graph_parse_ptr(g.c, cc, ic, oc, nil))
|
return newError(C.avfilter_graph_parse_ptr(g.c, cc, ic, oc, nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *FilterGraph) ParseSegment(content string) (*FilterGraphSegment, error) {
|
||||||
|
cc := C.CString(content)
|
||||||
|
defer C.free(unsafe.Pointer(cc))
|
||||||
|
var cs *C.AVFilterGraphSegment
|
||||||
|
if err := newError(C.avfilter_graph_segment_parse(g.c, cc, 0, &cs)); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return newFilterGraphSegmentFromC(cs), nil
|
||||||
|
}
|
||||||
|
|
||||||
func (g *FilterGraph) Configure() error {
|
func (g *FilterGraph) Configure() error {
|
||||||
return newError(C.avfilter_graph_config(g.c, nil))
|
return newError(C.avfilter_graph_config(g.c, nil))
|
||||||
}
|
}
|
||||||
|
36
filter_graph_segment.go
Normal file
36
filter_graph_segment.go
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
package astiav
|
||||||
|
|
||||||
|
//#include <libavfilter/avfilter.h>
|
||||||
|
import "C"
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// https://github.com/FFmpeg/FFmpeg/blob/n7.0/libavfilter/avfilter.h#L1156
|
||||||
|
type FilterGraphSegment struct {
|
||||||
|
c *C.AVFilterGraphSegment
|
||||||
|
}
|
||||||
|
|
||||||
|
func newFilterGraphSegmentFromC(c *C.AVFilterGraphSegment) *FilterGraphSegment {
|
||||||
|
if c == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &FilterGraphSegment{c: c}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fgs *FilterGraphSegment) Free() {
|
||||||
|
C.avfilter_graph_segment_free(&fgs.c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fgs *FilterGraphSegment) Chains() (cs []*FilterChain) {
|
||||||
|
ccs := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.AVFilterChain)(nil))](*C.AVFilterChain))(unsafe.Pointer(fgs.c.chains))
|
||||||
|
for i := 0; i < fgs.NbChains(); i++ {
|
||||||
|
cs = append(cs, newFilterChainFromC(ccs[i]))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fgs *FilterGraphSegment) NbChains() int {
|
||||||
|
return int(fgs.c.nb_chains)
|
||||||
|
}
|
@@ -97,13 +97,13 @@ func TestFilterGraph(t *testing.T) {
|
|||||||
channelLayout: ChannelLayoutStereo,
|
channelLayout: ChannelLayoutStereo,
|
||||||
mediaType: MediaTypeAudio,
|
mediaType: MediaTypeAudio,
|
||||||
sampleFormat: SampleFormatS16,
|
sampleFormat: SampleFormatS16,
|
||||||
sampleRate: 4,
|
sampleRate: 3,
|
||||||
timeBase: NewRational(1, 4),
|
timeBase: NewRational(1, 4),
|
||||||
},
|
},
|
||||||
buffersinkName: "abuffersink",
|
buffersinkName: "abuffersink",
|
||||||
buffersrcName: "abuffer",
|
buffersrcName: "abuffer",
|
||||||
content: "[input_1]aformat=sample_fmts=s16:channel_layouts=stereo:sample_rates=4,asettb=1/4",
|
content: "[input_1]aformat=sample_fmts=s16:channel_layouts=stereo:sample_rates=3,asettb=1/4",
|
||||||
s: " +---------------+\nParsed_asettb_1:default--[4Hz 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--[4Hz s16:stereo]--default| Parsed_aformat_0 |default--[4Hz s16:stereo]--Parsed_asettb_1:default\n | (aformat) |\n +------------------+\n\n +-----------------+\nParsed_aformat_0:default--[4Hz s16:stereo]--default| Parsed_asettb_1 |default--[4Hz s16:stereo]--filter_out:default\n | (asettb) |\n +-----------------+\n\n +------------------+\nfilter_in_1:default--[2Hz fltp:mono]--default| auto_aresample_0 |default--[4Hz 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(),
|
||||||
@@ -201,6 +201,26 @@ func TestFilterGraph(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fg2 := AllocFilterGraph()
|
||||||
|
require.NotNil(t, fg2)
|
||||||
|
defer fg2.Free()
|
||||||
|
fgs, err := fg2.ParseSegment("anullsrc")
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer fgs.Free()
|
||||||
|
require.Equal(t, 1, fgs.NbChains())
|
||||||
|
cs := fgs.Chains()
|
||||||
|
require.Equal(t, 1, len(cs))
|
||||||
|
require.Equal(t, 1, cs[0].NbFilters())
|
||||||
|
fs := cs[0].Filters()
|
||||||
|
require.Equal(t, 1, len(fs))
|
||||||
|
f := FindFilterByName(fs[0].FilterName())
|
||||||
|
require.NotNil(t, f)
|
||||||
|
require.Equal(t, 0, f.NbInputs())
|
||||||
|
require.Equal(t, 1, f.NbOutputs())
|
||||||
|
os := f.Outputs()
|
||||||
|
require.Equal(t, 1, len(os))
|
||||||
|
require.Equal(t, MediaTypeAudio, os[0].MediaType())
|
||||||
|
|
||||||
// TODO Test BuffersrcAddFrame
|
// TODO Test BuffersrcAddFrame
|
||||||
// TODO Test BuffersinkGetFrame
|
// TODO Test BuffersinkGetFrame
|
||||||
}
|
}
|
||||||
|
14
filter_pad.go
Normal file
14
filter_pad.go
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package astiav
|
||||||
|
|
||||||
|
// Struct attributes are internal but there are C functions to get some of them
|
||||||
|
type FilterPad struct {
|
||||||
|
mediaType MediaType
|
||||||
|
}
|
||||||
|
|
||||||
|
func newFilterPad(mediaType MediaType) *FilterPad {
|
||||||
|
return &FilterPad{mediaType: mediaType}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fp *FilterPad) MediaType() MediaType {
|
||||||
|
return fp.mediaType
|
||||||
|
}
|
20
filter_params.go
Normal file
20
filter_params.go
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package astiav
|
||||||
|
|
||||||
|
//#include <libavfilter/avfilter.h>
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
// https://github.com/FFmpeg/FFmpeg/blob/n7.0/libavfilter/avfilter.h#L1075
|
||||||
|
type FilterParams struct {
|
||||||
|
c *C.AVFilterParams
|
||||||
|
}
|
||||||
|
|
||||||
|
func newFilterParamsFromC(c *C.AVFilterParams) *FilterParams {
|
||||||
|
if c == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &FilterParams{c: c}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fp *FilterParams) FilterName() string {
|
||||||
|
return C.GoString(fp.c.filter_name)
|
||||||
|
}
|
Reference in New Issue
Block a user