Added frame filler

This commit is contained in:
Quentin Renard
2023-05-01 10:31:41 +02:00
parent 686b9e82e4
commit 59f5ecbe9e
2 changed files with 139 additions and 0 deletions

82
libav/frame_filler.go Normal file
View File

@@ -0,0 +1,82 @@
package astilibav
import (
"fmt"
"github.com/asticode/go-astiav"
"github.com/asticode/go-astiencoder"
"github.com/asticode/go-astikit"
)
type FrameFiller struct {
eh *astiencoder.EventHandler
fallbackFrame *astiav.Frame
previousFrame *astiav.Frame
previousNode astiencoder.Node
onPuts []func(f *astiav.Frame, n astiencoder.Node)
p *framePool
target interface{}
}
func NewFrameFiller(c *astikit.Closer, eh *astiencoder.EventHandler, target interface{}) *FrameFiller {
return &FrameFiller{
eh: eh,
p: newFramePool(c),
target: target,
}
}
func (ff *FrameFiller) WithFallbackFrame(a FrameAdapter) (dst *FrameFiller, err error) {
// Create dst
dst = ff
// Get frame
f := ff.p.get()
// Adapt frame
if err = a(f); err != nil {
err = fmt.Errorf("astilibav: adapting frame failed: %w", err)
return
}
// Store frame
ff.fallbackFrame = f
return
}
func (ff *FrameFiller) WithPreviousFrame() *FrameFiller {
// Add on put
ff.onPuts = append(ff.onPuts, func(f *astiav.Frame, n astiencoder.Node) {
// Store node
ff.previousNode = n
// Create frame
if ff.previousFrame == nil {
ff.previousFrame = ff.p.get()
} else {
ff.previousFrame.Unref()
}
// Copy frame
if err := ff.previousFrame.Ref(f); err != nil {
emitError(ff.target, ff.eh, err, "refing frame")
ff.p.put(ff.previousFrame)
ff.previousFrame = nil
}
})
return ff
}
func (ff *FrameFiller) Get() (*astiav.Frame, astiencoder.Node) {
if ff.previousFrame != nil {
return ff.previousFrame, ff.previousNode
}
return ff.fallbackFrame, nil
}
func (ff *FrameFiller) Put(f *astiav.Frame, n astiencoder.Node) {
// Loop through on puts
for _, onPut := range ff.onPuts {
onPut(f, n)
}
}

View File

@@ -0,0 +1,57 @@
package astilibav
import (
"testing"
"github.com/asticode/go-astiav"
"github.com/asticode/go-astiencoder"
"github.com/asticode/go-astikit"
"github.com/stretchr/testify/require"
)
func TestFrameFiller(t *testing.T) {
c := astikit.NewCloser()
defer c.Close()
eh := astiencoder.NewEventHandler()
var logs []string
eh.AddForEventName(astiencoder.EventNameError, func(e astiencoder.Event) (deleteListener bool) {
t.Log(e.Payload)
logs = append(logs, e.Payload.(error).Error())
return
})
ff := NewFrameFiller(c, eh, nil)
f, n := ff.Get()
require.Nil(t, f)
require.Nil(t, n)
ff.WithPreviousFrame()
_, err := ff.WithFallbackFrame(EmptyVideoFrameAdapter(astiav.ColorRangeUnspecified, astiav.PixelFormatYuv420P, 4, 2))
require.NoError(t, err)
f, n = ff.Get()
require.NotNil(t, f)
require.Equal(t, 4, f.Width())
require.Nil(t, n)
nf := astiav.AllocFrame()
defer nf.Free()
ff.Put(nf, nil)
require.Equal(t, []string{"astilibav: refing frame failed: Invalid argument"}, logs)
f, n = ff.Get()
require.NotNil(t, f)
require.Equal(t, 4, f.Width())
require.Nil(t, n)
err = EmptyVideoFrameAdapter(astiav.ColorRangeUnspecified, astiav.PixelFormatYuv420P, 6, 2)(nf)
require.NoError(t, err)
nn := &Filterer{}
ff.Put(nf, nn)
for i := 0; i <= 1; i++ {
f, n = ff.Get()
require.NotNil(t, f)
require.Equal(t, 6, f.Width())
require.Equal(t, nn, n)
}
}