C++ Directshow在捕获期间调整大小

C++ Directshow在捕获期间调整大小,c++,window,directshow,capture,C++,Window,Directshow,Capture,我有一个directshow过滤器,我使用下面的代码捕获屏幕 首先,我使用 EnumWindows 这给了我正确的答案 HDC hMemDC; HBITMAP hBitmap, hOldBitmap; int nX, nY, nX2, nY2; int nWidth, nHeight; if (IsRectEmpty(lpRect)) return NULL; hMemDC = CreateCompatibleDC(hScrDC)

我有一个directshow过滤器,我使用下面的代码捕获屏幕

首先,我使用

EnumWindows
这给了我正确的答案

HDC         hMemDC;
HBITMAP     hBitmap, hOldBitmap;
int         nX, nY, nX2, nY2;
int         nWidth, nHeight;

if (IsRectEmpty(lpRect))
  return NULL;

hMemDC = CreateCompatibleDC(hScrDC);

nX  = lpRect->left;
nY  = lpRect->top;
nX2 = lpRect->right;
nY2 = lpRect->bottom;

nWidth  = nX2 - nX;
nHeight = nY2 - nY;

hBitmap = CreateCompatibleBitmap(hScrDC, nWidth, nHeight);

hOldBitmap = (HBITMAP) SelectObject(hMemDC, hBitmap);

BitBlt(hMemDC, 0, 0, nWidth, nHeight, hScrDC, nX, nY, SRCCOPY); 

hBitmap = (HBITMAP) SelectObject(hMemDC, hOldBitmap);

GetDIBits(hScrDC, hRawBitmap, 0, nHeightScanLines, pData, pHeader, DIB_RGB_COLORS);     

DeleteDC(hMemDC);
问题是当我调整我试图捕获的窗口的大小时,它应该是这样的

但结果是这样的


我感觉这是由于图像宽度的像素计数造成的,但我不确定如何调整directshow过滤器的输出宽度和高度?

当过滤器提供的视频样本的尺寸与协商的尺寸不同时,可能会出现此问题


如果筛选器只捕获窗口内容而不进行裁剪或填充,并且窗口大小发生变化,则应与下游筛选器重新协商媒体格式。本文介绍了不同的解决方案。另外,请参见以获取示例

造成的影响是,缓冲区与过滤器引脚连接上的介质类型不匹配。如中所述,如果过滤器(引脚)错误地处理扩展视频步幅更改,通常会发生这种情况


然而,在您的情况下,更可能的情况是您在尝试调整大小时丢失了正确的媒体类型。您的代码实际上没有进行任何大小调整,并且您可能希望进行大小调整,因此填充的缓冲区最终与连接上的媒体类型不匹配。

您可以共享执行实际大小调整的代码和执行渲染的代码吗?在某个地方,一个“pitch”变量似乎被忽略了。上面的代码就是我用来进行渲染的代码(在FillBuffer方法中)。对于调整大小,我实际上只是将lpRect更改为窗口的矩形。对,但是如何将这些位保存到文件和/或渲染到屏幕上?我怀疑你的问题就在那里。我在“HRESULT CScreenCap::FillBuffer(IMediaSample*pSample)”中获取样本,然后使用“pSample->GetPointer(&pData);”然后pData被传递到Dibits中。我怀疑在整个捕获和转换过程中的某个地方——你们中的一个“宽度”变量不能被4整除。您应该熟悉“表面步幅”,以及它与BMP文件和/或屏幕上的光点的关系。本页底部的更多详细信息:那么我是否正确地将ReceiveConnection函数添加到我的directshow筛选器中?是的,如果需要增加缓冲区大小。有关更多信息,请参阅。但是,这可能比使用
QueryAccept
方法更昂贵。因此,为了调整大小,我是否应该创建一个新的BITMAPINFO和VIDEOINFOHEADER并设置一个新的AM_媒体类型?您的过滤器在输出引脚上与特定媒体类型连接。您需要分别
FillBuffer
,以匹配此媒体类型。如果只更改一些
RECT
,没有人会为您调整负载数据的大小。因此,第一件事是缓冲区必须与媒体类型一致(产生效果的直接原因)。下一步是,如果你需要调整大小,发布更多的细节,何时以及如何完成。啊,好的!当我跟踪的窗口调整大小时,我试图使缓冲区调整大小。假设您有800x600窗口,并且您的过滤器连接了800x600视频媒体类型。然后将窗口的大小调整为640x480。您应该重新协商媒体类型,在此之前,您不能只推送视频大小为640x480的媒体。您有一些更改介质类型的选项,但请做好准备,以免失败:在运行时更改介质类型不是筛选器的强制功能,因此许多筛选器无法在图形运行时更改介质类型。这似乎更有意义!在阅读了msdn文档之后,我是否正确地说最好的方法是首先使用QueryAccept(下游),如果失败,那么尝试ReceiveConnection?