main.cpp
[The feature associated with this page, DirectShow, is a legacy feature. It has been superseded by MediaPlayer, IMFMediaEngine, and Audio/Video Capture in Media Foundation. Those features have been optimized for Windows 10 and Windows 11. Microsoft strongly recommends that new code use MediaPlayer, IMFMediaEngine and Audio/Video Capture in Media Foundation instead of DirectShow, when possible. Microsoft suggests that existing code that uses the legacy APIs be rewritten to use the new APIs if possible.]
This topic contains code for the tutorial Audio/Video Playback in DirectShow.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
#include <new>
#include <windows.h>
#include <dshow.h>
#include "playback.h"
#pragma comment(lib, "strmiids")
DShowPlayer *g_pPlayer = NULL;
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void CALLBACK OnGraphEvent(HWND hwnd, long eventCode, LONG_PTR param1, LONG_PTR param2);
void OnChar(HWND hwnd, wchar_t c);
void OnFileOpen(HWND hwnd);
void OnPaint(HWND hwnd);
void OnSize(HWND hwnd);
void NotifyError(HWND hwnd, PCWSTR pszMessage);
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow)
{
if (FAILED(CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE)))
{
NotifyError(NULL, L"CoInitializeEx failed.");
return 0;
}
// Register the window class.
const wchar_t CLASS_NAME[] = L"Sample Window Class";
WNDCLASS wc = { };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
HWND hwnd = CreateWindowEx(0, CLASS_NAME, L"DirectShow Playback",
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
if (hwnd == NULL)
{
NotifyError(NULL, L"CreateWindowEx failed.");
return 0;
}
ShowWindow(hwnd, nCmdShow);
// Run the message loop.
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CHAR:
OnChar(hwnd, (wchar_t)wParam);
return 0;
case WM_CREATE:
g_pPlayer = new (std::nothrow) DShowPlayer(hwnd);
if (g_pPlayer == NULL)
{
return -1;
}
return 0;
case WM_DESTROY:
delete g_pPlayer;
PostQuitMessage(0);
return 0;
case WM_DISPLAYCHANGE:
g_pPlayer->DisplayModeChanged();
break;
case WM_ERASEBKGND:
return 1;
case WM_PAINT:
OnPaint(hwnd);
return 0;
case WM_SIZE:
OnSize(hwnd);
return 0;
case WM_GRAPH_EVENT:
g_pPlayer->HandleGraphEvent(OnGraphEvent);
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
void OnPaint(HWND hwnd)
{
PAINTSTRUCT ps;
HDC hdc;
hdc = BeginPaint(hwnd, &ps);
if (g_pPlayer->State() != STATE_NO_GRAPH && g_pPlayer->HasVideo())
{
// The player has video, so ask the player to repaint.
g_pPlayer->Repaint(hdc);
}
else
{
FillRect(hdc, &ps.rcPaint, (HBRUSH) (COLOR_WINDOW+1));
}
EndPaint(hwnd, &ps);
}
void OnSize(HWND hwnd)
{
if (g_pPlayer)
{
RECT rc;
GetClientRect(hwnd, &rc);
g_pPlayer->UpdateVideoWindow(&rc);
}
}
void CALLBACK OnGraphEvent(HWND hwnd, long evCode, LONG_PTR param1, LONG_PTR param2)
{
switch (evCode)
{
case EC_COMPLETE:
case EC_USERABORT:
g_pPlayer->Stop();
break;
case EC_ERRORABORT:
NotifyError(hwnd, L"Playback error.");
g_pPlayer->Stop();
break;
}
}
void OnChar(HWND hwnd, wchar_t c)
{
switch (c)
{
case L'o':
case L'O':
OnFileOpen(hwnd);
break;
case L'p':
case L'P':
if (g_pPlayer->State() == STATE_RUNNING)
{
g_pPlayer->Pause();
}
else
{
g_pPlayer->Play();
}
break;
}
}
void OnFileOpen(HWND hwnd)
{
OPENFILENAME ofn;
ZeroMemory(&ofn, sizeof(ofn));
WCHAR szFileName[MAX_PATH];
szFileName[0] = L'\0';
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwnd;
ofn.hInstance = GetModuleHandle(NULL);
ofn.lpstrFilter = L"All (*.*)/0*.*/0";
ofn.lpstrFile = szFileName;
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_FILEMUSTEXIST;
HRESULT hr;
if (GetOpenFileName(&ofn))
{
hr = g_pPlayer->OpenFile(szFileName);
InvalidateRect(hwnd, NULL, FALSE);
if (SUCCEEDED(hr))
{
// If this file has a video stream, notify the video renderer
// about the size of the destination rectangle.
OnSize(hwnd);
}
else
{
NotifyError(hwnd, TEXT("Cannot open this file."));
}
}
}
void NotifyError(HWND hwnd, PCWSTR pszMessage)
{
MessageBox(hwnd, pszMessage, TEXT("Error"), MB_OK | MB_ICONERROR);
}
Related topics