DirectShow DeMystified. A Quick Reference

Introduction

Using DirectShow for Audio and Video Playback. A Note on DirectX : Microsoft DirectX is an advanced suite of multimedia application programming interfaces (APIs) built into Microsoft Windows; operating systems. DirectX provides a standard development platform for Windows-based PCs by enabling software developers to access specialized hardware features without having to write hardware-specific code. This technology was first introduced in 1995 and is a recognized standard for multimedia application development on the Windows platform. A Note on DirectShow : ActiveMovie was the original name for DirectShow. The term ActiveMovie is no longer used. Internally, DirectShow uses DirectSound and DirectDraw when the hardware supports it. Currently, there is only one book devoted entirely to DirectShow: Programming Microsoft DirectShow by Michael Linetsky (Wordware Publishing Inc.) A Note for programmers : Q: Is knowledge of COM essential for using DirectShow ? A: No. The basics of intializing the COM library and getting an interface would do.This tutorial also helps you in doing those 2 requisites. So, you'd just have to copy and paste the intialization routines in your application and it would do just fine. Q: Does DirectShow involve a steep learning curve ? A: Absolutely not. Just follow the steps outlined below and you can blindly use DirectShow in your application.


Implementation


   This tutorial describes how to use DirectShow from a MFC-based application.
For the sake of brevity and clarity, only Audio programming has been discussed
here. Video functionality can be achieved with a few modifications. It would
be a separate tutorial to help you understand the underlying concepts.


Step 1 : Downloading DirectX


	You need to have DirectX installed on your machine and you can download
it The Microsoft DirectX Site. After installing it, you can proceed to build your
application.


Step 2 : Libraries and Headers


To include DirectShow in your application, you need to include the header file
and library required for it. To do just that,add the following statements in
your header file.

        // Include header for DirectShow

	#include <dshow.h>

	// Libraries required for DirectShow GUID references

	#pragma comment(lib,"Strmiids.lib")

Step 3 : Declaring the Variables


Declare the following variables in your header file.

	IGraphBuilder *m_pGraph;	// Graph Builder interface
	IMediaControl *m_pControl;	// Media Control interface
	IMediaEvent   *m_pEvent;	// Media Event interface
	IMediaSeeking *m_pSeek;		// Media Seeking interface
	IBasicAudio   *m_pAudio;	// Audio Settings interface 
					// ( For Volume & Playback Rate)

Step 4 : Initialize DirectShow


In your application's Initialization routine, add the following code.
This can be called from your Application's Constructor too.

	// Initialize the COM library.

	HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
	if (FAILED(hr))
		return;

	// Initialize the DirectShow components

	m_pGraph	= NULL;
	m_pControl	= NULL;
	m_pEvent	= NULL;
	m_pSeek		= NULL;
	m_pAudio	= NULL;

	// Create the Filter Graph Manager and query for interfaces.

	hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,IID_IGraphBuilder, (void **)&m;_pGraph);
	if (FAILED(hr)) 
		return;

	hr = m_pGraph->QueryInterface(IID_IMediaSeeking, (void**)&m;_pSeek);
	if (FAILED(hr)) 
		return;

	hr = m_pGraph->QueryInterface(IID_IBasicAudio,(void**)&m;_pAudio);
	if (FAILED(hr)) 
		return;

	// Use IGraphBuilder::QueryInterface (inherited from IUnknown) to get the IMediaControl interface.

	hr = m_pGraph->QueryInterface(IID_IMediaControl, (void **)&m;_pControl);
	if (FAILED(hr)) 
	{
		m_pGraph->Release();
		m_pGraph = NULL; 
		CoUninitialize(); 
		return;
	}   
	
	// And get the Media Event interface, too.

	hr = m_pGraph->QueryInterface(IID_IMediaEvent, (void **)&m;_pEvent);
	if (FAILED(hr)) 
	{
		m_pGraph->Release();
		m_pControl->Release();
		CoUninitialize(); 
		return;
	}


Step 5 : Playing an Audio File


