mirror of
https://github.com/amitbet/vnc2video.git
synced 2025-04-28 10:33:24 +00:00
fixed rfb encoding (file-reader)
This commit is contained in:
parent
4f65cf3972
commit
be81a1eb67
12
.vscode/launch.json
vendored
12
.vscode/launch.json
vendored
@ -5,7 +5,7 @@
|
|||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"name": "Launch Package",
|
"name": "Launch Client",
|
||||||
"type": "go",
|
"type": "go",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"mode": "debug",
|
"mode": "debug",
|
||||||
@ -13,6 +13,16 @@
|
|||||||
"localhost:5903"
|
"localhost:5903"
|
||||||
],
|
],
|
||||||
"program": "${workspaceRoot}/example/client"
|
"program": "${workspaceRoot}/example/client"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Launch FbsReader",
|
||||||
|
"type": "go",
|
||||||
|
"request": "launch",
|
||||||
|
"mode": "debug",
|
||||||
|
"args": [
|
||||||
|
"/Users/amitbet/Downloads/vncproxy-darwin-amd64-v1.0/myfbs.fbs"
|
||||||
|
],
|
||||||
|
"program": "${workspaceRoot}/example/file-reader"
|
||||||
}
|
}
|
||||||
|
|
||||||
]
|
]
|
||||||
|
@ -36,6 +36,7 @@ func Connect(ctx context.Context, c net.Conn, cfg *ClientConfig) (*ClientConn, e
|
|||||||
|
|
||||||
for _, h := range cfg.Handlers {
|
for _, h := range cfg.Handlers {
|
||||||
if err := h.Handle(conn); err != nil {
|
if err := h.Handle(conn); err != nil {
|
||||||
|
logger.Error("Handshake failed, check that server is running: ", err)
|
||||||
conn.Close()
|
conn.Close()
|
||||||
cfg.ErrorCh <- err
|
cfg.ErrorCh <- err
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -85,8 +85,12 @@ func (enc *QTRLEImageEncoder) Init(videoFileName string) {
|
|||||||
}
|
}
|
||||||
func (enc *QTRLEImageEncoder) Run(videoFileName string) error {
|
func (enc *QTRLEImageEncoder) Run(videoFileName string) error {
|
||||||
if _, err := os.Stat(enc.FFMpegBinPath); os.IsNotExist(err) {
|
if _, err := os.Stat(enc.FFMpegBinPath); os.IsNotExist(err) {
|
||||||
|
if _, err := os.Stat(enc.FFMpegBinPath + ".exe"); os.IsNotExist(err) {
|
||||||
logger.Error("encoder file doesn't exist in path:", enc.FFMpegBinPath)
|
logger.Error("encoder file doesn't exist in path:", enc.FFMpegBinPath)
|
||||||
return errors.New("encoder file doesn't exist in path" + videoFileName)
|
return errors.New("encoder file doesn't exist in path" + videoFileName)
|
||||||
|
} else {
|
||||||
|
enc.FFMpegBinPath = enc.FFMpegBinPath + ".exe"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enc.Init(videoFileName)
|
enc.Init(videoFileName)
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"vnc2video/logger"
|
"vnc2video/logger"
|
||||||
)
|
)
|
||||||
@ -31,7 +32,7 @@ func (enc *X264ImageEncoder) Init(videoFileName string) {
|
|||||||
"-f", "image2pipe",
|
"-f", "image2pipe",
|
||||||
"-vcodec", "ppm",
|
"-vcodec", "ppm",
|
||||||
//"-r", strconv.Itoa(framerate),
|
//"-r", strconv.Itoa(framerate),
|
||||||
"-r", "12",
|
"-r", strconv.Itoa(enc.Framerate),
|
||||||
|
|
||||||
//"-re",
|
//"-re",
|
||||||
//"-i", "pipe:0",
|
//"-i", "pipe:0",
|
||||||
@ -53,15 +54,15 @@ func (enc *X264ImageEncoder) Init(videoFileName string) {
|
|||||||
// "-an", "-f", "webm",
|
// "-an", "-f", "webm",
|
||||||
"-preset", "veryfast",
|
"-preset", "veryfast",
|
||||||
//"-tune", "animation",
|
//"-tune", "animation",
|
||||||
"-maxrate", "0.5M",
|
// "-maxrate", "0.5M",
|
||||||
"-bufsize", "50M",
|
// "-bufsize", "50M",
|
||||||
"-g", "250",
|
"-g", "250",
|
||||||
|
|
||||||
//"-crf", "0", //for lossless encoding!!!!
|
//"-crf", "0", //for lossless encoding!!!!
|
||||||
|
|
||||||
//"-rc_lookahead", "16",
|
//"-rc_lookahead", "16",
|
||||||
//"-profile", "0",
|
//"-profile", "0",
|
||||||
"-crf", "34",
|
"-crf", "37",
|
||||||
//"-qmax", "51",
|
//"-qmax", "51",
|
||||||
//"-qmin", "7",
|
//"-qmin", "7",
|
||||||
//"-slices", "4",
|
//"-slices", "4",
|
||||||
@ -84,8 +85,12 @@ func (enc *X264ImageEncoder) Init(videoFileName string) {
|
|||||||
}
|
}
|
||||||
func (enc *X264ImageEncoder) Run(videoFileName string) error {
|
func (enc *X264ImageEncoder) Run(videoFileName string) error {
|
||||||
if _, err := os.Stat(enc.FFMpegBinPath); os.IsNotExist(err) {
|
if _, err := os.Stat(enc.FFMpegBinPath); os.IsNotExist(err) {
|
||||||
|
if _, err := os.Stat(enc.FFMpegBinPath + ".exe"); os.IsNotExist(err) {
|
||||||
logger.Error("encoder file doesn't exist in path:", enc.FFMpegBinPath)
|
logger.Error("encoder file doesn't exist in path:", enc.FFMpegBinPath)
|
||||||
return errors.New("encoder file doesn't exist in path" + videoFileName)
|
return errors.New("encoder file doesn't exist in path" + videoFileName)
|
||||||
|
} else {
|
||||||
|
enc.FFMpegBinPath = enc.FFMpegBinPath + ".exe"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enc.Init(videoFileName)
|
enc.Init(videoFileName)
|
||||||
|
@ -150,6 +150,11 @@ func (enc *TightEncoding) SetTargetImage(img draw.Image) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var counter int = 0
|
var counter int = 0
|
||||||
|
var disablePalette bool = false
|
||||||
|
var disableGradient bool = false
|
||||||
|
var disableCopy bool = false
|
||||||
|
var disableJpeg bool = false
|
||||||
|
var disableFill bool = false
|
||||||
|
|
||||||
func (enc *TightEncoding) Read(c Conn, rect *Rectangle) error {
|
func (enc *TightEncoding) Read(c Conn, rect *Rectangle) error {
|
||||||
|
|
||||||
@ -207,7 +212,9 @@ func (enc *TightEncoding) Read(c Conn, rect *Rectangle) error {
|
|||||||
dst := (enc.Image).(draw.Image) // enc.Image.(*image.RGBA)
|
dst := (enc.Image).(draw.Image) // enc.Image.(*image.RGBA)
|
||||||
myRect := MakeRectFromVncRect(rect)
|
myRect := MakeRectFromVncRect(rect)
|
||||||
logger.Tracef("--TIGHT_FILL: fill rect=%v,color=%v", myRect, rectColor)
|
logger.Tracef("--TIGHT_FILL: fill rect=%v,color=%v", myRect, rectColor)
|
||||||
|
if !disableFill {
|
||||||
FillRect(dst, &myRect, rectColor)
|
FillRect(dst, &myRect, rectColor)
|
||||||
|
}
|
||||||
|
|
||||||
if bytesPixel != 3 {
|
if bytesPixel != 3 {
|
||||||
return fmt.Errorf("non tight bytesPerPixel format, should be 3 bytes")
|
return fmt.Errorf("non tight bytesPerPixel format, should be 3 bytes")
|
||||||
@ -229,13 +236,19 @@ func (enc *TightEncoding) Read(c Conn, rect *Rectangle) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
//TODO: check if we can read jpeg directly from stream (this is safer for now)
|
|
||||||
buff := bytes.NewBuffer(jpegBytes)
|
buff := bytes.NewBuffer(jpegBytes)
|
||||||
img, err := jpeg.Decode(buff)
|
img, err := jpeg.Decode(buff)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("problem while decoding jpeg:", err)
|
logger.Error("problem while decoding jpeg:", err)
|
||||||
}
|
}
|
||||||
draw.Draw(enc.Image, enc.Image.Bounds(), img, image.Point{int(rect.X), int(rect.Y)}, draw.Src)
|
//logger.Info("not drawing:", img)
|
||||||
|
if !disableJpeg {
|
||||||
|
pos := image.Point{int(rect.X), int(rect.Y)}
|
||||||
|
DrawImage(enc.Image, img, pos)
|
||||||
|
|
||||||
|
//draw.Draw(enc.Image, enc.Image.Bounds(), img, pos, draw.Src)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
default:
|
default:
|
||||||
@ -251,6 +264,7 @@ func (enc *TightEncoding) Read(c Conn, rect *Rectangle) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (enc *TightEncoding) handleTightFilters(compCtl uint8, pixelFmt *PixelFormat, rect *Rectangle, r Conn) {
|
func (enc *TightEncoding) handleTightFilters(compCtl uint8, pixelFmt *PixelFormat, rect *Rectangle, r Conn) {
|
||||||
|
|
||||||
var STREAM_ID_MASK uint8 = 0x30
|
var STREAM_ID_MASK uint8 = 0x30
|
||||||
var FILTER_ID_MASK uint8 = 0x40
|
var FILTER_ID_MASK uint8 = 0x40
|
||||||
|
|
||||||
@ -304,8 +318,9 @@ func (enc *TightEncoding) handleTightFilters(compCtl uint8, pixelFmt *PixelForma
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
//logger.Errorf("handleTightFilters: got tight data: %v", tightBytes)
|
//logger.Errorf("handleTightFilters: got tight data: %v", tightBytes)
|
||||||
|
if !disablePalette {
|
||||||
enc.drawTightPalette(rect, palette, tightBytes)
|
enc.drawTightPalette(rect, palette, tightBytes)
|
||||||
|
}
|
||||||
//enc.Image = myImg
|
//enc.Image = myImg
|
||||||
case TightFilterGradient: //GRADIENT_FILTER
|
case TightFilterGradient: //GRADIENT_FILTER
|
||||||
logger.Debugf("----GRADIENT_FILTER: bytesPixel=%d, counter=%d", bytesPixel, counter)
|
logger.Debugf("----GRADIENT_FILTER: bytesPixel=%d, counter=%d", bytesPixel, counter)
|
||||||
@ -315,6 +330,7 @@ func (enc *TightEncoding) handleTightFilters(compCtl uint8, pixelFmt *PixelForma
|
|||||||
logger.Errorf("handleTightFilters: error in handling tight encoding, Reading GRADIENT_FILTER: %v", err)
|
logger.Errorf("handleTightFilters: error in handling tight encoding, Reading GRADIENT_FILTER: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
enc.decodeGradData(rect, data)
|
enc.decodeGradData(rect, data)
|
||||||
|
|
||||||
case TightFilterCopy: //BASIC_FILTER
|
case TightFilterCopy: //BASIC_FILTER
|
||||||
@ -327,7 +343,9 @@ func (enc *TightEncoding) handleTightFilters(compCtl uint8, pixelFmt *PixelForma
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
logger.Tracef("tightBytes len= %d", len(tightBytes))
|
logger.Tracef("tightBytes len= %d", len(tightBytes))
|
||||||
|
if !disableCopy {
|
||||||
enc.drawTightBytes(tightBytes, rect)
|
enc.drawTightBytes(tightBytes, rect)
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
logger.Errorf("handleTightFilters: Bad tight filter id: %d", filterid)
|
logger.Errorf("handleTightFilters: Bad tight filter id: %d", filterid)
|
||||||
return
|
return
|
||||||
@ -425,7 +443,9 @@ func (enc *TightEncoding) decodeGradData(rect *Rectangle, buffer []byte) {
|
|||||||
|
|
||||||
for idx := 3; idx < (len(thisRow) - 3); idx += 3 {
|
for idx := 3; idx < (len(thisRow) - 3); idx += 3 {
|
||||||
myColor := color.RGBA{R: (thisRow[idx]), G: (thisRow[idx+1]), B: (thisRow[idx+2]), A: 1}
|
myColor := color.RGBA{R: (thisRow[idx]), G: (thisRow[idx+1]), B: (thisRow[idx+2]), A: 1}
|
||||||
|
if !disableGradient {
|
||||||
enc.Image.Set(idx/3+int(rect.X)-1, int(rect.Y)+i, myColor)
|
enc.Image.Set(idx/3+int(rect.X)-1, int(rect.Y)+i, myColor)
|
||||||
|
}
|
||||||
//logger.Tracef("putting pixel: idx=%d, pos=(%d,%d), col=%v", idx, idx/3+int(rect.X), int(rect.Y)+i, myColor)
|
//logger.Tracef("putting pixel: idx=%d, pos=(%d,%d), col=%v", idx, idx/3+int(rect.X), int(rect.Y)+i, myColor)
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -530,7 +550,7 @@ func (enc *TightEncoding) readTightPalette(connReader Conn, bytesPixel int) (col
|
|||||||
|
|
||||||
func (enc *TightEncoding) ReadTightData(dataSize int, c Conn, decoderId int) ([]byte, error) {
|
func (enc *TightEncoding) ReadTightData(dataSize int, c Conn, decoderId int) ([]byte, error) {
|
||||||
|
|
||||||
logger.Tracef(">>> Reading zipped tight data from decoder: %d", decoderId)
|
logger.Tracef(">>> Reading zipped tight data from decoder Id: %d, openSize: %d", decoderId, dataSize)
|
||||||
if int(dataSize) < TightMinToCompress {
|
if int(dataSize) < TightMinToCompress {
|
||||||
return ReadBytes(int(dataSize), c)
|
return ReadBytes(int(dataSize), c)
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,8 @@ func (enc *TightPngEncoding) Read(c Conn, rect *Rectangle) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
draw.Draw(enc.Image, enc.Image.Bounds(), img, image.Point{X: int(rect.X), Y: int(rect.Y)}, draw.Src)
|
//draw.Draw(enc.Image, enc.Image.Bounds(), img, image.Point{X: int(rect.X), Y: int(rect.Y)}, draw.Src)
|
||||||
|
DrawImage(enc.Image, img, image.Point{X: int(rect.X), Y: int(rect.Y)})
|
||||||
case TightCompressionFill:
|
case TightCompressionFill:
|
||||||
var tpx TightPixel
|
var tpx TightPixel
|
||||||
if err := binary.Read(c, binary.BigEndian, &tpx); err != nil {
|
if err := binary.Read(c, binary.BigEndian, &tpx); err != nil {
|
||||||
|
@ -139,6 +139,15 @@ func Min(a, b int) int {
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func DrawImage(target draw.Image, imageToApply image.Image, pos image.Point) {
|
||||||
|
rect := imageToApply.Bounds()
|
||||||
|
for x := rect.Min.X; x < rect.Max.X; x++ {
|
||||||
|
for y := rect.Min.Y; y < rect.Max.Y; y++ {
|
||||||
|
target.Set(x+pos.X, y+pos.Y, imageToApply.At(x, y))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func FillRect(img draw.Image, rect *image.Rectangle, c color.Color) {
|
func FillRect(img draw.Image, rect *image.Rectangle, c color.Color) {
|
||||||
for x := rect.Min.X; x < rect.Max.X; x++ {
|
for x := rect.Min.X; x < rect.Max.X; x++ {
|
||||||
for y := rect.Min.Y; y < rect.Max.Y; y++ {
|
for y := rect.Min.Y; y < rect.Max.Y; y++ {
|
||||||
|
@ -17,6 +17,9 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
runtime.GOMAXPROCS(4)
|
runtime.GOMAXPROCS(4)
|
||||||
|
framerate := 12
|
||||||
|
runWithProfiler := false
|
||||||
|
|
||||||
// Establish TCP connection to VNC server.
|
// Establish TCP connection to VNC server.
|
||||||
nc, err := net.DialTimeout("tcp", os.Args[1], 5*time.Second)
|
nc, err := net.DialTimeout("tcp", os.Args[1], 5*time.Second)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -61,13 +64,15 @@ func main() {
|
|||||||
}
|
}
|
||||||
// out, err := os.Create("./output" + strconv.Itoa(counter) + ".jpg")
|
// out, err := os.Create("./output" + strconv.Itoa(counter) + ".jpg")
|
||||||
// if err != nil {
|
// if err != nil {
|
||||||
// fmt.Println(err)
|
// fmt.Println(err)p
|
||||||
// os.Exit(1)
|
// os.Exit(1)
|
||||||
// }
|
// }
|
||||||
vcodec := &encoders.MJPegImageEncoder{Quality: 60, Framerate: 12}
|
//vcodec := &encoders.MJPegImageEncoder{Quality: 60 , Framerate: framerate}
|
||||||
//vcodec := &encoders.X264ImageEncoder{FFMpegBinPath:"./ffmpeg"}
|
//vcodec := &encoders.X264ImageEncoder{FFMpegBinPath: "./ffmpeg", Framerate: framerate}
|
||||||
//vcodec := &encoders.VP8ImageEncoder{FFMpegBinPath:"./ffmpeg"}
|
//vcodec := &encoders.HuffYuvImageEncoder{FFMpegBinPath: "./ffmpeg", Framerate: framerate}
|
||||||
//vcodec := &encoders.DV9ImageEncoder{FFMpegBinPath:"./ffmpeg"}
|
vcodec := &encoders.QTRLEImageEncoder{FFMpegBinPath: "./ffmpeg", Framerate: framerate}
|
||||||
|
//vcodec := &encoders.VP8ImageEncoder{FFMpegBinPath:"./ffmpeg", Framerate: framerate}
|
||||||
|
//vcodec := &encoders.DV9ImageEncoder{FFMpegBinPath:"./ffmpeg", Framerate: framerate}
|
||||||
|
|
||||||
//counter := 0
|
//counter := 0
|
||||||
//vcodec.Init("./output" + strconv.Itoa(counter))
|
//vcodec.Init("./output" + strconv.Itoa(counter))
|
||||||
@ -98,7 +103,7 @@ func main() {
|
|||||||
vnc.EncPointerPosPseudo,
|
vnc.EncPointerPosPseudo,
|
||||||
vnc.EncCopyRect,
|
vnc.EncCopyRect,
|
||||||
vnc.EncTight,
|
vnc.EncTight,
|
||||||
//vnc.EncZRLE,
|
vnc.EncZRLE,
|
||||||
//vnc.EncHextile,
|
//vnc.EncHextile,
|
||||||
//vnc.EncZlib,
|
//vnc.EncZlib,
|
||||||
//vnc.EncRRE,
|
//vnc.EncRRE,
|
||||||
@ -113,7 +118,7 @@ func main() {
|
|||||||
|
|
||||||
vcodec.Encode(screenImage.Image)
|
vcodec.Encode(screenImage.Image)
|
||||||
|
|
||||||
timeTarget := timeStart.Add((1000 / 12) * time.Millisecond)
|
timeTarget := timeStart.Add((1000 / time.Duration(framerate)) * time.Millisecond)
|
||||||
timeLeft := timeTarget.Sub(time.Now())
|
timeLeft := timeTarget.Sub(time.Now())
|
||||||
if timeLeft > 0 {
|
if timeLeft > 0 {
|
||||||
time.Sleep(timeLeft)
|
time.Sleep(timeLeft)
|
||||||
@ -130,7 +135,6 @@ func main() {
|
|||||||
frameBufferReq := 0
|
frameBufferReq := 0
|
||||||
timeStart := time.Now()
|
timeStart := time.Now()
|
||||||
|
|
||||||
runWithProfiler := false
|
|
||||||
if runWithProfiler {
|
if runWithProfiler {
|
||||||
profFile := "prof.file"
|
profFile := "prof.file"
|
||||||
f, err := os.Create(profFile)
|
f, err := os.Create(profFile)
|
||||||
|
@ -1,15 +1,18 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"image"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"time"
|
||||||
vnc "vnc2video"
|
vnc "vnc2video"
|
||||||
"vnc2video/encoders"
|
"vnc2video/encoders"
|
||||||
"vnc2video/logger"
|
"vnc2video/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
framerate := 10
|
||||||
|
speedupFactor := 3.6
|
||||||
|
fastFramerate := int(float64(framerate) * speedupFactor)
|
||||||
|
|
||||||
if len(os.Args) <= 1 {
|
if len(os.Args) <= 1 {
|
||||||
logger.Errorf("please provide a fbs file name")
|
logger.Errorf("please provide a fbs file name")
|
||||||
@ -22,6 +25,8 @@ func main() {
|
|||||||
encs := []vnc.Encoding{
|
encs := []vnc.Encoding{
|
||||||
&vnc.RawEncoding{},
|
&vnc.RawEncoding{},
|
||||||
&vnc.TightEncoding{},
|
&vnc.TightEncoding{},
|
||||||
|
&vnc.CopyRectEncoding{},
|
||||||
|
&vnc.ZRLEEncoding{},
|
||||||
}
|
}
|
||||||
|
|
||||||
fbs, err := vnc.NewFbsConn(
|
fbs, err := vnc.NewFbsConn(
|
||||||
@ -34,14 +39,17 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//launch video encoding process:
|
//launch video encoding process:
|
||||||
vcodec := &encoders.X264ImageEncoder{FFMpegBinPath: "./ffmpeg"}
|
vcodec := &encoders.X264ImageEncoder{FFMpegBinPath: "./ffmpeg", Framerate: framerate}
|
||||||
//vcodec := &encoders.DV8ImageEncoder{}
|
//vcodec := &encoders.DV8ImageEncoder{}
|
||||||
//vcodec := &encoders.DV9ImageEncoder{}
|
//vcodec := &encoders.DV9ImageEncoder{}
|
||||||
dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
|
dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
|
||||||
logger.Tracef("current dir: %s", dir)
|
logger.Tracef("current dir: %s", dir)
|
||||||
go vcodec.Run("./output.mp4")
|
go vcodec.Run("./output.mp4")
|
||||||
|
|
||||||
screenImage := image.NewRGBA(image.Rect(0, 0, int(fbs.Width()), int(fbs.Height())))
|
//screenImage := image.NewRGBA(image.Rect(0, 0, int(fbs.Width()), int(fbs.Height())))
|
||||||
|
screenImage := vnc.NewVncCanvas(int(fbs.Width()), int(fbs.Height()))
|
||||||
|
screenImage.DrawCursor = false
|
||||||
|
|
||||||
for _, enc := range encs {
|
for _, enc := range encs {
|
||||||
myRenderer, ok := enc.(vnc.Renderer)
|
myRenderer, ok := enc.(vnc.Renderer)
|
||||||
|
|
||||||
@ -50,11 +58,33 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
msgReader := vnc.NewFBSPlayHelper(fbs)
|
go func() {
|
||||||
|
frameMillis := (1000.0 / float64(fastFramerate)) - 2 //a couple of millis, adjusting for time lost in software commands
|
||||||
|
frameDuration := time.Duration(frameMillis * float64(time.Millisecond))
|
||||||
|
//logger.Error("milis= ", frameMillis)
|
||||||
|
|
||||||
|
for {
|
||||||
|
timeStart := time.Now()
|
||||||
|
|
||||||
|
vcodec.Encode(screenImage.Image)
|
||||||
|
timeTarget := timeStart.Add(frameDuration)
|
||||||
|
timeLeft := timeTarget.Sub(time.Now())
|
||||||
|
//.Add(1 * time.Millisecond)
|
||||||
|
if timeLeft > 0 {
|
||||||
|
time.Sleep(timeLeft)
|
||||||
|
//logger.Error("sleeping= ", timeLeft)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
msgReader := vnc.NewFBSPlayHelper(fbs)
|
||||||
//loop over all messages, feed images to video codec:
|
//loop over all messages, feed images to video codec:
|
||||||
for {
|
for {
|
||||||
msgReader.ReadFbsMessage()
|
_, err := msgReader.ReadFbsMessage(true, speedupFactor)
|
||||||
vcodec.Encode(screenImage)
|
//vcodec.Encode(screenImage.Image)
|
||||||
|
if err != nil {
|
||||||
|
os.Exit(-1)
|
||||||
|
}
|
||||||
|
//vcodec.Encode(screenImage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,6 @@ func NewFbsConn(filename string, encs []Encoding) (*FbsConn, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//NewFbsReader("/Users/amitbet/vncRec/recording.rbs")
|
//NewFbsReader("/Users/amitbet/vncRec/recording.rbs")
|
||||||
initMsg, err := fbs.ReadStartSession()
|
initMsg, err := fbs.ReadStartSession()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -166,36 +165,42 @@ func NewFBSPlayHelper(r *FbsConn) *FBSPlayHelper {
|
|||||||
// return nil
|
// return nil
|
||||||
// }
|
// }
|
||||||
|
|
||||||
func (h *FBSPlayHelper) ReadFbsMessage() ServerMessage {
|
func (h *FBSPlayHelper) ReadFbsMessage(SyncWithTimestamps bool, SpeedFactor float64) (ServerMessage, error) {
|
||||||
var messageType uint8
|
var messageType uint8
|
||||||
//messages := make(map[uint8]ServerMessage)
|
//messages := make(map[uint8]ServerMessage)
|
||||||
fbs := h.Conn
|
fbs := h.Conn
|
||||||
//conn := h.Conn
|
//conn := h.Conn
|
||||||
err := binary.Read(fbs, binary.BigEndian, &messageType)
|
err := binary.Read(fbs, binary.BigEndian, &messageType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("TestServer.NewConnHandler: Error in reading FBS: ", err)
|
logger.Error("FBSConn.NewConnHandler: Error in reading FBS: ", err)
|
||||||
return nil
|
return nil, err
|
||||||
}
|
}
|
||||||
|
startTimeMsgHandling := time.Now()
|
||||||
//IClientConn{}
|
//IClientConn{}
|
||||||
//binary.Write(h.Conn, binary.BigEndian, messageType)
|
//binary.Write(h.Conn, binary.BigEndian, messageType)
|
||||||
msg := h.serverMessageMap[messageType]
|
msg := h.serverMessageMap[messageType]
|
||||||
if msg == nil {
|
if msg == nil {
|
||||||
logger.Error("TestServer.NewConnHandler: Error unknown message type: ", messageType)
|
logger.Error("FBSConn.NewConnHandler: Error unknown message type: ", messageType)
|
||||||
return nil
|
return nil, err
|
||||||
}
|
}
|
||||||
//read the actual message data
|
//read the actual message data
|
||||||
//err = binary.Read(fbs, binary.BigEndian, &msg)
|
//err = binary.Read(fbs, binary.BigEndian, &msg)
|
||||||
parsedMsg, err := msg.Read(fbs)
|
parsedMsg, err := msg.Read(fbs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("TestServer.NewConnHandler: Error in reading FBS message: ", err)
|
logger.Error("FBSConn.NewConnHandler: Error in reading FBS message: ", err)
|
||||||
return nil
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
timeSinceStart := int(time.Now().UnixNano()/int64(time.Millisecond)) - h.startTime
|
millisSinceStart := int(startTimeMsgHandling.UnixNano()/int64(time.Millisecond)) - h.startTime
|
||||||
timeToSleep := fbs.CurrentTimestamp() - timeSinceStart
|
adjestedTimeStamp := float64(fbs.CurrentTimestamp()) / SpeedFactor
|
||||||
if timeToSleep > 0 {
|
millisToSleep := adjestedTimeStamp - float64(millisSinceStart)
|
||||||
time.Sleep(time.Duration(timeToSleep) * time.Millisecond)
|
|
||||||
|
if millisToSleep > 0 && SyncWithTimestamps {
|
||||||
|
|
||||||
|
time.Sleep(time.Duration(millisToSleep) * time.Millisecond)
|
||||||
|
} else if millisToSleep < -450 {
|
||||||
|
logger.Errorf("rendering time is noticeably off, change speedup factor: videoTimeLine: %f, currentTime:%d, offset: %f", adjestedTimeStamp, millisSinceStart, millisToSleep)
|
||||||
}
|
}
|
||||||
|
|
||||||
return parsedMsg
|
return parsedMsg, nil
|
||||||
}
|
}
|
||||||
|
@ -154,7 +154,7 @@ func (fbs *FbsReader) ReadSegment() (*FbsSegment, error) {
|
|||||||
//read length
|
//read length
|
||||||
err := binary.Read(reader, binary.BigEndian, &bytesLen)
|
err := binary.Read(reader, binary.BigEndian, &bytesLen)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("FbsReader.ReadStartSession: read len, error reading rbs file: ", err)
|
logger.Error("FbsReader.ReadSegment: reading len, error reading rbs file: ", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,7 +164,7 @@ func (fbs *FbsReader) ReadSegment() (*FbsSegment, error) {
|
|||||||
bytes := make([]byte, paddedSize)
|
bytes := make([]byte, paddedSize)
|
||||||
_, err = reader.Read(bytes)
|
_, err = reader.Read(bytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("FbsReader.ReadSegment: read bytes, error reading rbs file: ", err)
|
logger.Error("FbsReader.ReadSegment: reading bytes, error reading rbs file: ", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,6 +149,7 @@ func (*DefaultClientSecurityHandler) Handle(c Conn) error {
|
|||||||
|
|
||||||
err := secType.Auth(c)
|
err := secType.Auth(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
logger.Error("Authentication error: ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user