1
0
mirror of https://github.com/amitbet/vnc2video.git synced 2025-05-05 13:56:21 +00:00
vnc2video/fbs-connection.go
2019-06-16 04:11:39 +03:00

207 lines
6.3 KiB
Go

package vnc2video
import (
"encoding/binary"
"net"
"github.com/amitbet/vnc2video/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.Tracef("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(SyncWithTimestamps bool, SpeedFactor float64) (ServerMessage, error) {
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("FBSConn.NewConnHandler: Error in reading FBS: ", err)
return nil, err
}
startTimeMsgHandling := time.Now()
//IClientConn{}
//binary.Write(h.Conn, binary.BigEndian, messageType)
msg := h.serverMessageMap[messageType]
if msg == nil {
logger.Error("FBSConn.NewConnHandler: Error unknown message type: ", messageType)
return nil, err
}
//read the actual message data
//err = binary.Read(fbs, binary.BigEndian, &msg)
parsedMsg, err := msg.Read(fbs)
if err != nil {
logger.Error("FBSConn.NewConnHandler: Error in reading FBS message: ", err)
return nil, err
}
millisSinceStart := int(startTimeMsgHandling.UnixNano()/int64(time.Millisecond)) - h.startTime
adjestedTimeStamp := float64(fbs.CurrentTimestamp()) / SpeedFactor
millisToSleep := adjestedTimeStamp - float64(millisSinceStart)
if millisToSleep > 0 && SyncWithTimestamps {
time.Sleep(time.Duration(millisToSleep) * time.Millisecond)
} else if millisToSleep < -400 {
logger.Errorf("rendering time is noticeably off, change speedup factor: videoTimeLine: %f, currentTime:%d, offset: %f", adjestedTimeStamp, millisSinceStart, millisToSleep)
}
return parsedMsg, nil
}