mirror of https://bitbucket.org/ausocean/av.git
codec/mjpeg/lex & lex_test.go: modified Lex to work with thumbnailed JPEG images and fixed Lex tests.
This commit is contained in:
parent
1179ab4293
commit
16d7a16762
|
@ -3,10 +3,12 @@ NAME
|
||||||
lex.go
|
lex.go
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
lex.go provides a lexer to extract separate JPEG images from a MJPEG stream.
|
lex.go provides a lexer to extract separate JPEG images from a JPEG stream.
|
||||||
|
This could either be a series of descrete JPEG images, or an MJPEG stream.
|
||||||
|
|
||||||
AUTHOR
|
AUTHOR
|
||||||
Dan Kortschak <dan@ausocean.org>
|
Dan Kortschak <dan@ausocean.org>
|
||||||
|
Saxon Nelson-Milton <saxon@ausocean.org>
|
||||||
|
|
||||||
LICENSE
|
LICENSE
|
||||||
lex.go is Copyright (C) 2017 the Australian Ocean Lab (AusOcean)
|
lex.go is Copyright (C) 2017 the Australian Ocean Lab (AusOcean)
|
||||||
|
@ -25,8 +27,6 @@ LICENSE
|
||||||
along with revid in gpl.txt. If not, see http://www.gnu.org/licenses.
|
along with revid in gpl.txt. If not, see http://www.gnu.org/licenses.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// lex.go provides a lexer to extract separate JPEG images from a MJPEG stream.
|
|
||||||
|
|
||||||
package mjpeg
|
package mjpeg
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -35,15 +35,19 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"bitbucket.org/ausocean/utils/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var Log logger.LoggerIF
|
||||||
|
|
||||||
var noDelay = make(chan time.Time)
|
var noDelay = make(chan time.Time)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
close(noDelay)
|
close(noDelay)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lex parses MJPEG frames read from src into separate writes to dst with
|
// Lex parses JPEG 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 Lex(dst io.Writer, src io.Reader, delay time.Duration) error {
|
func Lex(dst io.Writer, src io.Reader, delay time.Duration) error {
|
||||||
var tick <-chan time.Time
|
var tick <-chan time.Time
|
||||||
|
@ -65,9 +69,13 @@ func Lex(dst io.Writer, src io.Reader, delay time.Duration) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !bytes.Equal(buf, []byte{0xff, 0xd8}) {
|
if !bytes.Equal(buf, []byte{0xff, 0xd8}) {
|
||||||
return fmt.Errorf("parser: not MJPEG frame start: %#v", buf)
|
return fmt.Errorf("parser: not JPEG frame start: %#v", buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nImg := 1
|
||||||
|
|
||||||
var last byte
|
var last byte
|
||||||
for {
|
for {
|
||||||
b, err := r.ReadByte()
|
b, err := r.ReadByte()
|
||||||
|
@ -77,16 +85,28 @@ func Lex(dst io.Writer, src io.Reader, delay time.Duration) error {
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
buf = append(buf, b)
|
buf = append(buf, b)
|
||||||
|
|
||||||
|
if last == 0xff && b == 0xd8 {
|
||||||
|
nImg++
|
||||||
|
}
|
||||||
|
|
||||||
if last == 0xff && b == 0xd9 {
|
if last == 0xff && b == 0xd9 {
|
||||||
|
nImg--
|
||||||
|
}
|
||||||
|
|
||||||
|
if nImg == 0 {
|
||||||
|
<-tick
|
||||||
|
Log.Debug("writing buf","len(buf)",len(buf))
|
||||||
|
_, err = dst.Write(buf)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
last = b
|
last = b
|
||||||
}
|
}
|
||||||
<-tick
|
|
||||||
_, err = dst.Write(buf)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,10 +30,17 @@ LICENSE
|
||||||
package mjpeg
|
package mjpeg
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"bitbucket.org/ausocean/utils/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
var mjpegTests = []struct {
|
var jpegTests = []struct {
|
||||||
name string
|
name string
|
||||||
input []byte
|
input []byte
|
||||||
delay time.Duration
|
delay time.Duration
|
||||||
|
@ -42,18 +49,21 @@ var mjpegTests = []struct {
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "empty",
|
name: "empty",
|
||||||
|
err: io.ErrUnexpectedEOF,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "null",
|
name: "null",
|
||||||
input: []byte{0xff, 0xd8, 0xff, 0xd9},
|
input: []byte{0xff, 0xd8, 0xff, 0xd9},
|
||||||
delay: 0,
|
delay: 0,
|
||||||
want: [][]byte{{0xff, 0xd8, 0xff, 0xd9}},
|
want: [][]byte{{0xff, 0xd8, 0xff, 0xd9}},
|
||||||
|
err: io.ErrUnexpectedEOF,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "null delayed",
|
name: "null delayed",
|
||||||
input: []byte{0xff, 0xd8, 0xff, 0xd9},
|
input: []byte{0xff, 0xd8, 0xff, 0xd9},
|
||||||
delay: time.Millisecond,
|
delay: time.Millisecond,
|
||||||
want: [][]byte{{0xff, 0xd8, 0xff, 0xd9}},
|
want: [][]byte{{0xff, 0xd8, 0xff, 0xd9}},
|
||||||
|
err: io.ErrUnexpectedEOF,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "full",
|
name: "full",
|
||||||
|
@ -72,6 +82,7 @@ var mjpegTests = []struct {
|
||||||
{0xff, 0xd8, 'l', 'e', 'n', 'g', 't', 'h', 0xff, 0xd9},
|
{0xff, 0xd8, 'l', 'e', 'n', 'g', 't', 'h', 0xff, 0xd9},
|
||||||
{0xff, 0xd8, 's', 'p', 'r', 'e', 'a', 'd', 0xff, 0xd9},
|
{0xff, 0xd8, 's', 'p', 'r', 'e', 'a', 'd', 0xff, 0xd9},
|
||||||
},
|
},
|
||||||
|
err: io.ErrUnexpectedEOF,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "full delayed",
|
name: "full delayed",
|
||||||
|
@ -90,15 +101,15 @@ var mjpegTests = []struct {
|
||||||
{0xff, 0xd8, 'l', 'e', 'n', 'g', 't', 'h', 0xff, 0xd9},
|
{0xff, 0xd8, 'l', 'e', 'n', 'g', 't', 'h', 0xff, 0xd9},
|
||||||
{0xff, 0xd8, 's', 'p', 'r', 'e', 'a', 'd', 0xff, 0xd9},
|
{0xff, 0xd8, 's', 'p', 'r', 'e', 'a', 'd', 0xff, 0xd9},
|
||||||
},
|
},
|
||||||
|
err: io.ErrUnexpectedEOF,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME this needs to be adapted
|
func TestLex(t *testing.T) {
|
||||||
/*
|
Log = (*logger.TestLogger)(t)
|
||||||
func Lex(t *testing.T) {
|
for _, test := range jpegTests {
|
||||||
for _, test := range mjpegTests {
|
|
||||||
var buf chunkEncoder
|
var buf chunkEncoder
|
||||||
err := MJPEG(&buf, bytes.NewReader(test.input), test.delay)
|
err := Lex(&buf, bytes.NewReader(test.input), test.delay)
|
||||||
if fmt.Sprint(err) != fmt.Sprint(test.err) {
|
if fmt.Sprint(err) != fmt.Sprint(test.err) {
|
||||||
t.Errorf("unexpected error for %q: got:%v want:%v", test.name, err, test.err)
|
t.Errorf("unexpected error for %q: got:%v want:%v", test.name, err, test.err)
|
||||||
}
|
}
|
||||||
|
@ -111,4 +122,12 @@ func Lex(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
type chunkEncoder [][]byte
|
||||||
|
|
||||||
|
func (e *chunkEncoder) Write(b []byte) (int, error) {
|
||||||
|
*e = append(*e, b)
|
||||||
|
return len(b), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*chunkEncoder) Stream() <-chan []byte { panic("INVALID USE") }
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -4,7 +4,7 @@ go 1.13
|
||||||
|
|
||||||
require (
|
require (
|
||||||
bitbucket.org/ausocean/iot v1.3.0
|
bitbucket.org/ausocean/iot v1.3.0
|
||||||
bitbucket.org/ausocean/utils v1.2.15
|
bitbucket.org/ausocean/utils v1.2.17
|
||||||
github.com/Comcast/gots v0.0.0-20190305015453-8d56e473f0f7
|
github.com/Comcast/gots v0.0.0-20190305015453-8d56e473f0f7
|
||||||
github.com/go-audio/audio v0.0.0-20181013203223-7b2a6ca21480
|
github.com/go-audio/audio v0.0.0-20181013203223-7b2a6ca21480
|
||||||
github.com/go-audio/wav v0.0.0-20181013172942-de841e69b884
|
github.com/go-audio/wav v0.0.0-20181013172942-de841e69b884
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -6,6 +6,8 @@ bitbucket.org/ausocean/utils v1.2.14 h1:v5eBYavkEqKOBCppR6P451eT9UT/CQReMsOZZBUP
|
||||||
bitbucket.org/ausocean/utils v1.2.14/go.mod h1:uXzX9z3PLemyURTMWRhVI8uLhPX4uuvaaO85v2hcob8=
|
bitbucket.org/ausocean/utils v1.2.14/go.mod h1:uXzX9z3PLemyURTMWRhVI8uLhPX4uuvaaO85v2hcob8=
|
||||||
bitbucket.org/ausocean/utils v1.2.15 h1:Pz99ZfobdhACTtU6oj9BTyBcNSQulLvPT7wq4P343Es=
|
bitbucket.org/ausocean/utils v1.2.15 h1:Pz99ZfobdhACTtU6oj9BTyBcNSQulLvPT7wq4P343Es=
|
||||||
bitbucket.org/ausocean/utils v1.2.15/go.mod h1:uXzX9z3PLemyURTMWRhVI8uLhPX4uuvaaO85v2hcob8=
|
bitbucket.org/ausocean/utils v1.2.15/go.mod h1:uXzX9z3PLemyURTMWRhVI8uLhPX4uuvaaO85v2hcob8=
|
||||||
|
bitbucket.org/ausocean/utils v1.2.17 h1:6ZqXvxRXHHL18s2kn22E2/AORNn2WsgQXcEnctWwvrk=
|
||||||
|
bitbucket.org/ausocean/utils v1.2.17/go.mod h1:uoIRyy4jwH0/9b/t9tfPuV9Vl14AONeILw9KimUISYg=
|
||||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/Comcast/gots v0.0.0-20190305015453-8d56e473f0f7 h1:LdOc9B9Bj6LEsKiXShkLA3/kpxXb6LJpH+ekU2krbzw=
|
github.com/Comcast/gots v0.0.0-20190305015453-8d56e473f0f7 h1:LdOc9B9Bj6LEsKiXShkLA3/kpxXb6LJpH+ekU2krbzw=
|
||||||
|
|
Loading…
Reference in New Issue