⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 3dvideo.cpp

📁 Handle Videos in Forms Delphi... Play/Stop/Pause/FullScreen
💻 CPP
📖 第 1 页 / 共 2 页
字号:

// 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 + -