This repository has been archived on 2024-12-16. You can view files and clone it, but cannot push or open issues or pull requests.
CodeBlocksPortable/WATCOM/samples/directx/cpp/dshow/dshow.cpp

381 lines
11 KiB
C++
Raw Normal View History

//---------------------------------------------------------------------------------------
//
// Simple Windows DirectShow Example Code
//
// Jim Shaw 12/3/2004
//
//---------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------
// Always include windows.h for windows programs
//---------------------------------------------------------------------------------------
#define _WIN32_DCOM
#include <windows.h>
#ifdef __WATCOMC__
#define _WINGDI_
#define _IAMFilterGraphCallback_
#endif
#include <dshow.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <assert.h>
//---------------------------------------------------------------------------------------
// Screen dimensions
//---------------------------------------------------------------------------------------
#define SCREEN_X 640
#define SCREEN_Y 480
#define IN_OWN_WINDOW 1
//---------------------------------------------------------------------------------------
// Variable to hold the address of the Windows window
//---------------------------------------------------------------------------------------
HWND game_window;
//---------------------------------------------------------------------------------------
// Name of our window class. every class has a name. every window is one of a class.
// this can be pretty much anything
//---------------------------------------------------------------------------------------
char game_class[]="DSCPPWindow";
static int quit = 0;
//---------------------------------------------------------------------------------------
// Function prototypes
//---------------------------------------------------------------------------------------
void draw(void);
void flip(void);
int init_dshow(wchar_t *, int);
void shutdown_dshow(void);
int handle_dshow_event(void);
//---------------------------------------------------------------------------------------
// DirectShow Variables
//---------------------------------------------------------------------------------------
IGraphBuilder *pGB=NULL;
IMediaControl *pMC=NULL;
IMediaEventEx *pME=NULL;
IMediaSeeking *pMS=NULL;
IVMRWindowlessControl *pWC=NULL;
#define WM_GRAPHNOTIFY0 (WM_USER+13)
//---------------------------------------------------------------------------------------
// Every window has a WindowProc which handles messages Windows sends to them. These
// are things like key presses, mouse clicks, and thousands of other things you might
// be interested in.
//---------------------------------------------------------------------------------------
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
//this message gets sent to the window when you click the close box on it
case WM_DESTROY:
//tell Windows to close the app
PostQuitMessage(0);
quit = 1;
break;
//this message gets sent when you press a key
case WM_KEYDOWN:
switch (wParam)
{
//pressed Escape key?
case VK_ESCAPE:
//tell Windows to close the app
PostQuitMessage(0);
quit = 1;
break;
}
break;
case WM_GRAPHNOTIFY0:
if (handle_dshow_event())
{
PostQuitMessage(0);
quit = 1;
}
break;
//any message you don't process gets passed to this function inside Windows.
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
//any message you do process, return 0 (unless the message documentation says otherwise)
return 0;
}
//---------------------------------------------------------------------------------------
// Convert char string to wchar_t string
//---------------------------------------------------------------------------------------
static wchar_t c[_MAX_PATH];
static wchar_t *ctowc(char *p)
{
#ifdef __WATCOMC__
swprintf(c, _MAX_PATH, L"%hs", p);
#else
swprintf(c, L"%S", p);
#endif
return c;
}
//---------------------------------------------------------------------------------------
// WinMain
//---------------------------------------------------------------------------------------
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX clas;
MSG msg;
int style;
RECT rect;
//need COM for DirectShow
CoInitializeEx(NULL, COINIT_MULTITHREADED);
//Here we create the Class we named above
clas.cbSize = sizeof(WNDCLASSEX);
clas.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
clas.lpfnWndProc = WindowProc;//<- tell it where the WindowProc is
clas.cbClsExtra = 0;
clas.cbWndExtra = 0;
clas.hInstance = hInstance;
clas.hIcon = NULL;
clas.hCursor = NULL;
clas.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);//<- background colour of window
clas.lpszMenuName = NULL;
clas.lpszClassName = game_class;//<- the class name
clas.hIconSm = 0;
//do it!
RegisterClassEx(&clas);
//style of the window - what boxes do we need (close minimised etc)
style = WS_CAPTION|WS_SYSMENU|WS_MAXIMIZEBOX|WS_MINIMIZEBOX;
//create the window
game_window = CreateWindowEx(0, game_class, "DirectShow", style, CW_USEDEFAULT, CW_USEDEFAULT, 1,1, NULL, NULL, hInstance, 0);
//adjust the window size so that a SCREEN_X x SCREEN_Y window will fit inside its frame
rect.left = rect.top = 0;
rect.right = SCREEN_X;
rect.bottom = SCREEN_Y;
AdjustWindowRectEx(&rect, style , FALSE, 0);
SetWindowPos(game_window, NULL, 0,0, rect.right - rect.left, rect.bottom - rect.top, SWP_NOMOVE|SWP_NOZORDER);
//show the window on the desktop
ShowWindow(game_window, nCmdShow);
char filename[_MAX_PATH];
OPENFILENAME ofn;
BOOL res;
filename[0] = '\0';
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = NULL;
ofn.hInstance = NULL;
ofn.lpstrFilter = "AVI Files\0*.avi\0";
ofn.lpstrCustomFilter = NULL;
ofn.nMaxCustFilter = 0;
ofn.nFilterIndex = 0;
ofn.lpstrFile = filename;
ofn.nMaxFile = _MAX_PATH;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.lpstrTitle = "Select Video File";
ofn.Flags = OFN_FILEMUSTEXIST|OFN_EXPLORER;
ofn.nFileOffset=0;
ofn.nFileExtension=0;
ofn.lpstrDefExt="bin";
ofn.lCustData=0;
ofn.lpfnHook=NULL;
ofn.lpTemplateName="";
res = GetOpenFileName(&ofn);
if (res == 0)
return 0;
if (init_dshow(ctowc(filename), IN_OWN_WINDOW)==0)
{
MessageBox(NULL, "A problem occurred creating the DirectShow FilterGraph.\nCheck your video CODECs and "
"DirectX version.\nThis demo requires DirectX9.0 or better.", "DirectX Initialisation Error", MB_ICONWARNING|MB_OK);
shutdown_dshow();
return 0;
}
//message processing loop
//all Windows programs have one of these. It receives the messages Windows sends to the program and
//passes them to the WindowProc in the Class we registered for the window.
quit = 0;
do
{
//Are there any messages waiting?
while (PeekMessage(&msg, game_window, 0, 0, PM_NOREMOVE))
{
//yes! read it.
if (GetMessage(&msg, game_window, 0,0) < 0)
break;
//pass the message to WindowProc
TranslateMessage(&msg);
DispatchMessage(&msg);
}
} while (!quit);
shutdown_dshow();
CoUninitialize();
return 0;
}
//---------------------------------------------------------------------------------------
// Initialise all the DirectShow structures we need
//---------------------------------------------------------------------------------------
int init_dshow(wchar_t *FileName, int render_in_own_window)
{
HRESULT err;
FILTER_STATE state = State_Stopped;
// Create a new graph
err = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGB);
if (err != S_OK)
return 0;
// Get access to the video controls
err = pGB->QueryInterface(IID_IMediaControl, (void **)&pMC);
if (err != S_OK)
return 0;
err = pGB->QueryInterface(IID_IMediaSeeking, (void **)&pMS);
if (err != S_OK)
return 0;
err = pGB->QueryInterface(IID_IMediaEventEx, (void **)&pME);
if (err != S_OK)
return 0;
if (render_in_own_window)
{
IBaseFilter *pVMR;
IVMRFilterConfig *pFC;
long lWidth, lHeight;
RECT rcSrc, rcDest;
err = CoCreateInstance(CLSID_VideoMixingRenderer, NULL, CLSCTX_INPROC, IID_IBaseFilter, (void**)&pVMR);
if (err != S_OK)
return 0;
// Add the VMR to the filter graph.
err = pGB->AddFilter(pVMR, L"VMR");
if (err != S_OK)
return 0;
// Set the rendering mode.
err = pVMR->QueryInterface(IID_IVMRFilterConfig, (void**)&pFC);
if (err != S_OK)
return 0;
err = pFC->SetRenderingMode(VMRMode_Windowless);
if (err != S_OK)
return 0;
pFC->Release();
// Set the window.
err = pVMR->QueryInterface(IID_IVMRWindowlessControl, (void**)&pWC);
if (err != S_OK)
return 0;
err = pWC->SetVideoClippingWindow(game_window);
if (err != S_OK)
return 0;
pVMR->Release();
// Find the native video size.
err = pWC->GetNativeVideoSize(&lWidth, &lHeight, NULL, NULL);
// Set the source rectangle.
SetRect(&rcSrc, 0, 0, lWidth/2, lHeight/2);
// Get the window client area.
GetClientRect(game_window, &rcDest);
// Set the destination rectangle.
SetRect(&rcDest, 0, 0, rcDest.right, rcDest.bottom);
// Set the video position.
err = pWC->SetVideoPosition(&rcSrc, &rcDest);
}
// Add the source file
err = pGB->RenderFile(FileName, NULL);
if (err != S_OK)
return 0;
// Have the graph signal event via window callbacks for performance
err = pME->SetNotifyWindow((OAHWND)game_window, WM_GRAPHNOTIFY0, 0);
if (err != S_OK)
return 0;
err = pMS->SetTimeFormat(&TIME_FORMAT_FRAME);
if(err != S_OK)
{
err = pMS->SetTimeFormat(&TIME_FORMAT_MEDIA_TIME);
}
err = pMC->Run();
do
{
err = pMC->GetState(0, (long *)&state);
} while (state != State_Running);
return 1;
}
//---------------------------------------------------------------------------------------
// Shutdown DirectShow
//---------------------------------------------------------------------------------------
void shutdown_dshow(void)
{
if (pWC) pWC->Release();
if (pMS) pMS->Release();
if (pME) pME->Release();
if (pMC) pMC->Release();
if (pGB) pGB->Release();
}
//---------------------------------------------------------------------------------------
// Handle DirectShow Event
//---------------------------------------------------------------------------------------
int handle_dshow_event(void)
{
LONG evCode, evParam1, evParam2;
int stopping = 0;
// Make sure that we don't access the MediaEventEx interface after it has already been released.
if (!pME)
return S_OK;
// Process all queued events
while (pME->GetEvent(&evCode, &evParam1, &evParam2, 0) == S_OK)
{
switch (evCode)
{
case EC_COMPLETE:
stopping = 1;
break;
default:
break;
}
// Free memory associated with callback, since we're not using it
pME->FreeEventParams(evCode, evParam1, evParam2);
}
return stopping;
}