1、是给每帧图像加一个边框, 显示出来的视频的每一帧上下左右的几个像素都被填充的颜色覆盖掉了。
HRESULT Demo::ShowVideo(D3DFORMAT Format, BYTE * image, int width, int height, int borderWidth)
{
HRESULT hr;
int resizeYuvW = width;
int resizeYuvH = height;
// 锁定 swap-chain 表面.
D3DLOCKED_RECT lr;
hr = pPlainSurf_->LockRect(&lr, NULL, D3DLOCK_NOSYSLOCK);
if (FAILED(hr))
{
return hr;
}
BYTE* newImage = new BYTE[resizeYuvW*resizeYuvH * 3 / 2];
memcpy(newImage, image, resizeYuvW*resizeYuvH * 3 / 2);
// 将数据拷贝到 Direct3D surface.
BYTE *dest = (BYTE*)lr.pBits;
DrawBorder(newImage, resizeYuvW, resizeYuvH, 1, borderWidth);
BYTE *src = newImage;
int stride = lr.Pitch;
CopyFrameToD3DRectYV12(src, dest, resizeYuvW, resizeYuvH, stride);
delete[] newImage;
hr = pPlainSurf_->UnlockRect();
if (FAILED(hr))
{
return hr;
}
// 获取下一个表面.
IDirect3DSurface9 *pSurface = NULL;
hr = pSwapChain_->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &pSurface);
if (FAILED(hr))
{
return hr;
}
RECT srcRect, destRect;
::SetRect(&srcRect, 0, 0, resizeYuvW, resizeYuvH);
if (borderWidth != 0)
{
// 填充颜色.
hr = pDevice_->ColorFill(pSurface, NULL, D3DCOLOR_ARGB(0, 60, 210, 60));
::SetRect(&destRect, borderWidth, borderWidth, width_ - borderWidth, height_ - borderWidth);
}
else
{
::SetRect(&destRect, 0, 0, width_, height_);
}
hr = pDevice_->StretchRect(pPlainSurf_, &srcRect, pSurface, &destRect, D3DTEXF_LINEAR);
if (FAILED(hr))
{
SafeRelease(&pSurface);
return hr;
}
// 显示.
hr = pSwapChain_->Present(NULL, NULL, NULL, NULL, 0);
SafeRelease(&pSurface);
return hr;
}
void Demo::DrawBorder(BYTE * src, int w, int h, int num, int border)
{
for (int i = 0; i < num; i++)
{
for (int m = 0; m < h; m++)
{
for (int n = 0; n < w; n++)
{
if ((m < border) | (m > (h - border)) | (n < border) | (n > (w - border)))
{
src[m*w + n] = 105;
}
}
}
BYTE *U = src + w * h;
BYTE *V = src + w * h * 5 / 4;
for (int m = 0; m < h/2; m++)
{
for (int n = 0; n < w/2; n++)
{
if ((m < border/2) | (m > (h - border)/2) | (n < border/2) | (n >= (w - border)/2))
{
U[m*w / 2 + n] = 184;
V[m*w / 2 + n] = 63;
}
}
}
}
}
2、是给画布填充颜色,然后把显示video的部分上下左右各缩进几个像素
HRESULT Demo::ShowVideo(D3DFORMAT Format, BYTE * image, int width, int height, int borderWidth)
{
HRESULT hr;
int resizeYuvW = width;
int resizeYuvH = height;
// 锁定 swap-chain 表面.
D3DLOCKED_RECT lr;
hr = pPlainSurf_->LockRect(&lr, NULL, D3DLOCK_NOSYSLOCK);
if (FAILED(hr))
{
return hr;
}
// 将数据拷贝到 Direct3D surface.
BYTE *dest = (BYTE*)lr.pBits;
BYTE *src = image;
int stride = lr.Pitch;
CopyFrameToD3DRectYV12(src, dest, resizeYuvW, resizeYuvH, stride);
hr = pPlainSurf_->UnlockRect();
if (FAILED(hr))
{
return hr;
}
// 获取下一个表面.
IDirect3DSurface9 *pSurface = NULL;
hr = pSwapChain_->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &pSurface);
if (FAILED(hr))
{
return hr;
}
RECT srcRect, destRect;
::SetRect(&srcRect, 0, 0, resizeYuvW, resizeYuvH);
if (borderWidth != 0)
{
// 填充颜色.
hr = pDevice_->ColorFill(pSurface, NULL, D3DCOLOR_ARGB(0, 60, 210, 60));
::SetRect(&destRect, borderWidth, borderWidth, width_ - borderWidth, height_ - borderWidth);
}
else
{
::SetRect(&destRect, 0, 0, width_, height_);
}
hr = pDevice_->StretchRect(pPlainSurf_, &srcRect, pSurface, &destRect, D3DTEXF_LINEAR);
if (FAILED(hr))
{
SafeRelease(&pSurface);
return hr;
}
// 显示.
hr = pSwapChain_->Present(NULL, NULL, NULL, NULL, 0);
SafeRelease(&pSurface);
return hr;
}
void Demo::CopyFrameToD3DRectYV12(BYTE* src, BYTE* dest, int width, int height, int stride)
{
int bufferH = 1080;
int i = 0;
for (i = 0; i < height; i++)
{
memcpy(dest + i * stride, src + i * width, width);
}
for (i = 0; i < height / 2; i++)
{
memcpy(dest + stride * bufferH + i * stride / 2, src + width * height + width * height / 4 + i * width / 2, width / 2);
}
for (i = 0; i < height / 2; i++)
{
memcpy(dest + stride * bufferH + stride * bufferH / 4 + i * stride / 2, src + width * height + i * width / 2, width / 2);
}
}