📄 3dvideo.cpp
字号:
// Begin
/*
3DVideo.cpp - implementation of sample program that uses "grabber" library.
(c) 2005 - 2007 Aleksei Kazantsev (ajk.xyz@gmail.com)
last-modified: 2007/08/12
It is free software and is distributed under
the terms of the GNU General Public License (Version 2).
This software comes with ABSOLUTELY NO WARRANTY.
*/
//
#include <windows.h>
#include <stdio.h>
#include <d3d9.h>
#include <d3dx9.h>
#include <dshow.h>
#include "grabberds.h"
#include "3DVideo.h"
#include "resource.h"
//
//
#pragma warning(disable : 4995)
//
//
HWND g_hwndMain;
DWORD fps = 100;
volatile HRESULT hr;
DWORD back_color;
float angle;
float fovy = D3DX_PI / 3, zNear = 1.0f, zFar = 10.0f;
FILETIME t, k1, u1, k2, u2;
DWORD t1, t2;
DWORD threshold = 5000;
DWORD n_frames;
BOOL repaint;
wchar_t *g_szFileName;
HANDLE mutex;
BOOL g_bLocked; // to prevent WM_TIMER & WM_PAINT processing during constructing DShow graph
//
//
IDirect3D9 *d3d;
IDirect3DDevice9 *device;
IDirect3DSurface9 *surf_video;
IDirect3DTexture9 *tx_video;
//
//
D3DPRESENT_PARAMETERS d3dpp;
D3DFORMAT g_fmt;
//
//
IVideoGrabber *g_vg;
//
//
GUID *cap_subtype;
SIZE *cap_szMin, *cap_szMax, *cap_szStep, *cap_szDef;
float *cap_fpsMin, *cap_fpsMax, *cap_fpsDef;
DWORD cap_nFormats;
DWORD cap_i_sel;
//
//
inline void GUIDToFriendlyStr(const GUID& subtype, char *szFormat)
{
if(subtype == MEDIASUBTYPE_RGB32)
strcpy(szFormat, "RGB32");
else
if(subtype == MEDIASUBTYPE_ARGB32)
strcpy(szFormat, "ARGB32");
else
if(subtype == MEDIASUBTYPE_RGB24)
strcpy(szFormat, "RGB24");
else
if(subtype == MEDIASUBTYPE_RGB555)
strcpy(szFormat, "RGB555");
else
if(subtype == MEDIASUBTYPE_RGB565)
strcpy(szFormat, "RGB565");
else
if(subtype == MEDIASUBTYPE_YUY2)
strcpy(szFormat, "YUY2");
else
if(subtype == MEDIASUBTYPE_UYVY)
strcpy(szFormat, "UYVY");
else
if(subtype == MEDIASUBTYPE_YV12)
strcpy(szFormat, "YV12");
else
if(subtype == MEDIASUBTYPE_YVU9)
strcpy(szFormat, "YVU9");
else
sprintf(szFormat, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
subtype.Data1, subtype.Data2, subtype.Data3,
subtype.Data4[0], subtype.Data4[1],
subtype.Data4[2], subtype.Data4[3],
subtype.Data4[4], subtype.Data4[5],
subtype.Data4[6], subtype.Data4[7]);
}
//
//
void CloseClip()
{
SAFE_RELEASE(g_vg);
SAFE_RELEASE(tx_video);
SAFE_RELEASE(surf_video);
}
//
//
HRESULT __fastcall my_callback(IVideoGrabber *vg, void *buffer)
{
WaitForSingleObject(mutex, INFINITE);
HRESULT hr;
DWORD cx = vg->GetCX(),
cy = vg->GetCY();
if(!device)
{
hr = E_UNEXPECTED;
goto L_EXIT;
}
if((!surf_video) || (!tx_video))
{
SAFE_RELEASE(tx_video);
SAFE_RELEASE(surf_video);
const GUID *subtype = g_vg->GetSubtype();
g_fmt = (D3DFORMAT)0;
if(*subtype == MEDIASUBTYPE_YV12)
g_fmt = (D3DFORMAT)MAKEFOURCC('Y', 'V', '1', '2');
else
if(*subtype == MEDIASUBTYPE_RGB32)
g_fmt = D3DFMT_X8R8G8B8;
else
if(*subtype == MEDIASUBTYPE_YUY2)
g_fmt = (D3DFORMAT)MAKEFOURCC('Y', 'U', 'Y', '2');
else
if(*subtype == MEDIASUBTYPE_ARGB32)
g_fmt = D3DFMT_A8R8G8B8;
else
if(*subtype == MEDIASUBTYPE_UYVY)
g_fmt = (D3DFORMAT)MAKEFOURCC('U', 'Y', 'V', 'Y');
else
if(*subtype == MEDIASUBTYPE_NV12)
g_fmt = (D3DFORMAT)MAKEFOURCC('N', 'V', '1', '2');
else
if(*subtype == MEDIASUBTYPE_RGB555)
g_fmt = D3DFMT_X1R5G5B5;
else
if(*subtype == MEDIASUBTYPE_RGB565)
g_fmt = D3DFMT_R5G6B5;
hr = CreateVideoSurface(device, cx, cy, &surf_video, g_fmt);
if(FAILED(hr))
goto L_EXIT;
hr = device->CreateTexture(cx, cy, 1, D3DUSAGE_RENDERTARGET,
D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &tx_video, NULL);
if(FAILED(hr))
goto L_EXIT;
}
BYTE *pBits = (BYTE*)buffer;
if(surf_video)
{
switch(g_fmt)
{
case D3DFMT_X8R8G8B8:
case D3DFMT_A8R8G8B8:
hr = FillVideoSurface(surf_video, pBits, cx << 2, cy, TRUE);
break;
case D3DFMT_X1R5G5B5:
case D3DFMT_R5G6B5:
hr = FillVideoSurface(surf_video, pBits, cx << 1, cy, TRUE);
break;
case (D3DFORMAT)MAKEFOURCC('Y', 'V', '1', '2'):
hr = FillVideoSurfaceYV12(surf_video, pBits, cx, cy);
break;
case (D3DFORMAT)MAKEFOURCC('N', 'V', '1', '2'):
hr = FillVideoSurface(surf_video, pBits, cx, cy + (cy >> 1));
break;
default: // YUY2, UYVY
hr = FillVideoSurface(surf_video, pBits, cx << 1, cy);
}
if(SUCCEEDED(hr))
{
IDirect3DSurface9 *tx_video_surf;
hr = tx_video->GetSurfaceLevel(0, &tx_video_surf);
if(SUCCEEDED(hr))
{
hr = DrawVideoSurface(device, tx_video_surf, NULL, surf_video);
tx_video_surf->Release();
}
}
}
L_EXIT:
ReleaseMutex(mutex);
return hr;
}
//
//
BOOL WINAPI CaptureDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_INITDIALOG:
{
HRESULT hr;
IUnknown *cfg = NULL;
DWORD nFormats = 0;
hr = EnumVideoCaptureFormatsStart(NULL, &cfg, &cap_nFormats);
if(SUCCEEDED(hr))
{
DWORD nFormats = __min(100, cap_nFormats);
HWND hwnd_cb = GetDlgItem(hwnd, IDC_FORMATS);
DWORD i_sel = 0;
RECT rc;
GetWindowRect(hwnd_cb, &rc);
SetWindowPos(hwnd_cb, NULL, 0, 0, rc.right - rc.left, (rc.bottom - rc.top) * 10,
SWP_NOZORDER | SWP_NOMOVE);
for(DWORD i = 0; i < nFormats; i++)
{
hr = EnumVideoCaptureFormatsByIndex(cfg, i, &cap_subtype[i],
&cap_szMin[i], &cap_szMax[i], &cap_szStep[i],
&cap_fpsMin[i], &cap_fpsMax[i],
&cap_szDef[i], &cap_fpsDef[i]);
if(hr == S_OK)
i_sel = i;
char szFormat[64];
GUIDToFriendlyStr(cap_subtype[i], szFormat);
SendMessage(hwnd_cb, CB_ADDSTRING, 0, (LPARAM)szFormat);
}
SendMessage(hwnd_cb, CB_SETCURSEL, i_sel, 0);
EnumVideoCaptureFormatsEnd(cfg);
SendMessage(hwnd, WM_COMMAND, (DWORD)IDC_FORMATS | ((DWORD)CBN_SELCHANGE << 16), (LPARAM)hwnd_cb);
}
}
return TRUE;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDOK:
{
HWND hwnd_cb = GetDlgItem(hwnd, IDC_FORMATS);
cap_i_sel = SendMessage(hwnd_cb, CB_GETCURSEL, 0, 0);
if(cap_i_sel < cap_nFormats)
{
char str[64];
str[63] = 0;
HWND hwndCtl;
hwndCtl = GetDlgItem(hwnd, IDC_WIDTH);
GetWindowText(hwndCtl, str, 63);
sscanf(str, "%u", &cap_szDef[cap_i_sel].cx);
hwndCtl = GetDlgItem(hwnd, IDC_HEIGHT);
GetWindowText(hwndCtl, str, 63);
sscanf(str, "%u", &cap_szDef[cap_i_sel].cy);
hwndCtl = GetDlgItem(hwnd, IDC_FPS);
GetWindowText(hwndCtl, str, 63);
sscanf(str, "%f", &cap_fpsDef[cap_i_sel]);
}
EndDialog(hwnd, IDOK);
}
return TRUE;
case IDCANCEL:
PostMessage(hwnd, WM_CLOSE, 0, 0);
return TRUE;
case IDC_FORMATS:
if(HIWORD(wParam) == CBN_SELCHANGE)
{
DWORD i_sel = SendMessage((HWND)lParam, CB_GETCURSEL, 0, 0);
if(i_sel == CB_ERR)
break;
HWND hwndCtl;
char str[64];
hwndCtl = GetDlgItem(hwnd, IDC_MINWIDTH);
sprintf(str, "%d", cap_szMin[i_sel].cx);
SetWindowText(hwndCtl, str);
hwndCtl = GetDlgItem(hwnd, IDC_MAXWIDTH);
sprintf(str, "%d", cap_szMax[i_sel].cx);
SetWindowText(hwndCtl, str);
hwndCtl = GetDlgItem(hwnd, IDC_WIDTH);
sprintf(str, "%d", cap_szDef[i_sel].cx);
SetWindowText(hwndCtl, str);
hwndCtl = GetDlgItem(hwnd, IDC_MINHEIGHT);
sprintf(str, "%d", cap_szMin[i_sel].cy);
SetWindowText(hwndCtl, str);
hwndCtl = GetDlgItem(hwnd, IDC_MAXHEIGHT);
sprintf(str, "%d", cap_szMax[i_sel].cy);
SetWindowText(hwndCtl, str);
hwndCtl = GetDlgItem(hwnd, IDC_HEIGHT);
sprintf(str, "%d", cap_szDef[i_sel].cy);
SetWindowText(hwndCtl, str);
hwndCtl = GetDlgItem(hwnd, IDC_MINFPS);
sprintf(str, "%.2f", cap_fpsMin[i_sel]);
SetWindowText(hwndCtl, str);
hwndCtl = GetDlgItem(hwnd, IDC_MAXFPS);
sprintf(str, "%.2f", cap_fpsMax[i_sel]);
SetWindowText(hwndCtl, str);
hwndCtl = GetDlgItem(hwnd, IDC_FPS);
sprintf(str, "%.2f", cap_fpsDef[i_sel]);
SetWindowText(hwndCtl, str);
hwndCtl = GetDlgItem(hwnd, IDC_WIDTH_STEP);
sprintf(str, "%d", cap_szStep[i_sel].cx);
SetWindowText(hwndCtl, str);
hwndCtl = GetDlgItem(hwnd, IDC_HEIGHT_STEP);
sprintf(str, "%d", cap_szStep[i_sel].cy);
SetWindowText(hwndCtl, str);
}
}
break;
case WM_CLOSE:
EndDialog(hwnd, IDCANCEL);
}
return FALSE;
}
//
//
void OpenClip()
{
OPENFILENAMEW ofn;
ZeroMemory(&ofn, sizeof(ofn));
// Fill in standard structure fields
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = g_hwndMain;
ofn.lpstrFilter = L"Video files\0*.avi;*.mpg;*.ogm;*.mkv\0All files\0*.*\0\0";
ofn.lpstrFile = g_szFileName;
ofn.nMaxFile = 2048;
ofn.lpstrTitle = L"Open File...\0";
ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
if(GetOpenFileNameW(&ofn))
{
g_bLocked = TRUE;
CloseClip();
hr = VideoGrabberCreate(&g_vg);
if(FAILED(hr))
{
CloseClip();
goto L_EXIT;
}
/* Enable YUV subtypes (assume that videocard supports them) */
g_vg->EnableSubtype(&MEDIASUBTYPE_YV12);
g_vg->EnableSubtype(&MEDIASUBTYPE_NV12);
g_vg->EnableSubtype(&MEDIASUBTYPE_YUY2);
g_vg->EnableSubtype(&MEDIASUBTYPE_UYVY);
/* Enable common RGB subtypes */
g_vg->EnableSubtype(&MEDIASUBTYPE_RGB32);
g_vg->EnableSubtype(&MEDIASUBTYPE_ARGB32);
g_vg->EnableSubtype(&MEDIASUBTYPE_RGB555);
g_vg->EnableSubtype(&MEDIASUBTYPE_RGB565);
g_vg->SetCallback(my_callback);
g_vg->EnableLoop(TRUE);
hr = g_vg->RenderMediaFile(g_szFileName, TRUE);
if(FAILED(hr))
{
CloseClip();
goto L_EXIT;
}
IMediaControl *mc = (IMediaControl*)g_vg->GetMediaControl();
if(mc)
mc->Run();
}
else
{
CloseClip();
GUID guids[100];
SIZE sizes[400];
float fpss[300];
ZeroMemory(guids, sizeof(guids));
ZeroMemory(sizes, sizeof(sizes));
ZeroMemory(fpss, sizeof(fpss));
cap_subtype = &guids[0];
cap_szMin = &sizes[0];
cap_szMax = &sizes[100];
cap_szStep = &sizes[200];
cap_szDef = &sizes[300];
cap_fpsMin = &fpss[0];
cap_fpsMax = &fpss[100];
cap_fpsDef = &fpss[200];
cap_i_sel = 0xffffffff;
DialogBox(NULL, MAKEINTRESOURCE(IDD_CAPTURE), g_hwndMain, CaptureDialogProc);
g_bLocked = TRUE;
hr = VideoGrabberCreate(&g_vg);
if(FAILED(hr))
{
CloseClip();
goto L_EXIT;
}
/* Enable YUV subtypes (assume that videocard supports them) */
g_vg->EnableSubtype(&MEDIASUBTYPE_YV12);
g_vg->EnableSubtype(&MEDIASUBTYPE_NV12);
g_vg->EnableSubtype(&MEDIASUBTYPE_YUY2);
g_vg->EnableSubtype(&MEDIASUBTYPE_UYVY);
/* Enable common RGB subtypes */
g_vg->EnableSubtype(&MEDIASUBTYPE_RGB32);
g_vg->EnableSubtype(&MEDIASUBTYPE_ARGB32);
g_vg->EnableSubtype(&MEDIASUBTYPE_RGB555);
g_vg->EnableSubtype(&MEDIASUBTYPE_RGB565);
g_vg->SetCallback(my_callback);
if(cap_i_sel < cap_nFormats)
g_vg->SuggestVideoCaptureFormat(&cap_subtype[cap_i_sel], cap_szDef[cap_i_sel],
cap_fpsDef[cap_i_sel]);
hr = g_vg->RenderVideoCaptureSource(NULL);
if(hr != S_OK)
{
CloseClip();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -