求援,DirectX截屏难题

鲁夺 2012-08-08 10:24:00
问题描述:
众所周知,因为大多视频播放器使用DirectX直接写屏,所以使用GDI方法是无法来截取电影视频的。
(通过几天深挖论坛,也发现有一些自认为是大鸟的还不知道,悲剧)
通过搜索发现,网上几乎没有现成的视频截屏代码,真的希望高手能抻出援手,在下先谢过了!
要求,无论用什么方法实现视频截屏都可以(尽量不要在驱动层做文章),但源码工程要完整,
可编译,有相关原理注释。100分相赠。
...全文
343 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
鲁夺 2012-08-09
  • 打赏
  • 举报
回复
谢谢贴代码的兄弟,不过同样不是我想要的,这个问题确实挺剌手,先结了吧.
汪宁宇 2012-08-09
  • 打赏
  • 举报
回复
[Quote=引用楼主 的回复:]
问题描述:
众所周知,因为大多视频播放器使用DirectX直接写屏,所以使用GDI方法是无法来截取电影视频的。
(通过几天深挖论坛,也发现有一些自认为是大鸟的还不知道,悲剧)
通过搜索发现,网上几乎没有现成的视频截屏代码,真的希望高手能抻出援手,在下先谢过了!
要求,无论用什么方法实现视频截屏都可以(尽量不要在驱动层做文章),但源码工程要完整,
可编译,有相关原理注释。100分相赠。
[/Quote]

以前用过的DX截屏代码:

int CDemoDlg::Capture()
{
LPDIRECT3D9 g_pD3D = NULL;
D3DDISPLAYMODE ddm;
D3DPRESENT_PARAMETERS d3dpp;

IDirect3DDevice9 *g_pd3dDevice;
IDirect3DSurface9 *pSurface;

ZeroMemory(&d3dpp,sizeof(D3DPRESENT_PARAMETERS));
ZeroMemory( &d3dpp, sizeof(d3dpp) );


if((g_pD3D=Direct3DCreate9(D3D_SDK_VERSION))==NULL)
{
return 1;
}
if(FAILED(g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&ddm)))
{
return 1;
}

d3dpp.Windowed=TRUE;
d3dpp.Flags=D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
d3dpp.BackBufferFormat=ddm.Format;
d3dpp.BackBufferHeight=ddm.Height;
d3dpp.BackBufferWidth=ddm.Width;
d3dpp.MultiSampleType=D3DMULTISAMPLE_NONE;
d3dpp.SwapEffect=D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow=::GetDesktopWindow();
d3dpp.PresentationInterval=D3DPRESENT_INTERVAL_DEFAULT;
d3dpp.FullScreen_RefreshRateInHz=D3DPRESENT_RATE_DEFAULT;


if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,::GetDesktopWindow(),D3DCREATE_SOFTWARE_VERTEXPROCESSING ,&d3dpp,&g_pd3dDevice)))
{
return 1;
}

if(FAILED(g_pd3dDevice->CreateOffscreenPlainSurface(ddm.Width, ddm.Height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &pSurface, NULL)))
{
return 1;
}

g_pd3dDevice->CreateOffscreenPlainSurface(1024, 768,
D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &pSurface, NULL);
g_pd3dDevice->GetFrontBufferData(0, pSurface);

char szFileName[512];
CTime tmNow = CTime::GetCurrentTime();

wsprintf(szFileName,"%s\\%04d-%02d-%02d %02d%02d%02d.jpg",GetExePath(),tmNow.GetYear(),
tmNow.GetMonth(),tmNow.GetDay(),tmNow.GetHour(),tmNow.GetMinute(),tmNow.GetSecond());
D3DXSaveSurfaceToFile(szFileName,D3DXIFF_JPG,pSurface,NULL,NULL);//保存为 jpg格式

pSurface->Release();
g_pd3dDevice->Release();
g_pD3D->Release ();

return 0;

}