Here szFileName is the Name and path of the Audio file that you want to play

	HRESULT hr;

	#ifndef UNICODE 
		WCHAR wFileName[MAX_PATH];
		MultiByteToWideChar(CP_ACP, 0, m_szFileName, -1, wFileName,MAX_PATH); 
		hr = m_pGraph->RenderFile((LPCWSTR)wFileName, NULL);
	#else 
		hr = m_pGraph->RenderFile((LPCWSTR)g_PathFileName, NULL);
	#endif 

	if(FAILED(hr))
		return;

	// Run the graph

	hr = m_pControl->Run();

	if(FAILED(hr))
		return;


	// The following code gets the Duration in Seconds and NanoSeconds
	// This is the total duration of the audio file
	long lDurationInNanoSecs, lDurationInSecs;

	m_pSeek->GetDuration(&lDurationInNanoSecs;);
	lDurationInSecs = m_lDurationInNanoSecs / 10000000;


Step 6 : Pausing Playback


	HRESULT hr = m_pControl->Pause();


Step 7 : Stopping the Playback


	HRESULT hr = m_pControl->Stop();


Step 8 : Fast Forwarding and Rewinding


Get the current position first (Step 9) and then set the desired position correctly
Here, lPosition is a long value of the position that you want to set

	// Get the Duration of the playing file

	LONGLONG lTotalDuration = 0;
	m_pSeek->GetDuration(&lTotalDuration;);

	// Set the Current Playing position

	REFERENCE_TIME rtNew = (lTotalDuration * lPosition) / 100;
	HRESULT hr;

	hr = m_pSeek->SetPositions(&rtNew;, AM_SEEKING_AbsolutePositioning,NULL,AM_SEEKING_NoPositioning);


Step 9 : Getting Current position of playback


	REFERENCE_TIME timeNow;
	LONGLONG lPositionInSecs = 0;

	HRESULT hr = m_pSeek->GetCurrentPosition(&timeNow;);

	long lDurationInNanoSecs;
	m_pSeek->GetDuration(&lDurationInNanoSecs;);

	lPositionInSecs = (long)((timeNow * 100) / lDurationInNanoSecs);


Step 10 : Setting the Volume level


Here lVolume is a long variable that can be any value between -4000 and 0
-4000 indicates lowest Volume and 0 indicates Maximum Volume.

	HRESULT hr = m_pAudio->put_Volume(lVolumeLevel);

Step 11 : Muting Audio


As mentioned in Step 10, you can set the Volume levels. Setting it to a 
very low level, for example -10,000 would effectively mute the audio.
To Release the mute, you just have to set a volume with a parameter
between -4000 and 0.

	HRESULT hr = m_pAudio->put_Volume(-10000);


Step 12 : Setting the Playback Rate


Sometimes, you might want to slow down the playback rate or increase it.
To do that, you need to call the following piece of code. Here,
dPlaybackRate is a double variable which indicates the speed of playback.
For example, 2.0 increases the speed by 100%, 0.5 effectively halves
the speed of play.

	HRESULT hr = m_pSeek->SetRate(dPlaybackRate);

Step 13 : Releasing the components used


Now, that we've finished using the DirectShow Library, its time for us to
cleanup the code. Uninitialize ( or ) Release the components used and then
Uninitialize the COM Library too.


	if(m_pControl)
	{
		m_pControl->Release(); 
		m_pControl = NULL;
	}

	if(m_pEvent)
	{
		m_pEvent->Release(); 
		m_pEvent = NULL;
	}

	if(m_pGraph)
	{
		m_pGraph->Release();
		m_pGraph = NULL;
	}

	// UnInitialize the COM Library
	CoUninitialize();

Step 14 : Error Checking

 Note that i've used a HRESULT value ( hr ) throughout the code. You can and should
use it to check the status of your operation. To check the status of your operation,
you can use the FAILED and SUCCEEDED macros.

	if( FAILED ( hr ) )
	{
		// Means that your operation has failed	
		// Do some cleanup here or take corrective action.
	}

	if( SUCCEEDED ( hr ) )
	{
		// Congrats. The desired operation has succeeded.
		// Proceed ahead.
	}

Calling GetLastError would give the exact error codes incase an operation has failed.

Conclusion :

THATS ALL FOLKS. The end of a simple tutorial for using DirectShow within your applications.
Check out the following links too : 

The DirectShow FAQ.

The DirectX FAQ.

All Luck.

tutorials /
DirectShow
home /
1