mirror of https://bitbucket.org/ausocean/av.git
Merged in is-running-method (pull request #363)
device: add IsRunning method to AVDevice interface Approved-by: Saxon Milton <saxon.milton@gmail.com>
This commit is contained in:
commit
0dfb2df939
|
@ -462,3 +462,8 @@ func nearestPowerOfTwo(n int) int {
|
|||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// IsRunning is used to determine if the ALSA device is running.
|
||||
func (d *ALSA) IsRunning() bool {
|
||||
return d.mode == running
|
||||
}
|
||||
|
|
|
@ -4,9 +4,10 @@ NAME
|
|||
|
||||
AUTHOR
|
||||
Trek Hopton <trek@ausocean.org>
|
||||
Scott Barnard <scott@ausocean.org>
|
||||
|
||||
LICENSE
|
||||
This file is Copyright (C) 2019 the Australian Ocean Lab (AusOcean)
|
||||
This file is Copyright (C) 2019-2020 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
|
||||
|
@ -25,6 +26,7 @@ LICENSE
|
|||
package alsa
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strconv"
|
||||
|
@ -106,3 +108,47 @@ func TestNearestPowerOfTwo(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsRunning(t *testing.T) {
|
||||
const dur = 250 * time.Millisecond
|
||||
const sampleRate = 1000
|
||||
const channels = 1
|
||||
const bitDepth = 16
|
||||
const recPeriod = 1
|
||||
|
||||
l := logger.New(logger.Debug, &bytes.Buffer{}, true) // Discard logs.
|
||||
d := New(l)
|
||||
|
||||
err := d.Set(config.Config{
|
||||
SampleRate: sampleRate,
|
||||
Channels: channels,
|
||||
BitDepth: bitDepth,
|
||||
RecPeriod: recPeriod,
|
||||
InputCodec: codecutil.ADPCM,
|
||||
})
|
||||
if err != nil {
|
||||
t.Skipf("could not set device: %w", err)
|
||||
}
|
||||
|
||||
err = d.Start()
|
||||
if err != nil {
|
||||
t.Fatalf("could not start device %w", err)
|
||||
}
|
||||
|
||||
time.Sleep(dur)
|
||||
|
||||
if !d.IsRunning() {
|
||||
t.Error("device isn't running, when it should be")
|
||||
}
|
||||
|
||||
err = d.Stop()
|
||||
if err != nil {
|
||||
t.Error(err.Error())
|
||||
}
|
||||
|
||||
time.Sleep(dur)
|
||||
|
||||
if d.IsRunning() {
|
||||
t.Error("device is running, when it should not be")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,6 +55,9 @@ type AVDevice interface {
|
|||
// Stop will stop the AVDevice from capturing media data. From this point
|
||||
// Reads will no longer be successful.
|
||||
Stop() error
|
||||
|
||||
// IsRunning is used to determine if the device is running.
|
||||
IsRunning() bool
|
||||
}
|
||||
|
||||
// multiError implements the built in error interface. multiError is used here
|
||||
|
|
|
@ -36,8 +36,9 @@ import (
|
|||
// AVFile is an implementation of the AVDevice interface for a file containg
|
||||
// audio or video data.
|
||||
type AVFile struct {
|
||||
f io.ReadCloser
|
||||
cfg config.Config
|
||||
f io.ReadCloser
|
||||
cfg config.Config
|
||||
isRunning bool
|
||||
}
|
||||
|
||||
// NewAVFile returns a new AVFile.
|
||||
|
@ -62,11 +63,19 @@ func (m *AVFile) Start() error {
|
|||
if err != nil {
|
||||
return fmt.Errorf("could not open media file: %w", err)
|
||||
}
|
||||
m.isRunning = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// Stop will close the file such that any further reads will fail.
|
||||
func (m *AVFile) Stop() error { return m.f.Close() }
|
||||
func (m *AVFile) Stop() error {
|
||||
err := m.f.Close()
|
||||
if err == nil {
|
||||
m.isRunning = false
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Read implements io.Reader. If start has not been called, or Start has been
|
||||
// called and Stop has since been called, an error is returned.
|
||||
|
@ -76,3 +85,8 @@ func (m *AVFile) Read(p []byte) (int, error) {
|
|||
}
|
||||
return 0, errors.New("AV file is closed")
|
||||
}
|
||||
|
||||
// IsRunning is used to determine if the AVFile device is running.
|
||||
func (m *AVFile) IsRunning() bool {
|
||||
return m.f != nil && m.isRunning
|
||||
}
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
DESCRIPTION
|
||||
file_test.go tests the file AVDevice.
|
||||
|
||||
AUTHORS
|
||||
Scott Barnard <scott@ausocean.org>
|
||||
|
||||
LICENSE
|
||||
Copyright (C) 2020 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
|
||||
in gpl.txt. If not, see http://www.gnu.org/licenses.
|
||||
*/
|
||||
|
||||
package file
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"bitbucket.org/ausocean/av/revid/config"
|
||||
)
|
||||
|
||||
func TestIsRunning(t *testing.T) {
|
||||
const dur = 250 * time.Millisecond
|
||||
const path = "../../../test/test-data/av/input/motion-detection/mjpeg/school.mjpeg"
|
||||
|
||||
d := New()
|
||||
|
||||
err := d.Set(config.Config{
|
||||
InputPath: path,
|
||||
})
|
||||
if err != nil {
|
||||
t.Skipf("could not set device: %w", err)
|
||||
}
|
||||
|
||||
err = d.Start()
|
||||
if err != nil {
|
||||
t.Fatalf("could not start device %w", err)
|
||||
}
|
||||
|
||||
time.Sleep(dur)
|
||||
|
||||
if !d.IsRunning() {
|
||||
t.Error("device isn't running, when it should be")
|
||||
}
|
||||
|
||||
err = d.Stop()
|
||||
if err != nil {
|
||||
t.Error(err.Error())
|
||||
}
|
||||
|
||||
time.Sleep(dur)
|
||||
|
||||
if d.IsRunning() {
|
||||
t.Error("device is running, when it should not be")
|
||||
}
|
||||
}
|
|
@ -88,11 +88,12 @@ var (
|
|||
// IP camera. This has been designed to implement the GV-BX4700-8F in particular.
|
||||
// Any other models are untested.
|
||||
type GeoVision struct {
|
||||
cfg avconfig.Config
|
||||
log avconfig.Logger
|
||||
rtpClt *rtp.Client
|
||||
rtspClt *rtsp.Client
|
||||
rtcpClt *rtcp.Client
|
||||
cfg avconfig.Config
|
||||
log avconfig.Logger
|
||||
rtpClt *rtp.Client
|
||||
rtspClt *rtsp.Client
|
||||
rtcpClt *rtcp.Client
|
||||
isRunning bool
|
||||
}
|
||||
|
||||
// NewGeoVision returns a new GeoVision.
|
||||
|
@ -278,6 +279,7 @@ func (g *GeoVision) Start() error {
|
|||
}
|
||||
g.log.Log(logger.Debug, pkg+"RTSP server PLAY response", "response", resp.String())
|
||||
g.log.Log(logger.Info, pkg+"play requested, now receiving stream")
|
||||
g.isRunning = true
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -299,6 +301,8 @@ func (g *GeoVision) Stop() error {
|
|||
|
||||
g.log.Log(logger.Info, pkg+"RTP, RTSP and RTCP clients stopped and closed")
|
||||
|
||||
g.isRunning = false
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -339,3 +343,8 @@ func parseSvrRTCPPort(resp rtsp.Response) (int, error) {
|
|||
}
|
||||
return 0, errors.New("SETUP response did not provide RTCP port")
|
||||
}
|
||||
|
||||
// IsRunning is used to determine if the geovision is running.
|
||||
func (g *GeoVision) IsRunning() bool {
|
||||
return g.isRunning
|
||||
}
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
DESCRIPTION
|
||||
geovision_test.go tests the geovision AVDevice.
|
||||
|
||||
AUTHORS
|
||||
Scott Barnard <scott@ausocean.org>
|
||||
|
||||
LICENSE
|
||||
Copyright (C) 2020 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
|
||||
in gpl.txt. If not, see http://www.gnu.org/licenses.
|
||||
*/
|
||||
|
||||
package geovision
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"bitbucket.org/ausocean/av/codec/codecutil"
|
||||
"bitbucket.org/ausocean/av/revid/config"
|
||||
"bitbucket.org/ausocean/utils/logger"
|
||||
)
|
||||
|
||||
func TestIsRunning(t *testing.T) {
|
||||
const dur = 250 * time.Millisecond
|
||||
const ip = "192.168.4.20"
|
||||
|
||||
l := logger.New(logger.Debug, &bytes.Buffer{}, true) // Discard logs.
|
||||
d := New(l)
|
||||
|
||||
err := d.Set(config.Config{
|
||||
Logger: l,
|
||||
InputCodec: codecutil.H264,
|
||||
CameraIP: ip,
|
||||
})
|
||||
if err != nil {
|
||||
t.Skipf("could not set device: %w", err)
|
||||
}
|
||||
|
||||
err = d.Start()
|
||||
if err != nil {
|
||||
t.Fatalf("could not start device %w", err)
|
||||
}
|
||||
|
||||
time.Sleep(dur)
|
||||
|
||||
if !d.IsRunning() {
|
||||
t.Error("device isn't running, when it should be")
|
||||
}
|
||||
|
||||
err = d.Stop()
|
||||
if err != nil {
|
||||
t.Error(err.Error())
|
||||
}
|
||||
|
||||
time.Sleep(dur)
|
||||
|
||||
if d.IsRunning() {
|
||||
t.Error("device is running, when it should not be")
|
||||
}
|
||||
}
|
|
@ -107,11 +107,12 @@ var AutoWhiteBalanceModes = [...]string{
|
|||
// Raspivid is an implementation of AVDevice that provides control over the
|
||||
// raspivid command to allow reading of data from a Raspberry Pi camera.
|
||||
type Raspivid struct {
|
||||
cfg config.Config
|
||||
cmd *exec.Cmd
|
||||
out io.ReadCloser
|
||||
log config.Logger
|
||||
done chan struct{}
|
||||
cfg config.Config
|
||||
cmd *exec.Cmd
|
||||
out io.ReadCloser
|
||||
log config.Logger
|
||||
done chan struct{}
|
||||
isRunning bool
|
||||
}
|
||||
|
||||
// New returns a new Raspivid.
|
||||
|
@ -287,6 +288,7 @@ func (r *Raspivid) Start() error {
|
|||
if err != nil {
|
||||
return fmt.Errorf("could not start raspivid command: %w", err)
|
||||
}
|
||||
r.isRunning = true
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -310,5 +312,11 @@ func (r *Raspivid) Stop() error {
|
|||
if err != nil {
|
||||
return fmt.Errorf("could not kill raspivid process: %w", err)
|
||||
}
|
||||
r.isRunning = false
|
||||
return r.out.Close()
|
||||
}
|
||||
|
||||
// IsRunning is used to determine if the pi's camera is running.
|
||||
func (r *Raspivid) IsRunning() bool {
|
||||
return r.isRunning
|
||||
}
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
DESCRIPTION
|
||||
raspivid_test.go tests the raspivid AVDevice.
|
||||
|
||||
AUTHORS
|
||||
Scott Barnard <scott@ausocean.org>
|
||||
|
||||
LICENSE
|
||||
Copyright (C) 2020 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
|
||||
in gpl.txt. If not, see http://www.gnu.org/licenses.
|
||||
*/
|
||||
package raspivid
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"bitbucket.org/ausocean/av/codec/codecutil"
|
||||
"bitbucket.org/ausocean/av/revid/config"
|
||||
"bitbucket.org/ausocean/utils/logger"
|
||||
)
|
||||
|
||||
func TestIsRunning(t *testing.T) {
|
||||
const dur = 250 * time.Millisecond
|
||||
|
||||
l := logger.New(logger.Debug, &bytes.Buffer{}, true) // Discard logs.
|
||||
d := New(l)
|
||||
|
||||
err := d.Set(config.Config{
|
||||
Logger: l,
|
||||
InputCodec: codecutil.H264,
|
||||
})
|
||||
if err != nil {
|
||||
t.Skipf("could not set device: %w", err)
|
||||
}
|
||||
|
||||
err = d.Start()
|
||||
if err != nil {
|
||||
t.Fatalf("could not start device %w", err)
|
||||
}
|
||||
|
||||
time.Sleep(dur)
|
||||
|
||||
if !d.IsRunning() {
|
||||
t.Error("device isn't running, when it should be")
|
||||
}
|
||||
|
||||
err = d.Stop()
|
||||
if err != nil {
|
||||
t.Error(err.Error())
|
||||
}
|
||||
|
||||
time.Sleep(dur)
|
||||
|
||||
if d.IsRunning() {
|
||||
t.Error("device is running, when it should not be")
|
||||
}
|
||||
}
|
|
@ -62,11 +62,12 @@ var (
|
|||
// Webcam is an implementation of the AVDevice interface for a Webcam. Webcam
|
||||
// uses an ffmpeg process to pipe the video data from the webcam.
|
||||
type Webcam struct {
|
||||
out io.ReadCloser
|
||||
log config.Logger
|
||||
cfg config.Config
|
||||
cmd *exec.Cmd
|
||||
done chan struct{}
|
||||
out io.ReadCloser
|
||||
log config.Logger
|
||||
cfg config.Config
|
||||
cmd *exec.Cmd
|
||||
done chan struct{}
|
||||
isRunning bool
|
||||
}
|
||||
|
||||
// New returns a new Webcam.
|
||||
|
@ -161,6 +162,8 @@ func (w *Webcam) Start() error {
|
|||
return fmt.Errorf("could not pipe command error: %w", err)
|
||||
}
|
||||
|
||||
w.isRunning = true
|
||||
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
|
@ -202,7 +205,12 @@ func (w *Webcam) Stop() error {
|
|||
if err != nil {
|
||||
return fmt.Errorf("could not kill ffmpeg process: %w", err)
|
||||
}
|
||||
return w.out.Close()
|
||||
err = w.out.Close()
|
||||
if err == nil {
|
||||
w.isRunning = false
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Read implements io.Reader. If the pipe is nil a read error is returned.
|
||||
|
@ -212,3 +220,8 @@ func (w *Webcam) Read(p []byte) (int, error) {
|
|||
}
|
||||
return 0, errors.New("webcam not streaming")
|
||||
}
|
||||
|
||||
// IsRunning is used to determine if the webcam is running.
|
||||
func (w *Webcam) IsRunning() bool {
|
||||
return w.isRunning
|
||||
}
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
DESCRIPTION
|
||||
webcam_test.go tests the webcam AVDevice.
|
||||
|
||||
AUTHORS
|
||||
Scott Barnard <scott@ausocean.org>
|
||||
|
||||
LICENSE
|
||||
Copyright (C) 2020 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
|
||||
in gpl.txt. If not, see http://www.gnu.org/licenses.
|
||||
*/
|
||||
package webcam
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"bitbucket.org/ausocean/av/codec/codecutil"
|
||||
"bitbucket.org/ausocean/av/revid/config"
|
||||
"bitbucket.org/ausocean/utils/logger"
|
||||
)
|
||||
|
||||
func TestIsRunning(t *testing.T) {
|
||||
const dur = 250 * time.Millisecond
|
||||
|
||||
l := logger.New(logger.Debug, &bytes.Buffer{}, true) // Discard logs.
|
||||
d := New(l)
|
||||
|
||||
err := d.Set(config.Config{
|
||||
Logger: l,
|
||||
InputCodec: codecutil.H264,
|
||||
})
|
||||
if err != nil {
|
||||
t.Skipf("could not set device: %w", err)
|
||||
}
|
||||
|
||||
err = d.Start()
|
||||
if err != nil {
|
||||
t.Fatalf("could not start device %w", err)
|
||||
}
|
||||
|
||||
time.Sleep(dur)
|
||||
|
||||
if !d.IsRunning() {
|
||||
t.Error("device isn't running, when it should be")
|
||||
}
|
||||
|
||||
err = d.Stop()
|
||||
if err != nil {
|
||||
t.Error(err.Error())
|
||||
}
|
||||
|
||||
time.Sleep(dur)
|
||||
|
||||
if d.IsRunning() {
|
||||
t.Error("device is running, when it should not be")
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue