【问题标题】:Directshow Resize During CaptureDirectshow 在捕获期间调整大小
【发布时间】:2012-01-26 21:34:08
【问题描述】:

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

首先我使用

获得窗口矩形
EnumWindows

这给了我 lpRect

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 过滤器的输出宽度和高度?

【问题讨论】:

  • 您能分享实际调整大小的代码和进行渲染的代码吗?某处似乎“音高”变量被忽略了。
  • 上面的代码是我用来做渲染的(在FillBuffer方法中)。对于调整大小,我实际上只是将 lpRect 更改为窗口的矩形。
  • 对,但是您如何将这些位保存到文件和/或将它们呈现到屏幕上?我怀疑你的问题出在那儿。
  • 我在“HRESULT CScreenCap::FillBuffer(IMediaSample *pSample)”中获取样本,然后使用“pSample->GetPointer(&pData);”然后 pData 被传递到 DIBits
  • 我怀疑在所有这些捕获和转换过程中的某个地方 - 你们中的一个“宽度”变量不能被 4 整除。您应该熟悉“表面步幅”以及它与 BMP 文件和/或blitting到屏幕上。本页底部的更多详细信息:msdn.microsoft.com/en-us/library/windows/desktop/…

标签: c++ window directshow capture


【解决方案1】:

您的效果是您的缓冲区与您的过滤器在其引脚连接上的媒体类型不匹配。通常,如果过滤器(引脚)不正确地处理扩展的视频步幅变化,如Handling Format Changes from the Video Renderer 中所述。

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

【讨论】:

  • 所以为了调整大小,我应该创建一个新的 BITMAPINFO 和 VIDEOINFOHEADER 并设置一个新的 AM_MEDIA_TYPE 吗?
  • 您的过滤器与输出引脚上的特定媒体类型连接。你要分别FillBuffer,来匹配这个媒体类型。如果您只更改一些RECT,没有人会为您调整有效负载数据的大小。因此,第一件事是您的缓冲区必须与媒体类型一致(您所拥有的效果的直接原因)。接下来是如果您需要调整大小,请在何时以及如何完成时发布更多详细信息。
  • 啊,好吧!当我正在跟踪的窗口被调整大小时,我试图让缓冲区调整大小
  • 假设您有 800x600 的窗口,并且您的过滤器与 800x600 视频媒体类型相关联。然后你的窗口被调整为 640x480。您应该重新协商媒体类型,在它发生之前您不能只推送 640x480 大小的视频。您有一些用于更改媒体类型的选项msdn.microsoft.com/en-us/library/windows/desktop/… 但请准备好它们可能会失败:在运行时更改媒体类型也不是过滤器的强制功能,因此许多过滤器只是无法更改媒体类型,而绘制他的跑步图。
  • 这似乎更有意义!在阅读完 msdn 文档后,我是否正确地说最好的方法是首先使用 QueryAccept (Downstream),如果失败则尝试 ReceiveConnection?
【解决方案2】:

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

如果过滤器应该只捕获窗口内容而不进行裁剪或填充并且窗口大小发生变化,那么它应该与下游过滤器重新协商媒体格式。文章Dynamic Format Changes 描述了不同的解决方案。此外,请参阅 Custom DirectShow Source Filter - Dynamic Resolution Change 以获取示例。

【讨论】:

  • 那么将 ReceiveConnection 函数添加到我的 directshow 过滤器是否正确?
  • 是的,如果您需要增加缓冲区大小。有关更多信息,请参阅Handling Dynamic Format Changes in DirectShow。不过,它可能比使用QueryAccept 方法更昂贵。
猜你喜欢
  • 2023-03-10
  • 2015-10-04
  • 1970-01-01
  • 2023-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多