Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1156945
  • 博文数量: 222
  • 博客积分: 5262
  • 博客等级: 大校
  • 技术积分: 3028
  • 用 户 组: 普通用户
  • 注册时间: 2009-11-22 19:10
文章分类

全部博文(222)

文章存档

2012年(2)

2011年(192)

2010年(28)

分类: WINDOWS

2011-02-16 12:00:21

高效屏幕录制
屏幕录制有着广泛的用途,主要用于建立演示培训,或者远程屏幕监视和广播。由于屏幕的大小和色深通常很高,而且具有大块背景色、窗口拖动/卷动造成的内容移动和菜单弹出造成的瞬时变化等特性,因此需要在数据采集、压缩和传输/存储上多加考虑。
录制之前
录制之前,应该选择录制方法,压缩方式和录制范围。
有必要尽可能缩小录制的区域以减少数据量。在录制开始之前,可以让用户指定录制的范围,例如全屏幕,指定窗口,指定/自适应坐标等等。小的录制区域意味着更少的原始数据。
尽可能降低录制的色深以减少数据量。通常,用于简单教学的录制只需要256色。
录制之前,应该停用屏幕保护,桌布和活动桌面的一些特性以避免不必要的录制。
录制方法
录制分两种方式,一种是推模式,也就是录制模块不断录制数据,一种是拉模式,录制模块在需要的时候才录制数据。对于低带宽的场合,拉模式可以有效的减少原始数据量。对于需要基本无损回放的场合,推模式在监测到屏幕变化时就录制数据,可以减少视频质量的损失。在推模式下需要选取录制的时机,以避免大量的重复数据。
压缩编码
适当的编码方式可以有效地减少录制时的资源占用。
联合图像专家组(Joint Photographic Experts Group,JPEG)编码
在有损压缩时,对于静态图像具有比较好的压缩比率。但是有损压缩可能会使得屏幕上的文字变得模糊。
运动图像专家(MPEG)组编码
适合运动的图像,但是剧烈变化的图像,例如菜单的弹出,可能会暂时使录制的视频质量降低,以及CPU资源占用的升高。
远程帧缓冲(Remote Frame Buffer,RFB)编码
包括对于窗口拖动/卷动造成的内容移动造成的矩形复制(copy rectangle)和背景色的优化。对于每个矩形,可以有各种不同的编码方式,例如MPEG或者JPEG。
分块比较编码
将每次录制的屏幕分块和上次录制的屏幕内容比较,如果某块抽样变化了,那么编码整个块。对于每个块,可以有各种不同的编码方式,例如MPEG或者JPEG。
根据录制内容的不同,以及编码设置的不同(例如质量和分块大小设置),以上编码方式可能各有所长。
额外的考虑
扫描线
隔行扫描而不是逐行扫描屏幕数据可以有效地减少录制的数据量,同时录制的视频质量降低不大。
录制时机
虚拟显示设备或者适当的系统钩子可以使你在屏幕变化或者即将变化时得到通知,这样可以尽可能地减少录制的次数。参见 以及 提供的VNC源代码中的VNCHooks。
DirectX
使用DirectX可以进行直接的显存访问,这对提高性能很有好处。但是也由于DirectX的特性,某些使用DirectX等技术的程序可能无法录制,例如大多数游戏和媒体播放器,即使可以录制也比较慢。录制这样的程序的窗口内容的方法是局部或者全局地禁用部分或者全部DirectX加速功能。
机器码
在录制和编码过程中,使用机器码模块可以有效地加强程序的性能。例如XVID的很多核心模块就是机器码。
分块的大小
大的分块意味着录制时录制的次数少,但是小的分块可能意味着较少的数据量。对于依赖于背景色的编码方式,分块大小也影响数据量。
?
其他录制内容
鼠标,水印和其他图像
在录制图像的同时,可能同时需要在屏幕内容上叠加其他图像,例如鼠标或者水印。这可以通过在每一次录制的图像上在指定位置上叠加指定的图像来完成。
//Draw the Cursor
if (g_recordcursor==1) {
   ICONINFO iconinfo ;
   BOOL ret;
   ret = GetIconInfo( hcur, &iconinfo );
   if (ret) {
     xPoint.x -= iconinfo.xHotspot;
     xPoint.y -= iconinfo.yHotspot;
     //need to delete the hbmMask and hbmColor bitmaps
     //otherwise the program will crash after a while after running out of resource
     if (iconinfo.hbmMask) DeleteObject(iconinfo.hbmMask);
     if (iconinfo.hbmColor) DeleteObject(iconinfo.hbmColor);
   }
   :: DrawIcon( hMemDC, xPoint.x, xPoint.y, hcur);
}
这里hMemDC包含已经录制的屏幕内容,hcur表示当前缓存的光标(因为光标不是每次录制都变化,所以缓存起来效率较高)。
音频
为了丰富媒体内容,可能有必要在录制屏幕时同时录制音频。屏幕录制占用了大量资源时,有可能造成音频的录制和压缩慢于预计的频率,结果是录制的媒体音调降低,以及可能的同步问题。
加密
如果录制的内容需要保密,那么必须考虑实施加密的性能和可行性。一般来说,为每个会话产生一个不同的密钥来进行初步的加密就可以了。
# 回复: 高效屏幕录制
jiangsheng :
你好,前一段时间我研究了一下VNC的源代码,发现现在最好的截屏方法是Mirror Driver,ultravnc就是用了这种技术,可是它的这部分代码并没有公开。我搜索到有一个有一个Winvncdrv也实现了这个功能,但是网上提供的网址不能够访问了。不知道你是否有这方面编程经验或者源代码。
我的邮箱地址是,希望能够得到你的回复。
2004/2/16 20:34 | shootingstar

