视频捕获增加color space converter + Transform Filter

参考:http://blog.csdn.net/luckyboy101/article/details/7836693

http://blog.csdn.net/luckyboy101/article/details/7841673

其它不解释,贴是代码:

IPFilter.h

//
// Sample DirectShow In-Place Transform Filter that accepts data for use in application
//

#include <streams.h>

// This is an example transform filter that is created within
// the application, and not by CoCreateInstance
class CAppTransform : public CTransformFilter
{
public:
    CAppTransform(LPUNKNOWN pUnkOuter, HRESULT *phr);

    HRESULT CheckInputType(const CMediaType* mtIn);
    
	HRESULT Transform(IMediaSample *pIn, IMediaSample *pOut);
	HRESULT CheckTransform(const CMediaType *mtIn,const CMediaType *mtOut);
	HRESULT DecideBufferSize(IMemAllocator *pAlloc,
		ALLOCATOR_PROPERTIES *pProperties);
	HRESULT GetMediaType(int iPosition, CMediaType *pMediaType);
private:
	HRESULT Copy(IMediaSample *pSource, IMediaSample *pDest) const;
	HRESULT Transform(IMediaSample *pSample);
};


// DirectShow graph management sample code:
// This builds a playback graph using RenderFile
// and then inserts a transform filter on the uncompressed video.
class CAppGraphBuilder
{
private:
	CAppTransform*   m_pFilter;
	DWORD		     m_dwObjectTable; 
	ICaptureGraphBuilder2 *m_pBuild;
	IGraphBuilder *m_pGraph;

public:
    CAppGraphBuilder();
    ~CAppGraphBuilder();

    void DestroyGraph(void);

    HRESULT BuildFromFile(LPCWSTR pszFile);
    HRESULT Run(void);
    HRESULT MakeChild(HWND hwnd);
    HRESULT ResizeVideoWindow(RECT* prc);

private:
	void CreateAppFilter(void);
	HRESULT FindFilterByInterface(REFIID riid, IBaseFilter** ppFilter);
	HRESULT ConnectUpstreamOf(IBaseFilter* pFilter,IBaseFilter*pColor, IBaseFilter* pTransform);
	HRESULT NextUpstream(IBaseFilter* pFilter, IBaseFilter** ppNext);  
	HRESULT CAppGraphBuilder::AddFilterByCLSID(IGraphBuilder *pGraph,const GUID& clsid,LPCWSTR wszName,IBaseFilter **ppF);
	
	HRESULT InitCaptureGraphBuilder(IGraphBuilder **ppGraph,ICaptureGraphBuilder2 **ppBuild);
	HRESULT EnumerateDevices(REFGUID category, IEnumMoniker **ppEnum);
	void DisplayDeviceInformation(IEnumMoniker *pEnum, IMoniker** pMoniker);

	IPin* GetPin(IBaseFilter* pFilter, PIN_DIRECTION dirRequest);
	// Helper methods
	IPin* InputPinOf(IBaseFilter* pFilter) 
	{
		return GetPin(pFilter, PINDIR_INPUT);
	}
	IPin* OutputPinOf(IBaseFilter* pFilter) 
	{
		return GetPin(pFilter, PINDIR_OUTPUT);
	}

	void AddToObjectTable(void) ;
	void RemoveFromObjectTable(void);
};



IPFilter.cpp

//
// Sample DirectShow Transform Filter that accepts data for use in application
//

#include "stdafx.h"
#include "IPFilter.h"

