126 lines
3.7 KiB
Go
126 lines
3.7 KiB
Go
package mxladapter
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
"time"
|
|
|
|
"mxl-player/internal/playback"
|
|
"mxl-player/internal/source"
|
|
|
|
mxl "github.com/qvest-digital/go-mxl/mxl"
|
|
)
|
|
|
|
type fakeLocalSyncSource struct {
|
|
video source.Frame
|
|
audio source.AudioFrame
|
|
readErr error
|
|
rate mxl.Rational
|
|
timeout time.Duration
|
|
closed bool
|
|
closeError error
|
|
}
|
|
|
|
func (s *fakeLocalSyncSource) NextSync(
|
|
_ context.Context,
|
|
timeout time.Duration,
|
|
) (source.Frame, source.AudioFrame, error) {
|
|
s.timeout = timeout
|
|
return s.video, s.audio, s.readErr
|
|
}
|
|
|
|
func (s *fakeLocalSyncSource) AudioRate() mxl.Rational { return s.rate }
|
|
func (s *fakeLocalSyncSource) Close() error {
|
|
s.closed = true
|
|
return s.closeError
|
|
}
|
|
|
|
func syncFeedConfigs() (playback.FeedConfig, playback.FeedConfig) {
|
|
return playback.FeedConfig{Domain: "/mxl", UUID: "video", Active: true},
|
|
playback.FeedConfig{Domain: "/mxl", UUID: "audio", Active: true}
|
|
}
|
|
|
|
func TestSyncFactoryRejectsDifferentDomains(t *testing.T) {
|
|
video, audio := syncFeedConfigs()
|
|
audio.Domain = "/other"
|
|
reader, err := (SyncFactory{}).OpenSync(context.Background(), video, audio)
|
|
if reader != nil {
|
|
t.Fatal("OpenSync() reader is not nil")
|
|
}
|
|
if !errors.Is(err, ErrNativeSyncDifferentDomains) {
|
|
t.Fatalf("OpenSync() error = %v, want %v", err, ErrNativeSyncDifferentDomains)
|
|
}
|
|
if source.KindOf(err) != source.ErrorKindInvalidConfig {
|
|
t.Fatalf("error kind = %v, want invalid config", source.KindOf(err))
|
|
}
|
|
if ShouldRetry(err) {
|
|
t.Fatal("ShouldRetry() = true for different domains")
|
|
}
|
|
}
|
|
|
|
func TestSyncFactoryUsesDefaultsAndForwardsFeeds(t *testing.T) {
|
|
fake := &fakeLocalSyncSource{rate: mxl.Rational{Num: 48_000, Den: 1}}
|
|
var domain, videoUUID, audioUUID string
|
|
factory := SyncFactory{open: func(d, v, a string) (localSyncSource, error) {
|
|
domain, videoUUID, audioUUID = d, v, a
|
|
return fake, nil
|
|
}}
|
|
video, audio := syncFeedConfigs()
|
|
|
|
reader, err := factory.OpenSync(context.Background(), video, audio)
|
|
if err != nil {
|
|
t.Fatalf("OpenSync() error = %v", err)
|
|
}
|
|
if domain != video.Domain || videoUUID != video.UUID || audioUUID != audio.UUID {
|
|
t.Fatalf("open args = %q %q %q", domain, videoUUID, audioUUID)
|
|
}
|
|
got := reader.(*syncReader)
|
|
if got.readTimeout != DefaultSyncReadTimeout {
|
|
t.Fatalf("reader timeout=%s, want %s", got.readTimeout, DefaultSyncReadTimeout)
|
|
}
|
|
}
|
|
|
|
func TestSyncReaderConvertsPairWithoutCopying(t *testing.T) {
|
|
videoPayload := []byte{1, 2, 3}
|
|
audioSamples := [][]byte{{4, 5, 6, 7}}
|
|
fake := &fakeLocalSyncSource{
|
|
video: source.Frame{Index: 10, Width: 20, Height: 30, Payload: videoPayload},
|
|
audio: source.AudioFrame{Index: 40, SampleCount: 1, Channels: 1, Samples: audioSamples},
|
|
rate: mxl.Rational{Num: 48_000, Den: 1},
|
|
}
|
|
reader := &syncReader{
|
|
source: fake, readTimeout: 7 * time.Millisecond,
|
|
rateNumerator: 48_000, rateDenominator: 1,
|
|
}
|
|
|
|
frame, err := reader.ReadSync(context.Background())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if fake.timeout != 7*time.Millisecond {
|
|
t.Fatalf("NextSync() timeout=%s", fake.timeout)
|
|
}
|
|
if frame.Video.Index != 10 || frame.Audio.Index != 40 || frame.Audio.SampleRateNumerator != 48_000 {
|
|
t.Fatalf("frame = %+v", frame)
|
|
}
|
|
if &frame.Video.Payload[0] != &videoPayload[0] || &frame.Audio.Samples[0][0] != &audioSamples[0][0] {
|
|
t.Fatal("sync payload was copied")
|
|
}
|
|
}
|
|
|
|
func TestSyncFactoryReturnsPreCanceledContextWithoutOpening(t *testing.T) {
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
cancel()
|
|
opened := false
|
|
factory := SyncFactory{open: func(string, string, string) (localSyncSource, error) {
|
|
opened = true
|
|
return nil, nil
|
|
}}
|
|
video, audio := syncFeedConfigs()
|
|
reader, err := factory.OpenSync(ctx, video, audio)
|
|
if reader != nil || !errors.Is(err, context.Canceled) || opened {
|
|
t.Fatalf("reader=%v error=%v opened=%t", reader, err, opened)
|
|
}
|
|
}
|