之前在网上查找的关于DXGI的截屏demo中成功实现了利用截屏来生成视频并进行屏幕广播,但是最近使用之前的demo时遇到了一个问题:
==》在一些机器上使用如下代码获取图像数据及其每行数据的像素数:
IDXGISurface *hStagingSurf = NULL;
DXGI_MAPPED_RECT mappedRect;
hr = hStagingSurf->Map(&mappedRect, DXGI_MAP_READ);
可是发现如下问题,在一些机器上获取得到的mappedRect->Pitch/4==width(显示器的宽)而另外一些电脑则获取到的是mappedRect->Pitch/4!=width(显示器的宽),因此如果忽略掉这个这问题的处理的话,往往会可能出现一开始分配的存储数据的缓存大小不够,导致memcpy时出现越界导致段错误的情况。
为避免上面的情况导致段错误的发生,需要对mappedRect->Pitch/4与width是否相等进行分情况处理。
==>mappedRect->Pitch/4==width是直接拷贝数据到缓存中再进行后续编解码处理。
==>mappedRect->Pitch/4!=width(显示器的宽)时需要将正确的数据进行拷贝然后再进行后续的处理。
至于如何进行正确的拷贝呢,就需要知道发生这种情况的原因是什么:
在《Width vs. Pitch (Direct3D 9)》这一篇windows的接口说明的文章中提到了:
Pitch是两个内存地址之间的距离,以字节为单位,表示一个位图行的开始和下一个位图行的开始。因为间距(Pitch)是以字节而不是像素来测量的,所以640x480x8曲面的间距值与具有相同尺寸但像素格式不同的曲面的间距(Pitch)值非常不同。此外,Pitch值有时反映Direct3D保留为缓存的字节,因此假设节距只是宽度乘以每个像素的字节数是不安全的。相反,如下图1.1所示,将宽度(width)和间距(Pitch)之间的差异可视化。在这个图中,前缓冲区和后缓冲区都是640x480x8,缓存是384x480x8。
图1.1 width和pitch数据存储结构对比
从上面的说明可以知道,使用map获取得到的DXGI_MAPPED_RECT的图像数据及Pitch值并不是单单我们理解的显示器中的height和width的格式来的,而是会根据显卡和硬件不同它会有时带有一点缓存(字节对齐时伴随的),因此在处理从map获取得到的DXGI_MAPPED_RECT的图像数据分为上述两种情况来处理。
DXGI_MAPPED_RECT mappedRect;
IDXGISurface *hStagingSurf = NULL;
hr = hStagingSurf->Map(&mappedRect, DXGI_MAP_READ);
if (SUCCEEDED(hr))
{
nImgSize = abs((Coordinates[mode_cap].right - Coordinates[mode_cap].left)*(Coordinates[mode_cap].bottom - Coordinates[mode_cap].top) * 4);
if ((mappedRect.Pitch / 4) == abs(Coordinates[mode_cap].right - Coordinates[mode_cap].left))
{
memcpy((BYTE*)pImgData, mappedRect.pBits, nImgSize);
}
else
{
int count_tmp = abs(Coordinates[mode_cap].bottom - Coordinates[mode_cap].top);//列数
int count_tmp2 = abs(Coordinates[mode_cap].right - Coordinates[mode_cap].left);//每一行的像素数
int diff_tmp = (mappedRect.Pitch / 4 - count_tmp2)*4;//每一行与需要的实际差异
BYTE *ptr_tmp = mappedRect.pBits;
for (int i = 0; i < count_tmp; i++)
{
memcpy((BYTE*)pImgData + i*count_tmp2*4, ptr_tmp, count_tmp2*4);
ptr_tmp = ptr_tmp + count_tmp2*4 + diff_tmp;
}
}
hStagingSurf->Unmap();
}
else
{
xhlog("QueryFrame error5: 'hStagingSurf->Map(&mappedRect, DXGI_MAP_READ)'\n");
}
参考链接:https://docs.microsoft.com/zh-cn/windows/win32/direct3d9/width-vs--pitch?redirectedfrom=MSDN
每写一篇文章都不容易,尊重别人的知识产权才是对自己和技术的尊重。为了避免发生知识产权被侵权的情况,我决定做出以下声明:
1.博客中标注原创的文章,版权归原作者 吴豪乐工作室 所有;
2.未经原作者允许不得转载本文内容,否则将视为侵权;
3.转载或者引用本文内容请注明来源及原作者;
4.对于不遵守此声明或者其他违法使用本文内容者,本人依法保留追究权等。