////////////////////////////////////////////////////////////////////////////////
CAppTransform::CAppTransform(LPUNKNOWN pUnkOuter, HRESULT *phr) : 
CTransformFilter(NAME("App Transform"), pUnkOuter, GUID_NULL)
{
}
//
// CheckTransform
//
// To be able to transform the formats must be identical
//
HRESULT CAppTransform::CheckTransform(const CMediaType *mtIn,const CMediaType *mtOut)
{
	CheckPointer(mtIn,E_POINTER);
	CheckPointer(mtOut,E_POINTER);

	HRESULT hr;
	if(FAILED(hr = CheckInputType(mtIn)))
	{
		return hr;
	}

	// format must be a VIDEOINFOHEADER
	if(*mtOut->FormatType() != FORMAT_VideoInfo)
	{
		return E_INVALIDARG;
	}

	// formats must be big enough 
	if(mtIn->FormatLength() < sizeof(VIDEOINFOHEADER) ||
		mtOut->FormatLength() < sizeof(VIDEOINFOHEADER))
		return E_INVALIDARG;

	VIDEOINFO *pInput  = (VIDEOINFO *) mtIn->Format();
	VIDEOINFO *pOutput = (VIDEOINFO *) mtOut->Format();

	if(memcmp(&pInput->bmiHeader,&pOutput->bmiHeader,sizeof(BITMAPINFOHEADER)) == 0)
	{
		return NOERROR;
	}

	return E_INVALIDARG;

} // CheckTransform
//
// DecideBufferSize
//
// Tell the output pin's allocator what size buffers we
// require. Can only do this when the input is connected
//
HRESULT CAppTransform::DecideBufferSize(IMemAllocator *pAlloc,ALLOCATOR_PROPERTIES *pProperties)
{
	CheckPointer(pAlloc,E_POINTER);
	CheckPointer(pProperties,E_POINTER);

	// Is the input pin connected

	if(m_pInput->IsConnected() == FALSE)
	{
		return E_UNEXPECTED;
	}
	HRESULT hr = NOERROR;
	pProperties->cBuffers = 1;
	pProperties->cbBuffer = m_pInput->CurrentMediaType().GetSampleSize();

	ASSERT(pProperties->cbBuffer);

	// If we don't have fixed sized samples we must guess some size

	if(!m_pInput->CurrentMediaType().bFixedSizeSamples)
	{
		if(pProperties->cbBuffer < 100000)
		{
			// nothing more than a guess!!
			pProperties->cbBuffer = 100000;
		}
	}

	// Ask the allocator to reserve us some sample memory, NOTE the function
	// can succeed (that is return NOERROR) but still not have allocated the
	// memory that we requested, so we must check we got whatever we wanted

	ALLOCATOR_PROPERTIES Actual;

	hr = pAlloc->SetProperties(pProperties,&Actual);
	if(FAILED(hr))
	{
		return hr;
	}

	ASSERT(Actual.cBuffers == 1);

	if(pProperties->cBuffers > Actual.cBuffers ||
		pProperties->cbBuffer > Actual.cbBuffer)
	{
		return E_FAIL;
	}

	return NOERROR;

} // DecideBufferSize
//
// GetMediaType
//
// I support one type, namely the type of the input pin
// We must be connected to support the single output type
//
HRESULT CAppTransform::GetMediaType(int iPosition, CMediaType *pMediaType)
{
	// Is the input pin connected

	if(m_pInput->IsConnected() == FALSE)
	{
		return E_UNEXPECTED;
	}

	// This should never happen

	if(iPosition < 0)
	{
		return E_INVALIDARG;
	}

	// Do we have more items to offer

	if(iPosition > 0)
	{
		return VFW_S_NO_MORE_ITEMS;
	}

	CheckPointer(pMediaType,E_POINTER);

	*pMediaType = m_pInput->CurrentMediaType();
	return NOERROR;

}
HRESULT CAppTransform::Copy(IMediaSample *pSource, IMediaSample *pDest) const
{
	CheckPointer(pSource,E_POINTER);
	CheckPointer(pDest,E_POINTER);

	// Copy the sample data
	BYTE *pSourceBuffer, *pDestBuffer;
	long lSourceSize = pSource->GetActualDataLength();

#ifdef DEBUG
	long lDestSize = pDest->GetSize();
	ASSERT(lDestSize >= lSourceSize);
#endif

	pSource->GetPointer(&pSourceBuffer);
	pDest->GetPointer(&pDestBuffer);

	CopyMemory((PVOID) pDestBuffer,(PVOID) pSourceBuffer,lSourceSize);

	// Copy the sample times

	REFERENCE_TIME TimeStart, TimeEnd;
	if(NOERROR == pSource->GetTime(&TimeStart, &TimeEnd))
	{
		pDest->SetTime(&TimeStart, &TimeEnd);
	}

	LONGLONG MediaStart, MediaEnd;
	if(pSource->GetMediaTime(&MediaStart,&MediaEnd) == NOERROR)
	{
		pDest->SetMediaTime(&MediaStart,&MediaEnd);
	}

	// Copy the Sync point property

	HRESULT hr = pSource->IsSyncPoint();
	if(hr == S_OK)
	{
		pDest->SetSyncPoint(TRUE);
	}
	else if(hr == S_FALSE)
	{
		pDest->SetSyncPoint(FALSE);
	}
	else
	{  // an unexpected error has occured...
		return E_UNEXPECTED;
	}

	// Copy the media type

	AM_MEDIA_TYPE *pMediaType;
	pSource->GetMediaType(&pMediaType);
	pDest->SetMediaType(pMediaType);
	DeleteMediaType(pMediaType);

	// Copy the preroll property

	hr = pSource->IsPreroll();
	if(hr == S_OK)
	{
		pDest->SetPreroll(TRUE);
	}
	else if(hr == S_FALSE)
	{
		pDest->SetPreroll(FALSE);
	}
	else
	{  // an unexpected error has occured...
		return E_UNEXPECTED;
	}

	// Copy the discontinuity property

	hr = pSource->IsDiscontinuity();

	if(hr == S_OK)
	{
		pDest->SetDiscontinuity(TRUE);
	}
	else if(hr == S_FALSE)
	{
		pDest->SetDiscontinuity(FALSE);
	}
	else
	{  // an unexpected error has occured...
		return E_UNEXPECTED;
	}

	// Copy the actual data length

	long lDataLength = pSource->GetActualDataLength();
	pDest->SetActualDataLength(lDataLength);

	return NOERROR;

} // Copy
//
// Transform
//
// Copy the input sample into the output sample
// Then transform the output sample 'in place'
//
HRESULT CAppTransform::Transform(IMediaSample *pIn, IMediaSample *pOut)
{
	HRESULT hr = Copy(pIn, pOut);
	if (FAILED(hr)) {
		return hr;
	}

	return Transform(pOut);


} // Transform
HRESULT CAppTransform::Transform(IMediaSample *pSample)
{
	// Override to do something inside the application
	// Such as grabbing a poster frame...
	// ...
	BYTE *pData;                // Pointer to the actual image buffer
	long lDataLen;              // Holds length of any given sample
	int iPixel;                 // Used to loop through the image pixels
	tagRGBTRIPLE *prgb;            // Holds a pointer to the current pixel

	AM_MEDIA_TYPE* pType = &m_pInput->CurrentMediaType();
	VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER *) pType->pbFormat;
	ASSERT(pvi);

	CheckPointer(pSample,E_POINTER);
	pSample->GetPointer(&pData);
	lDataLen = pSample->GetSize();

	// Get the image properties from the BITMAPINFOHEADER

	int cxImage    = pvi->bmiHeader.biWidth;
	int cyImage    = pvi->bmiHeader.biHeight;
	int numPixels  = cxImage * cyImage;

	// int iPixelSize = pvi->bmiHeader.biBitCount / 8;
	// int cbImage    = cyImage * cxImage * iPixelSize;


	prgb = (tagRGBTRIPLE*) pData;
	for (iPixel=0; iPixel < numPixels; iPixel++, prgb++) {
	prgb->rgbtRed=prgb->rgbtBlue=prgb->rgbtGreen=(prgb->rgbtRed+prgb->rgbtBlue+prgb->rgbtGreen)/3;
	}
    return S_OK;
}

// Check if we can support this specific proposed type and format
HRESULT CAppTransform::CheckInputType(const CMediaType *pmt) 
{
	// We accept a series of raw media types
	/*if (pmt->majortype == MEDIATYPE_Video &&
	(pmt->subtype == MEDIASUBTYPE_RGB32 ||
	pmt->subtype == MEDIASUBTYPE_RGB24 ||
	pmt->subtype == MEDIASUBTYPE_RGB565 ||
	pmt->subtype == MEDIASUBTYPE_RGB555 ||
	pmt->subtype == MEDIASUBTYPE_UYVY ||
	pmt->subtype == MEDIASUBTYPE_YUY2)||
	pmt->subtype==MEDIASUBTYPE_NV12)*/
	if (pmt->majortype == MEDIATYPE_Video &&
		(pmt->subtype == MEDIASUBTYPE_RGB24))
	{
		return NOERROR;
	}
	return E_FAIL;
}


// --- graph building (examples) --------- 
CAppGraphBuilder::CAppGraphBuilder() : 
m_pBuild(NULL),
m_pGraph(NULL),
m_pFilter(NULL),
m_dwObjectTable(0)
{
    CoInitialize(NULL);
}

CAppGraphBuilder::~CAppGraphBuilder()
{
    DestroyGraph();
    CoUninitialize();
}
    
