111 lines
3.4 KiB
C
111 lines
3.4 KiB
C
#include <windows.h>
|
|
#include <vfw.h>
|
|
|
|
typedef struct
|
|
{
|
|
PAVISTREAM m_ps;
|
|
PAVISTREAM m_psCompressed;
|
|
AVISTREAMINFO m_strhdr;
|
|
AVICOMPRESSOPTIONS m_opts;
|
|
PAVIFILE m_pfile;
|
|
BITMAPINFOHEADER m_alpbi;
|
|
} AVIWRITER;
|
|
|
|
static AVIWRITER avi;
|
|
static int frame;
|
|
static unsigned char* vbuffer;
|
|
static ID3D11Texture2D* vresolvedTexture;
|
|
static ID3D11Texture2D* vstagingTexture;
|
|
static D3D11_MAPPED_SUBRESOURCE vanalysisResource;
|
|
static D3D11_TEXTURE2D_DESC vstagingDesc;
|
|
extern ID3D11Texture2D* backBufferPtr;
|
|
extern ID3D11Device* device;
|
|
extern ID3D11DeviceContext* deviceContext;
|
|
|
|
void InitVideo()
|
|
{
|
|
frame = 0;
|
|
|
|
AVIFileInit();
|
|
if (AVIFileOpen(&avi.m_pfile, "out.avi", OF_WRITE | OF_CREATE, NULL) != 0)
|
|
return;
|
|
|
|
memset(&avi.m_strhdr, 0, sizeof(avi.m_strhdr));
|
|
avi.m_strhdr.fccType = streamtypeVIDEO;
|
|
avi.m_strhdr.fccHandler = 0;
|
|
avi.m_strhdr.dwScale = 1;
|
|
avi.m_strhdr.dwRate = 60;
|
|
avi.m_strhdr.dwSuggestedBufferSize = 3 * screenWidth * screenHeight;
|
|
SetRect(&avi.m_strhdr.rcFrame, 0, 0, screenWidth, screenHeight);
|
|
|
|
if (AVIFileCreateStream(avi.m_pfile, &avi.m_ps, &avi.m_strhdr) != 0)
|
|
return;
|
|
|
|
memset(&avi.m_opts, 0, sizeof(avi.m_opts));
|
|
avi.m_opts.fccType = streamtypeVIDEO;
|
|
//avi.m_opts.fccHandler = mmioFOURCC('d','i','v','x'); // divx
|
|
avi.m_opts.fccHandler = mmioFOURCC('x','2','6','4'); // huffman uv
|
|
//avi.m_opts.fccHandler = mmioFOURCC('D', 'I', 'B', ' '); // uncompressed frames
|
|
avi.m_opts.dwKeyFrameEvery = 1;
|
|
avi.m_opts.dwQuality = 100;
|
|
avi.m_opts.dwBytesPerSecond = 0;
|
|
avi.m_opts.dwFlags = AVICOMPRESSF_DATARATE | AVICOMPRESSF_KEYFRAMES;
|
|
|
|
if (AVIMakeCompressedStream(&avi.m_psCompressed, avi.m_ps, &avi.m_opts, NULL) != AVIERR_OK)
|
|
return;
|
|
|
|
memset(&avi.m_alpbi, 0, sizeof(avi.m_alpbi));
|
|
avi.m_alpbi.biSize = sizeof(avi.m_alpbi);
|
|
avi.m_alpbi.biWidth = screenWidth;
|
|
avi.m_alpbi.biHeight = screenHeight;
|
|
avi.m_alpbi.biPlanes = 1;
|
|
avi.m_alpbi.biBitCount = 24;
|
|
avi.m_alpbi.biCompression = BI_RGB;
|
|
if (AVIStreamSetFormat(avi.m_psCompressed, 0, &avi.m_alpbi, sizeof(avi.m_alpbi)) != 0)
|
|
return;
|
|
|
|
vbuffer = (unsigned char *)malloc(screenWidth*screenHeight * 3 + 1);
|
|
if (!vbuffer)
|
|
return;
|
|
|
|
backBufferPtr->GetDesc(&vstagingDesc);
|
|
vstagingDesc.Usage = D3D11_USAGE_DEFAULT;
|
|
vstagingDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
|
vstagingDesc.BindFlags = 0;
|
|
vstagingDesc.SampleDesc.Count = 1;
|
|
device->CreateTexture2D(&vstagingDesc, NULL, &vresolvedTexture);
|
|
|
|
vstagingDesc.Usage = D3D11_USAGE_STAGING;
|
|
vstagingDesc.CPUAccessFlags |= D3D11_CPU_ACCESS_READ;
|
|
device->CreateTexture2D(&vstagingDesc, NULL, &vstagingTexture);
|
|
}
|
|
|
|
void VideoFrame()
|
|
{
|
|
deviceContext->ResolveSubresource(vresolvedTexture, 0, backBufferPtr, 0, vstagingDesc.Format);
|
|
deviceContext->CopyResource(vstagingTexture, vresolvedTexture);
|
|
deviceContext->Map(vstagingTexture, 0, D3D11_MAP_READ, 0, &vanalysisResource);
|
|
int* image = (int*)vanalysisResource.pData;
|
|
for (int y = 0; y < screenHeight; ++y)
|
|
for (int x = 0; x < screenWidth; ++x)
|
|
{
|
|
int pixel = image[screenWidth * y + x];
|
|
int* bufPtr = (int*)&vbuffer[(screenWidth * (screenHeight - y - 1) + x) * 3];
|
|
*bufPtr = ((pixel & 0x000000FF) << 16) | (pixel & 0x0000FF00) | ((pixel & 0x00FF0000) >> 16);
|
|
}
|
|
deviceContext->Unmap(stagingTexture, 0);
|
|
if (AVIStreamWrite(avi.m_psCompressed, frame++, 1, vbuffer, 3 * screenWidth * screenHeight, AVIIF_KEYFRAME, NULL, NULL) != 0)
|
|
throw;
|
|
}
|
|
|
|
void DoneVideo()
|
|
{
|
|
free(vbuffer);
|
|
|
|
AVIStreamClose(avi.m_ps);
|
|
AVIStreamClose(avi.m_psCompressed);
|
|
AVIFileClose(avi.m_pfile);
|
|
AVIFileExit();
|
|
}
|
|
|