diff --git a/cmd/rv/AusOcean_logo_1080p.h264 b/cmd/rv/logo.h264 similarity index 100% rename from cmd/rv/AusOcean_logo_1080p.h264 rename to cmd/rv/logo.h264 diff --git a/cmd/rv/main.go b/cmd/rv/main.go index 9590f53f..f332a1eb 100644 --- a/cmd/rv/main.go +++ b/cmd/rv/main.go @@ -56,6 +56,8 @@ package main import ( "io" + "io/ioutil" + "log" "os" "runtime/pprof" "strconv" @@ -105,46 +107,65 @@ const ( profilePath = "rv.prof" pkg = "rv: " runPreDelay = 20 * time.Second - turbidityDelay = 60 * time.Second + turbidityDelay = time.Second // Time delay for evaluating turbidity. + maxImages = 10 // Max number of images read when evaluating turbidity. ) // Software define pin values. // See https://netreceiver.appspot.com/help, External Pin Assignments. const ( - bitratePin = "X36" - saturationPin = "X38" - contrastPin = "X39" + bitratePin = "X36" + sharpnessPin = "X38" + contrastPin = "X39" ) // This is set to true if the 'profile' build tag is provided on build. var canProfile = false type turbidityProbe struct { - saturation, contrast float64 + sharpness, contrast float64 } // TODO(Russell): complete this implementation of Write. func (tp *turbidityProbe) Write(p []byte) (int, error) { - ticker := time.NewTicker(turbidityDelay) - const ( - rows = 2464 - cols = 3280 - ) go func() { for { select { case <-ticker.C: - mat, err := gocv.NewMatFromBytes(rows, cols, gocv.MatTypeCV8U, p) // IMDecode may also work + var imgs []gocv.Mat + img := gocv.NewMat() + + // Write byte array to a temp file. + file, err := ioutil.TempFile("temp", "video*.h264") if err != nil { - //TODO + log.Fatalf("failed to create temp file: %v", err) } - mat.GetUCharAt(0, 0) + defer os.Remove(file.Name()) + _, err = file.Write(p) + if err != nil { + log.Fatalf("failed to write to %v: %v", file.Name(), err) + } + + // Read the file and store each frame. + vc, err := gocv.VideoCaptureFile(file.Name()) + if err != nil { + log.Fatalf("failed to read read file, %v: %v", file.Name(), err) + } + for vc.Read(&img) && len(imgs) < maxImages { + imgs = append(imgs, img.Clone()) + } + + // Process video data to get saturation and contrast scores. - TODO + tp.contrast = float64(len(imgs)) + tp.sharpness = float64(len(imgs)) + return } } }() + time.Sleep(5 * time.Second) return len(p), nil } @@ -332,10 +353,10 @@ func readPin(p *turbidityProbe, rv *revid.Revid) func(pin *netsender.Pin) error } case pin.Name[0] == 'X': return sds.ReadSystem(pin) - case pin.Name == saturationPin: + case pin.Name == sharpnessPin: pin.Value = -1 if p != nil { - pin.Value = int(p.saturation * 1000) + pin.Value = int(p.sharpness * 1000) } case pin.Name == contrastPin: pin.Value = -1 diff --git a/cmd/rv/probe_test.go b/cmd/rv/probe_test.go index d5413f18..8b53aff8 100644 --- a/cmd/rv/probe_test.go +++ b/cmd/rv/probe_test.go @@ -3,32 +3,21 @@ package main import ( "io/ioutil" "testing" - - "gocv.io/x/gocv" ) -func TestMain(t *testing.T) { - //ts := new(turbidityProbe) - const ( - rows = 2464 - cols = 3280 - ) +// TestProbe reads a given video file and writes the sharpness and contrast scores to a turbidity probe +func TestProbe(t *testing.T) { + ts := new(turbidityProbe) - // Read frame - frame, err := ioutil.ReadFile("AusOcean_logo_1080p.h264") + video, err := ioutil.ReadFile("logo.h264") if err != nil { - t.Fatal(err) + t.Fatalf("failed to read file: %v", err) } - // Decode - //mat, err := gocv.NewMatFromBytes(rows, cols, gocv.MatTypeCV8UC3, frame) - mat, err := gocv.IMDecode(frame, gocv.IMReadUnchanged) + _, err = ts.Write(video) if err != nil { - t.Fatal(err) - } - if mat.Empty() { - t.Fatal("Empty gocv.Mat") + t.Fatalf("failed to write sharpness and contrast: %v", err) } - gocv.IMWrite("logo.jpg", mat) + t.Logf("contrast: %v, sharpness: %v\n", ts.contrast, ts.sharpness) }