package mxladapter import ( "context" "errors" "fmt" "time" "mxl-player/internal/playback" "mxl-player/internal/source" ) const DefaultVideoReadTimeout = 200 * time.Millisecond type VideoFactory struct { ReadTimeout time.Duration } type videoReader struct { source *source.Source timeout time.Duration } var _ playback.VideoReaderFactory = VideoFactory{} var _ playback.VideoReader = (*videoReader)(nil) func (f VideoFactory) OpenVideo( ctx context.Context, config playback.FeedConfig, ) (playback.VideoReader, error) { if err := ctx.Err(); err != nil { return nil, err } if err := config.Validate(); err != nil { return nil, &source.SourceError{ Op: "validate video feed", Kind: source.ErrorKindInvalidConfig, Err: err, } } if !config.IsConfigured() { return nil, &source.SourceError{ Op: "validate video feed", Kind: source.ErrorKindInvalidConfig, Err: errors.New("video feed is not configured"), } } src, err := source.Open(config.Domain, config.UUID) if err != nil { return nil, fmt.Errorf("open local MXL video: %w", err) } if err := ctx.Err(); err != nil { _ = src.Close() return nil, err } timeout := f.ReadTimeout if timeout <= 0 { timeout = DefaultVideoReadTimeout } return &videoReader{ source: src, timeout: timeout, }, nil } func (r *videoReader) ReadVideo( ctx context.Context, ) (playback.VideoFrame, error) { frame, err := r.source.NextCtx(ctx, r.timeout) if err != nil { return playback.VideoFrame{}, err } return playback.VideoFrame{ Index: frame.Index, Width: frame.Width, Height: frame.Height, Stride: frame.Stride, Size: frame.Size, Invalid: frame.Invalid, Payload: frame.Payload, }, nil } func (r *videoReader) Close() error { return r.source.Close() }