首页 > 代码库 > 【难题】如何在后台调用vfw的压缩保存
【难题】如何在后台调用vfw的压缩保存
原来做了一个小项目,其间解决了不少难题,算是得意之作。本想第二篇博文以此为内容,没想到一晃快两年过去了,微软的认证也就看了官网上的半级教程,C#也因项目的变化没有坚持深入(外包嘛,项目随时变)。现在做的却是web,用上了springmvc和angular4,差不多与原来完全脱离了干系。
做了这么多年,还是想往架构方向走。既然转向了web,那以后还是专心于web方向吧。但半路起家,各种基础都不牢固,于是大致归纳了一下web架构的各个方面,准备各个击破。这个过程中,需要将遇到的问题、解决办法、基础知识、视野扩展 等各个方面,都总结记录下来。于是重拾博客园,以此为阵地,开始自己的新征途。
上周已经下了一堆软件,搭起了虚拟机和centos系统。想将其中遇到的问题简单记录下。但两年前的那篇旧文还未完成,所以今天花点时间,为此画个句号,重起新的一段。
开始正题吧。其实也不算项目,就是一个小程序。背景是领导有天跟我说,他的朋友怀疑有人动了他的电脑,想用摄像头将其记录下来,于是让我搞个录屏的程序。
作为一个“资深“技术人员,首先考虑的不是怎么调用摄像头的api进行录像,而是这个录屏程序不要被对方发现。万一对方技术不错,能想办法将我的程序关掉,那不是白费功夫。于是在网上搜寻了一些如何隐藏进程的方法,发现可以将程序寄宿到svchost中,可随系统启动,并看不到自己的程序名。在任务管理器中,看到的只是个svchost,却不知那不是系统程序,而是自己做的后台监控。
于是立马选择了这个方案,在网上搜索了一个demo,拿来改了改,顺利跑了起来。这个在网上有很多资料,这里就不细说了。
接下来的问题就是录像了。继续搜索,发现vfw是通用usb摄像头的一个方案,用起来也简单。下了个demo,窗口上选好压缩格式,点击录像按钮,稍后再停止,视频文件就保存下来了。so easy嘛。
然后需要将其移植到没有窗口的svchost服务去(弹个窗口出来,当别人白痴啊)。这好办,服务开始就录像,服务关闭就停止,期间每隔一段时间就将录像保存到指定地点。这时问题来了。调用创建捕捉窗口句柄的capCreateCaptureWindow函数,需要一个窗口句柄作为入参。我这没有窗口啊,传个null也不行,怎么办?
WIN32的API CreateWindow倒是可以创建一个窗口。随便抄了一句该函数的使用,创建一个句柄,传给capCreateCaptureWindow。居然无法录像(或是报错?时间太久,不记得了)。
这下麻烦了,要舍弃svchost方案么。实在不甘心,于是研究起CreateWindow(或是WNDCLASS)的参数。折腾了一两天,尝试各种参数搭配,居然成功了,程序顺利运行了。
正在欣喜之际,很快又发现一个新问题。用demo选择压缩格式保存后,几分钟的视频文件才几百k,而现在后台录的1分钟要几十兆,完全没压缩嘛。那么要怎么选压缩协议呢。虽然提供了一个COMPVARS结构,但设置了也没效果,奇了怪了。
查了好几天资料,还发现了一个capSetCallbackOnFrame函数,但完全搞不懂怎么用。最后不得已,只好把主意打到窗口版的录屏程序上。
于是开始调试窗口录屏程序,点击录屏的地方下个断点,一步步跟进去,看下选择的压缩协议怎么生效的。结果发现一个奇怪的操作:API内部对capCreateCaptureWindow生成的句柄调用了GetWindowLong,然后将选择的压缩协议对应的COMPVARS放到了GetWindowLong返回地址后面的某个固定位置。我x,这是什么黑科技。我再调试我自己的程序,发现会跳过GetWindowLong的这一段,那压缩肯定没法生效了啊。
网上查不到对这段的说明,那只好照搬这段代码了。于是我的代码里出现了奇怪的几句:
不管这是啥意思,我的程序保存的视频,也只有几百k了。
任务算是完成。我也没心情去研究其中的原理了。前后折腾了两周,终于能交差了。
【难题】如何在后台调用vfw的压缩保存