다음을 통해 공유


Media Foundation 및 COM

Microsoft Media Foundation은 COM 구문을 혼합하여 사용하지만 완전히 COM 기반 API는 아닙니다. 이 항목에서는 COM과 Media Foundation 간의 상호 작용에 대해 설명합니다. 또한 Media Foundation 플러그 인 구성 요소를 개발하기 위한 몇 가지 모범 사례를 정의합니다. 이러한 사례를 따르면 몇 가지 일반적이지만 미묘한 프로그래밍 오류를 방지하는 데 도움이 될 수 있습니다.

애플리케이션에 대한 모범 사례

Media Foundation에서 비동기 처리 및 콜백은 작업 큐에서 처리됩니다. 작업 큐에는 항상 MTA(다중 스레드 아파트) 스레드가 있으므로 MTA 스레드에서도 실행되는 경우 애플리케이션이 더 간단한 구현을 갖습니다. 따라서 COINIT_MULTITHREADED 플래그를 사용하여 CoInitializeEx를 호출하는 것이 좋습니다.

Media Foundation은 STA(단일 스레드 아파트) 개체를 큐 스레드로 마샬링하지 않습니다. 또한 STA 고정이 유지되도록 보장하지 않습니다. 따라서 STA 애플리케이션은 STA 개체 또는 프록시를 Media Foundation API에 전달하지 않도록 주의해야 합니다. STA 전용 개체는 Media Foundation에서 지원되지 않습니다.

MTA 또는 자유 스레드 개체에 대한 STA 프록시가 있는 경우 작업 큐 콜백을 사용하여 개체를 MTA 프록시로 마샬링할 수 있습니다. CoCreateInstance 함수는 해당 CLSID에 대한 레지스트리에 정의된 개체 모델에 따라 원시 포인터 또는 STA 프록시를 반환할 수 있습니다. STA 프록시가 반환되는 경우 Media Foundation API에 포인터를 전달해서는 안 됩니다.

예를 들어 IPropertyStore 포인터를 IMFSourceResolver::BeginCreateObjectFromURL 메서드에 전달한다고 가정합니다. PSCreateMemoryPropertyStore를 호출하여 IPropertyStore 포인터를 만들 수 있습니다. STA에서 를 호출하는 경우 포인터를 BeginCreateObjectFromURL에 전달하기 전에 마샬링해야 합니다.

다음 코드에서는 MEDIA Foundation API에 STA 프록시를 마샬링하는 방법을 보여 있습니다.

class CCreateSourceMarshalCallback
    : public IMFAsyncCallback
{
public:
    CCreateSourceMarshalCallback(
        LPCWSTR szURL, 
        IMFSourceResolver* pResolver, 
        IPropertyStore* pSourceProps, 
        IMFAsyncCallback* pCompletionCallback, 
        HRESULT& hr
        )
        : m_szURL(szURL), 
          m_pResolver(pResolver), 
          m_pCompletionCallback(pCompletionCallback),
          m_pGIT(NULL),
          m_cRef(1)
    {
        hr = CoCreateInstance(CLSID_StdGlobalInterfaceTable, NULL, 
            CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&m_pGIT));

        if(SUCCEEDED(hr))
        {
            hr = m_pGIT->RegisterInterfaceInGlobal(
                pSourceProps, IID_IPropertyStore, &m_dwInterfaceCookie);
        }
    }
    ~CCreateSourceMarshalCallback()
    {
        SafeRelease(&m_pResolver);
        SafeRelease(&m_pCompletionCallback);
        SafeRelease(&m_pGIT);
    }


    STDMETHOD_(ULONG, AddRef)()
    {
        return InterlockedIncrement(&m_cRef);
    }

    STDMETHOD_(ULONG, Release)()
    {
        LONG cRef = InterlockedDecrement(&m_cRef);
        if (0 == cRef)
        {
            delete this;
        }
        return cRef;
    }

    STDMETHOD(QueryInterface)(REFIID riid, LPVOID* ppvObject)
    {
        static const QITAB qit[] = 
        {
            QITABENT(CCreateSourceMarshalCallback, IMFAsyncCallback),
            { 0 }
        };
        return QISearch(this, qit, riid, ppvObject);

    }

    STDMETHOD(GetParameters)(DWORD* pdwFlags, DWORD* pdwQueue)
    {
        return E_NOTIMPL;
    }

    STDMETHOD(Invoke)(IMFAsyncResult* pResult)
    {
        IPropertyStore *pSourceProps = NULL;

        HRESULT hr = m_pGIT->GetInterfaceFromGlobal(
            m_dwInterfaceCookie, 
            IID_PPV_ARGS(&pSourceProps)
            );

        if(SUCCEEDED(hr))
        {
            hr = m_pResolver->BeginCreateObjectFromURL(
                m_szURL, MF_RESOLUTION_MEDIASOURCE, pSourceProps, NULL, 
                m_pCompletionCallback, NULL);
        }

        SafeRelease(&pSourceProps);
        return hr;
    }

private:
    LPCWSTR m_szURL;
    IMFSourceResolver *m_pResolver;
    IMFAsyncCallback *m_pCompletionCallback;
    IGlobalInterfaceTable *m_pGIT;
    DWORD m_dwInterfaceCookie;
    LONG m_cRef;
};

전역 인터페이스 테이블에 대한 자세한 내용은 IGlobalInterfaceTable을 참조하세요.

Media Foundation In Process를 사용하는 경우 Media Foundation 메서드 및 함수에서 반환된 개체는 개체에 대한 직접 포인터입니다. 교차 프로세스 Media Foundation의 경우 이러한 개체는 MTA 프록시일 수 있으며 필요한 경우 STA 스레드로 마샬링되어야 합니다. 마찬가지로 콜백 내에서 가져온 개체(예: MESessionTopologyStatus 이벤트의 토폴로지)는 Media Foundation이 In Process에서 사용될 때 직접 포인터이지만 Media Foundation이 프로세스 간에 사용될 때 MTA 프록시입니다.

