added fbs reader with an example usage main function

This commit is contained in:
amit bezalel
2018-01-06 14:31:48 +02:00
parent b981839fc1
commit 1a112dbead
5 changed files with 457 additions and 2 deletions

View File

@@ -249,7 +249,9 @@ func (enc *TightEncoding) Read(c Conn, rect *Rectangle) error {
if err != nil { if err != nil {
logger.Error("problem while decoding jpeg:", err) logger.Error("problem while decoding jpeg:", err)
} }
enc.Image = img dest := enc.Image.(draw.Image)
draw.Draw(dest, dest.Bounds(), img, image.Point{int(rect.X), int(rect.Y)}, draw.Src)
return nil return nil
default: default:

View File

@@ -93,9 +93,10 @@ func main() {
//jpeg.Encode(out, screenImage, nil) //jpeg.Encode(out, screenImage, nil)
vcodec.Encode(screenImage) vcodec.Encode(screenImage)
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()}
//cc.ResetAllEncodings()
reqMsg.Write(cc) reqMsg.Write(cc)
} }
} }
} }
cc.Wait() //cc.Wait()
} }

View File

@@ -0,0 +1,61 @@
package main
import (
"image"
"os"
vnc "vnc2webm"
"vnc2webm/encoders"
"vnc2webm/logger"
"path/filepath"
)
func main() {
if len(os.Args) <= 1 {
logger.Errorf("please provide a fbs file name")
return
}
if _, err := os.Stat(os.Args[1]); os.IsNotExist(err) {
logger.Errorf("File doesn't exist", err)
return
}
encs := []vnc.Encoding{
&vnc.RawEncoding{},
&vnc.TightEncoding{},
}
fbs, err := vnc.NewFbsConn(
os.Args[1],
encs,
)
if err != nil {
logger.Error("failed to open fbs reader:", err)
//return nil, err
}
//launch video encoding process:
vcodec := &encoders.X264ImageEncoder{}
//vcodec := &encoders.DV8ImageEncoder{}
//vcodec := &encoders.DV9ImageEncoder{}
dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
logger.Debugf("current dir: %s", dir)
go vcodec.Run("./ffmpeg", "./output.mp4")
screenImage := image.NewRGBA(image.Rect(0, 0, int(fbs.Width()), int(fbs.Height())))
for _, enc := range encs {
myRenderer, ok := enc.(vnc.Renderer)
if ok {
myRenderer.SetTargetImage(screenImage)
}
}
msgReader := vnc.NewFBSPlayHelper(fbs)
//loop over all messages, feed images to video codec:
for {
msgReader.ReadFbsMessage()
vcodec.Encode(screenImage)
}
}

201
fbs-connection.go Normal file
View File

