i
i
i
i
i
i
i
i
390 15. Using Multimedia in VR
In multimedia applications, timing is important, and all FilterGraphs are
designed so that they can be synchronized with a real-time clock. Whether
playing back video files or recording video from a USB webcam, all programs
need to keep up with this clock. If the hardwar e or application software
cannot deliver the samples through the graph fast enough then some samples
will have to be discar ded.
For example, a video recorder application is saving AVI movie
files from a DV camera with a compression filter in the chain.
For NTSC video, it must read, compress and write 30 samples
(frames) per second. But suppose the compression filter can only
compress 25 samples per second. The camera cannot be slowed
down, nor are we allowed to only write 25 frames per second
into the AVI file while still claiming the AVI is a 30-fps movie
file.
DirectShow cleverly solved the problem for us, without any work
on the part of the program designer. It does this (in our exam-
ple) by dropping 5 out of every 30 samples, say samples 6, 12,
18, 24, 30, before the compression filter stage. After the com-
pression filter stage it adjusts the sample timings in the AVI file
so that either 30 samples (with some duplicates) are written per
second or 25 samples are written per second with the timing
changed so that a player will think each sample should be dis-
played for 40 ms instead of 33 ms.
Similar things happen in movie-player applications. If the video
source is supposed to play at 30 fps but the renderer filter can
only keep up at 25 fps then the DirectShow FilterGraph drops
five out of every 30 frames read from the file. It may even skip
reading samples from the source file itself.
Another term you will read about, with respect to DirectShow filters, is
the pin. A pin is a point of connection on a filter. Source filters have one
or more pins. Output filters generally have one pin. In-place filters have at
least two pins. Pins a re designated either as being an input pin or an output
pin. The FilterGraph is build by connecting one filter’s output pin to another
filter’s input pin. Thus, a FilterGraph can be something as simple as a source
filter and a sink filter, with the source filter’s output pin connected to the sink
filter’s input pin.
i
i
i
i
i
i
i
i
15.2. Methodology 391
15.1.1 Threading
A great deal of emphasis has been put on the importance of timing in Dir ect-
Show FilterGraphs. In addition, the FilterGraph seems almost to be an entity
working independently and only communicating with its driving application
from time to time. DirectShow is a multi-threaded technology. The Filter-
Graph executes in a separate thread
2
of execution. Programming in a multi-
threaded environment bring its own set of challenges. But to achieve the
real-time throughput demanded by multimedia applications, our programs
must embrace multi-threading concepts.
Nevertheless, this book is not focused on multi-threading or even about
writing multi-threaded code, so we will gloss over the important topics of
deadlocks, interlocks, synchronization, critical sections etc. In our example
programs, we will use only the idea of the critical section, in which blocks of
code that access global variables must not be executed at the same time by
different threads; say one thread reading from a variable and another thread
writing to it. We suggest that if you want to get a comprehensive explanation
of the whole minefield of multi-threaded programming in Windows, consult
one of the specialized texts [1] or [3].
There is one aspect of multi-threaded programming that we cannot avoid.
Applications must be linked with the multi-threaded C++ libraries.
15.2 Methodology
In this section, we will summarize what an application program must do in
order to use DirectShow. The flexibility of the FilterGraph concept means
that all multimedia applications follow these same simple rules:
Create a FilterGraph with a COM FilterGraph object and its interfaces.
Create instances of the filter objects and add them to the FilterGraph.
Usually there will be at least one source and one sink filter.
Linkthepinsofthefilterstogether to form the desired filter chain.
This can be done by creating a
CaptureGraphBuilder2 COM object,
and its COM interfaces. The CaptureGraphBuilder2 object is an
extremely useful tool because it implements what is known as intelligent
2
Threads are in essence processes or programs executing independently and concurrently
from one another, but they use the same address space and have access to the same data.
i
i
i
i
i
i
i
i
392 15. Using Multimedia in VR
connect. Without intelligent connect, building a FilterGraph would be
difficult indeed. To see why, consider a video player application. Two
filters are loaded into the FilterGraph, one to read the file and the other
to show the movie on the screen. They must be connected before the
graph can run. However, an AVI movie le will more likely than not
use data compression. If a matching filter is not added to the graph
and inserted between reader and renderer, the graph cannot be built.
This is were intelligent connect comes in. It can detect what filters are
required to match t he output of the file reader to the input of the screen
renderer. It can also load those filters and put them into the chain.
So using the CaptureGraphBuilder2 interface methods considerably
simplifies and shortens the code required to build the FilterGraph.
Acquire appropriate control interfaces to the FilterGraph; that is, at-
tach whatever parts of the application program require it to the Filter-
Graph. For example, tell the FilterGraph to render its video output in
the application programs window.
Start, stop, rewind, pause etc. the FilterGraph as required.
Destroy the FilterGraph when finished and exit the application.
Figure 15.3 shows diagrammatically the programming strategy for all appli-
cations in this book that use DirectShow.
Figure 15.3. A DirectShow application builds and controls a FilterGraph to carry of
the bulk of the work of the program.
i
i
i
i
i
i
i
i
15.3. A Movie Player 393
Note the mention of the COM. As we discussed in Section 12.4,
DirectShow’s API is a prime example of an API specification conforming to
the component object model. Any program hoping to build and use a Filter-
Graph must do so using COM objects and interfaces. In the next few sections,
we will write a few basic DirectS how programs that cover a broad spectrum
of multimedia applications. Later, we will embellish and adapt them for use
as some inter esting and specialized VR tools.
15.3 A Movie Player
As a first application, we will look at a very basic use of DirectShow: play-
ing an AVI movie file. Its simplicity is the very reason why DirectShow can
be so useful. The F i lterGraph we require for this application is shown in
Figure 15.4.
Figure 15.4. A movie player FilterGraph.
The application has an entry point, message loop and window message
handling function, as illustrated in Listing 15.1.
All the other DirectS how applications that we will examine in
this and subsequent chapters use an overall skeleton structure as
outlined in Listing 15.1. Each example will require some minor
modifications and additions to each of the functions listed. We
will not reprint this code in each program listing and only refer
to additions if they are very significant. Using our annotated
printed listings, it should be possible to gain an understanding
of the program logic and follow the execution path.
i
i
i
i
i
i
i
i
394 15. Using Multimedia in VR
#include <windows.h> // This is the minimal set of header files required
#include <atlbase.h> // for a DirectShow applucation.
#include <dshow.h>
HWND ghApp=0; // our application window’s handle
HINSTANCE ghInst=0; // the application’s instance handle
char gFileName[MAX_PATH]; // string for filename
IGraphBuilder
*
pGB = NULL; // pointer to the graph builder interface
IMediaControl
*
pMC = NULL; // pointer to the media control interface
LRESULT CALLBACK WndMainProc(HWND hWnd,UINT message,
WPARAM wParam,LPARAM lParam){
switch(message){
case WM_COMMAND: // menu command messages
switch(wParam) {
case ID_FILE_OPENCLIP:
OpenClip(NULL); break; // open a movie file - this builds the graph
case ID_FILE_EXIT:
CloseClip(); // this stops the movie playing
// and destroys the graph
PostQuitMessage(0) break;
case: ..// // other menu commands
default: break;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
..// Other messages
default: break
return DefWindowProc(hWnd, message, wParam, lParam);
}
int PASCAL WinMain(HINSTANCE hInstC, HINSTANCE hInstP,
LPSTR lpCmdLine, int nCmdShow){
.. // declare local variables and fill window class "wc"
CoInitialize(NULL); // tell Windows we use COM
ghInst = hInstC;
// register the window class
RegisterClass(&wc);
// create the application’s window
ghApp = CreateWindow(CLASSNAME, APPLICATIONNAME, ...
while(GetMessage(&msg,NULL,0,0)){
TranslateMessage(&msg); // message loop
DispatchMessage(&msg);
}
CoUninitialize(); // release COM
return (int)0;
}
Listing 15.1. The outline of the movie player application.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.54.242