#pragma include_alias( "dxtrans.h", "qedit.h" )
#define __IDxtCompositor_INTERFACE_DEFINED__
#define __IDxtAlphaSetter_INTERFACE_DEFINED__
#define __IDxtJpeg_INTERFACE_DEFINED__
#define __IDxtKey_INTERFACE_DEFINED__

#include <qedit.h>

VS2008 에서 Dshow 관련 컴파일 오류시...
qedit.h 는 SDK 6.0A 에 있는걸 7.0 이나 7.1 로 복사하면 됨.

DirectShow 에서 I420 포맷은 정의되어 있지 않다.

아래와 같이 정의하면 사용할 수 있다.

// {30323449-0000-0010-8000-00aa00389b71}
DEFINE_GUID(MEDIASUBTYPE_I420,
   0x30323449, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);

IEnumPins *pEnumPins;
pCap->EnumPins(&pEnumPins);
IPin *pPin;
PIN_DIRECTION PinDir;
while(pEnumPins->Next(1, &pPin, 0)==S_OK) {
        pPin->QueryDirection(&PinDir);
        if(PinDir == PINDIR_OUTPUT) {
                CComQIPtr pAMSC (pPin);
                
                int iCount, iSize;
                VIDEO_STREAM_CONFIG_CAPS scc;
                AM_MEDIA_TYPE *pmt;

                pAMSC->GetNumberOfCapabilities(&iCount, &iSize);
                
                if(sizeof(scc) != iSize)
                {
                        // This is not the structure we were expecting.
                        return E_FAIL;
                }
                // Get the first format.
                hr = pAMSC->GetStreamCaps(0, &pmt, reinterpret_cast(&scc));
                if(hr == S_OK)
                {
                        pmt->subtype = MEDIASUBTYPE_RGB24;
                        VIDEOINFOHEADER *vih = reinterpret_cast(pmt->pbFormat);
                        vih->bmiHeader.biWidth = 640;
                        vih->bmiHeader.biHeight = 480;
                        vih->bmiHeader.biSizeImage = 640*480*3;
                        pmt->lSampleSize = 640*480*3;
                        pAMSC->SetFormat(pmt);
                }

                break;
        }
}
필터클래스 상위 부분에

// 인터페이스 선언
#ifdef __cplusplus
extern "C" {
#endif
    // {45F7E6B9-861F-46fb-9549-7F70EB5DCFF0}
        DEFINE_GUID(IID_INetworkTCP,
                0x45f7e6b9, 0x861f, 0x46fb, 0x95, 0x49, 0x7f, 0x70, 0xeb, 0x5d, 0xcf, 0xf0);
        
        
    DECLARE_INTERFACE_(INetworkTCP, IUnknown)
    {
        STDMETHOD(LoadMessageBox) (THIS_  char*  msg) PURE;
    };
        
#ifdef __cplusplus
}
#endif

//////////////////////////////////////////////////////////////////////////

위와 같이 인터페이스를 선언해주고

class CNetworkTCPStream;

인터페이스를 상속받는다.

class CNetworkTCPFilter : public CSource
, public INetworkTCP
{
        friend class CNetworkTCPStream;

public:
        CNetworkTCPFilter(LPUNKNOWN pUnk, HRESULT *phr);
        virtual ~CNetworkTCPFilter(void);

// static
public:
        static CUnknown * WINAPI CreateInstance(LPUNKNOWN pUnk, HRESULT *phr);

// Attributes
public:

// Operations
public:

        // 이 메소드는 인터페이스의 가상함수. 구현하여준다.
        STDMETHODIMP LoadMessageBox(char* msg) {
                MessageBox(NULL, msg, NULL, NULL);
        }


// Overrides
protected:

// Implementations
protected:

        // 인터페이스를 외부에 노출시킨다
        DECLARE_IUNKNOWN;
        STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv) {
                if(riid == IID_INetworkTCP)
                        return GetInterface((INetworkTCP*)this, ppv);
                else
                        return CSource::NonDelegatingQueryInterface(riid, ppv);
        }


// member variables
private:
};

위와 같이 하면 인터페이스를 상속받고 구현하여 노출시키면 사용할 수 있다.

사용방법은 어플리케이션에서 인터페이스 선언부분을 가져다 적어주고

인터페이스를 호출하여 사용하면 된다.

예)

INetworkTCP* pITCP;
pFilterNetworkTCPFilter->QueryInterface(IID_INetworkTCP, (void**)&pITCP);
pITCP->LoadMessageBox("Test");

