revid: added chunkSize to audioInput and bufferSize to lex functions

The audio lexers need to know how much data they will be receiving unlike video which has a fixed buffer size.
This means that all the lex function will need to be given a buffer size since they are used as a function pointer with the same signature.
This commit is contained in:
Trek H 2019-05-05 17:56:14 +09:30
parent 09db8907a5
commit a3c7cb5616
3 changed files with 20 additions and 23 deletions

View File

@ -135,6 +135,8 @@ func handleFlags() revid.Config {
saturationPtr = flag.Int("Saturation", 0, "Set Saturation. (100-100)") saturationPtr = flag.Int("Saturation", 0, "Set Saturation. (100-100)")
exposurePtr = flag.String("Exposure", "auto", "Set exposure mode. ("+strings.Join(revid.ExposureModes[:], ",")+")") exposurePtr = flag.String("Exposure", "auto", "Set exposure mode. ("+strings.Join(revid.ExposureModes[:], ",")+")")
autoWhiteBalancePtr = flag.String("Awb", "auto", "Set automatic white balance mode. ("+strings.Join(revid.AutoWhiteBalanceModes[:], ",")+")") autoWhiteBalancePtr = flag.String("Awb", "auto", "Set automatic white balance mode. ("+strings.Join(revid.AutoWhiteBalanceModes[:], ",")+")")
// Audio specific flags.
sampleRatePtr = flag.Int("SampleRate", 48000, "Sample rate of recorded audio") sampleRatePtr = flag.Int("SampleRate", 48000, "Sample rate of recorded audio")
channelsPtr = flag.Int("Channels", 1, "Record in Mono or Stereo (1 or 2)") channelsPtr = flag.Int("Channels", 1, "Record in Mono or Stereo (1 or 2)")
recPeriodPtr = flag.Int("recPeriod", 5, "How many seconds to record at a time") recPeriodPtr = flag.Int("recPeriod", 5, "How many seconds to record at a time")

View File

@ -36,10 +36,6 @@ import (
"time" "time"
) )
const (
audioChunkSize = 16000
)
var noDelay = make(chan time.Time) var noDelay = make(chan time.Time)
func init() { func init() {
@ -52,7 +48,7 @@ var h264Prefix = [...]byte{0x00, 0x00, 0x01, 0x09, 0xf0}
// successive writes being performed not earlier than the specified delay. // successive writes being performed not earlier than the specified delay.
// NAL units are split after type 1 (Coded slice of a non-IDR picture), 5 // NAL units are split after type 1 (Coded slice of a non-IDR picture), 5
// (Coded slice of a IDR picture) and 8 (Picture parameter set). // (Coded slice of a IDR picture) and 8 (Picture parameter set).
func H264(dst io.Writer, src io.Reader, delay time.Duration) error { func H264(dst io.Writer, src io.Reader, delay time.Duration, bufSize int) error {
var tick <-chan time.Time var tick <-chan time.Time
if delay == 0 { if delay == 0 {
tick = noDelay tick = noDelay
@ -62,7 +58,7 @@ func H264(dst io.Writer, src io.Reader, delay time.Duration) error {
tick = ticker.C tick = ticker.C
} }
const bufSize = 8 << 10 bufSize = 8 << 10 //TODO(Trek): Pass this in rather than set it in here.
c := newScanner(src, make([]byte, 4<<10)) // Standard file buffer size. c := newScanner(src, make([]byte, 4<<10)) // Standard file buffer size.
@ -207,7 +203,7 @@ func (c *scanner) reload() error {
// MJPEG parses MJPEG frames read from src into separate writes to dst with // MJPEG parses MJPEG frames read from src into separate writes to dst with
// successive writes being performed not earlier than the specified delay. // successive writes being performed not earlier than the specified delay.
func MJPEG(dst io.Writer, src io.Reader, delay time.Duration) error { func MJPEG(dst io.Writer, src io.Reader, delay time.Duration, bufSize int) error {
var tick <-chan time.Time var tick <-chan time.Time
if delay == 0 { if delay == 0 {
tick = noDelay tick = noDelay
@ -252,7 +248,7 @@ func MJPEG(dst io.Writer, src io.Reader, delay time.Duration) error {
// PCM reads from the given source and breaks the PCM into chunks that // PCM reads from the given source and breaks the PCM into chunks that
// are an appropriate size for mts and pes packets. // are an appropriate size for mts and pes packets.
func PCM(dst io.Writer, src io.Reader, delay time.Duration) error { func PCM(dst io.Writer, src io.Reader, delay time.Duration, bufSize int) error {
var tick <-chan time.Time var tick <-chan time.Time
if delay == 0 { if delay == 0 {
tick = noDelay tick = noDelay
@ -263,7 +259,7 @@ func PCM(dst io.Writer, src io.Reader, delay time.Duration) error {
} }
for { for {
buf := make([]byte, 0, audioChunkSize) buf := make([]byte, 0, bufSize)
_, err := src.Read(buf) _, err := src.Read(buf)
if err != nil { if err != nil {
return err return err
@ -281,7 +277,7 @@ func PCM(dst io.Writer, src io.Reader, delay time.Duration) error {
// are an appropriate size for mts and pes packets. // are an appropriate size for mts and pes packets.
// Since PCM and ADPCM are not any different when it comes to how they are // Since PCM and ADPCM are not any different when it comes to how they are
// transmitted, ADPCM is just a wrapper for PCM. // transmitted, ADPCM is just a wrapper for PCM.
func ADPCM(dst io.Writer, src io.Reader, delay time.Duration) error { func ADPCM(dst io.Writer, src io.Reader, delay time.Duration, bufSize int) error {
err := PCM(dst, src, delay) err := PCM(dst, src, delay, bufSize)
return err return err
} }

View File

@ -103,7 +103,7 @@ type Revid struct {
cmd *exec.Cmd cmd *exec.Cmd
// lexTo, encoder and packer handle transcoding the input stream. // lexTo, encoder and packer handle transcoding the input stream.
lexTo func(dest io.Writer, src io.Reader, delay time.Duration) error lexTo func(dest io.Writer, src io.Reader, delay time.Duration, bufSize int) error
// buffer handles passing frames from the transcoder // buffer handles passing frames from the transcoder
// to the target destination. // to the target destination.
@ -620,7 +620,7 @@ func (r *Revid) startRaspivid() error {
} }
r.wg.Add(1) r.wg.Add(1)
go r.processFrom(stdout, 0) go r.processFrom(stdout, 0, 0)
return nil return nil
} }
@ -662,7 +662,7 @@ func (r *Revid) startV4L() error {
} }
r.wg.Add(1) r.wg.Add(1)
go r.processFrom(stdout, time.Duration(0)) go r.processFrom(stdout, time.Duration(0), 0)
return nil return nil
} }
@ -678,21 +678,20 @@ func (r *Revid) setupInputForFile() error {
// TODO(kortschak): Maybe we want a context.Context-aware parser that we can stop. // TODO(kortschak): Maybe we want a context.Context-aware parser that we can stop.
r.wg.Add(1) r.wg.Add(1)
go r.processFrom(f, time.Second/time.Duration(r.config.FrameRate)) go r.processFrom(f, time.Second/time.Duration(r.config.FrameRate), 0)
return nil return nil
} }
// startAudioInput is used to start capturing audio from an audio device and processing it. // startAudioInput is used to start capturing audio from an audio device and processing it.
func (r *Revid) startAudioInput() error { func (r *Revid) startAudioInput() error {
ai := NewAudioInput(&r.config) ai := NewAudioInput(&r.config)
go r.processFrom(ai, time.Second/time.Duration(r.config.WriteRate), ai.ChunkSize())
go r.processFrom(ai, time.Second/time.Duration(r.config.WriteRate))
return nil return nil
} }
func (r *Revid) processFrom(read io.Reader, delay time.Duration) { func (r *Revid) processFrom(read io.Reader, delay time.Duration, bufSize int) {
r.config.Logger.Log(logger.Info, pkg+"reading input data") r.config.Logger.Log(logger.Info, pkg+"reading input data")
r.err <- r.lexTo(r.buffer, read, delay) r.err <- r.lexTo(r.buffer, read, delay, bufSize)
r.config.Logger.Log(logger.Info, pkg+"finished reading input data") r.config.Logger.Log(logger.Info, pkg+"finished reading input data")
r.wg.Done() r.wg.Done()
} }