Skip to content

Commit

Permalink
[RSDK-9513] Add VideoSourceFromCamera helper in stream camera utils (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
hexbabe authored Dec 16, 2024
1 parent cbe96a4 commit 6274a3f
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 1 deletion.
26 changes: 25 additions & 1 deletion robot/web/stream/camera/camera.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
// Package camera provides functions for looking up a camera from a robot using a stream
// Package camera provides utilities for working with camera resources in the context of streaming.
package camera

import (
"context"
"image"

"github.com/pion/mediadevices/pkg/prop"

"go.viam.com/rdk/components/camera"
"go.viam.com/rdk/gostream"
"go.viam.com/rdk/resource"
Expand All @@ -19,3 +24,22 @@ func Camera(robot robot.Robot, stream gostream.Stream) (camera.Camera, error) {
}
return cam, nil
}

// VideoSourceFromCamera converts a camera resource into a gostream VideoSource.
// This is useful for streaming video from a camera resource.
func VideoSourceFromCamera(ctx context.Context, cam camera.Camera) gostream.VideoSource {
reader := gostream.VideoReaderFunc(func(ctx context.Context) (image.Image, func(), error) {
img, err := camera.DecodeImageFromCamera(ctx, "", nil, cam)
if err != nil {
return nil, func() {}, err
}
return img, func() {}, nil
})

img, err := camera.DecodeImageFromCamera(ctx, "", nil, cam)
if err == nil {
return gostream.NewVideoSource(reader, prop.Video{Width: img.Bounds().Dx(), Height: img.Bounds().Dy()})
}
// Okay to return empty prop because processInputFrames will tick and set them
return gostream.NewVideoSource(reader, prop.Video{})
}
37 changes: 37 additions & 0 deletions robot/web/stream/camera/camera_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package camera_test

import (
"context"
"image"
"testing"

"go.viam.com/test"

"go.viam.com/rdk/components/camera"
"go.viam.com/rdk/rimage"
camerautils "go.viam.com/rdk/robot/web/stream/camera"
"go.viam.com/rdk/testutils/inject"
"go.viam.com/rdk/utils"
)

func TestVideoSourceFromCamera(t *testing.T) {
sourceImg := image.NewRGBA(image.Rect(0, 0, 3, 3))
cam := &inject.Camera{
ImageFunc: func(ctx context.Context, mimeType string, extra map[string]interface{}) ([]byte, camera.ImageMetadata, error) {
imgBytes, err := rimage.EncodeImage(ctx, sourceImg, utils.MimeTypePNG)
test.That(t, err, test.ShouldBeNil)
return imgBytes, camera.ImageMetadata{MimeType: utils.MimeTypePNG}, nil
},
}
vs := camerautils.VideoSourceFromCamera(context.Background(), cam)

stream, err := vs.Stream(context.Background())
test.That(t, err, test.ShouldBeNil)

img, _, err := stream.Next(context.Background())
test.That(t, err, test.ShouldBeNil)

diffVal, _, err := rimage.CompareImages(img, sourceImg)
test.That(t, err, test.ShouldBeNil)
test.That(t, diffVal, test.ShouldEqual, 0)
}

0 comments on commit 6274a3f

Please sign in to comment.