# 回复: 高效屏幕录制
经验没有,不过WindowsDDK里面好像有Mirror Driver的例子
2004/2/18 17:37 | jiangsheng
# re: 高效屏幕录制
唉,
近段时间我被win32下的屏幕录制和屏幕广播弄得焦头烂额,
不知道大家可否交流一下这方面的经验,
这段时间里我分析了RealVNC的源码:包括VNCHook,WinVNC的屏幕截取方法,双缓冲管理方法和VNCViewer的刷写方法,
另外,看了这篇文章后,我又看了一遍,MIRROR Driver的源码(这东西微软没有更新win 2k 的DDK和win2003 的DDK的都是一样的),对两种屏幕录制的方法(像VNC哪样在用户模式下的屏幕截取,和像一般商业的教学软件里的,在内核模式下的屏幕截取)大致了解,但是无法结合两种方法的优点~~~~。
针对这两种屏幕录制,我有以下感觉:
VNC-like:VNC很巧妙地利用了Win32下的消息机制,通过系统钩子的通知和GDI引擎的位传送(BitBlt)在DibSection上完成屏幕截取,并且通过双倍桢缓冲机制减少传送像素数据所需的网络带宽,VNC能做成这样,确实是很让我惊讶,但是,在RealVNC自己写的WinVNC里面,我觉得,Win32的消息机制会造成屏幕截取的较大延迟,而且使用了BitBlt来截屏,照样是截取不了DirectX或电影的画面,另外,在用户模式下,VNC的内存容量、带宽的占用是很大的(在下,需要3 X 1024X768 X4 bytes约等于4~5M的空间,另外还有3条线程在协调工作)
Mirror-Driver-like:Mirror Driver的好处是可以直接利用硬件,达到用户模式下让人难以企及的“实时”,然而,在内核模式下却好像难以利用VNC哪种钩子带来的好处(CPU占用率低,因为需要历遍的像素数量少得多),最大的问题还是在于我不知道怎样把内核模式里面的数据怎样带到用户模式中去(因为要发送到网络上~~~~~~~)shit~~~
GetCurrentImage(...)好像可以把DirectX的图像也截取下来,不知道能不能替代BitBlt来完成所有的屏幕截呢~~~~~~~?
希望能与正在从事这方面开发的程序员交流一下
2004/7/24 16:38 | softworm
# re: 高效屏幕录制
请问:用什么方式可以达到高帧率,低消耗呢?我看到一个软件捕捉屏幕的速度远高于vnc而其cpu开销只有vnc的1/3。高手可否告知其使用的是什么捕捉屏幕的方法?
2004/8/10 13:23 | wdh
# re: 高效屏幕录制
因为要做屏幕广播,所以也在研究了一点屏幕抓图,我看的源码是
UltraVNC
说点经验及问题:
(1)两者差别
驱动方式(推模式)Mirror Driver:
优点:占用CPU资源少(1-5%),速度快。实时性高。
缺点:a. window 2000/xp/2003支持,98不支持。
b. 装完驱动需重新启动方能使用。
HOOK方式(拉模式)HOOK:
优点:系统支持广泛,装后不需要重启就能使用。
缺点:占用CPU资源大。
解决方法:两种都开发,window 2000/xp/2003系统采用驱动方动,其它系统使 用HOOK方式。
(2)问题
1)我已提取出了VNC中的驱动方式抓屏方法。
但在分析HOOK方式时,发现没有HOOK DLL也可以抓屏,而且CPU占有率也不是很高。怀疑是用全屏的方式定时抓的。
2)双缓冲管理方法是什么意思?有朋友可以解释一下吗?
我的MSN:,有从事这方面开发的程序员交流一下
2004/10/14 15:57 | fastxyf
# re: 高效屏幕录制
双缓冲或者多缓冲的技术去看看DirectShow的pin的采样数据区分配算法
2004/10/20 5:00 | jiangsheng
# re: 高效屏幕录制
请问VNC不能捕获WINDOWS MEDIA PLAYER REALPLAY 播放的视频,大家最近采用什么来截屏啊,用DIRECTSHOW能不能捕获啊,我用directdraw捕获也捕获不到,windows media player 播放的视频,捕获结果就是屏幕+黑屏(播放的视频)
2004/12/8 16:43 | 胡胡
# re: 高效屏幕录制
to softworm,是不是在故弄玄虚呀,mirror driver的源码能看出什么名堂来,你能否说说看,比如Applications如何通过GDI或者是其他方式取得屏幕图像数据的。
2004/12/20 12:40 | hhh
2005/2/26 10:21 | 过客
# re: 高效屏幕录制
我用bitblt来截屏,鼠标会闪烁,
如果用DirectX截屏,是否可以避免鼠标会闪烁?
2005/3/7 21:28 | WT
# re: 高效屏幕录制
双缓冲可以避免闪烁
2005/3/24 9:07 | heifei
# re: 高效屏幕录制
swordxie是用什么方法抓屏啊?
是不是DirectX的效率最高啊?
2005/4/8 7:00 | xiaoxiao
# re: 高效屏幕录制
其实可以直接用winvnc中间的那两个文件,*.sys & *.dll,
winvnc源码中封装了对他们的调用。可以看看源码。
况且搞一个mirror也没有什么了不起。
2005/5/29 9:48 | win_dev@hotmail.com

