mirror of https://bitbucket.org/ausocean/av.git
device/raspistill & revid/config: PR problem fixes run 1
This commit is contained in:
parent
8a792099a5
commit
c18e263d95
|
@ -81,7 +81,7 @@ func (r *Raspistill) start() error {
|
||||||
"--rotation", fmt.Sprint(r.cfg.Rotation),
|
"--rotation", fmt.Sprint(r.cfg.Rotation),
|
||||||
"--timeout", fmt.Sprint(r.cfg.TimelapseDuration),
|
"--timeout", fmt.Sprint(r.cfg.TimelapseDuration),
|
||||||
"--timelapse", fmt.Sprint(r.cfg.TimelapseInterval),
|
"--timelapse", fmt.Sprint(r.cfg.TimelapseInterval),
|
||||||
"--quality", fmt.Sprint(r.cfg.SnapQuality),
|
"--quality", fmt.Sprint(r.cfg.JPEGQuality),
|
||||||
}
|
}
|
||||||
|
|
||||||
r.log.Info(pkg+"raspistill args", "args", strings.Join(args, " "))
|
r.log.Info(pkg+"raspistill args", "args", strings.Join(args, " "))
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
test.go provides test implementations of the raspistill methods when the
|
test.go provides test implementations of the raspistill methods when the
|
||||||
"test" build tag is specified. In this mode, raspistill simply provides
|
"test" build tag is specified. In this mode, raspistill simply provides
|
||||||
arbitrary loaded JPEG images when Raspistill.Read() is called.
|
specific test JPEG images when Raspistill.Read() is called.
|
||||||
|
|
||||||
AUTHORS
|
AUTHORS
|
||||||
Saxon Nelson-Milton <saxon@ausocean.org>
|
Saxon Nelson-Milton <saxon@ausocean.org>
|
||||||
|
@ -29,10 +29,9 @@ LICENSE
|
||||||
package raspistill
|
package raspistill
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
@ -41,22 +40,23 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
noOfImages = 6
|
// TODO(Saxon): find nImages programmatically ?
|
||||||
imgDir = "/go/src/bitbucket.org/ausocean/test/test-data/av/input/jpeg/"
|
nImages = 6
|
||||||
jpgExt = ".jpg"
|
|
||||||
|
imgPath = "../../../test/test-data/av/input/jpeg/"
|
||||||
|
jpgExt = ".jpg"
|
||||||
)
|
)
|
||||||
|
|
||||||
type raspistill struct {
|
type raspistill struct {
|
||||||
|
images [nImages][]byte
|
||||||
|
imgCnt int // Number of images that have been loaded thus far.
|
||||||
|
durTicker *time.Ticker // Tracks timelapse duration.
|
||||||
|
intvlTicker *time.Ticker // Tracks current interval in the timelapse.
|
||||||
log config.Logger
|
log config.Logger
|
||||||
cfg config.Config
|
cfg config.Config
|
||||||
isRunning bool
|
isRunning bool
|
||||||
images [noOfImages][]byte
|
buf []byte // Holds frame data to be read.
|
||||||
imgCnt int
|
term chan struct{} // Signals termination when close() is called.
|
||||||
durTicker *time.Ticker
|
|
||||||
intvlTicker *time.Ticker
|
|
||||||
buf []byte
|
|
||||||
init bool
|
|
||||||
term chan struct{}
|
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,18 +65,13 @@ func new(l config.Logger) raspistill {
|
||||||
|
|
||||||
r := raspistill{log: l}
|
r := raspistill{log: l}
|
||||||
|
|
||||||
// Get to the right file location of the JPEG images.
|
|
||||||
home, err := os.UserHomeDir()
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Sprintf("could not get home directory: %v", err))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load the test images into the images slice.
|
// Load the test images into the images slice.
|
||||||
// We expect the 6 images test images to be named 0.jpg through to 5.jpg.
|
// We expect the 6 images test images to be named 0.jpg through to 5.jpg.
|
||||||
r.log.Debug("loading test JPEG images")
|
r.log.Debug("loading test JPEG images")
|
||||||
for i, _ := range r.images {
|
for i, _ := range r.images {
|
||||||
path := imgDir + strconv.Itoa(i) + jpgExt
|
absPath, err := filepath.Abs(imgPath)
|
||||||
r.images[i], err = ioutil.ReadFile(home + imgDir + strconv.Itoa(i) + jpgExt)
|
path := absPath + "/" + strconv.Itoa(i) + jpgExt
|
||||||
|
r.images[i], err = ioutil.ReadFile(path)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.log.Fatal("error loading test image", "imageNum", i, "error", err)
|
r.log.Fatal("error loading test image", "imageNum", i, "error", err)
|
||||||
|
@ -86,16 +81,16 @@ func new(l config.Logger) raspistill {
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
// stop sets isRunning flag to false, indicating no further captures. Calls on
|
// stop sets isRunning flag to false, indicating no further captures. Future
|
||||||
// Raspistill.read return error.
|
// calls on Raspistill.read will return an error.
|
||||||
func (r *Raspistill) stop() error {
|
func (r *Raspistill) stop() error {
|
||||||
r.log.Debug("stopping test raspistill")
|
r.log.Debug("stopping test raspistill")
|
||||||
r.isRunning = false
|
r.setRunning(false)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// start creates the timelapse interval and duration tickers i.e. also starting
|
// start creates and starts the timelapse and duration tickers and sets
|
||||||
// them and sets isRunning flag to true indicating that raspistill is capturing.
|
// isRunning flag to true indicating that raspistill is capturing.
|
||||||
func (r *Raspistill) start() error {
|
func (r *Raspistill) start() error {
|
||||||
r.log.Debug("starting test raspistill")
|
r.log.Debug("starting test raspistill")
|
||||||
r.durTicker = time.NewTicker(r.cfg.TimelapseDuration)
|
r.durTicker = time.NewTicker(r.cfg.TimelapseDuration)
|
||||||
|
@ -113,8 +108,8 @@ func (r *Raspistill) start() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Raspistill) loadImg() {
|
func (r *Raspistill) loadImg() {
|
||||||
r.log.Debug("appending new image on to buffer and copying next image p", "imgCnt", r.imgCnt)
|
r.log.Debug("appending new image on to buffer and copying next image p", "nImg", r.imgCnt)
|
||||||
imgBytes := r.images[r.imgCnt%noOfImages]
|
imgBytes := r.images[r.imgCnt%nImages]
|
||||||
if len(imgBytes) == 0 {
|
if len(imgBytes) == 0 {
|
||||||
panic("length of image bytes should not be 0")
|
panic("length of image bytes should not be 0")
|
||||||
}
|
}
|
||||||
|
@ -122,7 +117,7 @@ func (r *Raspistill) loadImg() {
|
||||||
|
|
||||||
r.mu.Lock()
|
r.mu.Lock()
|
||||||
r.buf = append(r.buf, imgBytes...)
|
r.buf = append(r.buf, imgBytes...)
|
||||||
r.log.Debug("added img to buf", "len(imgBytes)", len(imgBytes))
|
r.log.Debug("added image to buf", "nBytes", len(imgBytes))
|
||||||
r.mu.Unlock()
|
r.mu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,7 +156,6 @@ func (r *Raspistill) read(p []byte) (int, error) {
|
||||||
return 0, io.EOF
|
return 0, io.EOF
|
||||||
}
|
}
|
||||||
n := copy(p, r.buf)
|
n := copy(p, r.buf)
|
||||||
r.log.Debug("copied", "p[:2]", p[:2], "p[n-2:n]", p[n-2:n])
|
|
||||||
r.buf = r.buf[n:]
|
r.buf = r.buf[n:]
|
||||||
|
|
||||||
return n, nil
|
return n, nil
|
||||||
|
|
|
@ -49,27 +49,27 @@ const (
|
||||||
maxTimelapseInterval = 86400 * time.Second // s = 24 hours
|
maxTimelapseInterval = 86400 * time.Second // s = 24 hours
|
||||||
)
|
)
|
||||||
|
|
||||||
// Raspivid configuration defaults.
|
// Raspistill configuration defaults.
|
||||||
const (
|
const (
|
||||||
defaultRotation = 0 // degrees
|
defaultRotation = 0 // degrees
|
||||||
defaultWidth = 1280 // pixels
|
defaultWidth = 1280 // pixels
|
||||||
defaultHeight = 720 // pixels
|
defaultHeight = 720 // pixels
|
||||||
defaultSnapQuality = 75 // %
|
defaultJPEGQuality = 75 // %
|
||||||
defaultTimelapseDuration = maxTimelapseDuration // ms
|
defaultTimelapseDuration = maxTimelapseDuration // ms
|
||||||
defaultTimelapseInterval = 3600 * time.Second // ms
|
defaultTimelapseInterval = 3600 * time.Second // ms
|
||||||
)
|
)
|
||||||
|
|
||||||
// Configuration errors.
|
// Configuration errors.
|
||||||
var (
|
var (
|
||||||
errBadRotation = fmt.Errorf("rotation bad or unset, defaulting to: %v", defaultRotation)
|
errBadRotation = fmt.Errorf("Rotation bad or unset, defaulting to: %v", defaultRotation)
|
||||||
errBadWidth = fmt.Errorf("width bad or unset, defaulting to: %v", defaultWidth)
|
errBadWidth = fmt.Errorf("Width bad or unset, defaulting to: %v", defaultWidth)
|
||||||
errBadHeight = fmt.Errorf("height bad or unset, defaulting to: %v", defaultHeight)
|
errBadHeight = fmt.Errorf("Height bad or unset, defaulting to: %v", defaultHeight)
|
||||||
errBadSnapQuality = fmt.Errorf("SnapQuality bad or unset, defaulting to: %v", defaultSnapQuality)
|
errBadJPEGQuality = fmt.Errorf("JPEGQuality bad or unset, defaulting to: %v", defaultJPEGQuality)
|
||||||
errBadTimelapseDuration = fmt.Errorf("TimelapseDuration bad or unset, defaulting to: %v", defaultTimelapseDuration)
|
errBadTimelapseDuration = fmt.Errorf("TimelapseDuration bad or unset, defaulting to: %v", defaultTimelapseDuration)
|
||||||
errBadTimelapseInterval = fmt.Errorf("TimelapseInterval bad or unset, defaulting to: %v", defaultTimelapseInterval)
|
errBadTimelapseInterval = fmt.Errorf("TimelapseInterval bad or unset, defaulting to: %v", defaultTimelapseInterval)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Misc erros.
|
// Misc errors.
|
||||||
var errNotStarted = errors.New("cannot read, raspistill not started")
|
var errNotStarted = errors.New("cannot read, raspistill not started")
|
||||||
|
|
||||||
// Raspistill is an implementation of AVDevice that provides control over the
|
// Raspistill is an implementation of AVDevice that provides control over the
|
||||||
|
@ -77,7 +77,7 @@ var errNotStarted = errors.New("cannot read, raspistill not started")
|
||||||
// singular images.
|
// singular images.
|
||||||
type Raspistill struct{ raspistill }
|
type Raspistill struct{ raspistill }
|
||||||
|
|
||||||
// New returns a new Raspivid.
|
// New returns a new Raspistill.
|
||||||
func New(l config.Logger) *Raspistill { return &Raspistill{raspistill: new(l)} }
|
func New(l config.Logger) *Raspistill { return &Raspistill{raspistill: new(l)} }
|
||||||
|
|
||||||
// Start will prepare the arguments for the raspistill command using the
|
// Start will prepare the arguments for the raspistill command using the
|
||||||
|
@ -119,9 +119,9 @@ func (r *Raspistill) Set(c config.Config) error {
|
||||||
errs = append(errs, errBadHeight)
|
errs = append(errs, errBadHeight)
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.SnapQuality < 0 || c.SnapQuality > 100 {
|
if c.JPEGQuality < 0 || c.JPEGQuality > 100 {
|
||||||
c.SnapQuality = defaultSnapQuality
|
c.JPEGQuality = defaultJPEGQuality
|
||||||
errs = append(errs, errBadSnapQuality)
|
errs = append(errs, errBadJPEGQuality)
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.TimelapseDuration > maxTimelapseDuration || c.TimelapseDuration < minTimelapseDuration {
|
if c.TimelapseDuration > maxTimelapseDuration || c.TimelapseDuration < minTimelapseDuration {
|
||||||
|
|
|
@ -234,14 +234,14 @@ type Config struct {
|
||||||
SampleRate uint // Samples a second (Hz).
|
SampleRate uint // Samples a second (Hz).
|
||||||
Saturation int
|
Saturation int
|
||||||
|
|
||||||
// SnapQuality is a value 0-100 inclusive, controlling JPEG compression of the
|
// JPEGQuality is a value 0-100 inclusive, controlling JPEG compression of the
|
||||||
// timelapse snaps. 100 represents minimal compression and 0 represents the most
|
// timelapse snaps. 100 represents minimal compression and 0 represents the most
|
||||||
// compression.
|
// compression.
|
||||||
SnapQuality int
|
JPEGQuality int
|
||||||
|
|
||||||
Suppress bool // Holds logger suppression state.
|
Suppress bool // Holds logger suppression state.
|
||||||
|
|
||||||
// TimelapseInterval defines the interval between timelapse snaps when using
|
// TimelapseInterval defines the interval between timelapse images when using
|
||||||
// raspistill input.
|
// raspistill input.
|
||||||
TimelapseInterval time.Duration
|
TimelapseInterval time.Duration
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,7 @@ const (
|
||||||
KeyRTPAddress = "RTPAddress"
|
KeyRTPAddress = "RTPAddress"
|
||||||
KeySampleRate = "SampleRate"
|
KeySampleRate = "SampleRate"
|
||||||
KeySaturation = "Saturation"
|
KeySaturation = "Saturation"
|
||||||
KeySnapQuality = "SnapQuality"
|
KeyJPEGQuality = "JPEGQuality"
|
||||||
KeySuppress = "Suppress"
|
KeySuppress = "Suppress"
|
||||||
KeyTimelapseDuration = "TimelapseDuration"
|
KeyTimelapseDuration = "TimelapseDuration"
|
||||||
KeyTimelapseInterval = "TimelapseInterval"
|
KeyTimelapseInterval = "TimelapseInterval"
|
||||||
|
@ -578,14 +578,14 @@ var Variables = []struct {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: KeySnapQuality,
|
Name: KeyJPEGQuality,
|
||||||
Type_: typeUint,
|
Type_: typeUint,
|
||||||
Update: func(c *Config, v string) {
|
Update: func(c *Config, v string) {
|
||||||
_v, err := strconv.Atoi(v)
|
_v, err := strconv.Atoi(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Logger.Log(logger.Warning, "invalid SnapQuality param", "value", v)
|
c.Logger.Log(logger.Warning, "invalid JPEGQuality param", "value", v)
|
||||||
}
|
}
|
||||||
c.SnapQuality = _v
|
c.JPEGQuality = _v
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue