首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

视频播放器增多color space converter + Transform Filter

2012-09-25 
视频播放器增加color space converter + Transform Filter视频播放器增加color space converterIn-Place T

视频播放器增加color space converter + Transform Filter
视频播放器增加color space converter + In-Place Transform Filter

见http://blog.csdn.net/luckyboy101/article/details/7836094

由于In-Place Transform Filter功能少,把In-Place Transform Filter修改为Transform Filter

IPFilter.h

//// 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 VIDEOINFOHEADERif(*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 connectedif(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 sizeif(!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 wantedALLOCATOR_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 connectedif(m_pInput->IsConnected() == FALSE){return E_UNEXPECTED;}// This should never happenif(iPosition < 0){return E_INVALIDARG;}// Do we have more items to offerif(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 dataBYTE *pSourceBuffer, *pDestBuffer;long lSourceSize = pSource->GetActualDataLength();#ifdef DEBUGlong lDestSize = pDest->GetSize();ASSERT(lDestSize >= lSourceSize);#endifpSource->GetPointer(&pSourceBuffer);pDest->GetPointer(&pDestBuffer);CopyMemory((PVOID) pDestBuffer,(PVOID) pSourceBuffer,lSourceSize);// Copy the sample timesREFERENCE_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 propertyHRESULT 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 typeAM_MEDIA_TYPE *pMediaType;pSource->GetMediaType(&pMediaType);pDest->SetMediaType(pMediaType);DeleteMediaType(pMediaType);// Copy the preroll propertyhr = 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 propertyhr = 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 lengthlong 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);} // TransformHRESULT 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 pixelstagRGBTRIPLE *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 = (tagRGBTRIPLE*) pData;for (iPixel=0; iPixel < numPixels; iPixel++, prgb++) {prgb->rgbtRed=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 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_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::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;elsepF->Release();}return hr;}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();// Add Color Space ConvertIBaseFilter *pColor;hr=AddFilterByCLSID(m_pGraph, CLSID_Colour, L"Color Space Converter", &pColor);// Try to insert our transform filterhr = ConnectUpstreamOf(pVR, pColor,m_pFilter);//pVR->Release();//pColor->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*pColor,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* 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 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;    }}

color space converter

http://msdn.microsoft.com/en-us/library/aa926076

热点排行