-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy path文档.html
155 lines (135 loc) · 5.91 KB
/
文档.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
<!DOCTYPE html>
<html>
<head>
<title>regioncontro 项目文档</title>
<link rel="stylesheet" href="文档.css" />
</head>
<body>
<h2 id="regioncontro">regioncontro 项目文档</h2>
<h4 id="section">原理</h4>
<p>被控端 录屏 编码h264 发送到控制端 =》 控制端接收解码显示</p>
<p>控制端接收并模拟鼠标键盘消息 《= 控制端发送鼠标键盘消息</p>
<h4 id="section-1">源码项目描述</h4>
<p>controlled 被控制端核心静态lib库,录屏负责编码 处理鼠标键盘消息</p>
<p>regioncontro 调用controlled传参,exe程序</p>
<p>ControlRemote 控制端库,负责接收h264解码,并发送鼠标键盘消息</p>
<p>WindowsFormsApp winfrom控制端,调用ControlRemote.dll</p>
<hr />
<h4 id="controlled.lib">被控制端controlled.lib 静态库详情</h4>
<p>整个库就一个核心接口是<code>class Work</code></p>
<pre><code>
//const Monitor&, 屏幕数据,其中包括录屏的区域
//int fps, 每秒帧数
//bool capture_cursor, 是否显示鼠标
//int bitrate, 比特率
//std::string& x264_preset,
//std::string& x264_tune,
//check_key ckcall,键盘事件验证,返回false则不处理消息,用与拦截某些按键
//std::string& record_file 录制文件
//初始化函数
bool Init(const Monitor&,int fps, bool capture_cursor, int bitrate, std::string& x264_preset, std::string& x264_tune, check_key ckcall,std::string& record_file);
//开始函数
void Start(SOCKET socket_con);
//手动结束清理
void StopClear();
//等待一个结束信号
void WaitStop();
</code></pre>
<p>调用流程</p>
<pre><code>Init 初始化 -> Start 开始 -> StopClear 结束
WaitStop 函数可以等待recv线程结束
</code></pre>
<p>引用库:</p>
<p><code>libx264-148.dll</code> 此库为x264编码库</p>
<p><code>libyuv</code> 此静态库是yuv和rgba快速转换库,为谷歌开源项目</p>
<p>源码解析:</p>
<p><code>CaptureCommon.cpp</code> 为获取屏幕大小</p>
<p><code>Capture.cpp</code> 截屏功能 核心函数是BitBlt</p>
<p><code>flvenc.cpp</code> 保存h264为flv文件的功能</p>
<p><code>LSendInput.cpp</code> 向本机发送鼠标键盘消息</p>
<p><code>net_protocol.cpp</code> 简易通讯相关</p>
<p><code>pkt_queue.cpp</code> 一个简单的cas锁队列</p>
<p><code>Work.cpp</code> 核心代码 这个类会开启<code>四个线程</code>来工作,分别是,
如下</p>
<pre><code> void CaptureWork();截屏线程
void EncoderWork();编码线程
void OutPutWork();发送h264到远端&保存文件线程
void RecvCtr(); 接收远端鼠标键盘线程 并发送到本地
</code></pre>
<p>线程之间用event和pkt_queue队列通讯</p>
<hr />
<h4 id="controlremote.dll">控制端ControlRemote.dll</h4>
<p>此库共提供一下几个接口</p>
<pre><code>//程序启动调用
int _stdcall DLLInit();
/*创建一个上下文
HWND hwnd, 窗口句柄
SOCKET socket_con, socket 句柄
StartCall startCall, 开始回调,传入视频高宽
DisconnectCall disconnectCall, 断开回调
ErrorMessageCall errorMessageCall 错误消息回调
*/
void*_stdcall NewContext(HWND hwnd,SOCKET socket_con,
StartCall startCall, DisconnectCall disconnectCall, ErrorMessageCall errorMessageCall);
//删除并停止这个上下文线程
void _stdcall DeleteStopContext(Context* context);
//开始线程
int _stdcall StartWork(Context* context);
//发送鼠标位置
int _stdcall SendCursorPos(Context* context, int x, int y);
//发送鼠标点击事件
int _stdcall SendMouseEvent(Context* context, unsigned int action, int wheel);
//发送键盘事件
int _stdcall SendKeyEvent(Context* context, int VK, bool down);
</code></pre>
<p>调用流程</p>
<pre><code>
DLLInit
NewContext
|
StartWork
|
[SendCursorPos SendMouseEvent SendKeyEvent]
|
DeleteStopContext
</code></pre>
<p>引用库:</p>
<p><code>ffmpeg</code> 解码</p>
<p><code>SDL</code> sdl显示库</p>
<p>源码解析:</p>
<p>核心就一个<code>ControlRemote.cpp</code></p>
<p>接收h264并解码显示</p>
<hr />
<h4 id="windowsformsapp">WindowsFormsApp 说明</h4>
<p>控制端ControlRemote.dll只是最底层的功能,实现完整的控制必须依赖前段界面</p>
<p>ControlRemote.dll的线程只负责接收h264解码显示,</p>
<p>发送鼠标键盘消息,是winfrom调用ControlRemote.dll完成,并不在ControlRemote.dll创建的线程里</p>
<p>winform会把自己的某个空间句柄传给ControlRemote.dll 当做显示界面,示例代码是用一个 PictureBox控件来显示</p>
<p>更多请参见源码</p>
<hr />
<h4 id="section-2">通讯协议简单描述</h4>
<p>简单的通讯协议定义为 <code>net_protocol.h cpp</code>文件</p>
<p>一个包分为 包头和正文</p>
<p>包头:起始标志+包类型+正文长度正文</p>
<pre><code>struct PacketHead
{
//起始标志位0xffffffff uint32 max
uint32_t start_sign;
//类型
uint32_t type;
//正文长度
uint32_t len;
};
</code></pre>
<p>接收这个固定长度头部,开始接收正文长度<code>uint32_t len;</code></p>
<p><code>uint32_t type;</code>是类型,大体分为,屏幕数据包,鼠标键盘消息包等等</p>
<p>在通讯开始的时候会有一个read包发送和接收,参见<code>Work::ReadyCheck</code></p>
<hr />
<h5 id="ffmpeg">ffmpeg编译</h5>
<p>ffmpeg 和libx264都是开源项目,可以自己百度搜索如何编译,</p>
<p>ffmpeg 编译参数为:</p>
<pre><code>./configure --enable-shared --prefix=/ffmpeg/ --disable-everything --enable-decoder=h264 --enable-parser=h264 --enable-demuxer=h264 --disable-programs --disable-iconv --extra-ldlibflags="-static-libgcc" --disable-avdevice --disable-swresample --disable-swscale --disable-postproc --disable-avfilter --disable-avformat
</code></pre>
<p>注意,mingw编译的ffmpeg和x264 的lib文件在vs2010下没法用,必须用工具通过dll重新生成lib,否则在vs2010的release模式下编译运行会出错!!</p>
</body>
</html>