Repository: pion/mediadevices (go)

Issue:
Add video throttle transform
Drop frames to limit output framerate.

Pull request description:
Add video throttle transform
### Reference issue
Fixes #63


Patch:
diff --git a/pkg/io/video/throttle.go b/pkg/io/video/throttle.go
new file mode 100644
index 0000000..45707ce
--- /dev/null
+++ b/pkg/io/video/throttle.go
@@ -0,0 +1,28 @@
+package video
+
+import (
+	"image"
+	"time"
+)
+
+// Throttle returns video throttling transform.
+// This transform drops some of the incoming frames to achieve given framerate in fps.
+func Throttle(rate float32) TransformFunc {
+	return func(r Reader) Reader {
+		ticker := time.NewTicker(time.Duration(int64(float64(time.Second) / float64(rate))))
+		return ReaderFunc(func() (image.Image, error) {
+			for {
+				img, err := r.Read()
+				if err != nil {
+					ticker.Stop()
+					return nil, err
+				}
+				select {
+				case <-ticker.C:
+					return img, nil
+				default:
+				}
+			}
+		})
+	}
+}


Test patch:
diff --git a/pkg/io/video/throttle_test.go b/pkg/io/video/throttle_test.go
new file mode 100644
index 0000000..d6536fa
--- /dev/null
+++ b/pkg/io/video/throttle_test.go
@@ -0,0 +1,34 @@
+package video
+
+import (
+	"image"
+	"testing"
+	"time"
+)
+
+func TestThrottle(t *testing.T) {
+	img := image.NewRGBA(image.Rect(0, 0, 640, 480))
+
+	ticker := time.NewTicker(time.Millisecond)
+	defer ticker.Stop()
+
+	var cntPush int
+	trans := Throttle(100)
+	r := trans(ReaderFunc(func() (image.Image, error) {
+		<-ticker.C
+		cntPush++
+		return img, nil
+	}))
+
+	for i := 0; i < 50; i++ {
+		_, err := r.Read()
+		if err != nil {
+			t.Fatalf("Unexpected error: %v", err)
+		}
+	}
+	cntExpected := 500
+	if cntPush < cntExpected*9/10 || cntExpected*11/10 < cntPush {
+		t.Fatalf("Number of pushed images is expected to be %d, but pushed %d", cntExpected, cntPush)
+	}
+	t.Log(cntPush)
+}