mirror of
https://github.com/amitbet/vnc2video.git
synced 2025-09-20 01:17:39 +00:00
fixed hextile, now tested & working
This commit is contained in:
@@ -20,6 +20,10 @@ func (enc *CursorPseudoEncoding) SetTargetImage(img draw.Image) {
|
|||||||
enc.Image = img
|
enc.Image = img
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (enc *CursorPseudoEncoding) Reset() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (*CursorPseudoEncoding) Type() EncodingType { return EncCursorPseudo }
|
func (*CursorPseudoEncoding) Type() EncodingType { return EncCursorPseudo }
|
||||||
|
|
||||||
func (enc *CursorPseudoEncoding) Read(c Conn, rect *Rectangle) error {
|
func (enc *CursorPseudoEncoding) Read(c Conn, rect *Rectangle) error {
|
||||||
|
@@ -1,8 +1,6 @@
|
|||||||
package vnc2video
|
package vnc2video
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
|
||||||
"errors"
|
|
||||||
"image"
|
"image"
|
||||||
"image/color"
|
"image/color"
|
||||||
"image/draw"
|
"image/draw"
|
||||||
@@ -24,51 +22,32 @@ type HextileEncoding struct {
|
|||||||
Image draw.Image
|
Image draw.Image
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read unmarshal color from conn
|
func (enc *HextileEncoding) SetTargetImage(img draw.Image) {
|
||||||
func ReadColor(c io.Reader, pf *PixelFormat) (*color.RGBA, error) {
|
enc.Image = img
|
||||||
if pf.TrueColor == 0 {
|
|
||||||
return nil, errors.New("support for non true color formats was not implemented")
|
|
||||||
}
|
|
||||||
order := pf.order()
|
|
||||||
var pixel uint32
|
|
||||||
|
|
||||||
switch pf.BPP {
|
|
||||||
case 8:
|
|
||||||
var px uint8
|
|
||||||
if err := binary.Read(c, order, &px); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
pixel = uint32(px)
|
|
||||||
case 16:
|
|
||||||
var px uint16
|
|
||||||
if err := binary.Read(c, order, &px); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
pixel = uint32(px)
|
|
||||||
case 32:
|
|
||||||
var px uint32
|
|
||||||
if err := binary.Read(c, order, &px); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
pixel = uint32(px)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rgb := color.RGBA{
|
func (*HextileEncoding) Supported(Conn) bool {
|
||||||
R: uint8((pixel >> pf.RedShift) & uint32(pf.RedMax)),
|
return true
|
||||||
G: uint8((pixel >> pf.GreenShift) & uint32(pf.GreenMax)),
|
|
||||||
B: uint8((pixel >> pf.BlueShift) & uint32(pf.BlueMax)),
|
|
||||||
A: 1,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &rgb, nil
|
func (enc *HextileEncoding) Reset() error {
|
||||||
|
//enc.decoders = make([]io.Reader, 4)
|
||||||
|
//enc.decoderBuffs = make([]*bytes.Buffer, 4)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (z *HextileEncoding) Type() int32 {
|
func (z *HextileEncoding) Type() EncodingType {
|
||||||
return 5
|
return EncHextile
|
||||||
}
|
}
|
||||||
|
|
||||||
func (z *HextileEncoding) WriteTo(w io.Writer) (n int, err error) {
|
func (z *HextileEncoding) WriteTo(w io.Writer) (n int, err error) {
|
||||||
return w.Write(z.bytes)
|
return w.Write(z.bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (enc *HextileEncoding) Write(c Conn, rect *Rectangle) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (z *HextileEncoding) Read(r Conn, rect *Rectangle) error {
|
func (z *HextileEncoding) Read(r Conn, rect *Rectangle) error {
|
||||||
//func (z *HextileEncoding) Read(pixelFmt *PixelFormat, rect *Rectangle, r io.Reader) (Encoding, error) {
|
//func (z *HextileEncoding) Read(pixelFmt *PixelFormat, rect *Rectangle, r io.Reader) (Encoding, error) {
|
||||||
//bytesPerPixel := int(r.PixelFormat().BPP) / 8
|
//bytesPerPixel := int(r.PixelFormat().BPP) / 8
|
||||||
@@ -83,7 +62,7 @@ func (z *HextileEncoding) Read(r Conn, rect *Rectangle) error {
|
|||||||
// defer func() {
|
// defer func() {
|
||||||
// z.bytes = r.EndByteCollection()
|
// z.bytes = r.EndByteCollection()
|
||||||
// }()
|
// }()
|
||||||
|
logger.Debugf("HextileEncoding.Read: got hextile rect: %v", rect)
|
||||||
for ty := rect.Y; ty < rect.Y+rect.Height; ty += 16 {
|
for ty := rect.Y; ty < rect.Y+rect.Height; ty += 16 {
|
||||||
th := 16
|
th := 16
|
||||||
if rect.Y+rect.Height-ty < 16 {
|
if rect.Y+rect.Height-ty < 16 {
|
||||||
@@ -106,19 +85,31 @@ func (z *HextileEncoding) Read(r Conn, rect *Rectangle) error {
|
|||||||
|
|
||||||
if (subencoding & HextileRaw) != 0 {
|
if (subencoding & HextileRaw) != 0 {
|
||||||
rawEnc := r.GetEncInstance(EncRaw)
|
rawEnc := r.GetEncInstance(EncRaw)
|
||||||
rawEnc.Read(r, &Rectangle{0, 0, uint16(tw), uint16(th), EncRaw, rawEnc})
|
rawEnc.Read(r, &Rectangle{X: uint16(tx), Y: uint16(ty), Width: uint16(tw), Height: uint16(th), EncType: EncRaw, Enc: rawEnc})
|
||||||
//ReadBytes(tw*th*bytesPerPixel, r)
|
//ReadBytes(tw*th*int(pf.BPP)/8, r)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if (subencoding & HextileBackgroundSpecified) != 0 {
|
if (subencoding & HextileBackgroundSpecified) != 0 {
|
||||||
//ReadBytes(int(bytesPerPixel), r)
|
//ReadBytes(int(bytesPerPixel), r)
|
||||||
|
|
||||||
bgCol, err = ReadColor(r, &pf)
|
bgCol, err = ReadColor(r, &pf)
|
||||||
rBounds := image.Rectangle{Min: image.Point{int(tx), int(ty)}, Max: image.Point{int(tw), int(th)}}
|
if err != nil {
|
||||||
FillRect(z.Image, &rBounds, bgCol)
|
logger.Errorf("HextileEncoding.Read: error in hextile bg color reader: %v", err)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//logger.Debugf("%v %v", rBounds, bgCol)
|
||||||
|
}
|
||||||
|
rBounds := image.Rectangle{Min: image.Point{int(tx), int(ty)}, Max: image.Point{int(tx) + int(tw), int(ty) + int(th)}}
|
||||||
|
logger.Debugf("filling background rect: %v, col: %v", rBounds, bgCol)
|
||||||
|
FillRect(z.Image, &rBounds, bgCol)
|
||||||
|
|
||||||
if (subencoding & HextileForegroundSpecified) != 0 {
|
if (subencoding & HextileForegroundSpecified) != 0 {
|
||||||
fgCol, err = ReadColor(r, &pf)
|
fgCol, err = ReadColor(r, &pf)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("HextileEncoding.Read: error in hextile fg color reader: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (subencoding & HextileAnySubrects) == 0 {
|
if (subencoding & HextileAnySubrects) == 0 {
|
||||||
//logger.Debug("hextile reader: no Subrects")
|
//logger.Debug("hextile reader: no Subrects")
|
||||||
@@ -136,7 +127,7 @@ func (z *HextileEncoding) Read(r Conn, rect *Rectangle) error {
|
|||||||
if colorSpecified {
|
if colorSpecified {
|
||||||
color, err = ReadColor(r, &pf)
|
color, err = ReadColor(r, &pf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("Hextile decoder: problem reading color from connection: ", err)
|
logger.Error("HextileEncoding.Read: problem reading color from connection: ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -146,20 +137,21 @@ func (z *HextileEncoding) Read(r Conn, rect *Rectangle) error {
|
|||||||
fgCol = color
|
fgCol = color
|
||||||
dimensions, err = ReadUint8(r) // bits 7-4 for x, bits 3-0 for y
|
dimensions, err = ReadUint8(r) // bits 7-4 for x, bits 3-0 for y
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("Hextile decoder: problem reading dimensions from connection: ", err)
|
logger.Error("HextileEncoding.Read: problem reading dimensions from connection: ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
subtileX := dimensions >> 4 & 0x0f
|
subtileX := dimensions >> 4 & 0x0f
|
||||||
subtileY := dimensions & 0x0f
|
subtileY := dimensions & 0x0f
|
||||||
dimensions, err = ReadUint8(r) // bits 7-4 for w, bits 3-0 for h
|
dimensions, err = ReadUint8(r) // bits 7-4 for w, bits 3-0 for h
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("Hextile decoder: problem reading 2nd dimensions from connection: ", err)
|
logger.Error("HextileEncoding.Read: problem reading 2nd dimensions from connection: ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
subtileWidth := 1 + (dimensions >> 4 & 0x0f)
|
subtileWidth := 1 + (dimensions >> 4 & 0x0f)
|
||||||
subtileHeight := 1 + (dimensions & 0x0f)
|
subtileHeight := 1 + (dimensions & 0x0f)
|
||||||
subrectBounds := image.Rectangle{Min: image.Point{int(tx) + int(subtileX), int(ty) + int(subtileY)}, Max: image.Point{int(subtileWidth), int(subtileHeight)}}
|
subrectBounds := image.Rectangle{Min: image.Point{int(tx) + int(subtileX), int(ty) + int(subtileY)}, Max: image.Point{int(tx) + int(subtileX) + int(subtileWidth), int(ty) + int(subtileY) + int(subtileHeight)}}
|
||||||
FillRect(z.Image, &subrectBounds, color)
|
FillRect(z.Image, &subrectBounds, color)
|
||||||
|
//logger.Debugf("%v", subrectBounds)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,19 +1,57 @@
|
|||||||
package vnc2video
|
package vnc2video
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"errors"
|
||||||
"image"
|
"image"
|
||||||
"image/color"
|
"image/color"
|
||||||
"image/draw"
|
"image/draw"
|
||||||
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
func FillRect(img draw.Image, rect *image.Rectangle, c color.Color) {
|
func FillRect(img draw.Image, rect *image.Rectangle, c color.Color) {
|
||||||
for x := 0; x < rect.Max.X; x++ {
|
for x := rect.Min.X; x < rect.Max.X; x++ {
|
||||||
for y := 0; y < rect.Max.Y; y++ {
|
for y := rect.Min.Y; y < rect.Max.Y; y++ {
|
||||||
img.Set(x, y, c)
|
img.Set(x, y, c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func DrawLine(img draw.Image, rect *image.Rectangle, c color.Color) {
|
// Read unmarshal color from conn
|
||||||
|
func ReadColor(c io.Reader, pf *PixelFormat) (*color.RGBA, error) {
|
||||||
|
if pf.TrueColor == 0 {
|
||||||
|
return nil, errors.New("support for non true color formats was not implemented")
|
||||||
|
}
|
||||||
|
order := pf.order()
|
||||||
|
var pixel uint32
|
||||||
|
|
||||||
|
switch pf.BPP {
|
||||||
|
case 8:
|
||||||
|
var px uint8
|
||||||
|
if err := binary.Read(c, order, &px); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
pixel = uint32(px)
|
||||||
|
case 16:
|
||||||
|
var px uint16
|
||||||
|
if err := binary.Read(c, order, &px); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
pixel = uint32(px)
|
||||||
|
case 32:
|
||||||
|
var px uint32
|
||||||
|
if err := binary.Read(c, order, &px); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
pixel = uint32(px)
|
||||||
|
}
|
||||||
|
|
||||||
|
rgb := color.RGBA{
|
||||||
|
R: uint8((pixel >> pf.RedShift) & uint32(pf.RedMax)),
|
||||||
|
G: uint8((pixel >> pf.GreenShift) & uint32(pf.GreenMax)),
|
||||||
|
B: uint8((pixel >> pf.BlueShift) & uint32(pf.BlueMax)),
|
||||||
|
A: 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
return &rgb, nil
|
||||||
}
|
}
|
||||||
|
@@ -35,7 +35,12 @@ func main() {
|
|||||||
ClientMessageCh: cchClient,
|
ClientMessageCh: cchClient,
|
||||||
ServerMessageCh: cchServer,
|
ServerMessageCh: cchServer,
|
||||||
Messages: vnc.DefaultServerMessages,
|
Messages: vnc.DefaultServerMessages,
|
||||||
Encodings: []vnc.Encoding{&vnc.RawEncoding{}, &vnc.TightEncoding{}},
|
Encodings: []vnc.Encoding{
|
||||||
|
&vnc.RawEncoding{},
|
||||||
|
//&vnc.TightEncoding{},
|
||||||
|
&vnc.HextileEncoding{},
|
||||||
|
//&vnc.CursorPseudoEncoding{},
|
||||||
|
},
|
||||||
ErrorCh: errorCh,
|
ErrorCh: errorCh,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,7 +60,8 @@ func main() {
|
|||||||
|
|
||||||
//counter := 0
|
//counter := 0
|
||||||
//vcodec.Init("./output" + strconv.Itoa(counter))
|
//vcodec.Init("./output" + strconv.Itoa(counter))
|
||||||
go vcodec.Run("./ffmpeg", "./output.mp4")
|
//go vcodec.Run("./ffmpeg", "./output.mp4")
|
||||||
|
go vcodec.Run("/Users/amitbet/Dropbox/go/src/vnc2webm/example/file-reader/ffmpeg", "./output.mp4")
|
||||||
|
|
||||||
screenImage := image.NewRGBA(image.Rect(0, 0, int(cc.Width()), int(cc.Height())))
|
screenImage := image.NewRGBA(image.Rect(0, 0, int(cc.Width()), int(cc.Height())))
|
||||||
for _, enc := range ccfg.Encodings {
|
for _, enc := range ccfg.Encodings {
|
||||||
@@ -70,7 +76,7 @@ func main() {
|
|||||||
logger.Debugf("connected to: %s", os.Args[1])
|
logger.Debugf("connected to: %s", os.Args[1])
|
||||||
defer cc.Close()
|
defer cc.Close()
|
||||||
|
|
||||||
cc.SetEncodings([]vnc.EncodingType{vnc.EncTight})
|
cc.SetEncodings([]vnc.EncodingType{vnc.EncHextile})
|
||||||
//rect := image.Rect(0, 0, int(cc.Width()), int(cc.Height()))
|
//rect := image.Rect(0, 0, int(cc.Width()), int(cc.Height()))
|
||||||
//screenImage := image.NewRGBA64(rect)
|
//screenImage := image.NewRGBA64(rect)
|
||||||
// Process messages coming in on the ServerMessage channel.
|
// Process messages coming in on the ServerMessage channel.
|
||||||
|
Reference in New Issue
Block a user