mirror of
https://github.com/asticode/go-astiav.git
synced 2025-10-12 19:40:07 +08:00
Now removing from classers after the free method
This commit is contained in:
@@ -60,8 +60,15 @@ func (bsfc *BitStreamFilterContext) ReceivePacket(p *Packet) error {
|
||||
}
|
||||
|
||||
func (bsfc *BitStreamFilterContext) Free() {
|
||||
classers.del(bsfc)
|
||||
if bsfc.c != nil {
|
||||
// Make sure to clone the classer before freeing the object since
|
||||
// the C free method resets the pointer
|
||||
c := newClonedClasser(bsfc)
|
||||
C.av_bsf_free(&bsfc.c)
|
||||
// Make sure to remove from classers after freeing the object since
|
||||
// the C free method may use methods needing the classer
|
||||
classers.del(c)
|
||||
}
|
||||
}
|
||||
|
||||
func (bsfc *BitStreamFilterContext) InputTimeBase() Rational {
|
||||
|
20
class.go
20
class.go
@@ -52,6 +52,8 @@ type Classer interface {
|
||||
Class() *Class
|
||||
}
|
||||
|
||||
var _ Classer = (*UnknownClasser)(nil)
|
||||
|
||||
type UnknownClasser struct {
|
||||
c *Class
|
||||
}
|
||||
@@ -64,6 +66,24 @@ func (c *UnknownClasser) Class() *Class {
|
||||
return c.c
|
||||
}
|
||||
|
||||
var _ Classer = (*ClonedClasser)(nil)
|
||||
|
||||
type ClonedClasser struct {
|
||||
c *Class
|
||||
}
|
||||
|
||||
func newClonedClasser(c Classer) *ClonedClasser {
|
||||
cl := c.Class()
|
||||
if cl == nil {
|
||||
return nil
|
||||
}
|
||||
return &ClonedClasser{c: newClassFromC(cl.ptr)}
|
||||
}
|
||||
|
||||
func (c *ClonedClasser) Class() *Class {
|
||||
return c.c
|
||||
}
|
||||
|
||||
var classers = newClasserPool()
|
||||
|
||||
type classerPool struct {
|
||||
|
@@ -31,6 +31,10 @@ func TestClassers(t *testing.T) {
|
||||
f := AllocFilterGraph()
|
||||
c := FindDecoder(CodecIDMjpeg)
|
||||
require.NotNil(t, c)
|
||||
bf := FindBitStreamFilterByName("null")
|
||||
require.NotNil(t, bf)
|
||||
bfc, err := AllocBitStreamFilterContext(bf)
|
||||
require.NoError(t, err)
|
||||
cc := AllocCodecContext(c)
|
||||
require.NotNil(t, cc)
|
||||
bufferSink := FindFilterByName("buffersink")
|
||||
@@ -41,23 +45,27 @@ func TestClassers(t *testing.T) {
|
||||
fmc2 := AllocFormatContext()
|
||||
require.NoError(t, fmc2.OpenInput("testdata/video.mp4", nil, nil))
|
||||
path := filepath.Join(t.TempDir(), "iocontext.txt")
|
||||
ic, err := OpenIOContext(path, NewIOContextFlags(IOContextFlagWrite))
|
||||
ic1, err := OpenIOContext(path, NewIOContextFlags(IOContextFlagWrite))
|
||||
require.NoError(t, err)
|
||||
defer os.RemoveAll(path)
|
||||
ic2, err := AllocIOContext(1, true, nil, nil, nil)
|
||||
require.NoError(t, err)
|
||||
ssc, err := CreateSoftwareScaleContext(1, 1, PixelFormatRgba, 2, 2, PixelFormatRgba, NewSoftwareScaleContextFlags())
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, cl+8, len(classers.p))
|
||||
require.Equal(t, cl+10, len(classers.p))
|
||||
v, ok := classers.get(unsafe.Pointer(f.c))
|
||||
require.True(t, ok)
|
||||
require.Equal(t, f, v)
|
||||
|
||||
bfc.Free()
|
||||
cc.Free()
|
||||
fc.Free()
|
||||
f.Free()
|
||||
fmc1.Free()
|
||||
fmc2.CloseInput()
|
||||
require.NoError(t, ic.Close())
|
||||
require.NoError(t, ic1.Close())
|
||||
ic2.Free()
|
||||
ssc.Free()
|
||||
require.Equal(t, cl, len(classers.p))
|
||||
}
|
||||
|
@@ -38,8 +38,15 @@ func (cc *CodecContext) Free() {
|
||||
C.av_buffer_unref(&cc.hdc.c)
|
||||
cc.hdc = nil
|
||||
}
|
||||
classers.del(cc)
|
||||
if cc.c != nil {
|
||||
// Make sure to clone the classer before freeing the object since
|
||||
// the C free method resets the pointer
|
||||
c := newClonedClasser(cc)
|
||||
C.avcodec_free_context(&cc.c)
|
||||
// Make sure to remove from classers after freeing the object since
|
||||
// the C free method may use methods needing the classer
|
||||
classers.del(c)
|
||||
}
|
||||
}
|
||||
|
||||
func (cc *CodecContext) String() string {
|
||||
|
@@ -27,8 +27,10 @@ func newFilterContext(c *C.AVFilterContext) *FilterContext {
|
||||
var _ Classer = (*FilterContext)(nil)
|
||||
|
||||
func (fc *FilterContext) Free() {
|
||||
classers.del(fc)
|
||||
C.avfilter_free(fc.c)
|
||||
// Make sure to remove from classers after freeing the object since
|
||||
// the C free method may use methods needing the classer
|
||||
classers.del(fc)
|
||||
}
|
||||
|
||||
func (fc *FilterContext) BuffersrcAddFrame(f *Frame, fs BuffersrcFlags) error {
|
||||
|
@@ -28,9 +28,14 @@ func AllocFilterGraph() *FilterGraph {
|
||||
}
|
||||
|
||||
func (g *FilterGraph) Free() {
|
||||
classers.del(g)
|
||||
if g.c != nil {
|
||||
// Make sure to clone the classer before freeing the object since
|
||||
// the C free method resets the pointer
|
||||
c := newClonedClasser(g)
|
||||
C.avfilter_graph_free(&g.c)
|
||||
// Make sure to remove from classers after freeing the object since
|
||||
// the C free method may use methods needing the classer
|
||||
classers.del(c)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -51,8 +51,10 @@ func AllocOutputFormatContext(of *OutputFormat, formatName, filename string) (*F
|
||||
}
|
||||
|
||||
func (fc *FormatContext) Free() {
|
||||
classers.del(fc)
|
||||
C.avformat_free_context(fc.c)
|
||||
// Make sure to remove from classers after freeing the object since
|
||||
// the C free method may use methods needing the classer
|
||||
classers.del(fc)
|
||||
}
|
||||
|
||||
func (fc *FormatContext) BitRate() int64 {
|
||||
@@ -192,12 +194,18 @@ func (fc *FormatContext) OpenInput(url string, fmt *InputFormat, d *Dictionary)
|
||||
}
|
||||
|
||||
func (fc *FormatContext) CloseInput() {
|
||||
if pb := fc.Pb(); pb != nil {
|
||||
pb := fc.Pb()
|
||||
if fc.c != nil {
|
||||
// Make sure to clone the classer before freeing the object since
|
||||
// the C free method resets the pointer
|
||||
c := newClonedClasser(fc)
|
||||
C.avformat_close_input(&fc.c)
|
||||
// Make sure to remove from classers after freeing the object since
|
||||
// the C free method may use methods needing the classer
|
||||
if pb != nil {
|
||||
classers.del(pb)
|
||||
}
|
||||
classers.del(fc)
|
||||
if fc.c != nil {
|
||||
C.avformat_close_input(&fc.c)
|
||||
classers.del(c)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -122,15 +122,21 @@ func (ic *IOContext) Class() *Class {
|
||||
}
|
||||
|
||||
func (ic *IOContext) Close() error {
|
||||
classers.del(ic)
|
||||
if ic.c != nil {
|
||||
return newError(C.avio_closep(&ic.c))
|
||||
// Make sure to clone the classer before freeing the object since
|
||||
// the C free method resets the pointer
|
||||
c := newClonedClasser(ic)
|
||||
if err := newError(C.avio_closep(&ic.c)); err != nil {
|
||||
return err
|
||||
}
|
||||
// Make sure to remove from classers after freeing the object since
|
||||
// the C free method may use methods needing the classer
|
||||
classers.del(c)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ic *IOContext) Free() {
|
||||
classers.del(ic)
|
||||
if ic.c != nil {
|
||||
if ic.c.buffer != nil {
|
||||
C.av_freep(unsafe.Pointer(&ic.c.buffer))
|
||||
@@ -139,7 +145,13 @@ func (ic *IOContext) Free() {
|
||||
C.free(ic.handlerID)
|
||||
ic.handlerID = nil
|
||||
}
|
||||
// Make sure to clone the classer before freeing the object since
|
||||
// the C free method resets the pointer
|
||||
c := newClonedClasser(ic)
|
||||
C.avio_context_free(&ic.c)
|
||||
// Make sure to remove from classers after freeing the object since
|
||||
// the C free method may use methods needing the classer
|
||||
classers.del(c)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@@ -60,8 +60,13 @@ func CreateSoftwareScaleContext(srcW, srcH int, srcFormat PixelFormat, dstW, dst
|
||||
}
|
||||
|
||||
func (ssc *SoftwareScaleContext) Free() {
|
||||
classers.del(ssc)
|
||||
// Make sure to clone the classer before freeing the object since
|
||||
// the C free method may reset the pointer
|
||||
c := newClonedClasser(ssc)
|
||||
C.sws_freeContext(ssc.c)
|
||||
// Make sure to remove from classers after freeing the object since
|
||||
// the C free method may use methods needing the classer
|
||||
classers.del(c)
|
||||
}
|
||||
|
||||
var _ Classer = (*SoftwareScaleContext)(nil)
|
||||
|
Reference in New Issue
Block a user