void CAppGraphBuilder::DestroyGraph(void)
{
    if (m_pGraph) 
	{
		RemoveFromObjectTable();
        // ensure graph window is not child of ours
        IVideoWindow* pVW = NULL;
        HRESULT hr = m_pGraph->QueryInterface(IID_IVideoWindow, (void**)&pVW);
        if (SUCCEEDED(hr)) 
		{
            pVW->put_Visible(OAFALSE);
            pVW->put_Owner(NULL);
            pVW->put_MessageDrain(NULL);
            pVW->Release();
        }
        m_pGraph->Release();
        m_pGraph = NULL;
		m_pBuild->Release();
		m_pBuild = NULL;
    }

	if (m_pFilter) 
	{
		m_pFilter->Release();
		m_pFilter = NULL;
	}
}
HRESULT CAppGraphBuilder::InitCaptureGraphBuilder(
	IGraphBuilder **ppGraph,  // Receives the pointer.
	ICaptureGraphBuilder2 **ppBuild  // Receives the pointer.
	)
{
	if (!ppGraph || !ppBuild)
	{
		return E_POINTER;
	}
	IGraphBuilder *pGraph = NULL;
	ICaptureGraphBuilder2 *pBuild = NULL;

	// Create the Capture Graph Builder.
	HRESULT hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, 
		CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void**)&pBuild );
	if (SUCCEEDED(hr))
	{
		// Create the Filter Graph Manager.
		hr = CoCreateInstance(CLSID_FilterGraph, 0, CLSCTX_INPROC_SERVER,
			IID_IGraphBuilder, (void**)&pGraph);
		if (SUCCEEDED(hr))
		{
			// Initialize the Capture Graph Builder.
			pBuild->SetFiltergraph(pGraph);

			// Return both interface pointers to the caller.
			*ppBuild = pBuild;
			*ppGraph = pGraph; // The caller must release both interfaces.
			return S_OK;
		}
		else
		{
			pBuild->Release();
		}
	}
	return hr; // Failed
}