IEnumPins *pEnumPins;
pFilterMP3Encoder->EnumPins(&pEnumPins);
IPin *pPin;
PIN_DIRECTION PinDir;
while(pEnumPins->Next(1, &pPin, 0)==S_OK) {
        pPin->QueryDirection(&PinDir);
        if(PinDir == PINDIR_OUTPUT) {
                CComQIPtr pAMSC (pPin);
                
                int iCount, iSize;
                AUDIO_STREAM_CONFIG_CAPS scc;
                AM_MEDIA_TYPE *pmt;

                pAMSC->GetNumberOfCapabilities(&iCount, &iSize);
                
                if (sizeof(scc) != iSize)
                {
                        // This is not the structure we were expecting.
                        return E_FAIL;
                }
                // Get the first format.
                hr = pAMSC->GetStreamCaps(0, &pmt, reinterpret_cast<byte*>(&scc));
                if (hr == S_OK)
                {
                        if (pmt->formattype == FORMAT_WaveFormatEx && 
                                pmt->subtype == FORMAT_DYNA_MPEG3)
                        {
                                // Modify the format block.
                                WAVEFORMATEX *wave = 
                                        reinterpret_cast<waveformatex*>(pmt->pbFormat);
                                wave->nSamplesPerSec = 22050;
                                // Now set the format.
                                hr = pAMSC->SetFormat(pmt);
                                if (FAILED(hr))
                                {
                                        AfxMessageBox("SetFormat Failed");
                                }
                                DeleteMediaType(pmt);
                        }
                }
                break;
        }
}
// !!! What if this interface isnt supported?
// we use this interface to set the frame rate and get the capture size


if (hr != NOERROR)
{
        hr = m_pCapBuilder->FindInterface(&PIN_CATEGORY_CAPTURE,&MEDIATYPE_Video, m_pVCapFilter,
                IID_IAMStreamConfig, (void **)&m_pVStreamConfig);
        if (hr != NOERROR)
        {
                // this means we cant set frame
                rate (non-DV only)
                        ErrMsg("Error %x: Cannot find VCapture:IAMStreamConfig", hr);
                return hr;
        }
}

AM_MEDIA_TYPE *pmt;
// default capture format
if (m_pVStreamConfig && m_pVStreamConfig->GetFormat(&pmt) == S_OK)
{
        // DV capture does not use a VIDEOINFOHEADER
        if (pmt->formattype == FORMAT_VideoInfo)
        {
                VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER *)pmt->pbFormat;
                
                if(pmt->subtype == MEDIASUBTYPE_RGB24)
                {
                        pmt->lSampleSize = (LONG)(_DEFAULT_CAP_WIDTH * _DEFAULT_CAP_HEIGHT * 3);    // sample size calc
                        pvi->bmiHeader.biSizeImage = pmt->lSampleSize;
                }
        /// 프레임 조절                
                pvi->AvgTimePerFrame = (LONGLONG)(10000000 / m_fFramerate);    // frames
                
                pvi->bmiHeader.biWidth = _DEFAULT_CAP_WIDTH;                // frame width
                pvi->bmiHeader.biHeight = _DEFAULT_CAP_HEIGHT;                // frame height
                
        // resize our window to the default capture size
        //            ResizeWindow(HEADER(pmt->pbFormat)->biWidth,
        //                ABS(HEADER(pmt->pbFormat)->biHeight));
                
                m_pVStreamConfig->SetFormat(pmt);
        }
        DeleteMediaType(pmt);
}
#include <Dmodshow.h>

IBaseFilter *pFilter;
hr = CoCreateInstance(CLSID_DMOWrapperFilter, NULL, 
        CLSCTX_INPROC_SERVER, IID_IBaseFilter, 
        reinterpret_cast(&pFilter));

if (SUCCEEDED(hr)) 
{
        // Query for IDMOWrapperFilter.
        IDMOWrapperFilter *pDmoWrapper;
        hr = pFilter->QueryInterface(IID_IDMOWrapperFilter, 
                reinterpret_cast<void**>(&pDmoWrapper));
        
        if (SUCCEEDED(hr)) 
        {     
                // Initialize the filter.
                hr = pDmoWrapper->Init(CLSID_DYNA_MPEG43DMO, CLSID_LegacyAmFilterCategory); 
                pDmoWrapper->Release();
                
                if (SUCCEEDED(hr)) 
                {
                        // Add the filter to the graph.
                        hr = m_pGB->AddFilter(pFilter, L"Mpeg43 Decoder DMO");
                }
        }
        pFilter->Release();
}
// Dmoguids.lib 라이브러리 추가