现在的位置: 首页 > 综合 > 正文

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

2013年10月04日 ⁄ 综合 ⁄ 共 8766字 ⁄ 字号 评论关闭

参考: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(
	IGraphBui

抱歉!评论已关闭.