mirror of
https://github.com/pion/mediadevices.git
synced 2026-04-23 00:07:29 +08:00
Add screen capture device for Linux
This commit is contained in:
committed by
Lukas Herman
parent
f0cd710090
commit
9d598e21cb
@@ -0,0 +1,107 @@
|
||||
package screen
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"image"
|
||||
"image/color"
|
||||
"time"
|
||||
|
||||
"github.com/pion/mediadevices/pkg/driver"
|
||||
"github.com/pion/mediadevices/pkg/frame"
|
||||
"github.com/pion/mediadevices/pkg/io/video"
|
||||
"github.com/pion/mediadevices/pkg/prop"
|
||||
)
|
||||
|
||||
type screen struct {
|
||||
num int
|
||||
reader *reader
|
||||
tick *time.Ticker
|
||||
}
|
||||
|
||||
func deviceID(num int) string {
|
||||
return fmt.Sprintf("X11Screen%d", num)
|
||||
}
|
||||
|
||||
func init() {
|
||||
dp, err := openDisplay()
|
||||
if err != nil {
|
||||
// No x11 display available.
|
||||
return
|
||||
}
|
||||
defer dp.Close()
|
||||
numScreen := dp.NumScreen()
|
||||
for i := 0; i < numScreen; i++ {
|
||||
driver.GetManager().Register(
|
||||
&screen{
|
||||
num: i,
|
||||
},
|
||||
deviceID(i),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *screen) Open() error {
|
||||
r, err := newReader(s.num)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.reader = r
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *screen) Close() error {
|
||||
s.reader.Close()
|
||||
if s.tick != nil {
|
||||
s.tick.Stop()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *screen) VideoRecord(p prop.Media) (video.Reader, error) {
|
||||
rect := s.reader.img.Bounds()
|
||||
w := rect.Max.X - rect.Min.X
|
||||
h := rect.Max.Y - rect.Min.Y
|
||||
imgI444 := image.NewYCbCr(rect, image.YCbCrSubsampleRatio444)
|
||||
|
||||
if p.FrameRate == 0 {
|
||||
p.FrameRate = 10
|
||||
}
|
||||
s.tick = time.NewTicker(time.Duration(float32(time.Second) / p.FrameRate))
|
||||
|
||||
r := video.ReaderFunc(func() (image.Image, error) {
|
||||
<-s.tick.C
|
||||
img := s.reader.Read()
|
||||
// Convert it to I444
|
||||
for y := 0; y < h; y++ {
|
||||
iyBase := y * imgI444.YStride
|
||||
icBase := y * imgI444.CStride
|
||||
for x := 0; x < w; x++ {
|
||||
iy := iyBase + x
|
||||
ic := icBase + x
|
||||
r, g, b, _ := img.At(x, y).RGBA()
|
||||
yy, cb, cr := color.RGBToYCbCr(uint8(r/0x100), uint8(g/0x100), uint8(b/0x100))
|
||||
imgI444.Y[iy] = yy
|
||||
imgI444.Cb[ic] = cb
|
||||
imgI444.Cr[ic] = cr
|
||||
}
|
||||
}
|
||||
return imgI444, nil
|
||||
})
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (s *screen) Properties() []prop.Media {
|
||||
rect := s.reader.img.Bounds()
|
||||
w := rect.Max.X - rect.Min.X
|
||||
h := rect.Max.Y - rect.Min.Y
|
||||
return []prop.Media{
|
||||
{
|
||||
DeviceID: deviceID(s.num),
|
||||
Video: prop.Video{
|
||||
Width: w,
|
||||
Height: h,
|
||||
FrameFormat: frame.FormatI444,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user