package video import ( "context" "image" "image/color" "io" "time" "github.com/pion/mediadevices/pkg/frame" "github.com/pion/mediadevices/pkg/io/video" "github.com/pion/mediadevices/pkg/prop" "github.com/sirupsen/logrus" _ "github.com/jbuchbinder/gopnm" ) const DefaultFPS float32 = 60.0 type Frame struct { Time time.Time Image io.ReadCloser } type PPMStreamDriver struct { Height, Width int FPS float32 PPMImage <-chan Frame closed <-chan struct{} cancel func() } func (v *PPMStreamDriver) Open() error { defer logrus.Debug("device opened") ctx, cancel := context.WithCancel(context.Background()) v.closed = ctx.Done() v.cancel = cancel return nil } func (v *PPMStreamDriver) Close() error { v.cancel() return nil } func (v *PPMStreamDriver) Properties() []prop.Media { return []prop.Media{ { Video: prop.Video{ Width: v.Width, Height: v.Height, FrameRate: v.FPS, FrameFormat: frame.FormatYUYV, }, }, } } func (v *PPMStreamDriver) VideoRecord(p prop.Media) (video.Reader, error) { logrus.Debug(p) canvas := image.NewYCbCr( image.Rect(0, 0, p.Width, p.Height), image.YCbCrSubsampleRatio420, ) Y, Cb, Cr := color.RGBToYCbCr(0, 0, 0) for y := 0; y < canvas.Rect.Dy(); y++ { for x := 0; x < canvas.Rect.Dx(); x++ { canvas.Y[canvas.YOffset(x, y)] = Y canvas.Cb[canvas.COffset(x, y)] = Cb canvas.Cr[canvas.COffset(x, y)] = Cr } } r := video.ReaderFunc(func() (img image.Image, release func(), err error) { select { case <-v.closed: return nil, func() {}, io.EOF case ppmF := <-v.PPMImage: defer ppmF.Image.Close() img, _, err := image.Decode(ppmF.Image) if err != nil { return nil, func() {}, err } // resize image and draw it to canvas //resized := resize.Resize(uint(p.Width), uint(p.Height), img, resize.Bilinear) offsetX := (canvas.Rect.Dx() - img.Bounds().Dx()) / 2 offsetY := (canvas.Rect.Dy() - img.Bounds().Dy()) / 2 for y := 0; y < img.Bounds().Dy(); y++ { for x := 0; x < img.Bounds().Dx(); x++ { r, g, b, _ := img.At(x, y).RGBA() Y, Cb, Cr := color.RGBToYCbCr(uint8(r), uint8(g), uint8(b)) _x := offsetX + x _y := offsetY + y canvas.Y[canvas.YOffset(_x, _y)] = Y canvas.Cb[canvas.COffset(_x, _y)] = Cb canvas.Cr[canvas.COffset(_x, _y)] = Cr } } default: } return canvas, func() {}, nil }) return r, nil }