HRESULT CAppGraphBuilder::EnumerateDevices(REFGUID category, IEnumMoniker **ppEnum)
{
	ICreateDevEnum *pDevEnum = NULL;

	// Create the System Device Enumerator.
	HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
		CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, 
		reinterpret_cast<void**>(&pDevEnum));
	if (SUCCEEDED(hr))
	{
		// Create an enumerator for the video capture category.
		hr = pDevEnum->CreateClassEnumerator(
			CLSID_VideoInputDeviceCategory,
			ppEnum, 0);
	}
	return hr;
}
void CAppGraphBuilder::DisplayDeviceInformation(IEnumMoniker *pEnum, IMoniker** pMoniker)
{
	HWND hList; // Handle to the list box.
	while (pEnum->Next(1, pMoniker, NULL) == S_OK)
	{
		IPropertyBag *pPropBag;
		HRESULT hr = (*pMoniker)->BindToStorage(0, 0, IID_IPropertyBag, 
			(void**)(&pPropBag));
		if (FAILED(hr))
		{
			(*pMoniker)->Release();
			continue;  // Skip this one, maybe the next one will work.
		} 
		// Find the description or friendly name.
		VARIANT varName;
		VariantInit(&varName);
		hr = pPropBag->Read(L"Description", &varName, 0);
		if (FAILED(hr))
		{
			hr = pPropBag->Read(L"FriendlyName", &varName, 0);
		}
		if (SUCCEEDED(hr))
		{
			// Add it to the application's list box.
			USES_CONVERSION;
			/*(long)SendMessage(hList, LB_ADDSTRING, 0, 
			(LPARAM)OLE2T(varName.bstrVal));*/
			VariantClear(&varName); 
		}
		pPropBag->Release();
		(*pMoniker)->Release();
	}


}
HRESULT CAppGraphBuilder::AddFilterByCLSID(
	IGraphBuilder *pGraph,  // Pointer to the Filter Graph Manager.
	const GUID& clsid,      // CLSID of the filter to create.
	LPCWSTR wszName,        // A name for the filter.
	IBaseFilter **ppF)      // Receives a pointer to the filter.
{
	if (!pGraph || ! ppF) return E_POINTER;
	*ppF = 0;
	IBaseFilter *pF = 0;
	HRESULT hr = CoCreateInstance(clsid, 0, CLSCTX_INPROC_SERVER,
		IID_IBaseFilter, reinterpret_cast<void**>(&pF));
	if (SUCCEEDED(hr))
	{
		hr = pGraph->AddFilter(pF, wszName);
		if (SUCCEEDED(hr))
			*ppF = pF;
		else
			pF->Release();
	}
	return hr;
}
HRESULT CAppGraphBuilder::BuildFromFile(LPCWSTR pszFile)
{
	DestroyGraph();
	IMoniker* pMoniker;
	
	IMediaEvent   *pEvent;

	InitCaptureGraphBuilder(&m_pGraph,&m_pBuild);
	
	HRESULT hr = m_pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);

	AddToObjectTable();
	IBaseFilter *pCap; // Video capture filter.
	IEnumMoniker *pEnum;

	hr = EnumerateDevices(CLSID_VideoInputDeviceCategory, &pEnum);

	DisplayDeviceInformation(pEnum, &pMoniker);
	hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pCap);
	if (SUCCEEDED(hr))
	{
		hr = m_pGraph->AddFilter(pCap, L"Capture Filter");
	}
	hr = m_pBuild->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, pCap, NULL, NULL);


	IBaseFilter *pMux;
	hr = m_pBuild->SetOutputFileName(&MEDIASUBTYPE_Avi,L"D:\\Example.avi",&pMux,NULL);
	hr = m_pBuild->RenderStream(&PIN_CATEGORY_CAPTURE,&MEDIATYPE_Video,pCap,NULL,pMux);

	
	
	// Try to find the video renderer, by looking for IVideoWindow
	IBaseFilter* pVR;
	hr = FindFilterByInterface(IID_IVideoWindow, &pVR);
	if (FAILED(hr)) 
	{
		return hr;
	}

	// Find the media type on the input pin of the Video Renderer
	// to check for overlay connection where no actual data is passed
	IPin* pPin = InputPinOf(pVR);
	AM_MEDIA_TYPE mt;
	pPin->ConnectionMediaType(&mt);
	pPin->Release();
	CMediaType mtIn = mt;
	FreeMediaType(mt);

	if (mtIn.subtype == MEDIASUBTYPE_Overlay) 
	{
		// This connection may be a overlay mixer 
		// need to move upstream one place
		IBaseFilter* pOvMix = NULL;
		hr = NextUpstream(pVR, &pOvMix);
		pVR->Release();
		if (FAILED(hr)) 
		{
			return hr;
		}
		pVR = pOvMix;
	}

	// Create the transform and insert in graph
	CreateAppFilter();

	// Add Color Space Convert
	IBaseFilter *pColor;
	hr=AddFilterByCLSID(m_pGraph, CLSID_Colour, L"Color Space Converter", &pColor);

	// Try to insert our transform filter
	hr = ConnectUpstreamOf(pVR, pColor,m_pFilter);
	//pVR->Release();

	
	//pColor->Release();

	return hr;
}

// Start the graph
HRESULT CAppGraphBuilder::Run(void)
{
	IMediaControl* pControl = NULL;
	HRESULT hr = m_pGraph->QueryInterface(IID_IMediaControl, (void**)&pControl);
	if (SUCCEEDED(hr)) 
	{
		hr = pControl->Run();
		pControl->Release();
	}
	return hr;
}