# re: 高效屏幕录制
可以使用openinputdesktop获得当前活动的桌面来截屏。具体代码可以i参考vnc的源代码。
2005/6/4 10:33 | jiangsheng

# re: 高效屏幕录制
屏幕捕获,可以只采用BITBLT的方式,在网络情况好的情况下,可以达到每秒15帧左右,主要是因为GETDIBS这个函数花费了太多的时间(大约30-50ms一帧)有谁有方法取代这个函数吗???
读取数据我用的是读显存缓冲区,内存COPY
2005/8/31 5:26 | 猎人

# re: 高效屏幕录制
GDI32
DirectX is much slower
2005/10/5 15:56 | jiangsheng
# re: 高效屏幕录制
不知道那里可以找到VNC的代码文档,干看代码的话很痛苦啊~~
2005/10/25 0:43 | Kim
# re: 高效屏幕录制
花了几天时间硬着头皮分析了realvnc的代码(初学者,刚拿到代码的时候都不知道程序流程是什么样的,汗),主要是想把其中屏幕截取的部分拿出来单独做个屏幕录取的功能。程序别别扭扭地有个模样了,这时候我发现调用BitBlt函数的时候鼠标会闪烁,晕,回头看vnc运行的情况,发现vnc server端的主机鼠标也会闪,不过不是特别明显。有两个问题想不通,一是display那部分的代码我几乎没改,直接拿来用,为什么好像我的闪得厉害些(错觉??);二是如何能避免鼠标闪烁?看到有同志说是用双缓冲,不懂,只知道双缓冲往屏幕上贴图的时候用,不知道截屏也要用。唉,看了别人的代码,就知道自己有多少水水了。不过,整个vnc代码基本被我看懂了,呵呵,收获啊,网上居然没有初学者文档,没有人写一份么?
2005/11/5 9:47 | DryFisHH
# re: 高效屏幕录制
又用directdraw直接读显存试了一下,发现大部分的CPU都用在memcpy()从显存复制数据上了,对此我非常不解,用memcpy()复制同样大小的非显存的内存数据CPU使用率只有一点点,而且写入同样大小的内存数据到显存,CPU使用率也不是很高,不知为何唯独复制出来的如此耗费CPU
2006/4/5 7:36 | w_anthony
# re: 高效屏幕录制
不知Mirror Driver的原理是什么,是截屏的时候是根据画面变化复制一部分的变化区数据吗?那是不是和HOOK差不多了,为什么上面的说一者CPU使用率低,一者CPU使用率高啊?希望哪位提点一下,小弟没有源码
2006/4/5 7:41 | w_anthony
# re: 高效屏幕录制
关于Bitblt耗时的问题, 其实是硬件结构决定的, 并不是Bitblt慢。
Bitblt的优化做的非常的精良,有兴趣的可以参考一下MSDN中的光栅操作码的介绍。
针对与截取屏幕,我以前在非常古老的计算机上作过测试, DELPHI + GDI 和 VC + DirectX的速度相近,甚至前者还略略胜出些。 所以说, 在这个方面, DirectX并无优势可言。
2006/4/21 2:55 | Whoo
# re: 高效屏幕录制
使用Bitblt拷贝屏幕内容, 其数据需要从显存传输到内存,经过低速繁忙的总线,自然比从内存到内存的数据拷贝慢得多。
不过现在AGP(4x, 8x)的广泛使用以及pcix的开始, 这个瓶颈正在逐步的消失。
显存=>内存 vs 内存=>内存
对于老式机器来说(低速agp,甚至是pci),差别至少是一个数量级,甚至是两个。 对于当前的流行机器来说,应该在5倍以内。可以预见,如果pcix应用起来, 有一天从显存拷贝数据比从内存拷贝快也不是没有可能。
2006/4/23 21:29 | Whoo
# re: 高效屏幕录制
针对 显存 =〉内存 的瓶颈, 我还有个听起来很悖论的猜测:那就是某些低档的集成主板或者显卡,处于节省成本的原因,划分了一部分的系统内存当成显存来用。
如果结构合理的话,这个瓶颈就自然消失了。
2006/4/23 21:39 | Whoo
# re: 高效屏幕录制
请问楼上,如果是显存=〉内存存在瓶颈以至于速度慢,那么为什么内存=〉显存速度就快呢?而且Mirror Driver的也总要有个显存=〉内存的步骤吧,所以我觉得速度慢不完全是这个原因。
它应该还经过了些别的步骤吧,问题是用什么可以绕过这些步骤。
2006/5/2 20:41 | w_anthony
# re: 高效屏幕录制
//snk
这样可以映射显存,要在内核模式下运行,取得显卡的HANDLER首先,EngDeviceIOControl要自己从导入表中算出来,效果并没有想像的好,读写显存慢的很
int MapVideoMemory(){
DWORD NumRet;
static BOOL bFirst=TRUE;
VIDEO_MEMORY videoMemory = {0};
VIDEO_MEMORY_INFORMATION videoMemoryInformation = {0};
if(globalDrv && funcList.EngDeviceIoControl && bFirst){
DbgPrint("MapVideoMemory");
__try{
VIDEO_MODE_INFORMATION modeInformation;
funcList.EngDeviceIoControl(globalDrv,IOCTL_VIDEO_QUERY_CURRENT_MODE,NULL,
0,&modeInformation,sizeof(VIDEO_MODE_INFORMATION),&NumRet);
DbgPrint("stride %d",modeInformation.ScreenStride);
DbgPrint("bitmap width %d VisScreenWidth %d",modeInformation.VideoMemoryBitmapWidth,
modeInformation.VisScreenWidth);
DbgPrint("NumberRedBits %d NumberGreenBits %d NumberBlueBits %d",modeInformation.NumberRedBits
,modeInformation.NumberGreenBits,modeInformation.NumberBlueBits);
DbgPrint("RedMask %d GreenMask %d BlueMask %d 0x%x",modeInformation.RedMask
,modeInformation.GreenMask,modeInformation.BlueMask,modeInformation.AttributeFlags);
funcList.EngDeviceIoControl(globalDrv,IOCTL_VIDEO_MAP_VIDEO_MEMORY,&videoMemory,
sizeof(VIDEO_MEMORY),&videoMemoryInformation,sizeof(VIDEO_MEMORY_INFORMATION),&NumRet);
bFirst=FALSE;
uFramebufferLength=videoMemoryInformation.FrameBufferLength;
if(videoMemoryInformation.FrameBufferLengthuFramebufferLength=videoMemoryInformation.VideoRamLength;
}
pGVideo=(char*)videoMemoryInformation.FrameBufferBase;

DbgPrint("FrameBufferBase 0x%x FrameBufferLength 0x%x VideoRamBase 0x%x VideoRamLength 0x%x",
pGVideo,uFramebufferLength,videoMemoryInformation.VideoRamBase,
videoMemoryInformation.VideoRamLength);
}
__except(EXCEPTION_EXECUTE_HANDLER){
DbgPrint("Catch Error When MapVideoMemory");
}
}
CreateVideoShareMemory();
return 0;
}
2006/7/14 21:42 | snk
# re: 高效屏幕录制
各位高手:
象HyperSnap那样的抓图软件截图方式很多, 其中包括扩展活动窗口截图 和 滚屏截图, 用扩展活动窗口方式截图时, 能设置要截取的活动窗口的宽和高的像素大小(可以大于屏幕的像素大小),并能截取该窗口完整的图像,怎样编程实现啊???
另, 像snapit那样的抓图软件能进行DOS截屏, 又怎样编程实现呢???我想大概分以下两种情况来分析
1. 在Windows Vista, Windows XP, Windows 2000 Professional, Windows NT Workstation, Windows Me, Windows 98, or Windows 95上运行的DOS窗口时, 如何获取DOS窗口的句柄, 因为一旦获取窗口的句柄, 就能轻松编程截取该窗口的图像.在Windows XP及其后的Windows平台, 有GetConsoleWindow函数获取DOS窗口的句柄, 而Windows 98, Windows 95却没有, 怎样才能在上述所有平台上获取DOS窗口的句柄呢?? 在全屏DOS窗口下, 情况是否相同呢??

