mirror of
https://github.com/amitbet/vnc2video.git
synced 2025-08-14 02:35:48 +00:00
added video codecs, works with mjpeg & h264-ffmpeg
This commit is contained in:
parent
16f897ddfe
commit
a855abcb6c
84
encoders/dv8-enc.go
Normal file
84
encoders/dv8-enc.go
Normal file
@ -0,0 +1,84 @@
|
||||
package encoders
|
||||
|
||||
import (
|
||||
"image"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"vnc2webm/logger"
|
||||
)
|
||||
|
||||
type DV8ImageEncoder struct {
|
||||
cmd *exec.Cmd
|
||||
input io.WriteCloser
|
||||
}
|
||||
|
||||
func (enc *DV8ImageEncoder) Init(videoFileName string) {
|
||||
fileExt := ".webm"
|
||||
if !strings.HasSuffix(videoFileName, fileExt) {
|
||||
videoFileName = videoFileName + fileExt
|
||||
}
|
||||
binary := "./ffmpeg"
|
||||
cmd := exec.Command(binary,
|
||||
"-f", "image2pipe",
|
||||
"-vcodec", "ppm",
|
||||
//"-r", strconv.Itoa(framerate),
|
||||
"-r", "3",
|
||||
//"-i", "pipe:0",
|
||||
"-i", "-",
|
||||
"-vcodec", "libvpx", //"libvpx",//"libvpx-vp9"//"libx264"
|
||||
"-b:v", "2M",
|
||||
"-threads", "8",
|
||||
//"-speed", "0",
|
||||
//"-lossless", "1", //for vpx
|
||||
// "-tile-columns", "6",
|
||||
//"-frame-parallel", "1",
|
||||
// "-an", "-f", "webm",
|
||||
"-cpu-used", "-16",
|
||||
|
||||
"-preset", "ultrafast",
|
||||
"-deadline", "realtime",
|
||||
//"-cpu-used", "-5",
|
||||
"-maxrate", "2.5M",
|
||||
"-bufsize", "10M",
|
||||
"-g", "6",
|
||||
|
||||
//"-rc_lookahead", "16",
|
||||
//"-profile", "0",
|
||||
"-qmax", "51",
|
||||
"-qmin", "11",
|
||||
//"-slices", "4",
|
||||
//"-vb", "2M",
|
||||
|
||||
videoFileName,
|
||||
)
|
||||
//cmd := exec.Command("/bin/echo")
|
||||
|
||||
//io.Copy(cmd.Stdout, os.Stdout)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
|
||||
encInput, err := cmd.StdinPipe()
|
||||
enc.input = encInput
|
||||
if err != nil {
|
||||
logger.Error("can't get ffmpeg input pipe")
|
||||
}
|
||||
enc.cmd = cmd
|
||||
}
|
||||
func (enc *DV8ImageEncoder) Run() {
|
||||
logger.Debugf("launching binary: %v", enc.cmd.Args)
|
||||
err := enc.cmd.Run()
|
||||
if err != nil {
|
||||
logger.Error("error while launching ffmpeg:", err)
|
||||
}
|
||||
}
|
||||
func (enc *DV8ImageEncoder) Encode(img image.Image) {
|
||||
err := encodePPM(enc.input, img)
|
||||
if err != nil {
|
||||
logger.Error("error while encoding image:", err)
|
||||
}
|
||||
}
|
||||
func (enc *DV8ImageEncoder) Close() {
|
||||
|
||||
}
|
84
encoders/dv9-enc.go
Normal file
84
encoders/dv9-enc.go
Normal file
@ -0,0 +1,84 @@
|
||||
package encoders
|
||||
|
||||
import (
|
||||
"image"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"vnc2webm/logger"
|
||||
)
|
||||
|
||||
type DV9ImageEncoder struct {
|
||||
cmd *exec.Cmd
|
||||
input io.WriteCloser
|
||||
}
|
||||
|
||||
func (enc *DV9ImageEncoder) Init(videoFileName string) {
|
||||
fileExt := ".webm"
|
||||
if !strings.HasSuffix(videoFileName, fileExt) {
|
||||
videoFileName = videoFileName + fileExt
|
||||
}
|
||||
binary := "./ffmpeg"
|
||||
cmd := exec.Command(binary,
|
||||
"-f", "image2pipe",
|
||||
"-vcodec", "ppm",
|
||||
//"-r", strconv.Itoa(framerate),
|
||||
"-r", "3",
|
||||
//"-i", "pipe:0",
|
||||
"-i", "-",
|
||||
"-vcodec", "libvpx-vp9", //"libvpx",//"libvpx-vp9"//"libx264"
|
||||
"-b:v", "2M",
|
||||
"-threads", "8",
|
||||
//"-speed", "0",
|
||||
//"-lossless", "1", //for vpx
|
||||
// "-tile-columns", "6",
|
||||
//"-frame-parallel", "1",
|
||||
// "-an", "-f", "webm",
|
||||
"-cpu-used", "-16",
|
||||
|
||||
"-preset", "ultrafast",
|
||||
"-deadline", "realtime",
|
||||
//"-cpu-used", "-5",
|
||||
"-maxrate", "2.5M",
|
||||
"-bufsize", "10M",
|
||||
"-g", "6",
|
||||
|
||||
//"-rc_lookahead", "16",
|
||||
//"-profile", "0",
|
||||
"-qmax", "51",
|
||||
"-qmin", "11",
|
||||
//"-slices", "4",
|
||||
//"-vb", "2M",
|
||||
|
||||
videoFileName,
|
||||
)
|
||||
//cmd := exec.Command("/bin/echo")
|
||||
|
||||
//io.Copy(cmd.Stdout, os.Stdout)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
|
||||
encInput, err := cmd.StdinPipe()
|
||||
enc.input = encInput
|
||||
if err != nil {
|
||||
logger.Error("can't get ffmpeg input pipe")
|
||||
}
|
||||
enc.cmd = cmd
|
||||
}
|
||||
func (enc *DV9ImageEncoder) Run() {
|
||||
logger.Debugf("launching binary: %v", enc.cmd.Args)
|
||||
err := enc.cmd.Run()
|
||||
if err != nil {
|
||||
logger.Error("error while launching ffmpeg:", err)
|
||||
}
|
||||
}
|
||||
func (enc *DV9ImageEncoder) Encode(img image.Image) {
|
||||
err := encodePPM(enc.input, img)
|
||||
if err != nil {
|
||||
logger.Error("error while encoding image:", err)
|
||||
}
|
||||
}
|
||||
func (enc *DV9ImageEncoder) Close() {
|
||||
|
||||
}
|
43
encoders/image-enc.go
Normal file
43
encoders/image-enc.go
Normal file
@ -0,0 +1,43 @@
|
||||
package encoders
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"image"
|
||||
"image/color"
|
||||
"io"
|
||||
)
|
||||
|
||||
func encodePPM(w io.Writer, img image.Image) error {
|
||||
maxvalue := 255
|
||||
size := img.Bounds()
|
||||
// write ppm header
|
||||
_, err := fmt.Fprintf(w, "P6\n%d %d\n%d\n", size.Dx(), size.Dy(), maxvalue)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// write the bitmap
|
||||
colModel := color.RGBAModel
|
||||
row := make([]uint8, size.Dx()*3)
|
||||
for y := size.Min.Y; y < size.Max.Y; y++ {
|
||||
i := 0
|
||||
for x := size.Min.X; x < size.Max.X; x++ {
|
||||
color := colModel.Convert(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(row); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ImageEncoder interface {
|
||||
Init(string)
|
||||
Run()
|
||||
Encode(image.Image)
|
||||
Close()
|
||||
}
|
56
encoders/mjpeg-enc.go
Normal file
56
encoders/mjpeg-enc.go
Normal file
@ -0,0 +1,56 @@
|
||||
package encoders
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"image"
|
||||
"image/jpeg"
|
||||
"strings"
|
||||
"vnc2webm/logger"
|
||||
|
||||
"github.com/icza/mjpeg"
|
||||
)
|
||||
|
||||
type MJPegImageEncoder struct {
|
||||
avWriter mjpeg.AviWriter
|
||||
Quality int
|
||||
Framerate int32
|
||||
}
|
||||
|
||||
func (enc *MJPegImageEncoder) Init(videoFileName string) {
|
||||
fileExt := ".avi"
|
||||
if !strings.HasSuffix(videoFileName, fileExt) {
|
||||
videoFileName = videoFileName + fileExt
|
||||
}
|
||||
if enc.Framerate <= 0 {
|
||||
enc.Framerate = 5
|
||||
}
|
||||
avWriter, err := mjpeg.New(videoFileName, 1024, 768, enc.Framerate)
|
||||
if err != nil {
|
||||
logger.Error("Error during mjpeg init: ", err)
|
||||
}
|
||||
enc.avWriter = avWriter
|
||||
}
|
||||
func (enc *MJPegImageEncoder) Run() {
|
||||
}
|
||||
func (enc *MJPegImageEncoder) Encode(img image.Image) {
|
||||
buf := &bytes.Buffer{}
|
||||
jOpts := &jpeg.Options{Quality: enc.Quality}
|
||||
if enc.Quality <= 0 {
|
||||
jOpts = nil
|
||||
}
|
||||
err := jpeg.Encode(buf, img, jOpts)
|
||||
if err != nil {
|
||||
logger.Error("Error while creating jpeg: ", err)
|
||||
}
|
||||
err = enc.avWriter.AddFrame(buf.Bytes())
|
||||
if err != nil {
|
||||
logger.Error("Error while adding frame to mjpeg: ", err)
|
||||
}
|
||||
|
||||
}
|
||||
func (enc *MJPegImageEncoder) Close() {
|
||||
err := enc.avWriter.Close()
|
||||
if err != nil {
|
||||
logger.Error("Error while closing mjpeg: ", err)
|
||||
}
|
||||
}
|
92
encoders/x264-enc.go
Normal file
92
encoders/x264-enc.go
Normal file
@ -0,0 +1,92 @@
|
||||
package encoders
|
||||
|
||||
import (
|
||||
"image"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"vnc2webm/logger"
|
||||
)
|
||||
|
||||
type X264ImageEncoder struct {
|
||||
cmd *exec.Cmd
|
||||
binaryPath string
|
||||
input io.WriteCloser
|
||||
}
|
||||
|
||||
func (enc *X264ImageEncoder) Init(videoFileName string) {
|
||||
fileExt := ".mp4"
|
||||
if !strings.HasSuffix(videoFileName, fileExt) {
|
||||
videoFileName = videoFileName + fileExt
|
||||
}
|
||||
//binary := "./ffmpeg"
|
||||
cmd := exec.Command(enc.binaryPath,
|
||||
"-f", "image2pipe",
|
||||
"-vcodec", "ppm",
|
||||
//"-r", strconv.Itoa(framerate),
|
||||
"-r", "4",
|
||||
//"-i", "pipe:0",
|
||||
"-i", "-",
|
||||
"-vcodec", "libx264", //"libvpx",//"libvpx-vp9"//"libx264"
|
||||
"-b:v", "2M",
|
||||
"-threads", "8",
|
||||
//"-speed", "0",
|
||||
//"-lossless", "1", //for vpx
|
||||
// "-tile-columns", "6",
|
||||
//"-frame-parallel", "1",
|
||||
// "-an", "-f", "webm",
|
||||
"-cpu-used", "-16",
|
||||
|
||||
"-preset", "ultrafast",
|
||||
"-deadline", "realtime",
|
||||
//"-cpu-used", "-5",
|
||||
"-maxrate", "2.5M",
|
||||
"-bufsize", "10M",
|
||||
"-g", "6",
|
||||
|
||||
//"-rc_lookahead", "16",
|
||||
//"-profile", "0",
|
||||
"-qmax", "51",
|
||||
"-qmin", "11",
|
||||
//"-slices", "4",
|
||||
//"-vb", "2M",
|
||||
|
||||
videoFileName,
|
||||
)
|
||||
//cmd := exec.Command("/bin/echo")
|
||||
|
||||
//io.Copy(cmd.Stdout, os.Stdout)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
|
||||
encInput, err := cmd.StdinPipe()
|
||||
enc.input = encInput
|
||||
if err != nil {
|
||||
logger.Error("can't get ffmpeg input pipe")
|
||||
}
|
||||
enc.cmd = cmd
|
||||
}
|
||||
func (enc *X264ImageEncoder) Run(encoderFilePath string, videoFileName string) {
|
||||
if _, err := os.Stat(encoderFilePath); os.IsNotExist(err) {
|
||||
logger.Error("encoder file doesn't exist in path:", encoderFilePath)
|
||||
return
|
||||
}
|
||||
|
||||
enc.binaryPath = encoderFilePath
|
||||
enc.Init(videoFileName)
|
||||
logger.Infof("launching binary: %v", enc.cmd)
|
||||
err := enc.cmd.Run()
|
||||
if err != nil {
|
||||
logger.Errorf("error while launching ffmpeg: %v\n err: %v", enc.cmd.Args, err)
|
||||
}
|
||||
}
|
||||
func (enc *X264ImageEncoder) Encode(img image.Image) {
|
||||
err := encodePPM(enc.input, img)
|
||||
if err != nil {
|
||||
logger.Error("error while encoding image:", err)
|
||||
}
|
||||
}
|
||||
func (enc *X264ImageEncoder) Close() {
|
||||
|
||||
}
|
@ -3,6 +3,7 @@ package vnc2webm
|
||||
import (
|
||||
"bytes"
|
||||
"image"
|
||||
"image/draw"
|
||||
"sync"
|
||||
)
|
||||
|
||||
@ -78,6 +79,10 @@ var bPool = sync.Pool{
|
||||
},
|
||||
}
|
||||
|
||||
type Renderer interface {
|
||||
SetTargetImage(draw.Image)
|
||||
}
|
||||
|
||||
// Encoding represents interface for vnc encoding
|
||||
type Encoding interface {
|
||||
Type() EncodingType
|
||||
|
@ -12,8 +12,6 @@ import (
|
||||
"image/jpeg"
|
||||
"io"
|
||||
"math"
|
||||
"os"
|
||||
"strconv"
|
||||
"vnc2webm/logger"
|
||||
)
|
||||
|
||||
@ -79,9 +77,9 @@ func getTightColor(c io.Reader, pf *PixelFormat) (*color.RGBA64, error) {
|
||||
return nil, err
|
||||
}
|
||||
rgb := color.RGBA64{
|
||||
R: uint16(tbytes[0]), //byte(col >> pf.RedShift & int32(pf.RedMax)),
|
||||
G: uint16(tbytes[1]), //byte(col >> pf.GreenShift & int32(pf.GreenMax)),
|
||||
B: uint16(tbytes[2]), //byte(col >> pf.BlueShift & int32(pf.BlueMax)),
|
||||
R: uint16(tbytes[0]),
|
||||
G: uint16(tbytes[1]),
|
||||
B: uint16(tbytes[2]),
|
||||
A: uint16(1),
|
||||
}
|
||||
return &rgb, nil
|
||||
@ -114,24 +112,9 @@ func getTightColor(c io.Reader, pf *PixelFormat) (*color.RGBA64, error) {
|
||||
B: uint16((pixel >> pf.BlueShift) & uint32(pf.BlueMax)),
|
||||
}
|
||||
|
||||
// else {
|
||||
// *clr = clr.cm[pixel]
|
||||
// clr.cmIndex = pixel
|
||||
// }
|
||||
return &rgb, nil
|
||||
}
|
||||
|
||||
// func getTightColor(bytes []byte, pf *PixelFormat) color.RGBA {
|
||||
// col := (int32(bytes[0])&0xff)<<16 | (int32(bytes[1])&0xff)<<8 | int32(bytes[2])&0xff
|
||||
// rgb := color.RGBA{
|
||||
// R: byte(col >> pf.RedShift & int32(pf.RedMax)),
|
||||
// G: byte(col >> pf.GreenShift & int32(pf.GreenMax)),
|
||||
// B: byte(col >> pf.BlueShift & int32(pf.BlueMax)),
|
||||
// A: byte(1),
|
||||
// }
|
||||
// return rgb
|
||||
// }
|
||||
|
||||
func calcTightBytePerPixel(pf *PixelFormat) int {
|
||||
bytesPerPixel := int(pf.BPP / 8)
|
||||
|
||||
@ -153,16 +136,19 @@ func (enc *TightEncoding) resetDecoders(compControl uint8) {
|
||||
}
|
||||
}
|
||||
|
||||
func (enc *TightEncoding) SetTargetImage(img draw.Image) {
|
||||
enc.Image = img
|
||||
}
|
||||
|
||||
var counter int = 0
|
||||
|
||||
func (enc *TightEncoding) Read(c Conn, rect *Rectangle) error {
|
||||
|
||||
var out *os.File
|
||||
var err error
|
||||
////////////
|
||||
if counter > 40 {
|
||||
os.Exit(1)
|
||||
}
|
||||
// if counter > 40 {
|
||||
// os.Exit(1)
|
||||
// }
|
||||
////////////
|
||||
pixelFmt := c.PixelFormat()
|
||||
bytesPixel := calcTightBytePerPixel(&pixelFmt)
|
||||
@ -180,15 +166,16 @@ func (enc *TightEncoding) Read(c Conn, rect *Rectangle) error {
|
||||
compctl, err := ReadUint8(c)
|
||||
|
||||
/////////////////
|
||||
if out == nil {
|
||||
out, err = os.Create("./output" + strconv.Itoa(counter) + "-" + strconv.Itoa(int(compctl)) + ".jpg")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
defer func() { counter++ }()
|
||||
defer jpeg.Encode(out, enc.Image, nil)
|
||||
// var out *os.File
|
||||
// if out == nil {
|
||||
// out, err = os.Create("./output" + strconv.Itoa(counter) + "-" + strconv.Itoa(int(compctl)) + ".jpg")
|
||||
// if err != nil {
|
||||
// fmt.Println(err)
|
||||
// os.Exit(1)
|
||||
// }
|
||||
// }
|
||||
// defer func() { counter++ }()
|
||||
// defer jpeg.Encode(out, enc.Image, nil)
|
||||
//////////////
|
||||
|
||||
if err != nil {
|
||||
@ -213,15 +200,7 @@ func (enc *TightEncoding) Read(c Conn, rect *Rectangle) error {
|
||||
return err
|
||||
}
|
||||
|
||||
//logger.Debugf("bytesPixel= %d, compctl= %d, color= %v", bytesPixel, compctl, rectColor)
|
||||
|
||||
//imgRect := image.Rect(0, 0, int(c.Width()), int(c.Height()))
|
||||
// if enc.Image == nil {
|
||||
// enc.Image = image.NewRGBA(imgRect)
|
||||
// }
|
||||
|
||||
c1 := color.RGBAModel.Convert(rectColor).(color.RGBA)
|
||||
|
||||
dst := (enc.Image).(*image.RGBA) // enc.Image.(*image.RGBA)
|
||||
var x, y int
|
||||
|
||||
@ -232,14 +211,8 @@ func (enc *TightEncoding) Read(c Conn, rect *Rectangle) error {
|
||||
dst.Pix[offset+1] = c1.G
|
||||
dst.Pix[offset+2] = c1.B
|
||||
dst.Pix[offset+3] = c1.A
|
||||
|
||||
//dst.Set(int(x), int(y), c1)
|
||||
//dst.Pix[y*uint16(dst.Bounds().Max.Y)+x] = []uint8{rectColor.R, rectColor.G, rectColor.B}
|
||||
}
|
||||
}
|
||||
enc.Image = dst
|
||||
|
||||
//draw.Draw(dst, imgRect, &image.Uniform{rectColor}, image.ZP, draw.Src)
|
||||
|
||||
if bytesPixel != 3 {
|
||||
return fmt.Errorf("non tight bytesPerPixel format, should be 3 bytes")
|
||||
@ -337,27 +310,7 @@ func (enc *TightEncoding) handleTightFilters(compCtl uint8, pixelFmt *PixelForma
|
||||
}
|
||||
//logger.Errorf("handleTightFilters: got tight data: %v", tightBytes)
|
||||
|
||||
myImg := enc.Image.(draw.Image)
|
||||
bytePos := 0
|
||||
bitPos := 0
|
||||
var palettePos int
|
||||
for i := 0; i < int(rect.Height); i++ {
|
||||
for j := 0; j < int(rect.Width); j++ {
|
||||
if len(palette) == 2 {
|
||||
currByte := tightBytes[bytePos]
|
||||
palettePos = int(currByte&byte(math.Pow(2.0, float64(bitPos)))) >> uint(bitPos)
|
||||
//logger.Debugf("palletPos=%d, bitpos=%d, bytepos=%d", palettePos, bitPos, bytePos)
|
||||
bytePos = bytePos + int((bitPos+1.0)/8.0)
|
||||
bitPos = (bitPos + 1) % 8
|
||||
//logger.Debugf("next: bitpos=%d, bytepos=%d", bitPos, bytePos)
|
||||
} else {
|
||||
palettePos = int(tightBytes[bytePos])
|
||||
bytePos++
|
||||
}
|
||||
myImg.Set(int(rect.X)+j, int(rect.Y)+i, palette[palettePos])
|
||||
//logger.Debugf("(%d,%d): pos: %d col:%d", int(rect.X)+j, int(rect.Y)+i, palettePos, palette[palettePos])
|
||||
}
|
||||
}
|
||||
enc.drawTightPalette(rect, palette, tightBytes)
|
||||
//enc.Image = myImg
|
||||
case TightFilterGradient: //GRADIENT_FILTER
|
||||
logger.Debugf("----GRADIENT_FILTER: bytesPixel=%d, counter=%d", bytesPixel, counter)
|
||||
@ -387,6 +340,29 @@ func (enc *TightEncoding) handleTightFilters(compCtl uint8, pixelFmt *PixelForma
|
||||
|
||||
return
|
||||
}
|
||||
func (enc *TightEncoding) drawTightPalette(rect *Rectangle, palette color.Palette, tightBytes []byte) {
|
||||
myImg := enc.Image.(draw.Image)
|
||||
bytePos := 0
|
||||
bitPos := 0
|
||||
var palettePos int
|
||||
for i := 0; i < int(rect.Height); i++ {
|
||||
for j := 0; j < int(rect.Width); j++ {
|
||||
if len(palette) == 2 {
|
||||
currByte := tightBytes[bytePos]
|
||||
palettePos = int(currByte&byte(math.Pow(2.0, float64(bitPos)))) >> uint(bitPos)
|
||||
//logger.Debugf("palletPos=%d, bitpos=%d, bytepos=%d", palettePos, bitPos, bytePos)
|
||||
bytePos = bytePos + int((bitPos+1.0)/8.0)
|
||||
bitPos = (bitPos + 1) % 8
|
||||
//logger.Debugf("next: bitpos=%d, bytepos=%d", bitPos, bytePos)
|
||||
} else {
|
||||
palettePos = int(tightBytes[bytePos])
|
||||
bytePos++
|
||||
}
|
||||
myImg.Set(int(rect.X)+j, int(rect.Y)+i, palette[palettePos])
|
||||
//logger.Debugf("(%d,%d): pos: %d col:%d", int(rect.X)+j, int(rect.Y)+i, palettePos, palette[palettePos])
|
||||
}
|
||||
}
|
||||
}
|
||||
func (enc *TightEncoding) decodeGradData(rect *Rectangle, buffer []byte) {
|
||||
|
||||
logger.Debugf("putting gradient size: %v on image: %v", rect, enc.Image.Bounds())
|
||||
|
@ -3,11 +3,11 @@ package main
|
||||
import (
|
||||
"context"
|
||||
"image"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"time"
|
||||
vnc "vnc2webm"
|
||||
"vnc2webm/encoders"
|
||||
"vnc2webm/logger"
|
||||
)
|
||||
|
||||
@ -16,7 +16,7 @@ func main() {
|
||||
// Establish TCP connection to VNC server.
|
||||
nc, err := net.DialTimeout("tcp", os.Args[1], 5*time.Second)
|
||||
if err != nil {
|
||||
log.Fatalf("Error connecting to VNC host. %v", err)
|
||||
logger.Fatalf("Error connecting to VNC host. %v", err)
|
||||
}
|
||||
|
||||
logger.Debugf("starting up the client, connecting to: %s", os.Args[1])
|
||||
@ -41,31 +41,54 @@ func main() {
|
||||
|
||||
cc, err := vnc.Connect(context.Background(), nc, ccfg)
|
||||
if err != nil {
|
||||
log.Fatalf("Error negotiating connection to VNC host. %v", err)
|
||||
logger.Fatalf("Error negotiating connection to VNC host. %v", err)
|
||||
}
|
||||
// out, err := os.Create("./output" + strconv.Itoa(counter) + ".jpg")
|
||||
// if err != nil {
|
||||
// fmt.Println(err)
|
||||
// os.Exit(1)
|
||||
// }
|
||||
//vcodec := &encoders.MJPegImageEncoder{Quality: 60, Framerate: 6}
|
||||
vcodec := &encoders.X264ImageEncoder{}
|
||||
counter := 0
|
||||
//vcodec.Init("./output" + strconv.Itoa(counter))
|
||||
go vcodec.Run("./ffmpeg", "./output.mp4")
|
||||
|
||||
screenImage := image.NewRGBA(image.Rect(0, 0, int(cc.Width()), int(cc.Height())))
|
||||
for _, enc := range ccfg.Encodings {
|
||||
myRenderer, ok := enc.(vnc.Renderer)
|
||||
|
||||
if ok {
|
||||
myRenderer.SetTargetImage(screenImage)
|
||||
}
|
||||
}
|
||||
// var out *os.File
|
||||
|
||||
logger.Debugf("connected to: %s", os.Args[1])
|
||||
defer cc.Close()
|
||||
|
||||
cc.SetEncodings([]vnc.EncodingType{vnc.EncTight})
|
||||
rect := image.Rect(0, 0, int(cc.Width()), int(cc.Height()))
|
||||
screenImage := image.NewRGBA64(rect)
|
||||
//rect := image.Rect(0, 0, int(cc.Width()), int(cc.Height()))
|
||||
//screenImage := image.NewRGBA64(rect)
|
||||
// Process messages coming in on the ServerMessage channel.
|
||||
for {
|
||||
select {
|
||||
case err := <-errorCh:
|
||||
panic(err)
|
||||
case msg := <-cchClient:
|
||||
log.Printf("Received client message type:%v msg:%v\n", msg.Type(), msg)
|
||||
logger.Debugf("Received client message type:%v msg:%v\n", msg.Type(), msg)
|
||||
case msg := <-cchServer:
|
||||
log.Printf("Received server message type:%v msg:%v\n", msg.Type(), msg)
|
||||
myRenderer, ok := msg.(vnc.Renderer)
|
||||
logger.Debugf("Received server message type:%v msg:%v\n", msg.Type(), msg)
|
||||
|
||||
if ok {
|
||||
err = myRenderer.Render(screenImage)
|
||||
if err != nil {
|
||||
log.Printf("Received server message type:%v msg:%v\n", msg.Type(), msg)
|
||||
}
|
||||
}
|
||||
// out, err := os.Create("./output" + strconv.Itoa(counter) + ".jpg")
|
||||
// if err != nil {
|
||||
// fmt.Println(err)
|
||||
// os.Exit(1)
|
||||
// }
|
||||
|
||||
counter++
|
||||
//jpeg.Encode(out, screenImage, nil)
|
||||
vcodec.Encode(screenImage)
|
||||
reqMsg := vnc.FramebufferUpdateRequest{Inc: 1, X: 0, Y: 0, Width: cc.Width(), Height: cc.Height()}
|
||||
reqMsg.Write(cc)
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
_ "net/http/pprof"
|
||||
@ -15,6 +14,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
vnc "vnc2webm"
|
||||
"vnc2webm/logger"
|
||||
)
|
||||
|
||||
type Auth struct {
|
||||
@ -189,7 +189,7 @@ func (auth *AuthVNCHTTP) Auth(c vnc.Conn) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get auth data: %s", err.Error())
|
||||
}
|
||||
log.Printf("http auth: %s\n", buf.Bytes())
|
||||
logger.Infof("http auth: %s\n", buf.Bytes())
|
||||
res.Body.Close()
|
||||
data := strings.Split(buf.String(), " ")
|
||||
if len(data) < 2 {
|
||||
@ -223,12 +223,12 @@ func (*AuthVNCHTTP) SubType() vnc.SecuritySubType {
|
||||
|
||||
func main() {
|
||||
go func() {
|
||||
log.Println(http.ListenAndServe(":6060", nil))
|
||||
logger.Info(http.ListenAndServe(":6060", nil))
|
||||
}()
|
||||
|
||||
ln, err := net.Listen("tcp", ":6900")
|
||||
if err != nil {
|
||||
log.Fatalf("Error listen. %v", err)
|
||||
logger.Fatalf("Error listen. %v", err)
|
||||
}
|
||||
|
||||
schClient := make(chan vnc.ClientMessage)
|
||||
|
@ -4,17 +4,17 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"image"
|
||||
"log"
|
||||
"math"
|
||||
"net"
|
||||
"time"
|
||||
vnc "vnc2webm"
|
||||
"vnc2webm/logger"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ln, err := net.Listen("tcp", ":5900")
|
||||
if err != nil {
|
||||
log.Fatalf("Error listen. %v", err)
|
||||
logger.Fatalf("Error listen. %v", err)
|
||||
}
|
||||
|
||||
chServer := make(chan vnc.ClientMessage)
|
||||
@ -50,12 +50,12 @@ func main() {
|
||||
case msg := <-chClient:
|
||||
switch msg.Type() {
|
||||
default:
|
||||
log.Printf("11 Received message type:%v msg:%v\n", msg.Type(), msg)
|
||||
logger.Debugf("11 Received message type:%v msg:%v\n", msg.Type(), msg)
|
||||
}
|
||||
case msg := <-chServer:
|
||||
switch msg.Type() {
|
||||
default:
|
||||
log.Printf("22 Received message type:%v msg:%v\n", msg.Type(), msg)
|
||||
logger.Debugf("22 Received message type:%v msg:%v\n", msg.Type(), msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ package logger
|
||||
|
||||
import "fmt"
|
||||
|
||||
var simpleLogger = SimpleLogger{LogLevelDebug}
|
||||
var simpleLogger = SimpleLogger{LogLevelInfo}
|
||||
|
||||
type Logger interface {
|
||||
Debug(v ...interface{})
|
||||
|
10
messages.go
10
messages.go
@ -3,7 +3,6 @@ package vnc2webm
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"image/draw"
|
||||
"vnc2webm/logger"
|
||||
)
|
||||
|
||||
@ -83,10 +82,6 @@ type ServerMessage interface {
|
||||
Supported(Conn) bool
|
||||
}
|
||||
|
||||
type Renderer interface {
|
||||
Render(draw.Image) error
|
||||
}
|
||||
|
||||
// FramebufferUpdate holds a FramebufferUpdate wire format message.
|
||||
type FramebufferUpdate struct {
|
||||
_ [1]byte // pad
|
||||
@ -99,11 +94,6 @@ func (msg *FramebufferUpdate) String() string {
|
||||
return fmt.Sprintf("rects %d rectangle[]: { %v }", msg.NumRect, msg.Rects)
|
||||
}
|
||||
|
||||
func (msg *FramebufferUpdate) Render(draw.Image) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (msg *FramebufferUpdate) Supported(c Conn) bool {
|
||||
return true
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user