Click here to Skip to main content
15,897,891 members
Articles / Desktop Programming / MFC

Preview and Record with MPEG2 Capture device

Rate me:
Please Sign up or sign in to vote.
4.39/5 (16 votes)
11 Jun 20048 min read 220.2K   9.7K   94  
This article shows how to work with MPEG2 capture devices such as Preview, Record. Works with all video renderers. Grab picture and configure MPEG2 Demux.
// Mpeg2Handler.cpp: implementation of the CMPEG2Handler class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "MPEG2CaptureApp.h"
#include "MPEG2CaptureAppDlg.h"
#include "MPEG2Handler.h"
#include "DirectShowGraph.h"
#include "eVideoDecoder.h"
#include "MSFTAudioDecoder.h"


extern int use_vmr9; 


//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CLSID clsidCat; 
   
 
CMPEG2Handler::CMPEG2Handler(CMPEG2CaptureAppDlg    *dlg)
{

	dsGraph = new CDirectShowGraph(dlg);


	graph_mode = STOP_MODE;

	m_dlg = dlg; 


	/* Here we initialize the audio and video decoder */
	/* You can create your own two classes to select your favorite MPEG decoders */
	dsGraph->videoDecoder = new CeVideoDecoder(dsGraph);   
	dsGraph->audioDecoder = new CMSFTAudioDecoder(dsGraph); 



}



CMPEG2Handler::~CMPEG2Handler()
{



	if (graph_mode != STOP_MODE)  { 
	    Stop();
	} 

 
    //FullScreeMode(0);
	
	BSTR strCaption;
	if (dsGraph &&  dsGraph->m_pVW && S_OK == dsGraph->m_pVW->get_Caption(&strCaption))
	{
		CString str = strCaption;
		::SysFreeString( strCaption );
		HWND h  = ::FindWindow(NULL,str);
		if (h) 
			::SendMessage(h , WM_CLOSE , 0 , 0);
	}

  if (dsGraph &&  dsGraph->m_pME)        
	   dsGraph->m_pME->SetNotifyWindow((OAHWND)NULL, 0, 0);

    // Hide video window and remove owner.  This is not necessary here,
    // since we are about to destroy the filter graph, but it is included
    // for demonstration purposes.  Remember to hide the video window and
    // clear its owner when destroying a window that plays video.
    if(dsGraph &&  dsGraph->m_pVW) {
        dsGraph->m_pVW->NotifyOwnerMessage((LONG_PTR) m_dlg->GetSafeHwnd(), WM_CLOSE, 0, 0);
        dsGraph->m_pVW->put_Visible(OAFALSE);

    }

 

	if (dsGraph)
	{
		dsGraph->FreeAllResources();
		delete dsGraph;
	}
	dsGraph = NULL;

}
HRESULT CMPEG2Handler::Record(char *FileName)
{
	
	HRESULT hr ;

    hr = dsGraph->MakeGraph();
	if (hr != 1) 
		throw (0);



	hr = dsGraph->AddCaptureDevice();
	if (hr != S_OK) 
		throw (0);


	hr = dsGraph->AddMpeg2Demultiplex(1); /* 1 means record on. */
	if (hr != S_OK) 
		throw (0);  

	hr = dsGraph->GetVideoDecoder()->AddVideoDecoder();
	if (hr != S_OK) 
		throw (0);


	hr = dsGraph->GetAudioDecoder()->AddAudioDecoder();
	if (hr != S_OK) 
		throw (0);


	hr = dsGraph->AddDumpFilter();
	if (hr != S_OK)
		throw (0);

    
	wchar_t wcstr[400];
    mbstowcs(wcstr, FileName, 400);
	
	 

	hr = dsGraph->pFileSourceInterface->SetFileName(wcstr , NULL);
	if (hr != S_OK)
		throw (0);



	char temp[100];
	sprintf (temp , "Output%d" ,  2) ;
	dsGraph->pInfeeFilterOutPin[1] = dsGraph->GET_PIN(dsGraph->pInfeeFilter , 
									temp , 
									PINDIR_OUTPUT);



    hr = dsGraph->m_pGraph->Connect(dsGraph->pInfeeFilterOutPin[1] , 
		  							 dsGraph->pDumpInPin) ;	


	if (hr != S_OK) 
		throw (0);



   VInPin = dsGraph->GetVideoDecoder()->GetVideoDecoderInPin();


    /* now the connection */
	hr = dsGraph->m_pGraph->Connect(dsGraph->pDemuxVideoOutPin , 
		                             VInPin) ;		

	if (hr != S_OK) 
		throw (0);

	VOutPin = dsGraph->GetVideoDecoder()->GetVideoDecoderOutPin();



	switch (use_vmr9)  { 
	  case 0 :
		hr = dsGraph->AddVideoRendererFilter();
		if (hr != S_OK)
		   throw (0);
		hr = dsGraph->m_pGraph->Connect(VOutPin , 
										  dsGraph->pRendererInPin) ;	
		if (hr != S_OK) 
			throw (0);

		break; 
		case 1: 
			hr = dsGraph->InitializeWindowlessVMR9(pWindow); 
   			if (hr != S_OK) 
			   throw (0);
			 hr = dsGraph->pBuilder->Render(VOutPin);

	  		 if (hr != S_OK)
				throw (0);

		break; 
        case 2: 
			hr = dsGraph->InitializeWindowlessVMR(pWindow); 
   			if (hr != S_OK) 
			   throw (0);

			 hr = dsGraph->pBuilder->Render(VOutPin);

	  		 if (hr != S_OK)
				throw (0);
		break; 
		default: 
			{
				hr = dsGraph->AddVideoRendererFilter();
				if (hr != S_OK)
				   throw (0);
			}

	}
	

	AInPin = dsGraph->GetAudioDecoder()->GetAudioDecoderInPin();
	if (AInPin == NULL)
		throw (0); 


	hr = dsGraph->m_pGraph->Connect(dsGraph->pDemuxAudioOutPin , 
		                             AInPin) ;	
	if (hr != S_OK) 
		throw (0);
	
	AOutPin = dsGraph->GetAudioDecoder()->GetAudioDecoderOutPin();
	hr = dsGraph->pBuilder->Render(AOutPin);
	if (hr != S_OK) 
		throw (0);

	hr = dsGraph->pCaptureDevice->QueryInterface(IID_IAMVideoProcAmp,  (void **)&dsGraph->pVideoAmp);
	if (hr != S_OK) 
		throw (0);
	

	hr = GetCrossbarInterface();
	if (hr != S_OK)  
		throw (0);


    hr = GetAnalogVideoInterface();
	if (hr != S_OK) 
		throw (0);


	return hr;

}

