mirror of
https://github.com/asticode/go-astiencoder.git
synced 2025-12-24 13:57:53 +08:00
Added frame filler
This commit is contained in:
82
libav/frame_filler.go
Normal file
82
libav/frame_filler.go
Normal 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)
|
||||
}
|
||||
}
|
||||
57
libav/frame_filler_test.go
Normal file
57
libav/frame_filler_test.go
Normal 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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user