Skip to content

Commit

Permalink
Now removing from classers after the free method
Browse files Browse the repository at this point in the history
  • Loading branch information
asticode committed Oct 23, 2024
1 parent 716eb5d commit 6834c3b
Show file tree
Hide file tree
Showing 9 changed files with 92 additions and 18 deletions.
11 changes: 9 additions & 2 deletions bit_stream_filter_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,15 @@ func (bsfc *BitStreamFilterContext) ReceivePacket(p *Packet) error {
}

func (bsfc *BitStreamFilterContext) Free() {
classers.del(bsfc)
C.av_bsf_free(&bsfc.c)
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 {
Expand Down
20 changes: 20 additions & 0 deletions class.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ type Classer interface {
Class() *Class
}

var _ Classer = (*UnknownClasser)(nil)

type UnknownClasser struct {
c *Class
}
Expand All @@ -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 {
Expand Down
14 changes: 11 additions & 3 deletions class_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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))
}
11 changes: 9 additions & 2 deletions codec_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,15 @@ func (cc *CodecContext) Free() {
C.av_buffer_unref(&cc.hfc.c)
cc.hfc = nil
}
classers.del(cc)
C.avcodec_free_context(&cc.c)
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 {
Expand Down
4 changes: 3 additions & 1 deletion filter_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
7 changes: 6 additions & 1 deletion filter_graph.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}

Expand Down
18 changes: 13 additions & 5 deletions format_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -192,12 +194,18 @@ func (fc *FormatContext) OpenInput(url string, fmt *InputFormat, d *Dictionary)
}

func (fc *FormatContext) CloseInput() {
if pb := fc.Pb(); pb != nil {
classers.del(pb)
}
classers.del(fc)
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(c)
}
}

Expand Down
18 changes: 15 additions & 3 deletions io_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand All @@ -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
}
Expand Down
7 changes: 6 additions & 1 deletion software_scale_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 6834c3b

Please sign in to comment.