HRESULT CMPEG2Handler::Preview()
{

	HRESULT hr ;


	hr = dsGraph->MakeGraph();
	if (hr != 1) 
		throw (0);


	hr = dsGraph->AddCaptureDevice();
	if (hr != S_OK) 
		throw (0);

	hr = dsGraph->AddMpeg2Demultiplex();
	if (hr != S_OK)
	   throw (0);

	switch (use_vmr9)  { 
	  case 0 :
		hr = dsGraph->AddVideoRendererFilter();
		if (hr != S_OK)
		   throw (0);
		break; 
		case 1: 
			hr = dsGraph->InitializeWindowlessVMR9(pWindow); 
   			if (hr != S_OK) 
			   throw (0);
		break; 
        case 2: 
			hr = dsGraph->InitializeWindowlessVMR(pWindow); 
   			if (hr != S_OK) 
			   throw (0);
		break; 
		default: 
			{
				hr = dsGraph->AddVideoRendererFilter();
				if (hr != S_OK)
				   throw (0);
			}

	}


	hr = dsGraph->GetVideoDecoder()->AddVideoDecoder();
	if (hr != S_OK)
	   throw (0);

	hr = dsGraph->GetAudioDecoder()->AddAudioDecoder();
	if (hr != S_OK)
	   throw (0);


   
 
    VInPin = dsGraph->GetVideoDecoder()->GetVideoDecoderInPin();

	hr = GetCrossbarInterface();
	if (hr != S_OK)
	   throw (0);

    hr = GetAnalogVideoInterface();
	if (hr != S_OK)
	   throw (0);

 

    /* now the connection */
	hr = dsGraph->m_pGraph->Connect(dsGraph->pDemuxVideoOutPin , 
		                            VInPin) ;		


	if (hr != S_OK)
	   throw (0);
    

    VOutPin = dsGraph->GetVideoDecoder()->GetVideoDecoderOutPin();	

	hr = dsGraph->pBuilder->Render(VOutPin);

	if (hr != S_OK)
	   throw (0);

	AInPin = dsGraph->GetAudioDecoder()->GetAudioDecoderInPin();
	hr = dsGraph->m_pGraph->Connect(dsGraph->pDemuxAudioOutPin , 
		                             AInPin) ;	
	if (hr != S_OK)
	   throw (0);
	
	AOutPin = dsGraph->GetAudioDecoder()->GetAudioDecoderOutPin();
	hr = dsGraph->pBuilder->Render(AOutPin);

	if (hr != S_OK)
	   throw (0);

 
	hr = dsGraph->pCaptureDevice->QueryInterface(IID_IAMVideoProcAmp,  (void **)&dsGraph->pVideoAmp);
	
	if (hr != S_OK)
	   throw (0);
 

	return hr;

}




HRESULT CMPEG2Handler::Run()
{
	HRESULT hr ;


	dsGraph->SetupWindow(pWindow); 
    


	if (dsGraph->pCaptureDevice)  { 
		hr = dsGraph->pCaptureDevice->QueryInterface(IID_IAMVideoControl,  
															(void **)&dsGraph->pVideoControl);
		if (hr != S_OK) 
			return hr;
	}

 

	hr = dsGraph->m_pMC->Run();
     

  
    graph_mode = RUNNING_MODE;
    
  
	return hr;


}
HRESULT CMPEG2Handler::Stop()
{
	HRESULT hr ;
	

	if (graph_mode == STOP_MODE)
		 return S_OK;

 
	hr = dsGraph->m_pMC->Stop();

 
	hr = dsGraph->m_pVW->put_Visible(OAFALSE);

 
    graph_mode = STOP_MODE;
 
  

	return hr;
}
 

HRESULT CMPEG2Handler::Play()
{

 
	HRESULT hr = dsGraph->m_pMC->Run();
    graph_mode = PAUSE_MODE;

	return hr;
}
 
HRESULT CMPEG2Handler::Pause()
{

 
	HRESULT hr = dsGraph->m_pMC->Pause();
    graph_mode = PAUSE_MODE;

	return hr;
}
 
 
BOOL    CMPEG2Handler::IsRunning()
{


	if (graph_mode == RUNNING_MODE)
		return TRUE;

	return FALSE;

}
BOOL    CMPEG2Handler::IsPaused()
{
	if (graph_mode == PAUSE_MODE)
		return TRUE;

	return FALSE;

}
BOOL    CMPEG2Handler::IsStopped()
{
	if (graph_mode == STOP_MODE)
		return TRUE;

	return FALSE;

}
	
 
HRESULT CMPEG2Handler::SetBrightness(int value)
{

	HRESULT hr = dsGraph->pVideoAmp->Set(VideoProcAmp_Brightness,
								value,
								VideoProcAmp_Flags_Manual);
	
	return hr;

}

