ace/drivers/video/ppm.go

117 lines
2.6 KiB
Go
Raw Normal View History

2022-09-28 06:14:26 +00:00
package video
import (
"context"
"image"
2022-10-17 08:16:36 +00:00
"image/draw"
2022-09-28 06:14:26 +00:00
"io"
2022-10-12 03:23:14 +00:00
"time"
2022-09-28 06:14:26 +00:00
"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
2022-10-12 03:23:14 +00:00
type Frame struct {
Time time.Time
Image io.ReadCloser
}
2022-09-28 06:14:26 +00:00
type PPMStreamDriver struct {
Height, Width int
FPS float32
2022-10-12 03:23:14 +00:00
PPMImage <-chan Frame
2022-09-28 06:14:26 +00:00
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) {
2022-09-30 04:24:32 +00:00
logrus.Debug(p)
2022-10-17 08:16:36 +00:00
/*canvas := image.NewYCbCr(
2022-10-02 10:50:08 +00:00
image.Rect(0, 0, p.Width, p.Height),
image.YCbCrSubsampleRatio420,
)
2022-10-12 03:23:14 +00:00
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
}
2022-10-17 08:16:36 +00:00
}*/
canvas := image.NewRGBA(image.Rect(0, 0, p.Width, p.Height))
var (
prevHeight, prevWidth int
)
2022-10-12 03:23:14 +00:00
2022-09-28 06:14:26 +00:00
r := video.ReaderFunc(func() (img image.Image, release func(), err error) {
select {
case <-v.closed:
return nil, func() {}, io.EOF
2022-10-02 10:50:08 +00:00
case ppmF := <-v.PPMImage:
2022-10-12 03:23:14 +00:00
defer ppmF.Image.Close()
2022-09-28 06:14:26 +00:00
2022-10-17 08:16:36 +00:00
// skip timeouted frame
if time.Since(ppmF.Time) > time.Second/time.Duration(p.FrameRate) {
return canvas, func() {}, nil
}
2022-10-12 03:23:14 +00:00
img, _, err := image.Decode(ppmF.Image)
2022-09-28 06:14:26 +00:00
if err != nil {
return nil, func() {}, err
}
2022-10-17 08:16:36 +00:00
// screen geometroy change
if img.Bounds().Dx() != prevWidth || img.Bounds().Dy() != prevHeight {
draw.Draw(canvas, canvas.Rect, image.Black, image.Black.Bounds().Min, draw.Over)
prevWidth = img.Bounds().Dx()
prevHeight = img.Bounds().Dy()
}
2022-10-12 03:23:14 +00:00
offsetX := (canvas.Rect.Dx() - img.Bounds().Dx()) / 2
offsetY := (canvas.Rect.Dy() - img.Bounds().Dy()) / 2
2022-10-17 08:16:36 +00:00
draw.Draw(canvas, image.Rect(
offsetX, offsetY, offsetX+img.Bounds().Dx(), offsetY+img.Bounds().Dy(),
), img, img.Bounds().Min, draw.Over)
case <-time.After(time.Second / time.Duration(p.FrameRate)):
2022-10-11 00:31:16 +00:00
default:
2022-09-28 06:14:26 +00:00
}
return canvas, func() {}, nil
})
return r, nil
}