57 lines
1.0 KiB
Go
57 lines
1.0 KiB
Go
package playback
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
)
|
|
|
|
type videoSinkError struct {
|
|
err error
|
|
}
|
|
|
|
func (e *videoSinkError) Error() string {
|
|
return fmt.Sprintf("consume video: %v", e.err)
|
|
}
|
|
|
|
func (e *videoSinkError) Unwrap() error {
|
|
return e.err
|
|
}
|
|
|
|
func runVideoAttempt(
|
|
ctx context.Context,
|
|
factory VideoReaderFactory,
|
|
sink VideoSink,
|
|
config FeedConfig,
|
|
) (resultErr error) {
|
|
ctx = withVideoSource(ctx, config)
|
|
reader, err := factory.OpenVideo(ctx, config)
|
|
if err != nil {
|
|
return fmt.Errorf("open video: %w", err)
|
|
}
|
|
|
|
defer func() {
|
|
if closeErr := reader.Close(); closeErr != nil {
|
|
closeErr = fmt.Errorf("close video: %w", closeErr)
|
|
resultErr = errors.Join(resultErr, closeErr)
|
|
}
|
|
}()
|
|
|
|
for {
|
|
frame, err := reader.ReadVideo(ctx)
|
|
if err != nil {
|
|
if ctx.Err() != nil {
|
|
return ctx.Err()
|
|
}
|
|
return fmt.Errorf("read video: %w", err)
|
|
}
|
|
|
|
if err := sink.ConsumeVideo(ctx, frame); err != nil {
|
|
if ctx.Err() != nil {
|
|
return ctx.Err()
|
|
}
|
|
return &videoSinkError{err: err}
|
|
}
|
|
}
|
|
}
|