HRESULT CMPEG2Handler::SetHue(int value)
{

	HRESULT hr =  dsGraph->pVideoAmp->Set(VideoProcAmp_Hue,
									value,
									VideoProcAmp_Flags_Manual );

	return hr;
}
HRESULT CMPEG2Handler::SetChromeSaturation(int value)
{


		HRESULT hr =  dsGraph->pVideoAmp->Set(VideoProcAmp_Saturation,
										value,
										VideoProcAmp_Flags_Manual );


	
		return hr;

}

HRESULT CMPEG2Handler::SetContrast(int value)
{
 
	 
		HRESULT hr = dsGraph->pVideoAmp->Set(VideoProcAmp_Contrast,
									value,
									VideoProcAmp_Flags_Manual );
 	
		return hr;
}
 




HRESULT CMPEG2Handler::GetCrossbarInterface()
{


	HRESULT  hr = S_OK;

 
  

    USES_CONVERSION;

     
    IEnumMoniker *pEmCat = 0;
    ICreateDevEnum *pCreateDevEnum = NULL;
    int nClasses=0;

    // Create an enumerator
    hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
                          IID_ICreateDevEnum, (void**)&pCreateDevEnum);
    ASSERT(SUCCEEDED(hr));
    if (FAILED(hr))
        return hr;

    // Use the meta-category that contains a list of all categories.
    // This emulates the behavior of GraphEdit.
    hr = pCreateDevEnum->CreateClassEnumerator(
                         CLSID_ActiveMovieCategories, &pEmCat, 0);
    ASSERT(SUCCEEDED(hr));

    if(hr == S_OK)
    {
        IMoniker *pMCat;
        ULONG cFetched;

        // Enumerate over every category
        while(hr = pEmCat->Next(1, &pMCat, &cFetched),
              hr == S_OK)
        {


            IPropertyBag *pPropBag;

            // Associate moniker with a file
            hr = pMCat->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag);
            if(SUCCEEDED(hr))
            {
                VARIANT varCatClsid;
                varCatClsid.vt = VT_BSTR;

                // Read CLSID string from property bag
                hr = pPropBag->Read(L"CLSID", &varCatClsid, 0);
                if(SUCCEEDED(hr))
                {

                    if(CLSIDFromString(varCatClsid.bstrVal, &clsidCat) == S_OK)
                    {
                        // Use the guid if we can't get the name
                        WCHAR *wszCatName;
                        TCHAR szCatDesc[MAX_PATH];

                        VARIANT varCatName;
                        varCatName.vt = VT_BSTR;

                        // Read filter name
                        hr = pPropBag->Read(L"FriendlyName", &varCatName, 0);
                        if(SUCCEEDED(hr))
                            wszCatName = varCatName.bstrVal;
                        else
                            wszCatName = varCatClsid.bstrVal;

#ifndef UNICODE
                        WideCharToMultiByte(
                                CP_ACP, 0, wszCatName, -1,
                                szCatDesc, sizeof(szCatDesc), 0, 0);
#else
                        lstrcpy(szCatDesc, W2T(wszCatName));
#endif

                        if(SUCCEEDED(hr))
                            SysFreeString(varCatName.bstrVal);

                        // Add category name and CLSID to list box
                        //AddFilterCategory(szCatDesc, &clsidCat);
                        nClasses++;

						if (strcmp(szCatDesc  ,  "WDM Streaming Crossbar Devices") == 0) {
						     break;
						}
                    }
					
                    SysFreeString(varCatClsid.bstrVal);
                }

                pPropBag->Release();
            }
            else
            {
                break;
            }

            pMCat->Release();
        } // for loop

        pEmCat->Release();
    }

    pCreateDevEnum->Release();

    	
	ICreateDevEnum * m_pSysDevEnum;
 // Instantiate the system device enumerator
    m_pSysDevEnum = NULL;
    IEnumMoniker *pEnumCat = NULL;

    hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, 
                          CLSCTX_INPROC, IID_ICreateDevEnum, 
                          (void **)&m_pSysDevEnum);

 // Enumerate all filters of the selected category  
    hr = m_pSysDevEnum->CreateClassEnumerator(clsidCat, &pEnumCat, 0);
    ASSERT(SUCCEEDED(hr));
    if FAILED(hr)
        return hr;

    // Enumerate all filters using the category enumerator
    hr = EnumFilters(pEnumCat);


    return hr; 

 
}
HRESULT CMPEG2Handler::GetAnalogVideoInterface()
{

	   HRESULT      hr  = S_OK;
	   if (dsGraph->pAmAnalogVideo == NULL) { 
			hr = dsGraph->pCaptureDevice->QueryInterface(IID_IAMAnalogVideoDecoder ,  
				                                         (void **)&dsGraph->pAmAnalogVideo);
			if (FAILED(hr))  {
			   return hr;
			}
		}
	   return hr ; 
}
HRESULT CMPEG2Handler::Route(int in , int out)
{
	

	if (dsGraph->pAmCrossbar)
	   dsGraph->pAmCrossbar->Route (in  , out);

	return S_OK;
}


