Refactoring #3
@@ -120,15 +120,43 @@ func (s *Source) Close() error {
|
|||||||
|
|
||||||
func (s *Source) NextCtx(ctx context.Context, timeout time.Duration) (Frame, error) {
|
func (s *Source) NextCtx(ctx context.Context, timeout time.Duration) (Frame, error) {
|
||||||
for {
|
for {
|
||||||
|
frame, err := s.ReadOnceCtx(ctx, timeout)
|
||||||
|
if err == nil {
|
||||||
|
return frame, nil
|
||||||
|
}
|
||||||
|
if ctx.Err() != nil {
|
||||||
|
return Frame{}, ctx.Err()
|
||||||
|
}
|
||||||
|
if KindOf(err) != ErrorKindTemporary {
|
||||||
|
return Frame{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if errors.Is(err, mxl.ErrOutOfRangeEarly) {
|
||||||
select {
|
select {
|
||||||
|
case <-time.After(10 * time.Millisecond):
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return Frame{}, ctx.Err()
|
return Frame{}, ctx.Err()
|
||||||
default:
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Source) ReadOnceCtx(
|
||||||
|
ctx context.Context,
|
||||||
|
timeout time.Duration,
|
||||||
|
) (Frame, error) {
|
||||||
|
if err := ctx.Err(); err != nil {
|
||||||
|
return Frame{}, err
|
||||||
|
}
|
||||||
|
|
||||||
g, err := s.reader.GetGrain(s.idx, timeout)
|
g, err := s.reader.GetGrain(s.idx, timeout)
|
||||||
|
if ctx.Err() != nil {
|
||||||
|
return Frame{}, ctx.Err()
|
||||||
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case err == nil:
|
case err == nil:
|
||||||
f := Frame{
|
frame := Frame{
|
||||||
Index: g.Index,
|
Index: g.Index,
|
||||||
Width: s.width,
|
Width: s.width,
|
||||||
Height: s.height,
|
Height: s.height,
|
||||||
@@ -138,16 +166,44 @@ func (s *Source) NextCtx(ctx context.Context, timeout time.Duration) (Frame, err
|
|||||||
Payload: g.Payload,
|
Payload: g.Payload,
|
||||||
}
|
}
|
||||||
s.idx++
|
s.idx++
|
||||||
return f, nil
|
return frame, nil
|
||||||
|
|
||||||
case errors.Is(err, mxl.ErrTimeout):
|
case errors.Is(err, mxl.ErrTimeout):
|
||||||
s.idx = mxl.CurrentIndex(s.rate)
|
s.idx = mxl.CurrentIndex(s.rate)
|
||||||
|
return Frame{}, wrapError(
|
||||||
|
"read video",
|
||||||
|
ErrorKindTemporary,
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
|
||||||
case errors.Is(err, mxl.ErrOutOfRangeEarly):
|
case errors.Is(err, mxl.ErrOutOfRangeEarly):
|
||||||
time.Sleep(10 * time.Millisecond)
|
return Frame{}, wrapError(
|
||||||
|
"read video",
|
||||||
|
ErrorKindTemporary,
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
|
||||||
case errors.Is(err, mxl.ErrOutOfRangeLate):
|
case errors.Is(err, mxl.ErrOutOfRangeLate):
|
||||||
s.idx = mxl.CurrentIndex(s.rate)
|
s.idx = mxl.CurrentIndex(s.rate)
|
||||||
|
return Frame{}, wrapError(
|
||||||
|
"read video",
|
||||||
|
ErrorKindTemporary,
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
|
||||||
|
case errors.Is(err, mxl.ErrFlowInvalid):
|
||||||
|
return Frame{}, wrapError(
|
||||||
|
"read video",
|
||||||
|
ErrorKindUnavailable,
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return Frame{}, fmt.Errorf("GetGrain: %w", err)
|
return Frame{}, wrapError(
|
||||||
}
|
"read video",
|
||||||
|
ErrorKindUnavailable,
|
||||||
|
err,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user