// Make the video window a child of this app
HRESULT CAppGraphBuilder::MakeChild(HWND hwnd)
{
    if (!m_pGraph) 
	{
        return E_FAIL;
    }

    IVideoWindow* pVW = NULL;
	HRESULT hr = m_pGraph->QueryInterface(IID_IVideoWindow, (void**)&pVW);
    if (SUCCEEDED(hr)) 
	{
		HWND hwndOld;
		pVW->get_Owner((LONG*)&hwndOld);
		if (hwndOld != hwnd)
		{
			pVW->put_AutoShow(OAFALSE);
			pVW->put_Visible(OAFALSE);
			
			long    WindowStyle = 0;
			// Tweak the video's window style to get rid of the caption and frame:
			hr = pVW->get_WindowStyle(&WindowStyle);
			if (SUCCEEDED(hr)) 
			{
				WindowStyle &= ~WS_OVERLAPPEDWINDOW; // No frame junk
				WindowStyle |= WS_CHILD;             // Needs to be child
				hr = pVW->put_WindowStyle(WindowStyle);
			}

			pVW->put_Owner((LONG)hwnd);
			pVW->put_MessageDrain((LONG)hwnd);

            if (hwnd != NULL) 
			{
				RECT rc;
				GetClientRect(hwnd, &rc);
				pVW->SetWindowPosition(
						rc.left,
						rc.top,
						rc.right - rc.left,
						rc.bottom - rc.top);
				pVW->put_Visible(OATRUE);
            }
		}
		pVW->Release();
    }

    return hr;
}

// Resize the video window
HRESULT CAppGraphBuilder::ResizeVideoWindow(RECT* prc)
{
	if (!m_pGraph) 
	{
		return E_FAIL;
	}

	IVideoWindow* pVW = NULL;
	HRESULT hr = m_pGraph->QueryInterface(IID_IVideoWindow, (void**)&pVW);
	if (SUCCEEDED(hr)) 
	{
		hr = pVW->SetWindowPosition(
			prc->left,
			prc->top,
			prc->right - prc->left,
			prc->bottom - prc->top);
		pVW->Release();
	}
	return hr;
}

// Create the app-based filter and insert into graph (unconnected)
void CAppGraphBuilder::CreateAppFilter(void)
{
	if (m_pFilter) 
	{
		m_pFilter->Release();
		m_pFilter = NULL;
	}

	HRESULT hr = S_OK;
	m_pFilter = new CAppTransform(NULL, &hr);
	// Make the initial refcount 1 to match COM creation!!!
	m_pFilter->AddRef();

	// Add to graph -- nb need to Query properly for the
	// right interface before giving that to the graph object
	IBaseFilter* pFilter = NULL;
	hr = m_pFilter->QueryInterface(IID_IBaseFilter, (void**)&pFilter);
	if (SUCCEEDED(hr)) 
	{
		hr = m_pGraph->AddFilter(pFilter, L"App Transform");
		pFilter->Release();
	}
}

// Locate a filter within the graph by searching (from renderers upstream)
// looking for a specific interface on the filter
HRESULT CAppGraphBuilder::FindFilterByInterface(REFIID riid, IBaseFilter** ppFilter)
{
    *ppFilter = NULL;

    IEnumFilters* pEnum;
    HRESULT hr = m_pGraph->EnumFilters(&pEnum);
    if (FAILED(hr)) 
	{
		return hr;
    }

    IBaseFilter* pFilter = NULL;
    while (pEnum->Next(1, &pFilter, NULL) == S_OK) 
	{
		// Check for required interface
		IUnknown* pUnk;
		HRESULT hrQuery = pFilter->QueryInterface(riid, (void**)&pUnk);
		if (SUCCEEDED(hrQuery)) 
		{
			pUnk->Release();
			pEnum->Release();
			*ppFilter = pFilter;
			return S_OK;
		}
		pFilter->Release();
    }
    pEnum->Release();

    return E_FAIL;
}


