av/cmd/vidforward/slate.go

101 lines
3.2 KiB
Go
Raw Normal View History

/*
DESCRIPTION
slate.go houses vidforward slate functionality including the slate writing
routine and HTTP request handlers for receiving of new slate videos.
AUTHORS
Saxon A. Nelson-Milton <saxon@ausocean.org>
LICENSE
Copyright (C) 2022 the Australian Ocean Lab (AusOcean)
It is free software: you can redistribute it and/or modify them
under the terms of the GNU General Public License as published by the
Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
It is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with revid in gpl.txt. If not, see http://www.gnu.org/licenses.
*/
package main
import (
"errors"
"io"
"time"
"bitbucket.org/ausocean/av/codec/h264"
"bitbucket.org/ausocean/av/device/file"
"bitbucket.org/ausocean/utils/logging"
)
// writeSlate is a routine that employs a file input device and h264 lexer to
// write a h264 encoded slate image to the provided revid pipeline.
func writeSlate(dst io.Writer, errCh chan error, exitSignal chan struct{}, log logging.Logger) {
log.Info("writing slate")
const (
// This is temporary and will eventually be part of a broadcast configuration
// where the remote vidforward API user can provide the slate image.
slateFileName = "slate.h264"
// Assume 25fps until this becomes configurable.
slateFrameRate = 25
loopSetting = true
frameDelay = time.Second / slateFrameRate
)
fileInput := file.NewWith(log, slateFileName, loopSetting)
err := fileInput.Start()
if err != nil {
errCh <- err
return
}
// This will wait for a signal from the provided slateExitSignal (or from a
// timeout) to stop writing the slate by "Stopping" the file input which will
// terminate the Lex function.
go func() {
slateTimeoutTimer := time.NewTimer(24 * time.Hour)
select {
case <-slateTimeoutTimer.C:
log.Warning("slate timeout")
case <-exitSignal:
log.Info("slate exist signal")
}
log.Info("stopping file input")
fileInput.Stop()
}()
// Begin lexing the slate file and send frames to rv pipeline. We'll stay in
// here until file input closes or there's an unexpected error.
err = h264.Lex(dst, fileInput, frameDelay)
// If we get to this point, it means that the we've finished lexing for some
// reason; let's figure out why.
select {
// The only reason we'd get a receive on errCh from this side is if its been
// closed. This means that we've exceeded the "startup error" period, and that
// either the error is normal from stopping the input, or we can no longer inform
// the caller and just need to log the problem.
case <-errCh:
if errors.Is(err, io.EOF) || errors.Is(err, io.ErrUnexpectedEOF) {
log.Debug("got expected error", "error", err)
return
}
log.Error("got unexpected error", "error", err)
// This means that a problem occured pretty early in lexing.
default:
log.Error("unexpected error during lex startup", "error", err)
errCh <- err
}
log.Error("finished writing slate")
}