@@ -0,0 +1,201 @@
package vnc2webm
import (
"encoding/binary"
"net"
"vnc2webm/logger"
"io"
"time"
)
// Conn represents vnc conection
type FbsConn struct {
FbsReader
protocol string
//c net.IServerConn
//config *ClientConfig
colorMap ColorMap
// Encodings supported by the client. This should not be modified
// directly. Instead, SetEncodings should be used.
encodings []Encoding
// Height of the frame buffer in pixels, sent from the server.
fbHeight uint16
// Width of the frame buffer in pixels, sent from the server.
fbWidth uint16
desktopName string
// The pixel format associated with the connection. This shouldn't
// be modified. If you wish to set a new pixel format, use the
// SetPixelFormat method.
pixelFormat PixelFormat
}
// func (c *FbsConn) Close() error {
// return c.fbs.Close()
// }
// // Read reads data from conn
// func (c *FbsConn) Read(buf []byte) (int, error) {
// return c.fbs.Read(buf)
// }
//dummy, no writing to this conn...
func (c *FbsConn) Write(buf []byte) (int, error) {
return len(buf), nil
}
func (c *FbsConn) Conn() net.Conn {
return nil
}
func (c *FbsConn) Config() interface{} {
return nil
}
func (c *FbsConn) Protocol() string {
return "RFB 003.008"
}
func (c *FbsConn) PixelFormat() PixelFormat {
return c.pixelFormat
}
func (c *FbsConn) SetPixelFormat(pf PixelFormat) error {
c.pixelFormat = pf
return nil
}
func (c *FbsConn) ColorMap() ColorMap { return c.colorMap }
func (c *FbsConn) SetColorMap(cm ColorMap) { c.colorMap = cm }
func (c *FbsConn) Encodings() []Encoding { return c.encodings }
func (c *FbsConn) SetEncodings([]EncodingType) error { return nil }
func (c *FbsConn) Width() uint16 { return c.fbWidth }
func (c *FbsConn) Height() uint16 { return c.fbHeight }
func (c *FbsConn) SetWidth(w uint16) { c.fbWidth = w }
func (c *FbsConn) SetHeight(h uint16) { c.fbHeight = h }
func (c *FbsConn) DesktopName() []byte { return []byte(c.desktopName) }
func (c *FbsConn) SetDesktopName(d []byte) { c.desktopName = string(d) }
func (c *FbsConn) Flush() error { return nil }
func (c *FbsConn) Wait() {}
func (c *FbsConn) SetProtoVersion(string) {}
func (c *FbsConn) SetSecurityHandler(SecurityHandler) error { return nil }
func (c *FbsConn) SecurityHandler() SecurityHandler { return nil }
func (c *FbsConn) GetEncInstance(typ EncodingType) Encoding {
for _, enc := range c.encodings {
if enc.Type() == typ {
return enc
}
}
return nil
}
type VncStreamFileReader interface {
io.Reader
CurrentTimestamp() int
ReadStartSession() (*ServerInit, error)
CurrentPixelFormat() *PixelFormat
Encodings() []Encoding
}
type FBSPlayHelper struct {
Conn *FbsConn
//Fbs VncStreamFileReader
serverMessageMap map[uint8]ServerMessage
firstSegDone bool
startTime int
}
func NewFbsConn(filename string, encs []Encoding) (*FbsConn, error) {
fbs, err := NewFbsReader(filename)
if err != nil {
logger.Error("failed to open fbs reader:", err)
return nil, err
}
//NewFbsReader("/Users/amitbet/vncRec/recording.rbs")
initMsg, err := fbs.ReadStartSession()
if err != nil {
logger.Error("failed to open read fbs start session:", err)
return nil, err
}
fbsConn := &FbsConn{FbsReader: *fbs}
fbsConn.encodings = encs
fbsConn.SetPixelFormat(initMsg.PixelFormat)
fbsConn.SetHeight(initMsg.FBHeight)
fbsConn.SetWidth(initMsg.FBWidth)
fbsConn.SetDesktopName([]byte(initMsg.NameText))
return fbsConn, nil
}
func NewFBSPlayHelper(r *FbsConn) *FBSPlayHelper {
h := &FBSPlayHelper{Conn: r}
h.startTime = int(time.Now().UnixNano() / int64(time.Millisecond))
h.serverMessageMap = make(map[uint8]ServerMessage)
h.serverMessageMap[0] = &FramebufferUpdate{}
h.serverMessageMap[1] = &SetColorMapEntries{}
h.serverMessageMap[2] = &Bell{}
h.serverMessageMap[3] = &ServerCutText{}
return h
}
// func (handler *FBSPlayHelper) Consume(seg *RfbSegment) error {
// switch seg.SegmentType {
// case SegmentFullyParsedClientMessage:
// clientMsg := seg.Message.(ClientMessage)
// logger.Debugf("ClientUpdater.Consume:(vnc-server-bound) got ClientMessage type=%s", clientMsg.Type())
// switch clientMsg.Type() {
// case FramebufferUpdateRequestMsgType:
// if !handler.firstSegDone {
// handler.firstSegDone = true
// handler.startTime = int(time.Now().UnixNano() / int64(time.Millisecond))
// }
// handler.sendFbsMessage()
// }
// // server.MsgFramebufferUpdateRequest:
// }
// return nil
// }
func (h *FBSPlayHelper) ReadFbsMessage() ServerMessage {
var messageType uint8
//messages := make(map[uint8]ServerMessage)
fbs := h.Conn
//conn := h.Conn
err := binary.Read(fbs, binary.BigEndian, &messageType)
if err != nil {
logger.Error("TestServer.NewConnHandler: Error in reading FBS: ", err)
return nil
}
//IClientConn{}
//binary.Write(h.Conn, binary.BigEndian, messageType)
msg := h.serverMessageMap[messageType]
if msg == nil {
logger.Error("TestServer.NewConnHandler: Error unknown message type: ", messageType)
return nil
}
//read the actual message data
//err = binary.Read(fbs, binary.BigEndian, &msg)
parsedMsg, err := msg.Read(fbs)
if err != nil {
logger.Error("TestServer.NewConnHandler: Error in reading FBS message: ", err)
return nil
}
timeSinceStart := int(time.Now().UnixNano()/int64(time.Millisecond)) - h.startTime
timeToSleep := fbs.CurrentTimestamp() - timeSinceStart
if timeToSleep > 0 {
time.Sleep(time.Duration(timeToSleep) * time.Millisecond)
}
return parsedMsg
}

190
fbs-reader.go Normal file
View File

