Skip to content

Commit 4fc77c9

Browse files
committed
lint
1 parent f60a360 commit 4fc77c9

1 file changed

Lines changed: 80 additions & 43 deletions

File tree

encode.go

Lines changed: 80 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -195,28 +195,36 @@ func (e *Encoder) SetSize(size string) int64 {
195195
// If you want to control the context, use GetVideoContext().
196196
func (e *Encoder) GetVideo(input, title string) (string, io.ReadCloser, error) {
197197
ctx := context.Background()
198-
var cancel func()
198+
199+
var cancel context.CancelFunc
199200

200201
if e.config.Time > 0 {
201202
ctx, cancel = context.WithTimeout(ctx, time.Second*time.Duration(e.config.Time+1))
202203
}
203204

204-
return e.getVideoContext(ctx, cancel, input, title)
205+
cmdStr, stream, err := e.GetVideoContext(ctx, input, title)
206+
if err != nil {
207+
if cancel != nil {
208+
cancel()
209+
}
210+
211+
return cmdStr, nil, err
212+
}
213+
214+
if cancel == nil {
215+
return cmdStr, stream, nil
216+
}
217+
218+
return cmdStr, &cancelReadCloser{ReadCloser: stream, cancel: cancel}, nil
205219
}
206220

207221
// GetVideoContext retreives video from an input and returns an io.ReadCloser to consume the output.
208222
// Input must be an RTSP URL. Title is encoded into the video as the "movie title."
209223
// Returns command used for diagnostics, io.ReadCloser and error or nil.
210224
// Use the context to add a timeout value (max run duration) to the ffmpeg command.
225+
//
226+
//nolint:contextcheck // caller-provided context is accepted and used for command execution.
211227
func (e *Encoder) GetVideoContext(ctx context.Context, input, title string) (string, io.ReadCloser, error) {
212-
return e.getVideoContext(ctx, nil, input, title)
213-
}
214-
215-
func (e *Encoder) getVideoContext(
216-
ctx context.Context,
217-
parentCancel context.CancelFunc,
218-
input, title string,
219-
) (string, io.ReadCloser, error) {
220228
if input == "" {
221229
return "", nil, ErrInvalidInput
222230
}
@@ -233,35 +241,30 @@ func (e *Encoder) getVideoContext(
233241
stdoutpipe, err := cmd.StdoutPipe()
234242
if err != nil {
235243
cmdCancel()
236-
if parentCancel != nil {
237-
parentCancel()
238-
}
239244

240245
return cmdStr, nil, fmt.Errorf("subcommand failed: %w", err)
241246
}
242247

243248
err = cmd.Start()
244249
if err != nil {
245250
_ = stdoutpipe.Close()
251+
246252
cmdCancel()
247-
if parentCancel != nil {
248-
parentCancel()
249-
}
250253

251254
return cmdStr, nil, withStderr("run failed", err, stderr.String())
252255
}
253256

254257
done := make(chan error, 1)
258+
255259
go func() {
256260
done <- cmd.Wait()
257261
}()
258262

259263
return cmdStr, &streamResult{
260-
out: stdoutpipe,
261-
done: done,
262-
cmdCancel: cmdCancel,
263-
parentCancel: parentCancel,
264-
stderr: stderr,
264+
out: stdoutpipe,
265+
done: done,
266+
cmdCancel: cmdCancel,
267+
stderr: stderr,
265268
}, nil
266269
}
267270

@@ -305,7 +308,9 @@ func (e *Encoder) SaveVideoContext(
305308

306309
cmdStr, cmd := e.getVideoHandle(ctx, input, output, title)
307310
stderr := newTailBuffer(defaultStderrTail)
311+
308312
var stdout bytes.Buffer
313+
309314
cmd.Stdout = &stdout
310315
cmd.Stderr = stderr
311316

@@ -433,27 +438,37 @@ func (e *Encoder) getVideoHandle(ctx context.Context, input, output, title strin
433438

434439
// streamResult is our custom io.ReadCloser that also cleans up the command and context.
435440
type streamResult struct {
436-
out io.ReadCloser
437-
done <-chan error
438-
cmdCancel context.CancelFunc
439-
parentCancel context.CancelFunc
440-
stderr *tailBuffer
441-
closeOnce sync.Once
442-
closeErr error
441+
out io.ReadCloser
442+
done <-chan error
443+
cmdCancel context.CancelFunc
444+
stderr *tailBuffer
445+
closeOnce sync.Once
446+
closeErr error
443447
}
444448

445-
func (s *streamResult) Read(p []byte) (int, error) {
446-
return s.out.Read(p)
449+
func (s *streamResult) Read(data []byte) (int, error) {
450+
bytesRead, err := s.out.Read(data)
451+
if err == nil {
452+
return bytesRead, nil
453+
}
454+
455+
if errors.Is(err, io.EOF) {
456+
return bytesRead, io.EOF
457+
}
458+
459+
if err != nil {
460+
return bytesRead, fmt.Errorf("read stream: %w", err)
461+
}
462+
463+
return bytesRead, nil
447464
}
448465

449466
func (s *streamResult) Close() error {
450467
s.closeOnce.Do(func() {
451468
s.cmdCancel()
452-
if s.parentCancel != nil {
453-
s.parentCancel()
454-
}
455469

456470
_ = s.out.Close()
471+
457472
waitErr := <-s.done
458473
if waitErr != nil && !errors.Is(waitErr, context.Canceled) {
459474
s.closeErr = withStderr("run failed", waitErr, s.stderr.String())
@@ -468,29 +483,29 @@ type tailBuffer struct {
468483
max int
469484
}
470485

471-
func newTailBuffer(max int) *tailBuffer {
472-
return &tailBuffer{max: max}
486+
func newTailBuffer(limit int) *tailBuffer {
487+
return &tailBuffer{max: limit}
473488
}
474489

475-
func (t *tailBuffer) Write(p []byte) (int, error) {
490+
func (t *tailBuffer) Write(data []byte) (int, error) {
476491
if t.max <= 0 {
477-
return len(p), nil
492+
return len(data), nil
478493
}
479494

480-
if len(p) >= t.max {
481-
t.buf = append(t.buf[:0], p[len(p)-t.max:]...)
495+
if len(data) >= t.max {
496+
t.buf = append(t.buf[:0], data[len(data)-t.max:]...)
482497

483-
return len(p), nil
498+
return len(data), nil
484499
}
485500

486-
need := len(t.buf) + len(p) - t.max
501+
need := len(t.buf) + len(data) - t.max
487502
if need > 0 {
488503
t.buf = append(t.buf[:0], t.buf[need:]...)
489504
}
490505

491-
t.buf = append(t.buf, p...)
506+
t.buf = append(t.buf, data...)
492507

493-
return len(p), nil
508+
return len(data), nil
494509
}
495510

496511
func (t *tailBuffer) String() string {
@@ -504,3 +519,25 @@ func withStderr(prefix string, err error, stderr string) error {
504519

505520
return fmt.Errorf("%s: %w: %s", prefix, err, stderr)
506521
}
522+
523+
type cancelReadCloser struct {
524+
io.ReadCloser
525+
526+
cancel context.CancelFunc
527+
closeOnce sync.Once
528+
}
529+
530+
func (c *cancelReadCloser) Close() error {
531+
var err error
532+
533+
c.closeOnce.Do(func() {
534+
err = c.ReadCloser.Close()
535+
c.cancel()
536+
})
537+
538+
if err != nil {
539+
return fmt.Errorf("close stream: %w", err)
540+
}
541+
542+
return nil
543+
}

0 commit comments

Comments
 (0)