driver done
This commit is contained in:
92
drivers/video/ppm.go
Normal file
92
drivers/video/ppm.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package video
|
||||
|
||||
import (
|
||||
"context"
|
||||
"image"
|
||||
"image/color"
|
||||
"io"
|
||||
|
||||
"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 PPMStreamDriver struct {
|
||||
Height, Width int
|
||||
FPS float32
|
||||
PPMImage <-chan io.ReadCloser
|
||||
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) {
|
||||
r := video.ReaderFunc(func() (img image.Image, release func(), err error) {
|
||||
canvas := image.NewYCbCr(
|
||||
image.Rect(0, 0, p.Width, p.Height),
|
||||
image.YCbCrSubsampleRatio420,
|
||||
)
|
||||
|
||||
select {
|
||||
case <-v.closed:
|
||||
return nil, func() {}, io.EOF
|
||||
case ppmF, ok := <-v.PPMImage:
|
||||
if !ok {
|
||||
return nil, func() {}, io.ErrClosedPipe
|
||||
}
|
||||
defer ppmF.Close()
|
||||
|
||||
img, _, err := image.Decode(ppmF)
|
||||
if err != nil {
|
||||
return nil, func() {}, err
|
||||
}
|
||||
|
||||
// draw input image in middle of canvas
|
||||
offsetX := (canvas.Bounds().Dx() - img.Bounds().Dx()) / 2
|
||||
offsetY := (canvas.Bounds().Dy() - img.Bounds().Dy()) / 2
|
||||
for x := 0; x < img.Bounds().Dx(); x++ {
|
||||
for y := 0; y < img.Bounds().Dy(); y++ {
|
||||
r, g, b, _ := img.At(x, y).RGBA()
|
||||
Y, Cb, Cr := color.RGBToYCbCr(uint8(r), uint8(g), uint8(b))
|
||||
|
||||
canvas.Y[canvas.YOffset(offsetX+x, offsetY+y)] = Y
|
||||
canvas.Cb[canvas.COffset(offsetX+x, offsetY+y)] = Cb
|
||||
canvas.Cr[canvas.COffset(offsetX+x, offsetY+y)] = Cr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return canvas, func() {}, nil
|
||||
})
|
||||
return r, nil
|
||||
}
|
Reference in New Issue
Block a user