mirror of
https://github.com/asticode/go-astiav.git
synced 2025-09-27 04:26:30 +08:00
Removed args from NewXXXFilterContext()
This commit is contained in:
@@ -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
|
# v0.27.0
|
||||||
|
|
||||||
- make sure to call the `IOInterrupter`.`Free` method after using `NewIOInterrupter`
|
- make sure to call the `IOInterrupter`.`Free` method after using `NewIOInterrupter`
|
||||||
|
@@ -24,6 +24,11 @@ func (bfc *BuffersrcFilterContext) FilterContext() *FilterContext {
|
|||||||
return bfc.fc
|
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
|
// https://ffmpeg.org/doxygen/7.0/group__lavfi__buffersrc.html#ga398cd2a84f8b4a588197ab9d90135048
|
||||||
func (bfc *BuffersrcFilterContext) SetParameters(bfcp *BuffersrcFilterContextParameters) error {
|
func (bfc *BuffersrcFilterContext) SetParameters(bfcp *BuffersrcFilterContextParameters) error {
|
||||||
return newError(C.av_buffersrc_parameters_set(bfc.fc.c, bfcp.c))
|
return newError(C.av_buffersrc_parameters_set(bfc.fc.c, bfcp.c))
|
||||||
|
@@ -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
|
// https://ffmpeg.org/doxygen/7.0/structAVBufferSrcParameters.html#a86c49b4202433037c9e2b0b6ae541534
|
||||||
func (bfcp *BuffersrcFilterContextParameters) SetHardwareFrameContext(hfc *HardwareFrameContext) {
|
func (bfcp *BuffersrcFilterContextParameters) SetHardwareFrameContext(hfc *HardwareFrameContext) {
|
||||||
if bfcp.c.hw_frames_ctx != nil {
|
if bfcp.c.hw_frames_ctx != nil {
|
||||||
@@ -41,3 +82,73 @@ func (bfcp *BuffersrcFilterContextParameters) SetHardwareFrameContext(hfc *Hardw
|
|||||||
bfcp.c.hw_frames_ctx = nil
|
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)
|
||||||
|
}
|
||||||
|
34
buffersrc_filter_context_parameters_test.go
Normal file
34
buffersrc_filter_context_parameters_test.go
Normal file
@@ -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())
|
||||||
|
}
|
@@ -40,9 +40,9 @@ func TestClassers(t *testing.T) {
|
|||||||
require.NotNil(t, cc)
|
require.NotNil(t, cc)
|
||||||
bufferSink := FindFilterByName("buffersink")
|
bufferSink := FindFilterByName("buffersink")
|
||||||
require.NotNil(t, bufferSink)
|
require.NotNil(t, bufferSink)
|
||||||
fc1, err := f1.NewFilterContext(bufferSink, "filter_out", nil)
|
bfc1, err := f1.NewBuffersinkFilterContext(bufferSink, "filter_out")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
_, err = f2.NewFilterContext(bufferSink, "filter_out", nil)
|
_, err = f2.NewBuffersinkFilterContext(bufferSink, "filter_out")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
fmc1 := AllocFormatContext()
|
fmc1 := AllocFormatContext()
|
||||||
fmc2 := AllocFormatContext()
|
fmc2 := AllocFormatContext()
|
||||||
@@ -64,7 +64,7 @@ func TestClassers(t *testing.T) {
|
|||||||
|
|
||||||
bfc.Free()
|
bfc.Free()
|
||||||
cc.Free()
|
cc.Free()
|
||||||
fc1.Free()
|
bfc1.FilterContext().Free()
|
||||||
f1.Free()
|
f1.Free()
|
||||||
f2.Free()
|
f2.Free()
|
||||||
fmc1.Free()
|
fmc1.Free()
|
||||||
|
@@ -5,7 +5,6 @@ import (
|
|||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/asticode/go-astiav"
|
"github.com/asticode/go-astiav"
|
||||||
@@ -250,20 +249,36 @@ func initFilter() (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create filter contexts
|
// Create filter contexts
|
||||||
if s.buffersrcContext, err = s.filterGraph.NewBuffersrcFilterContext(buffersrc, "in", astiav.FilterArgs{
|
if s.buffersrcContext, err = s.filterGraph.NewBuffersrcFilterContext(buffersrc, "in"); err != nil {
|
||||||
"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 {
|
|
||||||
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.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)
|
err = fmt.Errorf("main: creating buffersink context failed: %w", err)
|
||||||
return
|
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
|
// Update outputs
|
||||||
outputs.SetName("in")
|
outputs.SetName("in")
|
||||||
outputs.SetFilterContext(s.buffersrcContext.FilterContext())
|
outputs.SetFilterContext(s.buffersrcContext.FilterContext())
|
||||||
|
@@ -5,7 +5,6 @@ import (
|
|||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/asticode/go-astiav"
|
"github.com/asticode/go-astiav"
|
||||||
@@ -294,28 +293,34 @@ func initFilter() (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create filter contexts
|
// Create filter contexts
|
||||||
if buffersrcContext, err = filterGraph.NewBuffersrcFilterContext(buffersrc, "in", astiav.FilterArgs{
|
if buffersrcContext, err = filterGraph.NewBuffersrcFilterContext(buffersrc, "in"); err != nil {
|
||||||
"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 {
|
|
||||||
err = fmt.Errorf("main: creating buffersrc context failed: %w", err)
|
err = fmt.Errorf("main: creating buffersrc context failed: %w", err)
|
||||||
return
|
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)
|
err = fmt.Errorf("main: creating buffersink context failed: %w", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create buffersrc parameters
|
// Create buffersrc context parameters
|
||||||
bfcp := astiav.AllocBuffersrcFilterContextParameters()
|
buffersrcContextParameters := astiav.AllocBuffersrcFilterContextParameters()
|
||||||
defer bfcp.Free()
|
defer buffersrcContextParameters.Free()
|
||||||
bfcp.SetHardwareFrameContext(decCodecContext.HardwareFrameContext())
|
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 parameters
|
// Set buffersrc context parameters
|
||||||
if err = buffersrcContext.SetParameters(bfcp); err != nil {
|
if err = buffersrcContext.SetParameters(buffersrcContextParameters); err != nil {
|
||||||
err = fmt.Errorf("main: setting buffersrc parameters failed: %w", err)
|
err = fmt.Errorf("main: setting buffersrc context parameters failed: %w", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize buffersrc context
|
||||||
|
if err = buffersrcContext.Initialize(); err != nil {
|
||||||
|
err = fmt.Errorf("main: initializing buffersrc context failed: %w", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -5,7 +5,6 @@ import (
|
|||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/asticode/go-astiav"
|
"github.com/asticode/go-astiav"
|
||||||
@@ -378,29 +377,29 @@ func initFilters() (err error) {
|
|||||||
}
|
}
|
||||||
c.Add(inputs.Free)
|
c.Add(inputs.Free)
|
||||||
|
|
||||||
|
// Create buffersrc context parameters
|
||||||
|
buffersrcContextParameters := astiav.AllocBuffersrcFilterContextParameters()
|
||||||
|
defer buffersrcContextParameters.Free()
|
||||||
|
|
||||||
// Switch on media type
|
// Switch on media type
|
||||||
var args astiav.FilterArgs
|
|
||||||
var buffersrc, buffersink *astiav.Filter
|
var buffersrc, buffersink *astiav.Filter
|
||||||
var content string
|
var content string
|
||||||
switch s.decCodecContext.MediaType() {
|
switch s.decCodecContext.MediaType() {
|
||||||
case astiav.MediaTypeAudio:
|
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")
|
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")
|
buffersink = astiav.FindFilterByName("abuffersink")
|
||||||
content = fmt.Sprintf("aformat=sample_fmts=%s:channel_layouts=%s", s.encCodecContext.SampleFormat().Name(), s.encCodecContext.ChannelLayout().String())
|
content = fmt.Sprintf("aformat=sample_fmts=%s:channel_layouts=%s", s.encCodecContext.SampleFormat().Name(), s.encCodecContext.ChannelLayout().String())
|
||||||
default:
|
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")
|
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")
|
buffersink = astiav.FindFilterByName("buffersink")
|
||||||
content = fmt.Sprintf("format=pix_fmts=%s", s.encCodecContext.PixelFormat().Name())
|
content = fmt.Sprintf("format=pix_fmts=%s", s.encCodecContext.PixelFormat().Name())
|
||||||
}
|
}
|
||||||
@@ -416,15 +415,27 @@ func initFilters() (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create filter contexts
|
// 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)
|
err = fmt.Errorf("main: creating buffersrc context failed: %w", err)
|
||||||
return
|
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)
|
err = fmt.Errorf("main: creating buffersink context failed: %w", err)
|
||||||
return
|
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
|
// Update outputs
|
||||||
outputs.SetName("in")
|
outputs.SetName("in")
|
||||||
outputs.SetFilterContext(s.buffersrcContext.FilterContext())
|
outputs.SetFilterContext(s.buffersrcContext.FilterContext())
|
||||||
|
@@ -3,7 +3,7 @@ package astiav
|
|||||||
//#include <libavfilter/avfilter.h>
|
//#include <libavfilter/avfilter.h>
|
||||||
import "C"
|
import "C"
|
||||||
import (
|
import (
|
||||||
"strings"
|
"errors"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -84,47 +84,29 @@ func (g *FilterGraph) SetThreadType(t ThreadType) {
|
|||||||
g.c.thread_type = C.int(t)
|
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
|
// https://ffmpeg.org/doxygen/7.0/group__lavfi.html#gac0788a9ab6966dba9318b5d5c7524fea
|
||||||
func (g *FilterGraph) NewFilterContext(f *Filter, name string, args FilterArgs) (*FilterContext, error) {
|
func (g *FilterGraph) NewBuffersinkFilterContext(f *Filter, name string) (*BuffersinkFilterContext, error) {
|
||||||
ca := (*C.char)(nil)
|
cname := C.CString(name)
|
||||||
if len(args) > 0 {
|
defer C.free(unsafe.Pointer(cname))
|
||||||
ca = C.CString(args.String())
|
|
||||||
defer C.free(unsafe.Pointer(ca))
|
|
||||||
}
|
|
||||||
cn := C.CString(name)
|
|
||||||
defer C.free(unsafe.Pointer(cn))
|
|
||||||
var c *C.AVFilterContext
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
fc := newFilterContext(c)
|
fc := newFilterContext(c)
|
||||||
g.fcs = append(g.fcs, fc)
|
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
|
return newBuffersinkFilterContext(fc), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *FilterGraph) NewBuffersrcFilterContext(f *Filter, name string, args FilterArgs) (*BuffersrcFilterContext, error) {
|
// https://ffmpeg.org/doxygen/7.0/group__lavfi.html#gaa9af17ecf4c5c87307b57cf08411088b
|
||||||
fc, err := g.NewFilterContext(f, name, args)
|
func (g *FilterGraph) NewBuffersrcFilterContext(f *Filter, name string) (*BuffersrcFilterContext, error) {
|
||||||
if err != nil {
|
cname := C.CString(name)
|
||||||
return nil, err
|
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
|
return newBuffersrcFilterContext(fc), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -5,7 +5,6 @@ package astiav
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@@ -49,13 +48,24 @@ func TestFilterGraph(t *testing.T) {
|
|||||||
type buffersrc struct {
|
type buffersrc struct {
|
||||||
name string
|
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 {
|
type graph struct {
|
||||||
buffersink buffersink
|
buffersink buffersink
|
||||||
buffersrc buffersrc
|
buffersrc buffersrc
|
||||||
commands []command
|
commands []command
|
||||||
content string
|
content string
|
||||||
s string
|
s string
|
||||||
sources []FilterArgs
|
sources []buffersrcParameters
|
||||||
}
|
}
|
||||||
for _, v := range []graph{
|
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",
|
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",
|
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",
|
height: 4,
|
||||||
"pix_fmt": strconv.Itoa(int(PixelFormatRgba)),
|
mediaType: MediaTypeVideo,
|
||||||
"sar": "1/2",
|
pixelFormat: PixelFormatRgba,
|
||||||
"time_base": "1/2",
|
sampleAspectRatio: NewRational(1, 2),
|
||||||
"width": "2",
|
timeBase: NewRational(1, 2),
|
||||||
|
width: 2,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -111,12 +122,13 @@ func TestFilterGraph(t *testing.T) {
|
|||||||
buffersrc: buffersrc{name: "abuffer"},
|
buffersrc: buffersrc{name: "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: []buffersrcParameters{
|
||||||
{
|
{
|
||||||
"channel_layout": ChannelLayoutMono.String(),
|
channelLayout: ChannelLayoutMono,
|
||||||
"sample_fmt": strconv.Itoa(int(SampleFormatFltp)),
|
mediaType: MediaTypeAudio,
|
||||||
"sample_rate": "2",
|
sampleFormat: SampleFormatFltp,
|
||||||
"time_base": "1/2",
|
sampleRate: 2,
|
||||||
|
timeBase: NewRational(1, 2),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -130,7 +142,7 @@ func TestFilterGraph(t *testing.T) {
|
|||||||
buffersink := FindFilterByName(v.buffersink.name)
|
buffersink := FindFilterByName(v.buffersink.name)
|
||||||
require.NotNil(t, buffersink)
|
require.NotNil(t, buffersink)
|
||||||
|
|
||||||
buffersinkContext, err := fg.NewBuffersinkFilterContext(buffersink, "filter_out", nil)
|
buffersinkContext, err := fg.NewBuffersinkFilterContext(buffersink, "filter_out")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
cl = buffersinkContext.FilterContext().Class()
|
cl = buffersinkContext.FilterContext().Class()
|
||||||
require.NotNil(t, cl)
|
require.NotNil(t, cl)
|
||||||
@@ -152,8 +164,25 @@ func TestFilterGraph(t *testing.T) {
|
|||||||
|
|
||||||
var buffersrcContexts []*BuffersrcFilterContext
|
var buffersrcContexts []*BuffersrcFilterContext
|
||||||
for idx, src := range v.sources {
|
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)
|
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)
|
buffersrcContexts = append(buffersrcContexts, buffersrcContext)
|
||||||
|
|
||||||
o := AllocFilterInOut()
|
o := AllocFilterInOut()
|
||||||
|
Reference in New Issue
Block a user