2. 在纯DOS环境下, 怎样做到按一下某个按键, 自动在后台启动指定的程序并能截取当前DOS屏幕的图像??(如果指定的程序已经启动, 则截取当前DOS屏幕的图像), 再按一下另一个键, 则退出指定的程序, 上述如何编程实现啊 
2006/7/25 18:13 | 林先生
# re: 高效屏幕录制
我也很奇怪,显存 =〉内存很慢,直接写显存似乎很快。
另外我也有GDI方式的屏幕捕获,效果比mirror也差不太多。
另外还有直接HOOK 显卡驱动的方式,这种方式效率应该是最高的,我还没有完全做好。
2006/8/1 1:02 | shenming
# re: 高效屏幕录制
Cannot open include file: 'aclui.h': No such file or directory
这个文件找不到,请问是什么原因 ?请多多指教。我的邮箱:
添加sdk,应该就可以了吧
2006/8/11 2:05 | juney
# re: 高效屏幕录制
我最近在写一个类似REALVNC的东西,实现了最简单的抓屏和鼠标/键盘操作,做完后才发现了频繁BitBlt非常之消耗CPU的问题.简直气炸了.如果用我自已的笔记本(迅驰1.5,ATI9700显卡)做SERVER的话,CPU只占30~40%,但如果用我公司的烂机器跑SERVER的话(P4,烂2D显卡,4M显存那种),CPU跑到80~99%,真是太慢啦,查来查去原来就是这个BitBlt,而且更奇怪的是,我把这部分代码提出来,在另一个程式里跑,也只有40~50%啊,真是怪死了.
2006/8/22 0:09 | Leon
# re: 高效屏幕录制
最近我也需要写截屏方面的代码,我用GDI方式截屏时,截不下鼠标和播放的视频,是不是用DirectShow方式就可以了呢?另外读显存是不是能够把鼠标和视频都截下来呢?有没有读显存的资料呢?
2006/8/27 19:45 | clint.guo
# re: 高效屏幕录制
to snk 和所有热心人,
EngDeviceIoControl(globalDrv,IOCTL_VIDEO_QUERY_CURRENT_MODE,NULL,..)
函数中 globalDrv怎么获得?
2006/11/2 1:58 | freestyle
# 回复: 高效屏幕录制
直接memcpy显存 显然很慢
内存到内存快得多
问题在于这是显存和内存的数据复制
想BitBlt和memcpy都是不符合性能要求的
另 显卡驱动不是IRP驱动的 IRP模型比较慢一点
2007/1/2 1:50 | developer
# 回复: 高效屏幕录制
看看我做的

有GDI和DRIVER2种。
2007/4/5 7:39 | shen ming
# 回复: 高效屏幕录制
查过一些资料,好像用netmeeting sdk和windows media format sdk也可以做这些远程控制的软件,这里怎么没有谈到这些的,是不是效率比较低??
2007/5/20 19:18 | yhs200
# 回复: 高效屏幕录制
windows media sdk效率相当低,我的机子P43.0,6600显卡,用了之后cpu占用高达90%,开个大点的应用就很慢了。
2007/6/2 23:16 | Coolboy

本文引用的地址为http://blog.joycode.com/jiangsheng/posts/10410.aspx
阅读(5271) | 评论(0) | 转发(0) |
0

上一篇:Vncconfig功能分析

下一篇:vnc video update

给主人留下些什么吧!~~