直接在MFC中用Directshow Transform filter

来源:互联网 发布:熊片数据库 安卓 编辑:程序博客网 时间:2024/05/21 10:50


IPFilter.h

//// Sample DirectShow In-Place Transform Filter that accepts data for use in application//#include <streams.h>// This is an example in-place transform filter that is created within// the application, and not by CoCreateInstanceclass CAppTransform : public CTransInPlaceFilter{public:    CAppTransform(LPUNKNOWN pUnkOuter, HRESULT *phr);    HRESULT CheckInputType(const CMediaType* mtIn);    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;    IGraphBuilder*   m_pGraph;DWORD     m_dwObjectTable; 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* pTransform);HRESULT NextUpstream(IBaseFilter* pFilter, IBaseFilter** ppNext);   IPin* GetPin(IBaseFilter* pFilter, PIN_DIRECTION dirRequest);// Helper methodsIPin* 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 In-Place Transform Filter that accepts data for use in application//#include "stdafx.h"#include "IPFilter.h"////////////////////////////////////////////////////////////////////////////////CAppTransform::CAppTransform(LPUNKNOWN pUnkOuter, HRESULT *phr) : CTransInPlaceFilter(NAME("App Transform"), pUnkOuter, GUID_NULL, phr){}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 bufferlong lDataLen;              // Holds length of any given sampleint iPixel;                 // Used to loop through the image pixelstagRGBQUAD *prgb;            // Holds a pointer to the current pixelAM_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 BITMAPINFOHEADERint 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 = (tagRGBQUAD*) pData;for (iPixel=0; iPixel < numPixels; iPixel++, prgb++) {prgb->rgbRed=255;}    return S_OK;}// Check if we can support this specific proposed type and formatHRESULT CAppTransform::CheckInputType(const CMediaType *pmt) {// We accept a series of raw media typesif (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){return NOERROR;}return E_FAIL;}// --- graph building (examples) --------- CAppGraphBuilder::CAppGraphBuilder() : m_pFilter(NULL),m_pGraph(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;    }    if (m_pFilter) {m_pFilter->Release();        m_pFilter = NULL;    }}HRESULT CAppGraphBuilder::BuildFromFile(LPCWSTR pszFile){DestroyGraph();// Build a filter graphHRESULT hr = CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC,IID_IGraphBuilder,(void**)&m_pGraph);if (FAILED(hr)){return hr;}AddToObjectTable();// render the file to build the initial graphhr = m_pGraph->RenderFile(pszFile, NULL);if (FAILED(hr)) {return hr;}// Try to find the video renderer, by looking for IVideoWindowIBaseFilter* 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 passedIPin* 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 placeIBaseFilter* pOvMix = NULL;hr = NextUpstream(pVR, &pOvMix);pVR->Release();if (FAILED(hr)) {return hr;}pVR = pOvMix;}// Create the transform and insert in graphCreateAppFilter();// Try to insert our transform filterhr = ConnectUpstreamOf(pVR, m_pFilter);pVR->Release();return hr;}// Start the graphHRESULT 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 appHRESULT 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 junkWindowStyle |= WS_CHILD;             // Needs to be childhr = 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 windowHRESULT 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 objectIBaseFilter* 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 filterHRESULT 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 interfaceIUnknown* 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* pTransform){IPin* pPinIn = InputPinOf(pFilter);if (!pPinIn) {return E_FAIL;}// Get the peer output pinIPin* pPinOut = NULL;HRESULT hr = pPinIn->ConnectedTo(&pPinOut);if (FAILED(hr)) {pPinIn->Release();return hr;}// Disconnect the current connectionhr = m_pGraph->Disconnect(pPinOut);if (SUCCEEDED(hr)) {hr = m_pGraph->Disconnect(pPinIn);}// Insert pTransform filter by connecting its input pin and output pinif (SUCCEEDED(hr)) {IPin* pPinInXfm = InputPinOf(pTransform);hr = m_pGraph->Connect(pPinOut, pPinInXfm);pPinInXfm->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 filterIPin* 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 pFilterHRESULT 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;    }}

然后建一个MFC 单文档添加成员:

CAppGraphBuilder m_Graph;

实现:

void CtestView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags){// TODO: 在此添加消息处理程序代码和/或调用默认值switch(nChar) { case VK_F1: {CString    strFilter = _T("AVI File (*.avi)|*.avi|");strFilter += _T("MPEG File (*.mpg;*.mpeg)|*.mpg;*.mpeg|");strFilter += _T("All Files (*.*)|*.*|");CFileDialog dlgOpen(TRUE, NULL, NULL, OFN_PATHMUSTEXIST | OFN_HIDEREADONLY, strFilter, this);if (IDOK != dlgOpen.DoModal()) {return;}WCHAR wchFile[MAX_PATH];wcscpy(wchFile,dlgOpen.GetPathName());//MultiByteToWideChar(CP_ACP, 0, dlgOpen.GetPathName(), -1, wchFile, MAX_PATH);m_Graph.BuildFromFile(wchFile);m_Graph.MakeChild(GetSafeHwnd());m_Graph.Run();}break;default:break;}CView::OnKeyDown(nChar, nRepCnt, nFlags);}



原创粉丝点击