@@ -0,0 +1,190 @@
package vnc2webm
import (
"bytes"
"encoding/binary"
"io"
"os"
//"vncproxy/common"
//"vncproxy/encodings"
"vnc2webm/logger"
//"vncproxy/encodings"
//"vncproxy/encodings"
)
type FbsReader struct {
reader io.ReadCloser
buffer bytes.Buffer
currentTimestamp int
//pixelFormat *PixelFormat
//encodings []IEncoding
}
func (fbs *FbsReader) Close() error {
return fbs.reader.Close()
}
func (fbs *FbsReader) CurrentTimestamp() int {
return fbs.currentTimestamp
}
func (fbs *FbsReader) Read(p []byte) (n int, err error) {
if fbs.buffer.Len() < len(p) {
seg, err := fbs.ReadSegment()
if err != nil {
logger.Error("FBSReader.Read: error reading FBSsegment: ", err)
return 0, err
}
fbs.buffer.Write(seg.bytes)
fbs.currentTimestamp = int(seg.timestamp)
}
return fbs.buffer.Read(p)
}
//func (fbs *FbsReader) CurrentPixelFormat() *PixelFormat { return fbs.pixelFormat }
//func (fbs *FbsReader) CurrentColorMap() *common.ColorMap { return &common.ColorMap{} }
//func (fbs *FbsReader) Encodings() []IEncoding { return fbs.encodings }
func NewFbsReader(fbsFile string) (*FbsReader, error) {
reader, err := os.OpenFile(fbsFile, os.O_RDONLY, 0644)
if err != nil {
logger.Error("NewFbsReader: can't open fbs file: ", fbsFile)
return nil, err
}
return &FbsReader{reader: reader}, //encodings: []IEncoding{
// //&encodings.CopyRectEncoding{},
// //&encodings.ZLibEncoding{},
// //&encodings.ZRLEEncoding{},
// //&encodings.CoRREEncoding{},
// //&encodings.HextileEncoding{},
// &TightEncoding{},
// //&TightPngEncoding{},
// //&EncCursorPseudo{},
// &RawEncoding{},
// //&encodings.RREEncoding{},
//},
nil
}
func (fbs *FbsReader) ReadStartSession() (*ServerInit, error) {
initMsg := ServerInit{}
reader := fbs.reader
var framebufferWidth uint16
var framebufferHeight uint16
var SecTypeNone uint32
//read rfb header information (the only part done without the [size|data|timestamp] block wrapper)
//.("FBS 001.000\n")
bytes := make([]byte, 12)
_, err := reader.Read(bytes)
if err != nil {
logger.Error("FbsReader.ReadStartSession: error reading rbs init message - FBS file Version:", err)
return nil, err
}
//read the version message into the buffer, it is written in the first fbs block
//RFB 003.008\n
bytes = make([]byte, 12)
_, err = fbs.Read(bytes)
if err != nil {
logger.Error("FbsReader.ReadStartSession: error reading rbs init - RFB Version: ", err)
return nil, err
}
//push sec type and fb dimensions
binary.Read(fbs, binary.BigEndian, &SecTypeNone)
if err != nil {
logger.Error("FbsReader.ReadStartSession: error reading rbs init - SecType: ", err)
}
//read frame buffer width, height
binary.Read(fbs, binary.BigEndian, &framebufferWidth)
if err != nil {
logger.Error("FbsReader.ReadStartSession: error reading rbs init - FBWidth: ", err)
return nil, err
}
initMsg.FBWidth = framebufferWidth
binary.Read(fbs, binary.BigEndian, &framebufferHeight)
if err != nil {
logger.Error("FbsReader.ReadStartSession: error reading rbs init - FBHeight: ", err)
return nil, err
}
initMsg.FBHeight = framebufferHeight
//read pixel format
pixelFormat := &PixelFormat{}
binary.Read(fbs, binary.BigEndian, pixelFormat)
if err != nil {
logger.Error("FbsReader.ReadStartSession: error reading rbs init - Pixelformat: ", err)
return nil, err
}
initMsg.PixelFormat = *pixelFormat
//read desktop name
var desknameLen uint32
binary.Read(fbs, binary.BigEndian, &desknameLen)
if err != nil {
logger.Error("FbsReader.ReadStartSession: error reading rbs init - deskname Len: ", err)
return nil, err
}
initMsg.NameLength = desknameLen
bytes = make([]byte, desknameLen)
fbs.Read(bytes)
if err != nil {
logger.Error("FbsReader.ReadStartSession: error reading rbs init - desktopName: ", err)
return nil, err
}
initMsg.NameText = bytes
return &initMsg, nil
}
func (fbs *FbsReader) ReadSegment() (*FbsSegment, error) {
reader := fbs.reader
var bytesLen uint32
//read length
err := binary.Read(reader, binary.BigEndian, &bytesLen)
if err != nil {
logger.Error("FbsReader.ReadStartSession: read len, error reading rbs file: ", err)
return nil, err
}
paddedSize := (bytesLen + 3) & 0x7FFFFFFC
//read bytes
bytes := make([]byte, paddedSize)
_, err = reader.Read(bytes)
if err != nil {
logger.Error("FbsReader.ReadSegment: read bytes, error reading rbs file: ", err)
return nil, err
}
//remove padding
actualBytes := bytes[:bytesLen]
//read timestamp
var timeSinceStart uint32
binary.Read(reader, binary.BigEndian, &timeSinceStart)
if err != nil {
logger.Error("FbsReader.ReadSegment: read timestamp, error reading rbs file: ", err)
return nil, err
}
//timeStamp := time.Unix(timeSinceStart, 0)
seg := &FbsSegment{bytes: actualBytes, timestamp: timeSinceStart}
return seg, nil
}
type FbsSegment struct {
bytes []byte
timestamp uint32
}