// Connect the filter pTransform upstream of pFilter by reconnecting pins.
// Assumes that pTransform has only one input and one output, and
// that pFilter has only one input.
HRESULT CAppGraphBuilder::ConnectUpstreamOf(IBaseFilter* pFilter, IBaseFilter*pColor,IBaseFilter* pTransform)
{
	IPin* pPinIn = InputPinOf(pFilter);
	if (!pPinIn) 
	{
		return E_FAIL;
	}

	// Get the peer output pin
	IPin* pPinOut = NULL;
	HRESULT hr = pPinIn->ConnectedTo(&pPinOut);
	if (FAILED(hr)) 
	{
		pPinIn->Release();
		return hr;
	}

	// Disconnect the current connection
	hr = m_pGraph->Disconnect(pPinOut);
	if (SUCCEEDED(hr)) 
	{
		hr = m_pGraph->Disconnect(pPinIn);
	}

	// Insert pTransform filter by connecting its input pin and output pin
	if (SUCCEEDED(hr)) 
	{
		IPin* pPinInCor = InputPinOf(pColor);
		hr = m_pGraph->Connect(pPinOut, pPinInCor);
		pPinInCor->Release();
	}
	if (SUCCEEDED(hr)) 
	{
		IPin* pPinInXfm = InputPinOf(pTransform);
		IPin* pPinOutCor = OutputPinOf(pColor);
		hr = m_pGraph->Connect(pPinOutCor, pPinInXfm);
		pPinInXfm->Release();
		pPinOutCor->Release();
	}
	if (SUCCEEDED(hr)) 
	{
		IPin* pPinOutXfm = OutputPinOf(pTransform);
		hr = m_pGraph->Connect(pPinOutXfm, pPinIn);
		pPinOutXfm->Release();
	}
	
	pPinIn->Release();
	pPinOut->Release();
	return hr;
}

// Find the first pin of a specific direction on a given filter
IPin* CAppGraphBuilder::GetPin(IBaseFilter* pFilter, PIN_DIRECTION dirRequest)
{
	IPin * foundPin = NULL;

    IEnumPins* pEnum = NULL;
    HRESULT hr = pFilter->EnumPins(&pEnum);
    if (SUCCEEDED(hr)) 
	{
		IPin* pPin = NULL;
        while (!foundPin && pEnum->Next(1, &pPin, 0) == S_OK) 
		{
			PIN_DIRECTION dir;
			pPin->QueryDirection(&dir);
			if (dir == dirRequest) 
			{
				foundPin = pPin;
			}
			else
			{
				pPin->Release();
			}
		}
		pEnum->Release();
    }
    return foundPin;
}

// Follow the pin connections to return the filter that is 
// connected to the first input pin of pFilter
HRESULT CAppGraphBuilder::NextUpstream(IBaseFilter* pFilter, IBaseFilter** ppNext)
{
    IPin* pPin = InputPinOf(pFilter);
    if (!pPin) 
	{
		return E_FAIL;
    }

	// Get the peer output pin
    IPin* pPinOut = NULL;
    HRESULT hr = pPin->ConnectedTo(&pPinOut);
    pPin->Release();
    if (FAILED(hr)) 
	{
		return hr;
    }

    PIN_INFO info;
    pPinOut->QueryPinInfo(&info);
	pPinOut->Release();
    *ppNext = info.pFilter;
    
    return S_OK;
}



//////////////////////// For GraphEdit Dubug purpose /////////////////////////////
void CAppGraphBuilder::AddToObjectTable(void)
{
	IMoniker * pMoniker = 0;
    IRunningObjectTable * objectTable = 0;
    if (SUCCEEDED(GetRunningObjectTable(0, &objectTable))) 
	{
		WCHAR wsz[256];
		wsprintfW(wsz, L"FilterGraph %08p pid %08x", (DWORD_PTR)m_pGraph, GetCurrentProcessId());
		HRESULT hr = CreateItemMoniker(L"!", wsz, &pMoniker);
		if (SUCCEEDED(hr)) 
		{
			hr = objectTable->Register(0, m_pGraph, pMoniker, &m_dwObjectTable);
			pMoniker->Release();
		}
		objectTable->Release();
	}
}

void CAppGraphBuilder::RemoveFromObjectTable(void)
{
	IRunningObjectTable * objectTable = 0;
    if (SUCCEEDED(GetRunningObjectTable(0, &objectTable))) 
	{
        objectTable->Revoke(m_dwObjectTable);
        objectTable->Release();
		m_dwObjectTable = 0;
    }
}
调用:

	LPCWSTR wchFile=L"D:\\example.avi";
			m_Graph.BuildFromFile(wchFile);
			m_Graph.MakeChild(GetSafeHwnd());
			m_Graph.Run();


最后记得

pControl->Stop();

你可能感兴趣的:(properties,filter,video,null,Graph,output)