HRESULT CMPEG2Handler::EnumFilters(IEnumMoniker *pEnumCat)
{

    HRESULT hr=S_OK;
    IMoniker *pMoniker;
    ULONG cFetched;
    VARIANT varName={0};
    int nFilters=0;

    
    // If there are no filters of a requested type, show default string
    if (!pEnumCat)
    {
        
        return S_FALSE;
    }

	int found  = 0;
again:

    // Enumerate all items associated with the moniker
    while(pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK)
    {
        IPropertyBag *pPropBag;
        ASSERT(pMoniker);

        // Associate moniker with a file
        hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, 
                                    (void **)&pPropBag);
        ASSERT(SUCCEEDED(hr));
        ASSERT(pPropBag);
        if (FAILED(hr))
            continue;

        // Read filter name from property bag
        varName.vt = VT_BSTR;
        hr = pPropBag->Read(L"FriendlyName", &varName, 0);
        if (FAILED(hr))
            continue;

        // Get filter name (converting BSTR name to a CString)
        CString str(varName.bstrVal);
        SysFreeString(varName.bstrVal);
        nFilters++;

		if (str != "BeCapture Crossbar")
			goto again;

		found = 1;

        // Read filter's CLSID from property bag.  This CLSID string will be
        // converted to a binary CLSID and passed to AddFilter(), which will
        // add the filter's name to the listbox and its CLSID to the listbox
        // item's DataPtr item.  When the user clicks on a filter name in
        // the listbox, we'll read the stored CLSID, convert it to a string,
        // and use it to find the filter's filename in the registry.
        VARIANT varFilterClsid;
        varFilterClsid.vt = VT_BSTR;

        // Read CLSID string from property bag
        hr = pPropBag->Read(L"CLSID", &varFilterClsid, 0);
        if(SUCCEEDED(hr))
        {
            CLSID clsidFilter;

            // Add filter name and CLSID to listbox
            if(CLSIDFromString(varFilterClsid.bstrVal, &clsidFilter) == S_OK)
            {
				
				// Bind Moniker to a filter object
				hr = pMoniker->BindToObject(0,0,IID_IBaseFilter, 
									       (void**)&dsGraph->pCrossbarDevice);
				if (FAILED(hr))
				{
					return hr;
				}

				
				 hr = dsGraph->pCrossbarDevice->QueryInterface(IID_IAMCrossbar,  (void **)&dsGraph->pAmCrossbar);
				 if (FAILED(hr))  {
				    return hr;
				 }
            }

            SysFreeString(varFilterClsid.bstrVal);
        }
       
        // Cleanup interfaces
        SAFE_RELEASE(pPropBag);
        SAFE_RELEASE(pMoniker);

		if (found)
			break;
    }

    
    return hr;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Israel Israel
Enjoy from Cabelim.com

Comments and Discussions