mirror of https://bitbucket.org/ausocean/av.git
Merged in correct-config-types (pull request #401)
Correct types of fields in revid/config/config.go Config struct
This commit is contained in:
parent
acb74e79f6
commit
4cf155bbc2
|
@ -143,17 +143,23 @@ func main() {
|
||||||
}
|
}
|
||||||
cf := pcm.BufferFormat{
|
cf := pcm.BufferFormat{
|
||||||
SFormat: sf,
|
SFormat: sf,
|
||||||
Channels: ab.Format.Channels,
|
Channels: uint(ab.Format.Channels),
|
||||||
Rate: ab.Format.Rate,
|
Rate: uint(ab.Format.Rate),
|
||||||
}
|
}
|
||||||
ac.pb = pcm.Buffer{
|
ac.pb = pcm.Buffer{
|
||||||
Format: cf,
|
Format: cf,
|
||||||
Data: ab.Data,
|
Data: ab.Data,
|
||||||
}
|
}
|
||||||
|
|
||||||
cs := pcm.DataSize(ac.parameters.rate, ac.parameters.channels, ac.parameters.bits, float64(ac.parameters.period), 0)
|
cs := pcm.DataSize(
|
||||||
|
uint(ac.parameters.rate),
|
||||||
|
uint(ac.parameters.channels),
|
||||||
|
uint(ac.parameters.bits),
|
||||||
|
float64(ac.parameters.period),
|
||||||
|
0,
|
||||||
|
)
|
||||||
rbLen := rbDuration / ac.period
|
rbLen := rbDuration / ac.period
|
||||||
ac.rb = ring.NewBuffer(rbLen, cs, rbTimeout)
|
ac.rb = ring.NewBuffer(int(rbLen), cs, rbTimeout)
|
||||||
|
|
||||||
go ac.input()
|
go ac.input()
|
||||||
|
|
||||||
|
@ -386,7 +392,7 @@ func (ac *audioClient) input() {
|
||||||
// This function also handles NetReceiver configuration requests and updating of NetReceiver vars.
|
// This function also handles NetReceiver configuration requests and updating of NetReceiver vars.
|
||||||
func (ac *audioClient) output() {
|
func (ac *audioClient) output() {
|
||||||
// Calculate the size of the output data based on wanted channels and rate.
|
// Calculate the size of the output data based on wanted channels and rate.
|
||||||
outLen := (((len(ac.pb.Data) / ac.pb.Format.Channels) * ac.channels) / ac.pb.Format.Rate) * ac.rate
|
outLen := (((len(ac.pb.Data) / int(ac.pb.Format.Channels)) * ac.channels) / int(ac.pb.Format.Rate)) * ac.rate
|
||||||
buf := make([]byte, outLen)
|
buf := make([]byte, outLen)
|
||||||
|
|
||||||
mime := "audio/x-wav;codec=pcm;rate=" + strconv.Itoa(ac.rate) + ";channels=" + strconv.Itoa(ac.channels) + ";bits=" + strconv.Itoa(ac.bits)
|
mime := "audio/x-wav;codec=pcm;rate=" + strconv.Itoa(ac.rate) + ";channels=" + strconv.Itoa(ac.channels) + ";bits=" + strconv.Itoa(ac.bits)
|
||||||
|
@ -533,13 +539,13 @@ func (ac *audioClient) formatBuffer() pcm.Buffer {
|
||||||
ac.mu.Unlock()
|
ac.mu.Unlock()
|
||||||
|
|
||||||
// If nothing needs to be changed, return the original.
|
// If nothing needs to be changed, return the original.
|
||||||
if ac.pb.Format.Channels == wantChannels && ac.pb.Format.Rate == wantRate {
|
if int(ac.pb.Format.Channels) == wantChannels && int(ac.pb.Format.Rate) == wantRate {
|
||||||
return ac.pb
|
return ac.pb
|
||||||
}
|
}
|
||||||
|
|
||||||
formatted := pcm.Buffer{Format: ac.pb.Format}
|
formatted := pcm.Buffer{Format: ac.pb.Format}
|
||||||
bufCopied := false
|
bufCopied := false
|
||||||
if ac.pb.Format.Channels != wantChannels {
|
if int(ac.pb.Format.Channels) != wantChannels {
|
||||||
|
|
||||||
// Convert channels.
|
// Convert channels.
|
||||||
if ac.pb.Format.Channels == 2 && wantChannels == 1 {
|
if ac.pb.Format.Channels == 2 && wantChannels == 1 {
|
||||||
|
@ -552,18 +558,18 @@ func (ac *audioClient) formatBuffer() pcm.Buffer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ac.pb.Format.Rate != wantRate {
|
if int(ac.pb.Format.Rate) != wantRate {
|
||||||
|
|
||||||
// Convert rate.
|
// Convert rate.
|
||||||
if bufCopied {
|
if bufCopied {
|
||||||
formatted, err = pcm.Resample(formatted, wantRate)
|
formatted, err = pcm.Resample(formatted, uint(wantRate))
|
||||||
} else {
|
} else {
|
||||||
formatted, err = pcm.Resample(ac.pb, wantRate)
|
formatted, err = pcm.Resample(ac.pb, uint(wantRate))
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Log(logger.Warning, "rate conversion failed, audio has remained original rate", "error", err.Error())
|
log.Log(logger.Warning, "rate conversion failed, audio has remained original rate", "error", err.Error())
|
||||||
} else {
|
} else {
|
||||||
formatted.Format.Rate = wantRate
|
formatted.Format.Rate = uint(wantRate)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return formatted
|
return formatted
|
||||||
|
|
|
@ -57,8 +57,8 @@ const (
|
||||||
// BufferFormat contains the format for a PCM Buffer.
|
// BufferFormat contains the format for a PCM Buffer.
|
||||||
type BufferFormat struct {
|
type BufferFormat struct {
|
||||||
SFormat SampleFormat
|
SFormat SampleFormat
|
||||||
Rate int
|
Rate uint
|
||||||
Channels int
|
Channels uint
|
||||||
}
|
}
|
||||||
|
|
||||||
// Buffer contains a buffer of PCM data and the format that it is in.
|
// Buffer contains a buffer of PCM data and the format that it is in.
|
||||||
|
@ -68,7 +68,7 @@ type Buffer struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// DataSize takes audio attributes describing audio data and returns the size of that data.
|
// DataSize takes audio attributes describing audio data and returns the size of that data.
|
||||||
func DataSize(rate, channels, bitDepth int, period float64, codec uint8) int {
|
func DataSize(rate, channels, bitDepth uint, period float64, codec uint8) int {
|
||||||
s := int(float64(channels) * float64(rate) * float64(bitDepth/8) * period)
|
s := int(float64(channels) * float64(rate) * float64(bitDepth/8) * period)
|
||||||
if codec == codecutil.ADPCM {
|
if codec == codecutil.ADPCM {
|
||||||
s = adpcm.EncBytes(s)
|
s = adpcm.EncBytes(s)
|
||||||
|
@ -81,7 +81,7 @@ func DataSize(rate, channels, bitDepth int, period float64, codec uint8) int {
|
||||||
// - Currently only downsampling is implemented and c's rate must be divisible by 'rate' or an error will occur.
|
// - Currently only downsampling is implemented and c's rate must be divisible by 'rate' or an error will occur.
|
||||||
// - If the number of bytes in c.Data is not divisible by the decimation factor (ratioFrom), the remaining bytes will
|
// - If the number of bytes in c.Data is not divisible by the decimation factor (ratioFrom), the remaining bytes will
|
||||||
// not be included in the result. Eg. input of length 480002 downsampling 6:1 will result in output length 80000.
|
// not be included in the result. Eg. input of length 480002 downsampling 6:1 will result in output length 80000.
|
||||||
func Resample(c Buffer, rate int) (Buffer, error) {
|
func Resample(c Buffer, rate uint) (Buffer, error) {
|
||||||
if c.Format.Rate == rate {
|
if c.Format.Rate == rate {
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
@ -96,9 +96,9 @@ func Resample(c Buffer, rate int) (Buffer, error) {
|
||||||
var sampleLen int
|
var sampleLen int
|
||||||
switch c.Format.SFormat {
|
switch c.Format.SFormat {
|
||||||
case S32_LE:
|
case S32_LE:
|
||||||
sampleLen = 4 * c.Format.Channels
|
sampleLen = int(4 * c.Format.Channels)
|
||||||
case S16_LE:
|
case S16_LE:
|
||||||
sampleLen = 2 * c.Format.Channels
|
sampleLen = int(2 * c.Format.Channels)
|
||||||
default:
|
default:
|
||||||
return Buffer{}, fmt.Errorf("Unhandled ALSA format: %v", c.Format.SFormat)
|
return Buffer{}, fmt.Errorf("Unhandled ALSA format: %v", c.Format.SFormat)
|
||||||
}
|
}
|
||||||
|
@ -106,8 +106,8 @@ func Resample(c Buffer, rate int) (Buffer, error) {
|
||||||
|
|
||||||
// Calculate sample rate ratio ratioFrom:ratioTo.
|
// Calculate sample rate ratio ratioFrom:ratioTo.
|
||||||
rateGcd := gcd(rate, c.Format.Rate)
|
rateGcd := gcd(rate, c.Format.Rate)
|
||||||
ratioFrom := c.Format.Rate / rateGcd
|
ratioFrom := int(c.Format.Rate / rateGcd)
|
||||||
ratioTo := rate / rateGcd
|
ratioTo := int(rate / rateGcd)
|
||||||
|
|
||||||
// ratioTo = 1 is the only number that will result in an even sampling.
|
// ratioTo = 1 is the only number that will result in an even sampling.
|
||||||
if ratioTo != 1 {
|
if ratioTo != 1 {
|
||||||
|
@ -197,7 +197,7 @@ func StereoToMono(c Buffer) (Buffer, error) {
|
||||||
|
|
||||||
// gcd is used for calculating the greatest common divisor of two positive integers, a and b.
|
// gcd is used for calculating the greatest common divisor of two positive integers, a and b.
|
||||||
// assumes given a and b are positive.
|
// assumes given a and b are positive.
|
||||||
func gcd(a, b int) int {
|
func gcd(a, b uint) uint {
|
||||||
for b != 0 {
|
for b != 0 {
|
||||||
a, b = b, a%b
|
a, b = b, a%b
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,9 +75,9 @@ type ALSA struct {
|
||||||
|
|
||||||
// Config provides parameters used by the ALSA device.
|
// Config provides parameters used by the ALSA device.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
SampleRate int
|
SampleRate uint
|
||||||
Channels int
|
Channels uint
|
||||||
BitDepth int
|
BitDepth uint
|
||||||
RecPeriod float64
|
RecPeriod float64
|
||||||
Codec uint8
|
Codec uint8
|
||||||
}
|
}
|
||||||
|
@ -145,8 +145,8 @@ func (d *ALSA) Set(c config.Config) error {
|
||||||
}
|
}
|
||||||
cf := pcm.BufferFormat{
|
cf := pcm.BufferFormat{
|
||||||
SFormat: sf,
|
SFormat: sf,
|
||||||
Channels: ab.Format.Channels,
|
Channels: uint(ab.Format.Channels),
|
||||||
Rate: ab.Format.Rate,
|
Rate: uint(ab.Format.Rate),
|
||||||
}
|
}
|
||||||
d.pb = pcm.Buffer{
|
d.pb = pcm.Buffer{
|
||||||
Format: cf,
|
Format: cf,
|
||||||
|
@ -258,10 +258,10 @@ func (d *ALSA) open() error {
|
||||||
var rate int
|
var rate int
|
||||||
foundRate := false
|
foundRate := false
|
||||||
for r := range rates {
|
for r := range rates {
|
||||||
if r < d.SampleRate {
|
if r < int(d.SampleRate) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if r%d.SampleRate == 0 {
|
if r%int(d.SampleRate) == 0 {
|
||||||
rate, err = d.dev.NegotiateRate(r)
|
rate, err = d.dev.NegotiateRate(r)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
foundRate = true
|
foundRate = true
|
||||||
|
|
|
@ -37,12 +37,12 @@ func main() {
|
||||||
var (
|
var (
|
||||||
hostPtr = flag.String("host", "192.168.1.50", "IP of GeoVision camera.")
|
hostPtr = flag.String("host", "192.168.1.50", "IP of GeoVision camera.")
|
||||||
codecPtr = flag.String("codec", "", "h264, h265 or mjpeg")
|
codecPtr = flag.String("codec", "", "h264, h265 or mjpeg")
|
||||||
heightPtr = flag.Int("height", 0, "256, 360 or 720")
|
heightPtr = flag.Uint("height", 0, "256, 360 or 720")
|
||||||
fpsPtr = flag.Int("fps", 0, "Frame rate in frames per second.")
|
fpsPtr = flag.Uint("fps", 0, "Frame rate in frames per second.")
|
||||||
vbrPtr = flag.Bool("vbr", false, "If true, variable bitrate.")
|
vbrPtr = flag.Bool("vbr", false, "If true, variable bitrate.")
|
||||||
vbrQualityPtr = flag.Int("quality", -1, "General quality under variable bitrate, 0 to 4 inclusive.")
|
vbrQualityPtr = flag.Int("quality", -1, "General quality under variable bitrate, 0 to 4 inclusive.")
|
||||||
vbrRatePtr = flag.Int("vbr-rate", 0, "Variable bitrate maximal bitrate in kbps.")
|
vbrRatePtr = flag.Uint("vbr-rate", 0, "Variable bitrate maximal bitrate in kbps.")
|
||||||
cbrRatePtr = flag.Int("cbr-rate", 0, "Constant bitrate, bitrate in kbps.")
|
cbrRatePtr = flag.Uint("cbr-rate", 0, "Constant bitrate, bitrate in kbps.")
|
||||||
refreshPtr = flag.Float64("refresh", 0, "Inter refresh period in seconds.")
|
refreshPtr = flag.Float64("refresh", 0, "Inter refresh period in seconds.")
|
||||||
)
|
)
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
|
@ -112,7 +112,7 @@ func Set(host string, options ...Option) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Channel will set the GeoVision channel we will be using.
|
// Channel will set the GeoVision channel we will be using.
|
||||||
func Channel(c int) Option {
|
func Channel(c uint8) Option {
|
||||||
return func(s settings) (settings, error) {
|
return func(s settings) (settings, error) {
|
||||||
if c != 1 && c != 2 {
|
if c != 1 && c != 2 {
|
||||||
return s, errors.New("invalid channel")
|
return s, errors.New("invalid channel")
|
||||||
|
@ -146,15 +146,15 @@ func CodecOut(c Codec) Option {
|
||||||
|
|
||||||
// Height will set the height component of the video resolution. Available
|
// Height will set the height component of the video resolution. Available
|
||||||
// heights are 256, 360 and 720.
|
// heights are 256, 360 and 720.
|
||||||
func Height(h int) Option {
|
func Height(h uint) Option {
|
||||||
return func(s settings) (settings, error) {
|
return func(s settings) (settings, error) {
|
||||||
var m map[int]string
|
var m map[uint]string
|
||||||
switch s.ch {
|
switch s.ch {
|
||||||
case 1:
|
case 1:
|
||||||
// TODO: add other resolutions supported by channel 1.
|
// TODO: add other resolutions supported by channel 1.
|
||||||
m = map[int]string{1080: res1080}
|
m = map[uint]string{1080: res1080}
|
||||||
case 2:
|
case 2:
|
||||||
m = map[int]string{256: res256, 360: res360, 720: res720}
|
m = map[uint]string{256: res256, 360: res360, 720: res720}
|
||||||
}
|
}
|
||||||
v, ok := m[h]
|
v, ok := m[h]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -167,12 +167,12 @@ func Height(h int) Option {
|
||||||
|
|
||||||
// FrameRate will set the frame rate of the video. This value is defined in
|
// FrameRate will set the frame rate of the video. This value is defined in
|
||||||
// units of frames per second, and must be between 1 and 30 inclusive.
|
// units of frames per second, and must be between 1 and 30 inclusive.
|
||||||
func FrameRate(f int) Option {
|
func FrameRate(f uint) Option {
|
||||||
return func(s settings) (settings, error) {
|
return func(s settings) (settings, error) {
|
||||||
if 1 > f || f > 30 {
|
if 1 > f || f > 30 {
|
||||||
return s, fmt.Errorf("invalid frame rate: %d", f)
|
return s, fmt.Errorf("invalid frame rate: %d", f)
|
||||||
}
|
}
|
||||||
s.frameRate = strconv.Itoa(f * 1000)
|
s.frameRate = strconv.Itoa(int(f * 1000))
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -221,9 +221,9 @@ func VBRQuality(q Quality) Option {
|
||||||
// the camera) as: 250, 500, 750, 1000, 1250, 1500, 1750, 2000, 2250 and 2500.
|
// the camera) as: 250, 500, 750, 1000, 1250, 1500, 1750, 2000, 2250 and 2500.
|
||||||
// If the passed rate does not match one of these values, the closest value is
|
// If the passed rate does not match one of these values, the closest value is
|
||||||
// selected.
|
// selected.
|
||||||
func VBRBitrate(r int) Option {
|
func VBRBitrate(r uint) Option {
|
||||||
return func(s settings) (settings, error) {
|
return func(s settings) (settings, error) {
|
||||||
var vbrRates = []int{250, 500, 750, 1000, 1250, 1500, 1750, 2000, 2250, 2500}
|
var vbrRates = []uint{250, 500, 750, 1000, 1250, 1500, 1750, 2000, 2250, 2500}
|
||||||
if s.vbr == "1" {
|
if s.vbr == "1" {
|
||||||
s.vbrBitrate = convRate(r, vbrRates)
|
s.vbrBitrate = convRate(r, vbrRates)
|
||||||
return s, nil
|
return s, nil
|
||||||
|
@ -239,13 +239,13 @@ func VBRBitrate(r int) Option {
|
||||||
// 720p: 1024, 2048, 4096, 6144
|
// 720p: 1024, 2048, 4096, 6144
|
||||||
// If the passed rate does not align with one of these values, the closest
|
// If the passed rate does not align with one of these values, the closest
|
||||||
// value is selected.
|
// value is selected.
|
||||||
func CBRBitrate(r int) Option {
|
func CBRBitrate(r uint) Option {
|
||||||
return func(s settings) (settings, error) {
|
return func(s settings) (settings, error) {
|
||||||
v, ok := map[string]string{
|
v, ok := map[string]string{
|
||||||
res1080: convRate(r, []int{2048, 4096, 6144, 8192}),
|
res1080: convRate(r, []uint{2048, 4096, 6144, 8192}),
|
||||||
res720: convRate(r, []int{1024, 2048, 4096, 6144}),
|
res720: convRate(r, []uint{1024, 2048, 4096, 6144}),
|
||||||
res360: convRate(r, []int{512, 1024, 2048, 3072}),
|
res360: convRate(r, []uint{512, 1024, 2048, 3072}),
|
||||||
res256: convRate(r, []int{128, 256, 512, 1024}),
|
res256: convRate(r, []uint{128, 256, 512, 1024}),
|
||||||
}[s.res]
|
}[s.res]
|
||||||
if !ok {
|
if !ok {
|
||||||
panic("bad resolution")
|
panic("bad resolution")
|
||||||
|
@ -269,8 +269,8 @@ func Refresh(r float64) Option {
|
||||||
return s, fmt.Errorf("invalid refresh period: %g", r)
|
return s, fmt.Errorf("invalid refresh period: %g", r)
|
||||||
}
|
}
|
||||||
|
|
||||||
refOptions := []int{250, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500, 5000}
|
refOptions := []uint{250, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500, 5000}
|
||||||
s.refresh = strconv.Itoa(refOptions[closestValIdx(int(r*1000), refOptions)])
|
s.refresh = strconv.Itoa(int(refOptions[closestValIdx(uint(r*1000), refOptions)]))
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,42 +33,42 @@ import (
|
||||||
|
|
||||||
func TestClosestValIdx(t *testing.T) {
|
func TestClosestValIdx(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
l []int
|
l []uint
|
||||||
v int
|
v uint
|
||||||
want int
|
want uint
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
l: []int{2, 5, 8, 11, 14},
|
l: []uint{2, 5, 8, 11, 14},
|
||||||
v: 6,
|
v: 6,
|
||||||
want: 1,
|
want: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
l: []int{2, 5, 8, 11, 14},
|
l: []uint{2, 5, 8, 11, 14},
|
||||||
v: 12,
|
v: 12,
|
||||||
want: 3,
|
want: 3,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
l: []int{2, 5, 8, 11, 14},
|
l: []uint{2, 5, 8, 11, 14},
|
||||||
v: 13,
|
v: 13,
|
||||||
want: 4,
|
want: 4,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
l: []int{2, 5, 8, 11, 14},
|
l: []uint{2, 5, 8, 11, 14},
|
||||||
v: 0,
|
v: 0,
|
||||||
want: 0,
|
want: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
l: []int{2, 5, 8, 11, 14},
|
l: []uint{2, 5, 8, 11, 14},
|
||||||
v: 17,
|
v: 17,
|
||||||
want: 4,
|
want: 4,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
l: []int{2, 5, 8, 11, 15},
|
l: []uint{2, 5, 8, 11, 15},
|
||||||
v: 13,
|
v: 13,
|
||||||
want: 3,
|
want: 3,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
l: []int{},
|
l: []uint{},
|
||||||
v: 17,
|
v: 17,
|
||||||
want: 0,
|
want: 0,
|
||||||
},
|
},
|
||||||
|
@ -84,22 +84,22 @@ func TestClosestValIdx(t *testing.T) {
|
||||||
|
|
||||||
func TestConvRate(t *testing.T) {
|
func TestConvRate(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
l []int
|
l []uint
|
||||||
v int
|
v uint
|
||||||
want string
|
want string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
l: []int{512, 1024, 2048, 3072},
|
l: []uint{512, 1024, 2048, 3072},
|
||||||
v: 1400,
|
v: 1400,
|
||||||
want: "1024000",
|
want: "1024000",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
l: []int{512, 1024, 2048, 3072},
|
l: []uint{512, 1024, 2048, 3072},
|
||||||
v: 1900,
|
v: 1900,
|
||||||
want: "2048000",
|
want: "2048000",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
l: []int{512, 1024, 2048, 3072},
|
l: []uint{512, 1024, 2048, 3072},
|
||||||
v: 4000,
|
v: 4000,
|
||||||
want: "3072000",
|
want: "3072000",
|
||||||
},
|
},
|
||||||
|
@ -180,7 +180,7 @@ func TestCodecOut(t *testing.T) {
|
||||||
func TestHeight(t *testing.T) {
|
func TestHeight(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
s settings
|
s settings
|
||||||
h int
|
h uint
|
||||||
want settings
|
want settings
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
|
@ -232,7 +232,7 @@ func TestHeight(t *testing.T) {
|
||||||
|
|
||||||
func TestVBRBitrate(t *testing.T) {
|
func TestVBRBitrate(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
r int
|
r uint
|
||||||
in settings
|
in settings
|
||||||
want settings
|
want settings
|
||||||
}{
|
}{
|
||||||
|
@ -264,7 +264,7 @@ func TestVBRBitrate(t *testing.T) {
|
||||||
|
|
||||||
func TestCBRBitrate(t *testing.T) {
|
func TestCBRBitrate(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
r int
|
r uint
|
||||||
in settings
|
in settings
|
||||||
want settings
|
want settings
|
||||||
}{
|
}{
|
||||||
|
|
|
@ -145,7 +145,7 @@ func submitSettings(c *http.Client, id, host string, s settings) error {
|
||||||
req.Header.Set("User-Agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36")
|
req.Header.Set("User-Agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36")
|
||||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3")
|
req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3")
|
||||||
req.Header.Set("Referer", "http://"+host+"/ssi.cgi/VideoSettingSub.htm?cam="+strconv.Itoa(s.ch))
|
req.Header.Set("Referer", "http://"+host+"/ssi.cgi/VideoSettingSub.htm?cam="+strconv.Itoa(int(s.ch)))
|
||||||
req.Header.Set("Accept-Encoding", "gzip, deflate")
|
req.Header.Set("Accept-Encoding", "gzip, deflate")
|
||||||
req.Header.Set("Accept-Language", "en-GB,en-US;q=0.9,en;q=0.8")
|
req.Header.Set("Accept-Language", "en-GB,en-US;q=0.9,en;q=0.8")
|
||||||
req.Header.Set("Cookie", "CLIENT_ID="+id)
|
req.Header.Set("Cookie", "CLIENT_ID="+id)
|
||||||
|
|
|
@ -67,7 +67,7 @@ type settings struct {
|
||||||
vbrBitrate string
|
vbrBitrate string
|
||||||
cbrBitrate string
|
cbrBitrate string
|
||||||
refresh string
|
refresh string
|
||||||
ch int
|
ch uint8
|
||||||
}
|
}
|
||||||
|
|
||||||
// newSetting will return a settings with default values.
|
// newSetting will return a settings with default values.
|
||||||
|
@ -94,20 +94,20 @@ func md5Hex(s string) string {
|
||||||
|
|
||||||
// closestValIdx will return the index of the value in l that is closest to the
|
// closestValIdx will return the index of the value in l that is closest to the
|
||||||
// value v.
|
// value v.
|
||||||
func closestValIdx(v int, l []int) int {
|
func closestValIdx(v uint, l []uint) uint {
|
||||||
var idx int
|
var idx int
|
||||||
for i := range l {
|
for i := range l {
|
||||||
if math.Abs(float64(l[i]-v)) < math.Abs(float64(l[idx]-v)) {
|
if math.Abs(float64(int(l[i])-int(v))) < math.Abs(float64(int(l[idx])-int(v))) {
|
||||||
idx = i
|
idx = i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return idx
|
return uint(idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// convRate is used to firstly find a value in l closest to the bitrate v (in
|
// convRate is used to firstly find a value in l closest to the bitrate v (in
|
||||||
// kbps), convert from kbps to bps, and the convert to string.
|
// kbps), convert from kbps to bps, and the convert to string.
|
||||||
func convRate(v int, l []int) string {
|
func convRate(v uint, l []uint) string {
|
||||||
return strconv.Itoa(l[closestValIdx(v, l)] * 1000)
|
return strconv.Itoa(int(l[closestValIdx(v, l)] * 1000))
|
||||||
}
|
}
|
||||||
|
|
||||||
// populateForm will populate the settings form using the passed settings struct
|
// populateForm will populate the settings form using the passed settings struct
|
||||||
|
|
|
@ -179,8 +179,8 @@ func (g *GeoVision) Set(c avconfig.Config) error {
|
||||||
codecutil.MJPEG: gvconfig.CodecMJPEG,
|
codecutil.MJPEG: gvconfig.CodecMJPEG,
|
||||||
}[g.cfg.InputCodec],
|
}[g.cfg.InputCodec],
|
||||||
),
|
),
|
||||||
gvconfig.Height(int(g.cfg.Height)),
|
gvconfig.Height(g.cfg.Height),
|
||||||
gvconfig.FrameRate(int(g.cfg.FrameRate)),
|
gvconfig.FrameRate(g.cfg.FrameRate),
|
||||||
gvconfig.VariableBitrate(!g.cfg.CBR),
|
gvconfig.VariableBitrate(!g.cfg.CBR),
|
||||||
gvconfig.VBRQuality(
|
gvconfig.VBRQuality(
|
||||||
map[avconfig.Quality]gvconfig.Quality{
|
map[avconfig.Quality]gvconfig.Quality{
|
||||||
|
@ -192,7 +192,7 @@ func (g *GeoVision) Set(c avconfig.Config) error {
|
||||||
}[g.cfg.VBRQuality],
|
}[g.cfg.VBRQuality],
|
||||||
),
|
),
|
||||||
gvconfig.VBRBitrate(g.cfg.VBRBitrate),
|
gvconfig.VBRBitrate(g.cfg.VBRBitrate),
|
||||||
gvconfig.CBRBitrate(int(g.cfg.Bitrate)),
|
gvconfig.CBRBitrate(g.cfg.Bitrate),
|
||||||
gvconfig.Refresh(float64(g.cfg.MinFrames)/float64(g.cfg.FrameRate)),
|
gvconfig.Refresh(float64(g.cfg.MinFrames)/float64(g.cfg.FrameRate)),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -39,9 +39,9 @@ import (
|
||||||
func main() {
|
func main() {
|
||||||
var inPath = *flag.String("in", "data.pcm", "file path of input data")
|
var inPath = *flag.String("in", "data.pcm", "file path of input data")
|
||||||
var outPath = *flag.String("out", "resampled.pcm", "file path of output")
|
var outPath = *flag.String("out", "resampled.pcm", "file path of output")
|
||||||
var from = *flag.Int("from", 48000, "sample rate of input file")
|
var from = *flag.Uint("from", 48000, "sample rate of input file")
|
||||||
var to = *flag.Int("to", 8000, "sample rate of output file")
|
var to = *flag.Uint("to", 8000, "sample rate of output file")
|
||||||
var channels = *flag.Int("ch", 1, "number of channels in input file")
|
var channels = *flag.Uint("ch", 1, "number of channels in input file")
|
||||||
var SFString = *flag.String("sf", "S16_LE", "sample format of input audio, eg. S16_LE")
|
var SFString = *flag.String("sf", "S16_LE", "sample format of input audio, eg. S16_LE")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
|
|
|
@ -53,11 +53,11 @@ type Basic struct {
|
||||||
img image.Image
|
img image.Image
|
||||||
bg [][]pixel
|
bg [][]pixel
|
||||||
bwImg *image.Gray
|
bwImg *image.Gray
|
||||||
thresh int
|
thresh float64
|
||||||
pix int
|
pix uint
|
||||||
w int
|
w int
|
||||||
h int
|
h int
|
||||||
motion int
|
motion uint
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBasic returns a pointer to a new Basic filter struct.
|
// NewBasic returns a pointer to a new Basic filter struct.
|
||||||
|
@ -75,7 +75,7 @@ func NewBasic(dst io.WriteCloser, c config.Config) *Basic {
|
||||||
|
|
||||||
return &Basic{
|
return &Basic{
|
||||||
dst: dst,
|
dst: dst,
|
||||||
thresh: int(c.MotionThreshold),
|
thresh: c.MotionThreshold,
|
||||||
pix: c.MotionPixels,
|
pix: c.MotionPixels,
|
||||||
debugging: newWindows("BASIC"),
|
debugging: newWindows("BASIC"),
|
||||||
}
|
}
|
||||||
|
@ -159,7 +159,7 @@ func (bf *Basic) process(j int, wg *sync.WaitGroup) {
|
||||||
|
|
||||||
diff := diffR + diffG + diffB
|
diff := diffR + diffG + diffB
|
||||||
|
|
||||||
if diff > bf.thresh {
|
if diff > int(bf.thresh) {
|
||||||
bf.motion++
|
bf.motion++
|
||||||
bf.bwImg.SetGray(i, j, color.Gray{0xff})
|
bf.bwImg.SetGray(i, j, color.Gray{0xff})
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -87,7 +87,7 @@ func NewMotion(dst io.WriteCloser, alg MotionAlgorithm, c config.Config) *Motion
|
||||||
scale: 1 / float64(c.MotionDownscaling),
|
scale: 1 / float64(c.MotionDownscaling),
|
||||||
sample: uint(c.MotionInterval),
|
sample: uint(c.MotionInterval),
|
||||||
padding: c.MotionPadding,
|
padding: c.MotionPadding,
|
||||||
frames: make(chan []byte, c.MotionInterval+int(c.MotionPadding)),
|
frames: make(chan []byte, c.MotionInterval+c.MotionPadding),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,10 +36,10 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *Revid) setupAudio() error {
|
func (r *Revid) setupAudio() error {
|
||||||
mts.Meta.Add("sampleRate", strconv.Itoa(r.cfg.SampleRate))
|
mts.Meta.Add("sampleRate", strconv.Itoa(int(r.cfg.SampleRate)))
|
||||||
mts.Meta.Add("channels", strconv.Itoa(r.cfg.Channels))
|
mts.Meta.Add("channels", strconv.Itoa(int(r.cfg.Channels)))
|
||||||
mts.Meta.Add("period", fmt.Sprintf("%.6f", r.cfg.RecPeriod))
|
mts.Meta.Add("period", fmt.Sprintf("%.6f", r.cfg.RecPeriod))
|
||||||
mts.Meta.Add("bitDepth", strconv.Itoa(r.cfg.BitDepth))
|
mts.Meta.Add("bitDepth", strconv.Itoa(int(r.cfg.BitDepth)))
|
||||||
|
|
||||||
switch r.cfg.InputCodec {
|
switch r.cfg.InputCodec {
|
||||||
case codecutil.PCM:
|
case codecutil.PCM:
|
||||||
|
|
|
@ -205,10 +205,10 @@ type Config struct {
|
||||||
|
|
||||||
// VBRBitrate describes maximal bitrate for the GeoVision camera when under
|
// VBRBitrate describes maximal bitrate for the GeoVision camera when under
|
||||||
// variable bitrate.
|
// variable bitrate.
|
||||||
VBRBitrate int
|
VBRBitrate uint
|
||||||
|
|
||||||
// This is the channel we're using for the GeoVision camera.
|
// This is the channel we're using for the GeoVision camera.
|
||||||
CameraChan int
|
CameraChan uint8
|
||||||
|
|
||||||
// MinFrames defines the frequency of key NAL units SPS, PPS and IDR in
|
// MinFrames defines the frequency of key NAL units SPS, PPS and IDR in
|
||||||
// number of NAL units. This will also determine the frequency of PSI if the
|
// number of NAL units. This will also determine the frequency of PSI if the
|
||||||
|
@ -241,10 +241,10 @@ type Config struct {
|
||||||
AutoWhiteBalance string
|
AutoWhiteBalance string
|
||||||
|
|
||||||
// Audio
|
// Audio
|
||||||
SampleRate int // Samples a second (Hz).
|
SampleRate uint // Samples a second (Hz).
|
||||||
RecPeriod float64 // How many seconds to record at a time.
|
RecPeriod float64 // How many seconds to record at a time.
|
||||||
Channels int // Number of audio channels, 1 for mono, 2 for stereo.
|
Channels uint // Number of audio channels, 1 for mono, 2 for stereo.
|
||||||
BitDepth int // Sample bit depth.
|
BitDepth uint // Sample bit depth.
|
||||||
|
|
||||||
RTPAddress string // RTPAddress defines the RTP output destination.
|
RTPAddress string // RTPAddress defines the RTP output destination.
|
||||||
BurstPeriod uint // BurstPeriod defines the revid burst period in seconds.
|
BurstPeriod uint // BurstPeriod defines the revid burst period in seconds.
|
||||||
|
@ -255,8 +255,8 @@ type Config struct {
|
||||||
|
|
||||||
HorizontalFlip bool // HorizontalFlip flips video horizontally for Raspivid input.
|
HorizontalFlip bool // HorizontalFlip flips video horizontally for Raspivid input.
|
||||||
VerticalFlip bool // VerticalFlip flips video vertically for Raspivid input.
|
VerticalFlip bool // VerticalFlip flips video vertically for Raspivid input.
|
||||||
Filters []int // Defines the methods of filtering to be used in between lexing and encoding.
|
Filters []uint8 // Defines the methods of filtering to be used in between lexing and encoding.
|
||||||
PSITime int // Sets the time between a packet being sent.
|
PSITime uint // Sets the time between a packet being sent.
|
||||||
|
|
||||||
// Ring buffer parameters.
|
// Ring buffer parameters.
|
||||||
RBCapacity uint // The number of bytes the ring buffer will occupy.
|
RBCapacity uint // The number of bytes the ring buffer will occupy.
|
||||||
|
@ -265,21 +265,21 @@ type Config struct {
|
||||||
// Motion filter parameters.
|
// Motion filter parameters.
|
||||||
// Some parameters can be used with any filter, while others can only be used by a few.
|
// Some parameters can be used with any filter, while others can only be used by a few.
|
||||||
MinFPS float64 // The reduced framerate of the video when there is no motion.
|
MinFPS float64 // The reduced framerate of the video when there is no motion.
|
||||||
MotionInterval int // Sets the number of frames that are held before the filter is used (on the nth frame).
|
MotionInterval uint // Sets the number of frames that are held before the filter is used (on the nth frame).
|
||||||
MotionDownscaling int // Downscaling factor of frames used for motion detection.
|
MotionDownscaling uint // Downscaling factor of frames used for motion detection.
|
||||||
|
|
||||||
MotionMinArea float64 // Used to ignore small areas of motion detection (KNN & MOG only).
|
MotionMinArea float64 // Used to ignore small areas of motion detection (KNN & MOG only).
|
||||||
MotionThreshold float64 // Intensity value that is considered motion.
|
MotionThreshold float64 // Intensity value that is considered motion.
|
||||||
MotionHistory uint // Length of filter's history (KNN & MOG only).
|
MotionHistory uint // Length of filter's history (KNN & MOG only).
|
||||||
MotionKernel uint // Size of kernel used for filling holes and removing noise (KNN only).
|
MotionKernel uint // Size of kernel used for filling holes and removing noise (KNN only).
|
||||||
MotionPixels int // Number of pixels with motion that is needed for a whole frame to be considered as moving (Basic only).
|
MotionPixels uint // Number of pixels with motion that is needed for a whole frame to be considered as moving (Basic only).
|
||||||
MotionPadding uint // Number of frames to keep before and after motion detected.
|
MotionPadding uint // Number of frames to keep before and after motion detected.
|
||||||
|
|
||||||
// If true will restart reading of input after an io.EOF.
|
// If true will restart reading of input after an io.EOF.
|
||||||
Loop bool
|
Loop bool
|
||||||
|
|
||||||
// Defines the rate at which frames from a file source are processed.
|
// Defines the rate at which frames from a file source are processed.
|
||||||
FileFPS int
|
FileFPS uint
|
||||||
}
|
}
|
||||||
|
|
||||||
// TypeData contains information about all of the variables that
|
// TypeData contains information about all of the variables that
|
||||||
|
|
|
@ -707,13 +707,13 @@ func (r *Revid) Update(vars map[string]string) error {
|
||||||
case "Filters":
|
case "Filters":
|
||||||
filters := strings.Split(value, ",")
|
filters := strings.Split(value, ",")
|
||||||
m := map[string]int{"NoOp": config.FilterNoOp, "MOG": config.FilterMOG, "VariableFPS": config.FilterVariableFPS, "KNN": config.FilterKNN, "Difference": config.FilterDiff, "Basic": config.FilterBasic}
|
m := map[string]int{"NoOp": config.FilterNoOp, "MOG": config.FilterMOG, "VariableFPS": config.FilterVariableFPS, "KNN": config.FilterKNN, "Difference": config.FilterDiff, "Basic": config.FilterBasic}
|
||||||
r.cfg.Filters = make([]int, len(filters))
|
r.cfg.Filters = make([]uint8, len(filters))
|
||||||
for i, filter := range filters {
|
for i, filter := range filters {
|
||||||
v, ok := m[filter]
|
v, ok := m[filter]
|
||||||
if !ok {
|
if !ok {
|
||||||
r.cfg.Logger.Log(logger.Warning, "invalid Filters param", "value", value)
|
r.cfg.Logger.Log(logger.Warning, "invalid Filters param", "value", value)
|
||||||
}
|
}
|
||||||
r.cfg.Filters[i] = v
|
r.cfg.Filters[i] = uint8(v)
|
||||||
}
|
}
|
||||||
case "PSITime":
|
case "PSITime":
|
||||||
v, err := strconv.Atoi(value)
|
v, err := strconv.Atoi(value)
|
||||||
|
@ -721,7 +721,7 @@ func (r *Revid) Update(vars map[string]string) error {
|
||||||
r.cfg.Logger.Log(logger.Warning, "invalid PSITime var", "value", value)
|
r.cfg.Logger.Log(logger.Warning, "invalid PSITime var", "value", value)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
r.cfg.PSITime = v
|
r.cfg.PSITime = uint(v)
|
||||||
case "BurstPeriod":
|
case "BurstPeriod":
|
||||||
v, err := strconv.Atoi(value)
|
v, err := strconv.Atoi(value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -780,14 +780,14 @@ func (r *Revid) Update(vars map[string]string) error {
|
||||||
r.cfg.Logger.Log(logger.Warning, "invalid VBRBitrate var", "value", value)
|
r.cfg.Logger.Log(logger.Warning, "invalid VBRBitrate var", "value", value)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
r.cfg.VBRBitrate = v
|
r.cfg.VBRBitrate = uint(v)
|
||||||
case "CameraChan":
|
case "CameraChan":
|
||||||
v, err := strconv.Atoi(value)
|
v, err := strconv.Atoi(value)
|
||||||
if err != nil || (v != 1 && v != 2) {
|
if err != nil || (v != 1 && v != 2) {
|
||||||
r.cfg.Logger.Log(logger.Warning, "invalid CameraChan var", "value", value)
|
r.cfg.Logger.Log(logger.Warning, "invalid CameraChan var", "value", value)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
r.cfg.CameraChan = v
|
r.cfg.CameraChan = uint8(v)
|
||||||
case "MinFPS":
|
case "MinFPS":
|
||||||
v, err := strconv.ParseFloat(value, 64)
|
v, err := strconv.ParseFloat(value, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -836,28 +836,28 @@ func (r *Revid) Update(vars map[string]string) error {
|
||||||
r.cfg.Logger.Log(logger.Warning, "invalid MotionPixels var", "value", value)
|
r.cfg.Logger.Log(logger.Warning, "invalid MotionPixels var", "value", value)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
r.cfg.MotionPixels = v
|
r.cfg.MotionPixels = uint(v)
|
||||||
case "MotionDownscaling":
|
case "MotionDownscaling":
|
||||||
v, err := strconv.Atoi(value)
|
v, err := strconv.Atoi(value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.cfg.Logger.Log(logger.Warning, "invalid MotionDownscaling var", "value", value)
|
r.cfg.Logger.Log(logger.Warning, "invalid MotionDownscaling var", "value", value)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
r.cfg.MotionDownscaling = v
|
r.cfg.MotionDownscaling = uint(v)
|
||||||
case "MotionInterval":
|
case "MotionInterval":
|
||||||
v, err := strconv.Atoi(value)
|
v, err := strconv.Atoi(value)
|
||||||
if err != nil || v < 0 {
|
if err != nil || v < 0 {
|
||||||
r.cfg.Logger.Log(logger.Warning, "invalid MotionInterval var", "value", value)
|
r.cfg.Logger.Log(logger.Warning, "invalid MotionInterval var", "value", value)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
r.cfg.MotionInterval = v
|
r.cfg.MotionInterval = uint(v)
|
||||||
case "FileFPS":
|
case "FileFPS":
|
||||||
v, err := strconv.Atoi(value)
|
v, err := strconv.Atoi(value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.cfg.Logger.Log(logger.Warning, "invalid FileFPS var", "value", value)
|
r.cfg.Logger.Log(logger.Warning, "invalid FileFPS var", "value", value)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
r.cfg.FileFPS = v
|
r.cfg.FileFPS = uint(v)
|
||||||
case "mode":
|
case "mode":
|
||||||
r.cfg.Loop = false
|
r.cfg.Loop = false
|
||||||
if value == "Loop" {
|
if value == "Loop" {
|
||||||
|
|
Loading…
Reference in New Issue