void CDemoDlg::CaptureD3D()
{
char szFileName[512];
CTime tmNow = CTime::GetCurrentTime();

wsprintf(szFileName,"%s\\%04d-%02d-%02d %02d%02d%02d.jpg",GetExePath(),tmNow.GetYear(),
tmNow.GetMonth(),tmNow.GetDay(),tmNow.GetHour(),tmNow.GetMinute(),tmNow.GetSecond());

HWND hWnd = ::GetDesktopWindow();//m_hWnd;//
HWND hCS = ::FindWindow(_T("Valve001"),_T("Counter-Strike"));

::SetActiveWindow(hCS);
if(FAILED(InitD3D(::GetDesktopWindow())))
return;

g_pd3dDevice->GetFrontBufferData(0, g_pSurface);
D3DXSaveSurfaceToFile(szFileName,D3DXIFF_JPG,g_pSurface,NULL,NULL); //Save to File


D3DLOCKED_RECT lockedRect;
if(FAILED(g_pSurface->LockRect(&lockedRect,NULL,D3DLOCK_NO_DIRTY_UPDATE|D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY)))
{
ErrorMessage("Unable to Lock Front Buffer Surface");
return;
}
for(int i=0;i<gScreenRect.bottom;i++)
{
memcpy((BYTE*)pBits+(gScreenRect.bottom-i-1)*gScreenRect.right*BITSPERPIXEL/8,(BYTE*)lockedRect.pBits+i*lockedRect.Pitch,gScreenRect.right*BITSPERPIXEL/8);//g_d3dpp.BackBufferHeight*g_d3dpp.BackBufferWidth*4);
}
g_pSurface->UnlockRect();
::InvalidateRect(hWnd,NULL,false);
//Capture();
}


//////////////////////////////////////////////////////////////////////////
// D3D截图函数

UINT_PTR nTimerId=0;
HMENU ghMenu=NULL;
RECT gScreenRect ={0,0,0,0};
bool gbCapturing=false;

HWND ghWnd;
HDC hBackDC=NULL;
LPVOID pBits=NULL;
HBITMAP hBackBitmap=NULL;
HBITMAP hOldBitmap=NULL;

int nDisplayWidth;
int nDisplayHeight;

IDirect3D9* g_pD3D=NULL;
IDirect3DDevice9* g_pd3dDevice=NULL;
IDirect3DSurface9* g_pSurface=NULL;

HRESULT Reset();
void Render();
void Cleanup();
HRESULT InitD3D(HWND hWnd);
void SaveBitmap(char *szFilename,HBITMAP hBitmap);

#define WINDOW_MODE true //Not in fullscreen mode
#define BITSPERPIXEL 32
#define ErrorMessage(x) ::MessageBox(NULL,x,"Error",MB_OK|MB_ICONERROR)

CString GetExePath();



鲁夺 2012-08-09
  • 打赏
  • 举报
回复
谁做过Mirror Driver, 这种驱动能否解决视频抓屏问题?
鲁夺 2012-08-08
  • 打赏
  • 举报
回复
1 如何用代码关闭硬件加速?
2 关闭硬件加速会不会影响正在播放的电影?
lqfcu2 2012-08-08
  • 打赏
  • 举报
回复
关闭,视频硬件加速,就可以用GDI截到视频的图像了
lang14 2012-08-08
  • 打赏
  • 举报
回复
没做过这方面的东西。不过directshow是专门针对视频的,你可以找找这方面的资料
鲁夺 2012-08-08
  • 打赏
  • 举报
回复
是啊,我看了好些贴子,讨论的挺欢,可是都没有实际的成果(源码), 唉.
kbh1984 2012-08-08
  • 打赏
  • 举报
回复
抓屏的问题讨论好久了吧,应该没有合适的方法
鲁夺 2012-08-08
  • 打赏
  • 举报
回复
我不是要从某个电影里抓帧,

我的任务是针对屏幕的,屏幕上可能是电影,也可能是正在运行的游戏,但它们的一个共同点是,使用了DirectX进行屏幕读写,所以用GDI是抓取不到的。
qlizhang 2012-08-08
  • 打赏
  • 举报
回复
转,参考
用DirectShow抓取影片帧
http://www.vckbase.com/index.php/cv/334
鲁夺 2012-08-08
  • 打赏
  • 举报
回复
望高手给份源码啊,我邮箱
zhangluduo_msn_com
替换为@ .
鲁夺 2012-08-08
  • 打赏
  • 举报
回复
可否给一个完整的,可编译工程,谢谢.
Ginie 2012-08-08
  • 打赏
  • 举报
回复
视频截取用directshow就可以,通过它的ISampleGrabber这个接口就行

19,469

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