mirror of
https://github.com/amitbet/vnc2video.git
synced 2025-05-05 13:56:21 +00:00
207 lines
6.3 KiB
Go
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
|
|
}
|