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.
|