mirror of
https://github.com/asticode/go-astiav.git
synced 2025-10-05 16:16:50 +08:00
206 lines
5.1 KiB
Go
206 lines
5.1 KiB
Go
package astiav_test
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"testing"
|
|
|
|
"github.com/asticode/go-astiav"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func videoInputLastVideoFrame() (f *astiav.Frame, err error) {
|
|
if global.frame != nil {
|
|
return global.frame, nil
|
|
}
|
|
|
|
var fc *astiav.FormatContext
|
|
if fc, err = videoInputFormatContext(); err != nil {
|
|
err = fmt.Errorf("astiav_test: getting input format context failed: %w", err)
|
|
return
|
|
}
|
|
|
|
var cc *astiav.CodecContext
|
|
var cs *astiav.Stream
|
|
for _, s := range fc.Streams() {
|
|
if s.CodecParameters().MediaType() != astiav.MediaTypeVideo {
|
|
continue
|
|
}
|
|
|
|
cs = s
|
|
|
|
c := astiav.FindDecoder(s.CodecParameters().CodecID())
|
|
if c == nil {
|
|
err = errors.New("astiav_test: no codec")
|
|
return
|
|
}
|
|
|
|
cc = astiav.AllocCodecContext(c)
|
|
if cc == nil {
|
|
err = errors.New("astiav_test: no codec context")
|
|
return
|
|
}
|
|
global.closer.Add(cc.Free)
|
|
|
|
if err = cs.CodecParameters().ToCodecContext(cc); err != nil {
|
|
err = fmt.Errorf("astiav_test: updating codec context failed: %w", err)
|
|
return
|
|
}
|
|
|
|
if err = cc.Open(c, nil); err != nil {
|
|
err = fmt.Errorf("astiav_test: opening codec context failed: %w", err)
|
|
return
|
|
}
|
|
break
|
|
}
|
|
|
|
if cs == nil {
|
|
err = errors.New("astiav_test: no valid video stream")
|
|
return
|
|
}
|
|
|
|
var pkt1 *astiav.Packet
|
|
if pkt1, err = videoInputFirstPacket(); err != nil {
|
|
err = fmt.Errorf("astiav_test: getting input first packet failed: %w", err)
|
|
return
|
|
}
|
|
|
|
pkt2 := astiav.AllocPacket()
|
|
global.closer.Add(pkt2.Free)
|
|
|
|
f = astiav.AllocFrame()
|
|
global.closer.Add(f.Free)
|
|
|
|
lastFrame := astiav.AllocFrame()
|
|
global.closer.Add(lastFrame.Free)
|
|
|
|
pkts := []*astiav.Packet{pkt1}
|
|
for {
|
|
if err = fc.ReadFrame(pkt2); err != nil {
|
|
if errors.Is(err, astiav.ErrEof) || errors.Is(err, astiav.ErrEagain) {
|
|
if err = f.Ref(lastFrame); err != nil {
|
|
err = fmt.Errorf("astiav_test: refing frame failed: %w", err)
|
|
return
|
|
}
|
|
err = nil
|
|
break
|
|
}
|
|
err = fmt.Errorf("astiav_test: reading frame failed: %w", err)
|
|
return
|
|
}
|
|
|
|
pkts = append(pkts, pkt2)
|
|
|
|
for _, pkt := range pkts {
|
|
if pkt.StreamIndex() != cs.Index() {
|
|
continue
|
|
}
|
|
|
|
if err = cc.SendPacket(pkt); err != nil {
|
|
err = fmt.Errorf("astiav_test: sending packet failed: %w", err)
|
|
return
|
|
}
|
|
|
|
for {
|
|
if err = cc.ReceiveFrame(f); err != nil {
|
|
if errors.Is(err, astiav.ErrEof) || errors.Is(err, astiav.ErrEagain) {
|
|
err = nil
|
|
break
|
|
}
|
|
err = fmt.Errorf("astiav_test: receiving frame failed: %w", err)
|
|
return
|
|
}
|
|
|
|
if err = lastFrame.Ref(f); err != nil {
|
|
err = fmt.Errorf("astiav_test: refing frame failed: %w", err)
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
pkts = []*astiav.Packet{}
|
|
}
|
|
return
|
|
}
|
|
|
|
func TestFrame(t *testing.T) {
|
|
f1, err := videoInputLastVideoFrame()
|
|
require.NoError(t, err)
|
|
b, err := ioutil.ReadFile("testdata/frame")
|
|
require.NoError(t, err)
|
|
require.Equal(t, string(b), fmt.Sprintf("%+v", f1.Data()))
|
|
require.Equal(t, [8]int{384, 192, 192, 0, 0, 0, 0, 0}, f1.Linesize())
|
|
require.Equal(t, int64(60928), f1.PktDts())
|
|
require.Equal(t, int64(60928), f1.PktPts())
|
|
|
|
f2 := astiav.AllocFrame()
|
|
require.NotNil(t, f2)
|
|
defer f2.Free()
|
|
f2.SetChannelLayout(astiav.ChannelLayout21)
|
|
f2.SetHeight(2)
|
|
f2.SetKeyFrame(true)
|
|
f2.SetNbSamples(4)
|
|
f2.SetPictureType(astiav.PictureTypeB)
|
|
f2.SetPixelFormat(astiav.PixelFormat0Bgr)
|
|
require.Equal(t, astiav.PixelFormat0Bgr, f2.PixelFormat()) // Need to test it right away as sample format actually updates the same field
|
|
f2.SetPts(7)
|
|
f2.SetSampleFormat(astiav.SampleFormatDbl)
|
|
require.Equal(t, astiav.SampleFormatDbl, f2.SampleFormat())
|
|
f2.SetSampleRate(9)
|
|
f2.SetWidth(10)
|
|
require.Equal(t, astiav.ChannelLayout21, f2.ChannelLayout())
|
|
require.Equal(t, 2, f2.Height())
|
|
require.True(t, f2.KeyFrame())
|
|
require.Equal(t, 4, f2.NbSamples())
|
|
require.Equal(t, astiav.PictureTypeB, f2.PictureType())
|
|
require.Equal(t, int64(7), f2.Pts())
|
|
require.Equal(t, 9, f2.SampleRate())
|
|
require.Equal(t, 10, f2.Width())
|
|
|
|
f3 := f1.Clone()
|
|
require.NotNil(t, f3)
|
|
defer f3.Free()
|
|
require.Equal(t, 180, f3.Height())
|
|
|
|
err = f2.AllocBuffer(0)
|
|
require.NoError(t, err)
|
|
err = f3.Ref(f2)
|
|
require.NoError(t, err)
|
|
require.Equal(t, 2, f3.Height())
|
|
|
|
f3.MoveRef(f1)
|
|
require.Equal(t, 180, f3.Height())
|
|
require.Equal(t, 0, f1.Height())
|
|
|
|
f3.Unref()
|
|
require.Equal(t, 0, f3.Height())
|
|
|
|
f4 := astiav.AllocFrame()
|
|
require.NotNil(t, f4)
|
|
defer f4.Free()
|
|
f4.SetNbSamples(960)
|
|
f4.SetChannelLayout(astiav.ChannelLayoutStereo)
|
|
f4.SetSampleFormat(astiav.SampleFormatS16)
|
|
f4.SetSampleRate(48000)
|
|
err = f4.AllocBuffer(0)
|
|
require.NoError(t, err)
|
|
err = f4.AllocSamples(0)
|
|
require.NoError(t, err)
|
|
|
|
f5 := astiav.AllocFrame()
|
|
require.NotNil(t, f5)
|
|
defer f5.Free()
|
|
sd := f5.NewSideData(astiav.FrameSideDataTypeAudioServiceType, 4)
|
|
require.NotNil(t, sd)
|
|
sd.SetData([]byte{1, 2, 3})
|
|
sd = f5.SideData(astiav.FrameSideDataTypeAudioServiceType)
|
|
require.NotNil(t, sd)
|
|
require.Equal(t, astiav.FrameSideDataTypeAudioServiceType, sd.Type())
|
|
require.Equal(t, []byte{1, 2, 3, 0}, sd.Data())
|
|
sd.SetData([]byte{1, 2, 3, 4, 5})
|
|
sd = f5.SideData(astiav.FrameSideDataTypeAudioServiceType)
|
|
require.NotNil(t, sd)
|
|
require.Equal(t, []byte{1, 2, 3, 4}, sd.Data())
|
|
}
|