Examining main

Examining main

As in our earlier examples, nearly all the application s work is performed inside its main function, as the following code shows:

int main(int argc, char* argv[]) { ICaptureGraphBuilder2 *pCaptureGraph = NULL; // Capture graph builder IGraphBuilder *pGraph = NULL; // Graph builder object IMediaControl *pControl = NULL; // Media control object IFileSinkFilter *pSink = NULL; // File sink object IBaseFilter *pAudioInputFilter = NULL; // Audio Capture filter IBaseFilter *pVideoInputFilter = NULL; // Video Capture filter IBaseFilter *pASFWriter = NULL; // WM ASF File filter // Initialize the COM library. HRESULT hr = CoInitialize(NULL); if (FAILED(hr)) { // We'll send our error messages to the console. printf("ERROR - Could not initialize COM library"); return hr; } // Create the Capture Graph Builder and query for interfaces. hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void **)&pCaptureGraph); if (FAILED(hr)) // FAILED is a macro that tests the return value { printf("ERROR - Could not create the Filter Graph Manager."); return hr; } // Use a method of the Capture Graph Builder // to create an output path for the stream. hr = pCaptureGraph->SetOutputFileName(&MEDIASUBTYPE_Asf, L"C:\\MyWebcam.ASF", &pASFWriter, &pSink); // Now configure the ASF Writer. // Present the property pages for this filter. hr = ShowFilterPropertyPages(pASFWriter); // Now get the Filter Graph Manager // that was created by the Capture Graph Builder. hr = pCaptureGraph->GetFiltergraph(&pGraph); // Using QueryInterface on the graph builder, // get the Media Control object. hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl); if (FAILED(hr)) { printf("ERROR - Could not create the Media Control object."); pGraph->Release(); // Clean up after ourselves CoUninitialize(); // And uninitalize COM return hr; } // Get an audio capture filter. // There are several to choose from, // so we need to enumerate them, pick one, and // then add the audio capture filter to the filter graph. hr = GetAudioInputFilter(&pAudioInputFilter, L"Logitech"); if (SUCCEEDED(hr)) { hr = pGraph->AddFilter(pAudioInputFilter, L"Webcam Audio Capture"); } // Now create the video input filter from the webcam. hr = GetVideoInputFilter(&pVideoInputFilter, L"Logitech"); if (SUCCEEDED(hr)) { hr = pGraph->AddFilter(pVideoInputFilter, L"Webcam Video Capture"); } // Use another method of the Capture Graph Builder // to provide a render path for video preview. IBaseFilter *pIntermediate = NULL; hr = pCaptureGraph->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, pVideoInputFilter, NULL, NULL); // Now add the video capture to the output file. hr = pCaptureGraph->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pVideoInputFilter, NULL, pASFWriter); // And do the same for the audio. hr = pCaptureGraph->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Audio, pAudioInputFilter, NULL, pASFWriter); if (SUCCEEDED(hr)) { // Run the graph. hr = pControl->Run(); if (SUCCEEDED(hr)) { // Wait patiently for completion of the recording. wprintf(L"Started recording...press Enter to stop recording.\n"); // Wait for completion. char ch; ch = getchar(); // We wait for keyboard input } // And stop the filter graph. hr = pControl->Stop(); wprintf(L"Stopped recording.\n"); // To the console // Before we finish, save the filter graph to a file. SaveGraphFile(pGraph, L"C:\\MyGraph.GRF"); } // Now release everything and clean up. pSink->Release(); pASFWriter->Release(); pVideoRenderer->Release(); pVideoInputFilter->Release(); pAudioInputFilter->Release(); pControl->Release(); pGraph->Release(); pCaptureGraph->Release(); CoUninitialize(); return 0; }

After COM has been initialized, we find ourselves in unfamiliar territory. Instead of instantiating a Filter Graph Manager object, we use CoCreateInstance to create an instance of the Capture Graph Builder object. This object is specifically designed to assist in the construction of filter graphs that capture audio and video input to files, but it can also be used to construct other types of graphs. As soon as the object has been created, we invoke its ICaptureGraphBuilder2::SetOutputFileName method. This method takes a pointer to a media type in this case, MEDIASUBTYPE_Asf, indicating an ASF file and creates an output file with the name passed as the next parameter.

The call to SetOutputFileName creates an instance of a WM ASF Writer filter. A pointer to the filter s IBaseFilter interface is returned in pASFWriter, and a pointer to the filter s IFileSinkFilter interface is returned in pSink. We ll need a pointer to the WM ASF Writer filter, and you might need the IFileSinkFilter interface. For example, if you want to change the name of the output file to some value other than that passed in the call to SetOutputFileName, you need IFileSinkFilter.

If we d wanted to create an AVI file as we will in the next chapter when we re dealing with digital video from a camcorder we would have passed a pointer to MEDIASUBTYPE_Avi as the first parameter. In that case, instead of returning a pointer to a WM ASF Writer filter, the call would have returned a pointer to an AVI Mux filter, which combines the audio and video streams into an AVI-formatted stream. You d still need to write that stream to a file by using the File Writer renderer filter, whereas the WM AVI Writer combines both multiplexing and file writing features in a single renderer filter.

When Should You Compress?

When capturing video, in some scenarios it is preferable to simply save the data without compressing it. Most webcams output some sort of YUV video, although some output RGB, which requires significantly more bandwidth and hard drive space. Depending on the type of video, the size of the video frames, and the speed of your CPU, a compressor might not be able to keep up with the incoming video stream. If you save the uncompressed data in an AVI file by using the AVI Mux and the File Writer, you can come back and compress it later. When the graph s source data is coming from a file, the compressor (in this case the WM ASF Writer) controls the speed at which the data is processed. In some cases, this might be faster than real time, and in some cases, it might be slower. Either way, no frames will be dropped because the source filter is reading from a local file.



Programming Microsoft DirectShow for Digital Video and Television
Programming Microsoft DirectShow for Digital Video and Television (Pro-Developer)
ISBN: 0735618216
EAN: 2147483647
Year: 2002
Pages: 108
Authors: Mark D. Pesce

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net