참고

Media Foundation 교차 프로세스를 사용하는 가장 일반적인 시나리오는 PMP( 보호된 미디어 경로 )를 사용하는 것입니다. 그러나 이러한 설명은 Media Foundation API가 RPC를 통해 사용되는 모든 상황에 적용됩니다.

 

IMFAsyncCallback의 모든 구현은 MTA와 호환되어야 합니다. 이러한 개체는 COM 개체일 필요가 없습니다. 그러나 만약 그렇다면 STA에서 실행할 수 없습니다. IMFAsyncCallback::Invoke 함수는 MTA 작업 큐 스레드에서 호출되고 제공된 IMFAsyncResult 개체는 직접 개체 포인터 또는 MTA 프록시가 됩니다.

Media Foundation 구성 요소에 대한 모범 사례

COM에 대해 염려해야 하는 Media Foundation 개체에는 두 가지 범주가 있습니다. 변환 또는 바이트 스트림 처리기와 같은 일부 구성 요소는 CLSID에서 만든 전체 COM 개체입니다. 이러한 개체는 IN-Process 및 크로스 프로세스 Media Foundation 모두에 대한 COM 아파트의 규칙을 따라야 합니다. 다른 Media Foundation 구성 요소는 전체 COM 개체가 아니지만 프로세스 간 재생을 위해 COM 프록시가 필요합니다. 이 범주의 개체에는 미디어 원본 및 활성화 개체가 포함됩니다. 이러한 개체는 In-process Media Foundation에만 사용되는 경우 아파트 문제를 무시할 수 있습니다.

모든 Media Foundation 개체가 COM 개체는 아니지만 모든 Media Foundation 인터페이스는 IUnknown에서 파생됩니다. 따라서 모든 Media Foundation 개체는 참조 계산 및 QueryInterface에 대한 규칙을 포함하여 COM 사양에 따라 IUnknown을 구현해야 합니다. 또한 모든 참조 개수의 개체는 개체가 계속 유지되는 동안 DllCanUnloadNow 에서 모듈을 언로드할 수 없도록 해야 합니다.

Media Foundation 구성 요소는 STA 개체일 수 없습니다. 대부분의 Media Foundation 개체는 COM 개체일 필요가 없습니다. 그러나 만약 그렇다면 STA에서 실행할 수 없습니다. 모든 Media Foundation 구성 요소는 스레드로부터 안전해야 합니다. 일부 Media Foundation 개체는 자유 스레드 또는 아파트 중립이어야 합니다. 다음 표에서는 사용자 지정 인터페이스 구현에 대한 요구 사항을 지정합니다.

인터페이스 범주 필수 아파트
IMFActivate 크로스 프로세스 프록시 자유 스레드 또는 중립
IMFByteStreamHandler COM 개체 MTA
IMFContentProtectionManager 크로스 프로세스 프록시 자유 스레드 또는 중립
IMFQualityManager COM 개체 자유 스레드 또는 중립
IMFMediaSource 크로스 프로세스 프록시 자유 스레드 또는 중립
IMFSchemeHandler COM 개체 MTA
IMFTopoLoader COM 개체 자유 스레드 또는 중립
IMFTransform COM 개체 MTA

 

구현에 따라 추가 요구 사항이 있을 수 있습니다. 예를 들어 미디어 싱크가 애플리케이션이 싱크에 대한 직접 함수 호출을 수행할 수 있도록 하는 다른 인터페이스를 구현하는 경우 싱크는 직접 프로세스 간 호출을 처리할 수 있도록 자유 스레드 또는 중립이어야 합니다. 모든 개체는 자유 스레드일 수 있습니다. 이 표는 최소 요구 사항을 지정합니다.

자유 스레드 또는 중립 개체를 구현하는 권장 방법은 자유 스레드 마샬러를 집계하는 것입니다. 자세한 내용은 CoCreateFreeThreadedMarshaler에 대한 MSDN 설명서를 참조하세요. STA 개체 또는 프록시를 Media Foundation API에 전달하지 않는 요구 사항에 따라 자유 스레드 개체는 자유 스레드 구성 요소에서 STA 입력 포인터를 마샬링하는 것에 대해 걱정할 필요가 없습니다.

MFASYNC_CALLBACK_QUEUE_LONG_FUNCTION(long-function work queue)를 사용하는 구성 요소는 더 많은 주의를 기울여야 합니다. long 함수 작업 큐의 스레드는 자체 STA를 만듭니다. 콜백에 긴 함수 작업 큐를 사용하는 구성 요소는 이러한 스레드에서 COM 개체를 만들지 않아야 하며 필요에 따라 프록시를 STA로 마샬링하는 데 주의해야 합니다.

요약

애플리케이션이 MTA 스레드에서 Media Foundation과 상호 작용하는 경우 시간이 더 쉬울 수 있지만 일부 주의해서 STA 스레드에서 Media Foundation을 사용할 수 있습니다. Media Foundation은 STA 구성 요소를 처리하지 않으며 애플리케이션은 STA 개체를 Media Foundation API에 전달하지 않도록 주의해야 합니다. 일부 개체에는 추가 요구 사항, 특히 프로세스 간 상황에서 실행되는 개체가 있습니다. 이러한 지침을 따르면 COM 오류, 교착 상태 및 예기치 않은 미디어 처리 지연을 방지하는 데 도움이 됩니다.

Media Foundation Platform API

미디어 파운데이션 아키텍처