1
0
mirror of https://github.com/amitbet/vnc2video.git synced 2025-05-11 08:44:22 +00:00

frame rate to variable

This commit is contained in:
amit bezalel 2018-02-11 09:40:40 +02:00
parent 5c4293d610
commit 4f65cf3972
9 changed files with 287 additions and 3 deletions

View File

@ -14,10 +14,14 @@ type VP8ImageEncoder struct {
FFMpegBinPath string
input io.WriteCloser
closed bool
Framerate int
}
func (enc *VP8ImageEncoder) Init(videoFileName string) {
fileExt := ".webm"
if enc.Framerate == 0 {
enc.Framerate = 12
}
if !strings.HasSuffix(videoFileName, fileExt) {
videoFileName = videoFileName + fileExt
}

View File

@ -13,10 +13,14 @@ type DV9ImageEncoder struct {
cmd *exec.Cmd
FFMpegBinPath string
input io.WriteCloser
Framerate int
}
func (enc *DV9ImageEncoder) Init(videoFileName string) {
fileExt := ".mp4"
if enc.Framerate == 0 {
enc.Framerate = 12
}
if !strings.HasSuffix(videoFileName, fileExt) {
videoFileName = videoFileName + fileExt
}

116
encoders/huffyuv-enc.go Normal file
View File

@ -0,0 +1,116 @@
package encoders
import (
"errors"
"image"
"io"
"os"
"os/exec"
"strings"
"vnc2video/logger"
)
// this is a very common loseless encoder (but produces huge files)
type HuffYuvImageEncoder struct {
FFMpegBinPath string
cmd *exec.Cmd
input io.WriteCloser
closed bool
Framerate int
}
func (enc *HuffYuvImageEncoder) Init(videoFileName string) {
if enc.Framerate == 0 {
enc.Framerate = 12
}
fileExt := ".avi"
if !strings.HasSuffix(videoFileName, fileExt) {
videoFileName = videoFileName + fileExt
}
//binary := "./ffmpeg"
cmd := exec.Command(enc.FFMpegBinPath,
"-f", "image2pipe",
"-vcodec", "ppm",
//"-r", strconv.Itoa(framerate),
"-r", "12",
//"-re",
//"-i", "pipe:0",
"-an", //no audio
//"-vsync", "2",
///"-probesize", "10000000",
"-y",
"-i", "-",
//"s", "640×360",
"-vcodec", "huffyuv", //"libvpx",//"libvpx-vp9"//"libx264"
//"-b:v", "0.33M",
"-threads", "7",
///"-coder", "1",
///"-bf", "0",
///"-me_method", "hex",
//"-speed", "0",
//"-lossless", "1", //for vpx
// "-an", "-f", "webm",
"-preset", "veryfast",
//"-tune", "animation",
"-maxrate", "0.5M",
"-bufsize", "50M",
"-g", "250",
//"-crf", "0", //for lossless encoding!!!!
//"-rc_lookahead", "16",
//"-profile", "0",
"-crf", "34",
//"-qmax", "51",
//"-qmin", "7",
//"-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 *HuffYuvImageEncoder) Run(videoFileName string) error {
if _, err := os.Stat(enc.FFMpegBinPath); os.IsNotExist(err) {
logger.Error("encoder file doesn't exist in path:", enc.FFMpegBinPath)
return errors.New("encoder file doesn't exist in path" + videoFileName)
}
enc.Init(videoFileName)
logger.Debugf("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)
return err
}
return nil
}
func (enc *HuffYuvImageEncoder) Encode(img image.Image) {
if enc.input == nil || enc.closed {
return
}
err := encodePPM(enc.input, img)
if err != nil {
logger.Error("error while encoding image:", err)
}
}
func (enc *HuffYuvImageEncoder) Close() {
enc.closed = true
//enc.cmd.Process.Kill()
}

View File

@ -19,6 +19,9 @@ type MJPegImageEncoder struct {
func (enc *MJPegImageEncoder) Init(videoFileName string) {
fileExt := ".avi"
if enc.Framerate == 0 {
enc.Framerate = 12
}
if !strings.HasSuffix(videoFileName, fileExt) {
videoFileName = videoFileName + fileExt
}

115
encoders/qtrle-enc.go Normal file
View File

@ -0,0 +1,115 @@
package encoders
import (
"errors"
"image"
"io"
"os"
"os/exec"
"strings"
"vnc2video/logger"
)
// QTRLEImageEncoder quick time rle is an efficient loseless codec, uses .mov extension
type QTRLEImageEncoder struct {
FFMpegBinPath string
cmd *exec.Cmd
input io.WriteCloser
closed bool
Framerate int
}
func (enc *QTRLEImageEncoder) Init(videoFileName string) {
fileExt := ".mov"
if enc.Framerate == 0 {
enc.Framerate = 12
}
if !strings.HasSuffix(videoFileName, fileExt) {
videoFileName = videoFileName + fileExt
}
//binary := "./ffmpeg"
cmd := exec.Command(enc.FFMpegBinPath,
"-f", "image2pipe",
"-vcodec", "ppm",
//"-r", strconv.Itoa(framerate),
"-r", "12",
//"-re",
//"-i", "pipe:0",
"-an", //no audio
//"-vsync", "2",
///"-probesize", "10000000",
"-y",
"-i", "-",
//"s", "640×360",
"-vcodec", "qtrle", //"libvpx",//"libvpx-vp9"//"libx264"
//"-b:v", "0.33M",
"-threads", "7",
///"-coder", "1",
///"-bf", "0",
///"-me_method", "hex",
//"-speed", "0",
//"-lossless", "1", //for vpx
// "-an", "-f", "webm",
"-preset", "veryfast",
//"-tune", "animation",
"-maxrate", "0.5M",
"-bufsize", "50M",
"-g", "250",
//"-crf", "0", //for lossless encoding!!!!
//"-rc_lookahead", "16",
//"-profile", "0",
"-crf", "34",
//"-qmax", "51",
//"-qmin", "7",
//"-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 *QTRLEImageEncoder) Run(videoFileName string) error {
if _, err := os.Stat(enc.FFMpegBinPath); os.IsNotExist(err) {
logger.Error("encoder file doesn't exist in path:", enc.FFMpegBinPath)
return errors.New("encoder file doesn't exist in path" + videoFileName)
}
enc.Init(videoFileName)
logger.Debugf("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)
return err
}
return nil
}
func (enc *QTRLEImageEncoder) Encode(img image.Image) {
if enc.input == nil || enc.closed {
return
}
err := encodePPM(enc.input, img)
if err != nil {
logger.Error("error while encoding image:", err)
}
}
func (enc *QTRLEImageEncoder) Close() {
enc.closed = true
//enc.cmd.Process.Kill()
}

View File

@ -15,10 +15,14 @@ type X264ImageEncoder struct {
cmd *exec.Cmd
input io.WriteCloser
closed bool
Framerate int
}
func (enc *X264ImageEncoder) Init(videoFileName string) {
fileExt := ".mp4"
if enc.Framerate == 0 {
enc.Framerate = 12
}
if !strings.HasSuffix(videoFileName, fileExt) {
videoFileName = videoFileName + fileExt
}

View File

@ -367,9 +367,8 @@ func (enc *TightEncoding) drawTightPalette(rect *Rectangle, palette color.Palett
enc.Image.Set(int(rect.X)+x, int(rect.Y)+y, palette[palettePos])
//logger.Tracef("(%d,%d): pos: %d col:%d", int(rect.X)+j, int(rect.Y)+i, palettePos, palette[palettePos])
}
// if bitPos != 7 {
// bytePos++
// }
// reset bit alignment to first bit in byte (msb)
bitPos = 7
}

View File

@ -3,12 +3,18 @@ package vnc2video
import (
"encoding/binary"
"errors"
"fmt"
"image"
"image/color"
"image/draw"
"io"
)
const (
BlockWidth = 16
BlockHeight = 16
)
type VncCanvas struct {
draw.Image
//DisplayBuff draw.Image
@ -20,6 +26,7 @@ type VncCanvas struct {
CursorOffset *image.Point
CursorLocation *image.Point
DrawCursor bool
Changed map[string]bool
}
func NewVncCanvas(width, height int) *VncCanvas {
@ -33,6 +40,23 @@ func NewVncCanvas(width, height int) *VncCanvas {
return &canvas
}
func (c *VncCanvas) SetChanged(rect *Rectangle) {
if c.Changed == nil {
c.Changed = make(map[string]bool)
}
for x := int(rect.X) / BlockWidth; x*BlockWidth < int(rect.X+rect.Width); x++ {
for y := int(rect.Y) / BlockHeight; y*BlockHeight < int(rect.Y+rect.Height); y++ {
key := fmt.Sprintf("%d,%d", x, y)
//fmt.Println("setting block: ", key)
c.Changed[key] = true
}
}
}
func (c *VncCanvas) Reset(rect *Rectangle) {
c.Changed = nil
}
func (c *VncCanvas) RemoveCursor() image.Image {
if c.Cursor == nil || c.CursorLocation == nil {
return c.Image

15
encoding_util_test.go Normal file
View File

@ -0,0 +1,15 @@
package vnc2video
import "testing"
func TestSetChanged(t *testing.T) {
canvas := &VncCanvas{}
rect := &Rectangle{X: 1, Y: 1, Width: 1024, Height: 64}
canvas.SetChanged(rect)
if canvas.Changed["64,0"] == false ||
canvas.Changed["64,1"] == false ||
canvas.Changed["64,4"] == false {
t.Fail()
}
}