189 lines
4.2 KiB
Go
189 lines
4.2 KiB
Go
package y4m
|
|
|
|
import (
|
|
"errors"
|
|
"git.gammaspectra.live/S.O.N.G/Ignite/frame"
|
|
"git.gammaspectra.live/S.O.N.G/Ignite/testdata"
|
|
"io"
|
|
"testing"
|
|
)
|
|
|
|
func testDecode(sample testdata.TestSample, t *testing.T) {
|
|
reader, err := sample.Open(t)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer reader.Close()
|
|
|
|
var y4m *Decoder
|
|
|
|
switch sample.Type {
|
|
case "y4m":
|
|
y4m, err = NewDecoder(reader, nil)
|
|
case "y4m.xz":
|
|
y4m, err = NewXZCompressedDecoder(reader, nil)
|
|
default:
|
|
t.Fatal("unsupported sample type")
|
|
}
|
|
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
} else {
|
|
defer y4m.Close()
|
|
decoded := 0
|
|
var lastPts int64
|
|
|
|
mod := sample.Frames / 5
|
|
|
|
var frameProperties frame.Properties
|
|
for decodedFrame := range y4m.DecodeStream().Channel() {
|
|
if decoded == 0 {
|
|
frameProperties = decodedFrame.Properties()
|
|
}
|
|
//ingest
|
|
decoded++
|
|
if decoded%mod == 0 {
|
|
t.Logf("%d/%d", decoded, sample.Frames)
|
|
}
|
|
lastPts = decodedFrame.PTS()
|
|
decodedFrame.Return()
|
|
}
|
|
if decoded%mod != 0 {
|
|
t.Logf("%d/%d", decoded, sample.Frames)
|
|
}
|
|
|
|
if decoded != sample.Frames {
|
|
t.Fatalf("expected %d frames, got %d", sample.Frames, decoded)
|
|
}
|
|
|
|
duration := y4m.Properties().TimeBase().PTSToDuration(lastPts)
|
|
|
|
if y4m.Properties().TimeBase().PTSToDuration(lastPts) != sample.Duration() {
|
|
t.Fatalf("expected %s duration, got %s", sample.Duration(), duration)
|
|
}
|
|
|
|
if frameProperties.Width != sample.Width {
|
|
t.Fatalf("expected %d width, got %d", sample.Width, frameProperties.Width)
|
|
}
|
|
|
|
if frameProperties.Height != sample.Height {
|
|
t.Fatalf("expected %d height, got %d", sample.Height, frameProperties.Height)
|
|
}
|
|
|
|
if frameProperties.ColorSpace.String() != sample.ColorSpace.String() {
|
|
t.Fatalf("expected %s color space, got %s", sample.ColorSpace.String(), frameProperties.ColorSpace.String())
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestDecode_YUV420_720p24_8bit(t *testing.T) {
|
|
testDecode(testdata.Y4M_Sintel_Trailer_720p24_YUV420_8bit, t)
|
|
}
|
|
|
|
func TestDecode_YUV444_720p50_8bit(t *testing.T) {
|
|
testDecode(testdata.Y4M_Ducks_Take_Off_720p50_YUV444_8bit, t)
|
|
}
|
|
|
|
func TestDecode_YUV422_720p50_8bit(t *testing.T) {
|
|
testDecode(testdata.Y4M_Ducks_Take_Off_720p50_YUV422_8bit, t)
|
|
}
|
|
|
|
func TestDecode_YUV420_2160p60_10bit(t *testing.T) {
|
|
testDecode(testdata.Y4M_Netflix_FoodMarket_2160p60_YUV420_10bit, t)
|
|
}
|
|
|
|
func TestDecode_YUV420_360p24_8bit_xz(t *testing.T) {
|
|
testDecode(testdata.Y4M_Big_Buck_Bunny_360p24_YUV420_8bit, t)
|
|
}
|
|
|
|
func testBench(sample testdata.TestSample, b *testing.B) {
|
|
b.ReportAllocs()
|
|
reader, err := sample.Open(b)
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
defer func() {
|
|
reader.Close()
|
|
}()
|
|
|
|
var y4m *Decoder
|
|
|
|
init := func() {
|
|
if y4m != nil {
|
|
y4m.Close()
|
|
}
|
|
|
|
if rsc, ok := reader.(io.ReadSeekCloser); ok {
|
|
_, err = rsc.Seek(0, io.SeekStart)
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
} else {
|
|
reader.Close()
|
|
reader, err = sample.Open(b)
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
|
|
switch sample.Type {
|
|
case "y4m":
|
|
y4m, err = NewDecoder(reader, nil)
|
|
case "y4m.xz":
|
|
y4m, err = NewXZCompressedDecoder(reader, nil)
|
|
default:
|
|
b.Fatal("unsupported sample type")
|
|
}
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
|
|
var bytesDecoded, framesDecoded int
|
|
|
|
init()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
decodedFrame, err := y4m.Decode()
|
|
if err != nil {
|
|
b.StopTimer()
|
|
if errors.Is(err, io.EOF) {
|
|
//reset to start
|
|
init()
|
|
b.StartTimer()
|
|
continue
|
|
} else {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
framesDecoded++
|
|
bytesDecoded += len(decodedFrame.GetJoint())
|
|
b.SetBytes(int64(len(decodedFrame.GetJoint())))
|
|
decodedFrame.Return()
|
|
}
|
|
b.StopTimer()
|
|
|
|
y4m.Close()
|
|
b.ReportMetric(float64(framesDecoded)/b.Elapsed().Seconds(), "frames/s")
|
|
}
|
|
|
|
func BenchmarkDecode_YUV420_720p24_8bit(b *testing.B) {
|
|
testBench(testdata.Y4M_Sintel_Trailer_720p24_YUV420_8bit, b)
|
|
}
|
|
|
|
func BenchmarkDecode_YUV444_720p50_8bit(b *testing.B) {
|
|
testBench(testdata.Y4M_Ducks_Take_Off_720p50_YUV444_8bit, b)
|
|
}
|
|
|
|
func BenchmarkDecode_YUV422_720p50_8bit(b *testing.B) {
|
|
testBench(testdata.Y4M_Ducks_Take_Off_720p50_YUV422_8bit, b)
|
|
}
|
|
|
|
func BenchmarkDecode_YUV420_2160p60_10bit(b *testing.B) {
|
|
testBench(testdata.Y4M_Netflix_FoodMarket_2160p60_YUV420_10bit, b)
|
|
}
|
|
|
|
func BenchmarkDecode_YUV420_360p24_8bit_xz(b *testing.B) {
|
|
testBench(testdata.Y4M_Big_Buck_Bunny_360p24_YUV420_8bit, b)
|
|
}
|