#include <windows.h>
#include <Dshow.h>
#include <iostream>
 
using namespace std;
 
// Macro to report success or failure, and return on failure (lazy shorthand... bad habit! :-)
#define REPORT_OUTCOME(hr) if (FAILED(hr)) { cout << "failed" << endl; return false; } cout << "success" << endl;
 
// Data
IGraphBuilder *pGraph = 0; // Filter graph manager
IMediaControl *pControl = 0; // Media control interface
IMediaEvent   *pEvent = 0; // Media event interface
 
 
// Function prototypes
bool init();
void run();
void clearup();
 
 
// Functions
int main()
{
    cout << "DirectShow Video Player" << endl;
    cout << "-----------------------" << endl << endl;
 
    // Attempt to initialise everything
    if (init())
    {
        // Run the app
        run();
 
        // Perform the clearup
        clearup();
    }
 
    cout << endl << endl << "Finished." << endl;
    system("pause");
    return 0;
}
 
 
bool init()
{
    // Attempt to initialise the COM
    cout << "Initialising COM... ";
    HRESULT hr = CoInitialize(NULL);
    REPORT_OUTCOME(hr);
 
    // Create the filter graph manager
    cout << "Creating filter graph manager... ";
    hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph);
    REPORT_OUTCOME(hr);
 
    // Get addition interfaces for it
    cout << "Getting media control interface... ";
    hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
    REPORT_OUTCOME(hr);
    cout << "Getting media event interface... ";
    hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
    REPORT_OUTCOME(hr);
 
    // Attempt to build the graph for file playback
    cout << "Building graph for file playback... ";
    hr = pGraph->RenderFile(L"INSERT YOUR VIDEO PATH/FILE HERE", NULL);
    REPORT_OUTCOME(hr);
 
    return true;
}
 
void run()
{
    // Attempt to start playing the file
    cout << endl << "Starting playback... ";
    HRESULT hr = pControl->Run();
    if (SUCCEEDED(hr))
    {
        cout << "running" << endl;
 
        // Block this thread until the video has finish playback
        //long evCode = 0;
        //pEvent->WaitForCompletion(INFINITE, &evCode);
 
        // Wait for user to press a key to stop
        system("pause");
        cout << endl << "Playback stopped" << endl << endl;
    } else {
        cout << "failed" << endl;
    }
}
 
void clearup()
{
    // Release our interfaces
    cout << "Releasing media control interface... " << endl;
    pControl->Release();
    cout << "Releasing media event interface... " << endl;
    pEvent->Release();
    cout << "Releasing filter graph manager... " << endl;
    pGraph->Release();
 
    // Shutdown COM
    cout << "Shutting down COM... " << endl;
    CoUninitialize();
}