mirror of
https://github.com/amitbet/vnc2video.git
synced 2025-09-09 08:39:17 +00:00
fixed tight encoding & refactored video encoders
This commit is contained in:
@@ -302,6 +302,7 @@ func (*DefaultClientMessageHandler) Handle(c Conn) error {
|
|||||||
canvas.RemoveCursor()
|
canvas.RemoveCursor()
|
||||||
parsedMsg, err := msg.Read(c)
|
parsedMsg, err := msg.Read(c)
|
||||||
canvas.PaintCursor()
|
canvas.PaintCursor()
|
||||||
|
//canvas.SwapBuffers()
|
||||||
logger.Debugf("============== End Message: type=%d ==============", messageType)
|
logger.Debugf("============== End Message: type=%d ==============", messageType)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@@ -11,8 +11,9 @@ import (
|
|||||||
|
|
||||||
type VP8ImageEncoder struct {
|
type VP8ImageEncoder struct {
|
||||||
cmd *exec.Cmd
|
cmd *exec.Cmd
|
||||||
binaryPath string
|
FFMpegBinPath string
|
||||||
input io.WriteCloser
|
input io.WriteCloser
|
||||||
|
closed bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (enc *VP8ImageEncoder) Init(videoFileName string) {
|
func (enc *VP8ImageEncoder) Init(videoFileName string) {
|
||||||
@@ -28,6 +29,10 @@ func (enc *VP8ImageEncoder) Init(videoFileName string) {
|
|||||||
"-vsync", "2",
|
"-vsync", "2",
|
||||||
"-r", "5",
|
"-r", "5",
|
||||||
"-probesize", "10000000",
|
"-probesize", "10000000",
|
||||||
|
"-an", //no audio
|
||||||
|
//"-vsync", "2",
|
||||||
|
///"-probesize", "10000000",
|
||||||
|
"-y",
|
||||||
//"-i", "pipe:0",
|
//"-i", "pipe:0",
|
||||||
"-i", "-",
|
"-i", "-",
|
||||||
|
|
||||||
@@ -53,6 +58,7 @@ func (enc *VP8ImageEncoder) Init(videoFileName string) {
|
|||||||
"-g", "180",
|
"-g", "180",
|
||||||
"-keyint_min", "180",
|
"-keyint_min", "180",
|
||||||
"-rc_lookahead", "20",
|
"-rc_lookahead", "20",
|
||||||
|
//"-crf", "34",
|
||||||
//"-profile", "0",
|
//"-profile", "0",
|
||||||
"-qmax", "51",
|
"-qmax", "51",
|
||||||
"-qmin", "3",
|
"-qmin", "3",
|
||||||
@@ -74,12 +80,12 @@ func (enc *VP8ImageEncoder) Init(videoFileName string) {
|
|||||||
}
|
}
|
||||||
enc.cmd = cmd
|
enc.cmd = cmd
|
||||||
}
|
}
|
||||||
func (enc *VP8ImageEncoder) Run(encoderFilePath string, videoFileName string) {
|
func (enc *VP8ImageEncoder) Run(videoFileName string) {
|
||||||
if _, err := os.Stat(encoderFilePath); os.IsNotExist(err) {
|
if _, err := os.Stat(enc.FFMpegBinPath); os.IsNotExist(err) {
|
||||||
logger.Error("encoder file doesn't exist in path:", encoderFilePath)
|
logger.Error("encoder file doesn't exist in path:", enc.FFMpegBinPath)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
enc.binaryPath = encoderFilePath
|
|
||||||
enc.Init(videoFileName)
|
enc.Init(videoFileName)
|
||||||
logger.Debugf("launching binary: %v", enc.cmd)
|
logger.Debugf("launching binary: %v", enc.cmd)
|
||||||
err := enc.cmd.Run()
|
err := enc.cmd.Run()
|
||||||
@@ -88,6 +94,10 @@ func (enc *VP8ImageEncoder) Run(encoderFilePath string, videoFileName string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (enc *VP8ImageEncoder) Encode(img image.Image) {
|
func (enc *VP8ImageEncoder) Encode(img image.Image) {
|
||||||
|
if enc.input == nil || enc.closed {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
err := encodePPM(enc.input, img)
|
err := encodePPM(enc.input, img)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("error while encoding image:", err)
|
logger.Error("error while encoding image:", err)
|
||||||
@@ -95,5 +105,5 @@ func (enc *VP8ImageEncoder) Encode(img image.Image) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (enc *VP8ImageEncoder) Close() {
|
func (enc *VP8ImageEncoder) Close() {
|
||||||
|
enc.closed = true
|
||||||
}
|
}
|
||||||
|
@@ -11,7 +11,7 @@ import (
|
|||||||
|
|
||||||
type DV9ImageEncoder struct {
|
type DV9ImageEncoder struct {
|
||||||
cmd *exec.Cmd
|
cmd *exec.Cmd
|
||||||
binaryPath string
|
FFMpegBinPath string
|
||||||
input io.WriteCloser
|
input io.WriteCloser
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,12 +67,12 @@ func (enc *DV9ImageEncoder) Init(videoFileName string) {
|
|||||||
}
|
}
|
||||||
enc.cmd = cmd
|
enc.cmd = cmd
|
||||||
}
|
}
|
||||||
func (enc *DV9ImageEncoder) Run(encoderFilePath string, videoFileName string) {
|
func (enc *DV9ImageEncoder) Run(videoFileName string) {
|
||||||
if _, err := os.Stat(encoderFilePath); os.IsNotExist(err) {
|
if _, err := os.Stat(enc.FFMpegBinPath); os.IsNotExist(err) {
|
||||||
logger.Error("encoder file doesn't exist in path:", encoderFilePath)
|
logger.Error("encoder file doesn't exist in path:", enc.FFMpegBinPath)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
enc.binaryPath = encoderFilePath
|
|
||||||
enc.Init(videoFileName)
|
enc.Init(videoFileName)
|
||||||
logger.Debugf("launching binary: %v", enc.cmd)
|
logger.Debugf("launching binary: %v", enc.cmd)
|
||||||
err := enc.cmd.Run()
|
err := enc.cmd.Run()
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
package encoders
|
package encoders
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"image"
|
"image"
|
||||||
"image/color"
|
"image/color"
|
||||||
@@ -47,43 +48,29 @@ func encodePPMforRGBA(w io.Writer, img *image.RGBA) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// write the bitmap
|
|
||||||
//colModel := color.RGBAModel
|
|
||||||
if convImage == nil {
|
if convImage == nil {
|
||||||
convImage = make([]uint8, size.Dy()*size.Dx()*3)
|
convImage = make([]uint8, size.Dy()*size.Dx()*3)
|
||||||
}
|
}
|
||||||
|
|
||||||
//img1 := (img.(*vnc2video.VncCanvas).Image).(*image.RGBA)
|
|
||||||
rowCount := 0
|
rowCount := 0
|
||||||
for i := 0; i < len(img.Pix); i++ {
|
for i := 0; i < len(img.Pix); i++ {
|
||||||
if (i % 4) != 3 {
|
if (i % 4) != 3 {
|
||||||
//logger.Debug("pix: ", i)
|
|
||||||
convImage[rowCount] = img.Pix[i]
|
convImage[rowCount] = img.Pix[i]
|
||||||
rowCount++
|
rowCount++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// for y := size.Min.Y; y < size.Max.Y; y++ {
|
|
||||||
// i := 0
|
|
||||||
// for x := size.Min.X; x < size.Max.X; x++ {
|
|
||||||
|
|
||||||
// color := (img.At(x, y)).(color.RGBA)
|
|
||||||
// row[i] = color.R
|
|
||||||
// row[i+1] = color.G
|
|
||||||
// row[i+2] = color.B
|
|
||||||
// i += 3
|
|
||||||
// }
|
|
||||||
|
|
||||||
if _, err := w.Write(convImage); err != nil {
|
if _, err := w.Write(convImage); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// if _, err := w.Write(img.Pix); err != nil {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func encodePPM(w io.Writer, img image.Image) error {
|
func encodePPM(w io.Writer, img image.Image) error {
|
||||||
|
if img == nil {
|
||||||
|
return errors.New("nil image")
|
||||||
|
}
|
||||||
img1, isRGBImage := img.(*vnc2video.RGBImage)
|
img1, isRGBImage := img.(*vnc2video.RGBImage)
|
||||||
img2, isRGBA := img.(*image.RGBA)
|
img2, isRGBA := img.(*image.RGBA)
|
||||||
if isRGBImage {
|
if isRGBImage {
|
||||||
@@ -103,40 +90,9 @@ func encodePPMforRGBImage(w io.Writer, img *vnc2video.RGBImage) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// write the bitmap
|
|
||||||
//colModel := color.RGBAModel
|
|
||||||
// // if convImage == nil {
|
|
||||||
// // convImage = make([]uint8, size.Dy()*size.Dx()*3)
|
|
||||||
// // }
|
|
||||||
|
|
||||||
// // img1 := (img.(*vnc2video.VncCanvas).Image).(*image.RGBA)
|
|
||||||
// // rowCount := 0
|
|
||||||
// // for i := 0; i < len(img1.Pix); i++ {
|
|
||||||
// // if (i % 4) != 3 {
|
|
||||||
// // //logger.Debug("pix: ", i)
|
|
||||||
// // convImage[rowCount] = img1.Pix[i]
|
|
||||||
// // rowCount++
|
|
||||||
// // }
|
|
||||||
// // }
|
|
||||||
|
|
||||||
// for y := size.Min.Y; y < size.Max.Y; y++ {
|
|
||||||
// i := 0
|
|
||||||
// for x := size.Min.X; x < size.Max.X; x++ {
|
|
||||||
|
|
||||||
// color := (img.At(x, y)).(color.RGBA)
|
|
||||||
// row[i] = color.R
|
|
||||||
// row[i+1] = color.G
|
|
||||||
// row[i+2] = color.B
|
|
||||||
// i += 3
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // if _, err := w.Write(convImage); err != nil {
|
|
||||||
// // return err
|
|
||||||
// // }
|
|
||||||
if _, err := w.Write(img.Pix); err != nil {
|
if _, err := w.Write(img.Pix); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// }
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -14,6 +14,7 @@ type MJPegImageEncoder struct {
|
|||||||
avWriter mjpeg.AviWriter
|
avWriter mjpeg.AviWriter
|
||||||
Quality int
|
Quality int
|
||||||
Framerate int32
|
Framerate int32
|
||||||
|
closed bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (enc *MJPegImageEncoder) Init(videoFileName string) {
|
func (enc *MJPegImageEncoder) Init(videoFileName string) {
|
||||||
@@ -35,6 +36,10 @@ func (enc *MJPegImageEncoder) Run(videoFileName string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (enc *MJPegImageEncoder) Encode(img image.Image) {
|
func (enc *MJPegImageEncoder) Encode(img image.Image) {
|
||||||
|
if enc.closed {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
buf := &bytes.Buffer{}
|
buf := &bytes.Buffer{}
|
||||||
jOpts := &jpeg.Options{Quality: enc.Quality}
|
jOpts := &jpeg.Options{Quality: enc.Quality}
|
||||||
if enc.Quality <= 0 {
|
if enc.Quality <= 0 {
|
||||||
@@ -55,6 +60,8 @@ func (enc *MJPegImageEncoder) Encode(img image.Image) {
|
|||||||
|
|
||||||
func (enc *MJPegImageEncoder) Close() {
|
func (enc *MJPegImageEncoder) Close() {
|
||||||
err := enc.avWriter.Close()
|
err := enc.avWriter.Close()
|
||||||
|
|
||||||
|
enc.closed = true
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("Error while closing mjpeg: ", err)
|
logger.Error("Error while closing mjpeg: ", err)
|
||||||
}
|
}
|
||||||
|
@@ -11,9 +11,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type X264ImageEncoder struct {
|
type X264ImageEncoder struct {
|
||||||
|
FFMpegBinPath string
|
||||||
cmd *exec.Cmd
|
cmd *exec.Cmd
|
||||||
binaryPath string
|
|
||||||
input io.WriteCloser
|
input io.WriteCloser
|
||||||
|
closed bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (enc *X264ImageEncoder) Init(videoFileName string) {
|
func (enc *X264ImageEncoder) Init(videoFileName string) {
|
||||||
@@ -22,37 +23,43 @@ func (enc *X264ImageEncoder) Init(videoFileName string) {
|
|||||||
videoFileName = videoFileName + fileExt
|
videoFileName = videoFileName + fileExt
|
||||||
}
|
}
|
||||||
//binary := "./ffmpeg"
|
//binary := "./ffmpeg"
|
||||||
cmd := exec.Command(enc.binaryPath,
|
cmd := exec.Command(enc.FFMpegBinPath,
|
||||||
"-f", "image2pipe",
|
"-f", "image2pipe",
|
||||||
"-vcodec", "ppm",
|
"-vcodec", "ppm",
|
||||||
//"-r", strconv.Itoa(framerate),
|
//"-r", strconv.Itoa(framerate),
|
||||||
"-r", "5",
|
"-r", "12",
|
||||||
|
|
||||||
//"-re",
|
//"-re",
|
||||||
//"-i", "pipe:0",
|
//"-i", "pipe:0",
|
||||||
|
"-an", //no audio
|
||||||
"-vsync", "2",
|
//"-vsync", "2",
|
||||||
///"-probesize", "10000000",
|
///"-probesize", "10000000",
|
||||||
"-y",
|
"-y",
|
||||||
|
|
||||||
"-i", "-",
|
"-i", "-",
|
||||||
|
//"–s", "640×360",
|
||||||
"-vcodec", "libx264", //"libvpx",//"libvpx-vp9"//"libx264"
|
"-vcodec", "libx264", //"libvpx",//"libvpx-vp9"//"libx264"
|
||||||
"-b:v", "0.5M",
|
//"-b:v", "0.33M",
|
||||||
"-threads", "8",
|
"-threads", "8",
|
||||||
|
///"-coder", "1",
|
||||||
|
///"-bf", "0",
|
||||||
|
///"-me_method", "hex",
|
||||||
//"-speed", "0",
|
//"-speed", "0",
|
||||||
//"-lossless", "1", //for vpx
|
//"-lossless", "1", //for vpx
|
||||||
// "-an", "-f", "webm",
|
// "-an", "-f", "webm",
|
||||||
"-preset", "veryfast",
|
"-preset", "veryfast",
|
||||||
"-tune", "animation",
|
//"-tune", "animation",
|
||||||
"-maxrate", "0.6M",
|
"-maxrate", "0.5M",
|
||||||
"-bufsize", "50M",
|
"-bufsize", "50M",
|
||||||
"-g", "120",
|
"-g", "250",
|
||||||
|
|
||||||
//"-crf", "0", //for lossless encoding!!!!
|
//"-crf", "0", //for lossless encoding!!!!
|
||||||
|
|
||||||
//"-rc_lookahead", "16",
|
//"-rc_lookahead", "16",
|
||||||
//"-profile", "0",
|
//"-profile", "0",
|
||||||
//"-crf", "18",
|
"-crf", "34",
|
||||||
"-qmax", "51",
|
//"-qmax", "51",
|
||||||
"-qmin", "7",
|
//"-qmin", "7",
|
||||||
//"-slices", "4",
|
//"-slices", "4",
|
||||||
//"-vb", "2M",
|
//"-vb", "2M",
|
||||||
|
|
||||||
@@ -71,13 +78,12 @@ func (enc *X264ImageEncoder) Init(videoFileName string) {
|
|||||||
}
|
}
|
||||||
enc.cmd = cmd
|
enc.cmd = cmd
|
||||||
}
|
}
|
||||||
func (enc *X264ImageEncoder) Run(encoderFilePath string, videoFileName string) error {
|
func (enc *X264ImageEncoder) Run(videoFileName string) error {
|
||||||
if _, err := os.Stat(encoderFilePath); os.IsNotExist(err) {
|
if _, err := os.Stat(enc.FFMpegBinPath); os.IsNotExist(err) {
|
||||||
logger.Error("encoder file doesn't exist in path:", encoderFilePath)
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
enc.binaryPath = encoderFilePath
|
|
||||||
enc.Init(videoFileName)
|
enc.Init(videoFileName)
|
||||||
logger.Debugf("launching binary: %v", enc.cmd)
|
logger.Debugf("launching binary: %v", enc.cmd)
|
||||||
err := enc.cmd.Run()
|
err := enc.cmd.Run()
|
||||||
@@ -88,11 +94,17 @@ func (enc *X264ImageEncoder) Run(encoderFilePath string, videoFileName string) e
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (enc *X264ImageEncoder) Encode(img image.Image) {
|
func (enc *X264ImageEncoder) Encode(img image.Image) {
|
||||||
|
if enc.input == nil || enc.closed {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
err := encodePPM(enc.input, img)
|
err := encodePPM(enc.input, img)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("error while encoding image:", err)
|
logger.Error("error while encoding image:", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (enc *X264ImageEncoder) Close() {
|
|
||||||
|
|
||||||
|
func (enc *X264ImageEncoder) Close() {
|
||||||
|
enc.closed = true
|
||||||
|
//enc.cmd.Process.Kill()
|
||||||
}
|
}
|
||||||
|
@@ -73,6 +73,7 @@ func (enc *CursorPseudoEncoding) Read(c Conn, rect *Rectangle) error {
|
|||||||
}
|
}
|
||||||
canvas.CursorOffset = &image.Point{int(rect.X), int(rect.Y)}
|
canvas.CursorOffset = &image.Point{int(rect.X), int(rect.Y)}
|
||||||
canvas.Cursor = cursorImg
|
canvas.Cursor = cursorImg
|
||||||
|
canvas.CursorBackup = image.NewRGBA(cursorImg.Bounds())
|
||||||
canvas.CursorMask = cursorMask
|
canvas.CursorMask = cursorMask
|
||||||
/*
|
/*
|
||||||
rectStride := 4 * rect.Width
|
rectStride := 4 * rect.Width
|
||||||
|
@@ -146,7 +146,7 @@ func (enc *TightEncoding) resetDecoders(compControl uint8) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (enc *TightEncoding) SetTargetImage(img draw.Image) {
|
func (enc *TightEncoding) SetTargetImage(img draw.Image) {
|
||||||
enc.Image = img.(*VncCanvas).Image
|
enc.Image = img
|
||||||
}
|
}
|
||||||
|
|
||||||
var counter int = 0
|
var counter int = 0
|
||||||
@@ -295,7 +295,7 @@ func (enc *TightEncoding) handleTightFilters(compCtl uint8, pixelFmt *PixelForma
|
|||||||
if len(palette) == 2 {
|
if len(palette) == 2 {
|
||||||
dataLength = int(rect.Height) * ((int(rect.Width) + 7) / 8)
|
dataLength = int(rect.Height) * ((int(rect.Width) + 7) / 8)
|
||||||
} else {
|
} else {
|
||||||
dataLength = int(rect.Width * rect.Height)
|
dataLength = int(rect.Width) * int(rect.Height)
|
||||||
}
|
}
|
||||||
tightBytes, err := enc.ReadTightData(dataLength, r, int(decoderId))
|
tightBytes, err := enc.ReadTightData(dataLength, r, int(decoderId))
|
||||||
//logger.Tracef("got tightBytes: %v", tightBytes)
|
//logger.Tracef("got tightBytes: %v", tightBytes)
|
||||||
@@ -438,50 +438,50 @@ func (enc *TightEncoding) decodeGradData(rect *Rectangle, buffer []byte) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (enc *TightEncoding) decodeGradientData(rect *Rectangle, buf []byte) {
|
// func (enc *TightEncoding) decodeGradientData(rect *Rectangle, buf []byte) {
|
||||||
logger.Tracef("putting gradient on image: %v", enc.Image.Bounds())
|
// logger.Tracef("putting gradient on image: %v", enc.Image.Bounds())
|
||||||
var dx, dy, c int
|
// var dx, dy, c int
|
||||||
prevRow := make([]byte, rect.Width*3) //new byte[w * 3];
|
// prevRow := make([]byte, rect.Width*3) //new byte[w * 3];
|
||||||
thisRow := make([]byte, rect.Width*3) //new byte[w * 3];
|
// thisRow := make([]byte, rect.Width*3) //new byte[w * 3];
|
||||||
pix := make([]byte, 3)
|
// pix := make([]byte, 3)
|
||||||
est := make([]int, 3)
|
// est := make([]int, 3)
|
||||||
|
|
||||||
dst := (enc.Image).(*image.RGBA) // enc.Image.(*image.RGBA)
|
// dst := (enc.Image) // enc.Image.(*image.RGBA)
|
||||||
//offset := int(rect.Y)*dst.Bounds().Max.X + int(rect.X)
|
// //offset := int(rect.Y)*dst.Bounds().Max.X + int(rect.X)
|
||||||
|
|
||||||
for dy = 0; dy < int(rect.Height); dy++ {
|
// for dy = 0; dy < int(rect.Height); dy++ {
|
||||||
//offset := dst.PixOffset(x, y)
|
// //offset := dst.PixOffset(x, y)
|
||||||
/* First pixel in a row */
|
// /* First pixel in a row */
|
||||||
for c = 0; c < 3; c++ {
|
// for c = 0; c < 3; c++ {
|
||||||
pix[c] = byte(prevRow[c] + buf[dy*int(rect.Width)*3+c])
|
// pix[c] = byte(prevRow[c] + buf[dy*int(rect.Width)*3+c])
|
||||||
thisRow[c] = pix[c]
|
// thisRow[c] = pix[c]
|
||||||
}
|
// }
|
||||||
//logger.Tracef("putting pixel:%d,%d,%d at offset: %d, pixArrayLen= %v, rect=x:%d,y:%d,w:%d,h:%d, Yposition=%d", pix[0], pix[1], pix[2], offset, len(dst.Pix), rect.X, rect.Y, rect.Width, rect.Height, dy)
|
// //logger.Tracef("putting pixel:%d,%d,%d at offset: %d, pixArrayLen= %v, rect=x:%d,y:%d,w:%d,h:%d, Yposition=%d", pix[0], pix[1], pix[2], offset, len(dst.Pix), rect.X, rect.Y, rect.Width, rect.Height, dy)
|
||||||
myColor := color.RGBA{R: (pix[0]), G: (pix[1]), B: (pix[2]), A: 1}
|
// myColor := color.RGBA{R: (pix[0]), G: (pix[1]), B: (pix[2]), A: 1}
|
||||||
dst.SetRGBA(int(rect.X), dy+int(rect.Y), myColor)
|
// dst.Set(int(rect.X), dy+int(rect.Y), myColor)
|
||||||
|
|
||||||
/* Remaining pixels of a row */
|
// /* Remaining pixels of a row */
|
||||||
for dx = 1; dx < int(rect.Width); dx++ {
|
// for dx = 1; dx < int(rect.Width); dx++ {
|
||||||
for c = 0; c < 3; c++ {
|
// for c = 0; c < 3; c++ {
|
||||||
est[c] = int((prevRow[dx*3+c] & 0xFF) + (pix[c] & 0xFF) - (prevRow[(dx-1)*3+c] & 0xFF))
|
// est[c] = int((prevRow[dx*3+c] & 0xFF) + (pix[c] & 0xFF) - (prevRow[(dx-1)*3+c] & 0xFF))
|
||||||
if est[c] > 0xFF {
|
// if est[c] > 0xFF {
|
||||||
est[c] = 0xFF
|
// est[c] = 0xFF
|
||||||
} else if est[c] < 0x00 {
|
// } else if est[c] < 0x00 {
|
||||||
est[c] = 0x00
|
// est[c] = 0x00
|
||||||
}
|
// }
|
||||||
pix[c] = (byte)(byte(est[c]) + buf[(dy*int(rect.Width)+dx)*3+c])
|
// pix[c] = (byte)(byte(est[c]) + buf[(dy*int(rect.Width)+dx)*3+c])
|
||||||
thisRow[dx*3+c] = pix[c]
|
// thisRow[dx*3+c] = pix[c]
|
||||||
}
|
// }
|
||||||
//logger.Tracef("putting pixel:%d,%d,%d at offset: %d, pixArrayLen= %v, rect=x:%d,y:%d,w:%d,h:%d, Yposition=%d", pix[0], pix[1], pix[2], offset, len(dst.Pix), x, y, w, h, dy)
|
// //logger.Tracef("putting pixel:%d,%d,%d at offset: %d, pixArrayLen= %v, rect=x:%d,y:%d,w:%d,h:%d, Yposition=%d", pix[0], pix[1], pix[2], offset, len(dst.Pix), x, y, w, h, dy)
|
||||||
myColor := color.RGBA{R: pix[0], G: (pix[1]), B: (pix[2]), A: 1}
|
// myColor := color.RGBA{R: pix[0], G: (pix[1]), B: (pix[2]), A: 1}
|
||||||
dst.SetRGBA(dx+int(rect.X), dy+int(rect.Y), myColor)
|
// dst.Set(dx+int(rect.X), dy+int(rect.Y), myColor)
|
||||||
|
|
||||||
}
|
// }
|
||||||
|
|
||||||
copy(prevRow, thisRow)
|
// copy(prevRow, thisRow)
|
||||||
}
|
// }
|
||||||
enc.Image = dst
|
// enc.Image = dst
|
||||||
}
|
// }
|
||||||
|
|
||||||
func ReadBytes(count int, r io.Reader) ([]byte, error) {
|
func ReadBytes(count int, r io.Reader) ([]byte, error) {
|
||||||
buff := make([]byte, count)
|
buff := make([]byte, count)
|
||||||
|
@@ -11,6 +11,9 @@ import (
|
|||||||
|
|
||||||
type VncCanvas struct {
|
type VncCanvas struct {
|
||||||
draw.Image
|
draw.Image
|
||||||
|
//DisplayBuff draw.Image
|
||||||
|
//WriteBuff draw.Image
|
||||||
|
imageBuffs [2]draw.Image
|
||||||
Cursor draw.Image
|
Cursor draw.Image
|
||||||
CursorMask [][]bool
|
CursorMask [][]bool
|
||||||
CursorBackup draw.Image
|
CursorBackup draw.Image
|
||||||
@@ -20,12 +23,16 @@ type VncCanvas struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewVncCanvas(width, height int) *VncCanvas {
|
func NewVncCanvas(width, height int) *VncCanvas {
|
||||||
img := NewRGBImage(image.Rect(0, 0, width, height))
|
//dispImg := NewRGBImage(image.Rect(0, 0, width, height))
|
||||||
|
writeImg := NewRGBImage(image.Rect(0, 0, width, height))
|
||||||
canvas := VncCanvas{
|
canvas := VncCanvas{
|
||||||
Image: img,
|
Image: writeImg,
|
||||||
|
//DisplayBuff: dispImg,
|
||||||
|
//WriteBuff: writeImg,
|
||||||
}
|
}
|
||||||
return &canvas
|
return &canvas
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *VncCanvas) RemoveCursor() image.Image {
|
func (c *VncCanvas) RemoveCursor() image.Image {
|
||||||
if c.Cursor == nil || c.CursorLocation == nil {
|
if c.Cursor == nil || c.CursorLocation == nil {
|
||||||
return c.Image
|
return c.Image
|
||||||
@@ -55,6 +62,13 @@ func (c *VncCanvas) RemoveCursor() image.Image {
|
|||||||
return img
|
return img
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// func (c *VncCanvas) SwapBuffers() {
|
||||||
|
// swapSpace := c.DisplayBuff
|
||||||
|
// c.DisplayBuff = c.WriteBuff
|
||||||
|
// c.WriteBuff = swapSpace
|
||||||
|
// c.Image = c.WriteBuff
|
||||||
|
// }
|
||||||
|
|
||||||
func (c *VncCanvas) PaintCursor() image.Image {
|
func (c *VncCanvas) PaintCursor() image.Image {
|
||||||
if c.Cursor == nil || c.CursorLocation == nil {
|
if c.Cursor == nil || c.CursorLocation == nil {
|
||||||
return c.Image
|
return c.Image
|
||||||
|
@@ -64,15 +64,15 @@ func main() {
|
|||||||
// fmt.Println(err)
|
// fmt.Println(err)
|
||||||
// os.Exit(1)
|
// os.Exit(1)
|
||||||
// }
|
// }
|
||||||
//vcodec := &encoders.MJPegImageEncoder{Quality: 60, Framerate: 4}
|
vcodec := &encoders.MJPegImageEncoder{Quality: 60, Framerate: 12}
|
||||||
vcodec := &encoders.X264ImageEncoder{}
|
//vcodec := &encoders.X264ImageEncoder{FFMpegBinPath:"./ffmpeg"}
|
||||||
//vcodec := &encoders.VP8ImageEncoder{}
|
//vcodec := &encoders.VP8ImageEncoder{FFMpegBinPath:"./ffmpeg"}
|
||||||
//vcodec := &encoders.DV9ImageEncoder{}
|
//vcodec := &encoders.DV9ImageEncoder{FFMpegBinPath:"./ffmpeg"}
|
||||||
|
|
||||||
//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("./output.mp4")
|
||||||
//windows
|
//windows
|
||||||
///go vcodec.Run("/Users/amitbet/Dropbox/go/src/vnc2webm/example/file-reader/ffmpeg", "./output.mp4")
|
///go vcodec.Run("/Users/amitbet/Dropbox/go/src/vnc2webm/example/file-reader/ffmpeg", "./output.mp4")
|
||||||
|
|
||||||
@@ -97,7 +97,7 @@ func main() {
|
|||||||
vnc.EncCursorPseudo,
|
vnc.EncCursorPseudo,
|
||||||
vnc.EncPointerPosPseudo,
|
vnc.EncPointerPosPseudo,
|
||||||
vnc.EncCopyRect,
|
vnc.EncCopyRect,
|
||||||
//vnc.EncTight,
|
vnc.EncTight,
|
||||||
//vnc.EncZRLE,
|
//vnc.EncZRLE,
|
||||||
//vnc.EncHextile,
|
//vnc.EncHextile,
|
||||||
//vnc.EncZlib,
|
//vnc.EncZlib,
|
||||||
@@ -107,13 +107,20 @@ func main() {
|
|||||||
//screenImage := image.NewRGBA64(rect)
|
//screenImage := image.NewRGBA64(rect)
|
||||||
// Process messages coming in on the ServerMessage channel.
|
// Process messages coming in on the ServerMessage channel.
|
||||||
|
|
||||||
// go func() {
|
go func() {
|
||||||
// for {
|
for {
|
||||||
// //logger.Debugf("encoding screen")
|
timeStart := time.Now()
|
||||||
// vcodec.Encode(screenImage)
|
|
||||||
// time.Sleep(100 * time.Millisecond)
|
vcodec.Encode(screenImage.Image)
|
||||||
// }
|
|
||||||
// }()
|
timeTarget := timeStart.Add((1000 / 12) * time.Millisecond)
|
||||||
|
timeLeft := timeTarget.Sub(time.Now())
|
||||||
|
if timeLeft > 0 {
|
||||||
|
time.Sleep(timeLeft)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
sigc := make(chan os.Signal, 1)
|
sigc := make(chan os.Signal, 1)
|
||||||
signal.Notify(sigc,
|
signal.Notify(sigc,
|
||||||
syscall.SIGHUP,
|
syscall.SIGHUP,
|
||||||
@@ -155,7 +162,7 @@ func main() {
|
|||||||
reqPerSec := float64(frameBufferReq) / secsPassed
|
reqPerSec := float64(frameBufferReq) / secsPassed
|
||||||
//counter++
|
//counter++
|
||||||
//jpeg.Encode(out, screenImage, nil)
|
//jpeg.Encode(out, screenImage, nil)
|
||||||
vcodec.Encode(screenImage.Image)
|
///vcodec.Encode(screenImage)
|
||||||
logger.Infof("reqs=%d, seconds=%f, Req Per second= %f", frameBufferReq, secsPassed, reqPerSec)
|
logger.Infof("reqs=%d, seconds=%f, Req Per second= %f", frameBufferReq, secsPassed, reqPerSec)
|
||||||
|
|
||||||
reqMsg := vnc.FramebufferUpdateRequest{Inc: 1, X: 0, Y: 0, Width: cc.Width(), Height: cc.Height()}
|
reqMsg := vnc.FramebufferUpdateRequest{Inc: 1, X: 0, Y: 0, Width: cc.Width(), Height: cc.Height()}
|
||||||
|
@@ -3,10 +3,10 @@ package main
|
|||||||
import (
|
import (
|
||||||
"image"
|
"image"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
vnc "vnc2video"
|
vnc "vnc2video"
|
||||||
"vnc2video/encoders"
|
"vnc2video/encoders"
|
||||||
"vnc2video/logger"
|
"vnc2video/logger"
|
||||||
"path/filepath"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -34,12 +34,12 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//launch video encoding process:
|
//launch video encoding process:
|
||||||
vcodec := &encoders.X264ImageEncoder{}
|
vcodec := &encoders.X264ImageEncoder{FFMpegBinPath: "./ffmpeg"}
|
||||||
//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("./ffmpeg", "./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())))
|
||||||
for _, enc := range encs {
|
for _, enc := range encs {
|
||||||
@@ -50,7 +50,6 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
msgReader := vnc.NewFBSPlayHelper(fbs)
|
msgReader := vnc.NewFBSPlayHelper(fbs)
|
||||||
|
|
||||||
//loop over all messages, feed images to video codec:
|
//loop over all messages, feed images to video codec:
|
||||||
|
@@ -151,7 +151,7 @@ func NewFBSPlayHelper(r *FbsConn) *FBSPlayHelper {
|
|||||||
// switch seg.SegmentType {
|
// switch seg.SegmentType {
|
||||||
// case SegmentFullyParsedClientMessage:
|
// case SegmentFullyParsedClientMessage:
|
||||||
// clientMsg := seg.Message.(ClientMessage)
|
// clientMsg := seg.Message.(ClientMessage)
|
||||||
// logger.Debugf("ClientUpdater.Consume:(vnc-server-bound) got ClientMessage type=%s", clientMsg.Type())
|
// logger.Tracef("ClientUpdater.Consume:(vnc-server-bound) got ClientMessage type=%s", clientMsg.Type())
|
||||||
// switch clientMsg.Type() {
|
// switch clientMsg.Type() {
|
||||||
|
|
||||||
// case FramebufferUpdateRequestMsgType:
|
// case FramebufferUpdateRequestMsgType:
|
||||||
|
Reference in New Issue
Block a user