Media Foundation dan COM
Microsoft Media Foundation menggunakan campuran konstruksi COM, tetapi bukan API berbasis COM sepenuhnya. Topik ini menjelaskan interaksi antara COM dan Media Foundation. Ini juga mendefinisikan beberapa praktik terbaik untuk mengembangkan komponen plug-in Media Foundation. Mengikuti praktik ini dapat membantu Anda menghindari beberapa kesalahan pemrograman yang umum tetapi halus.
- Praktik Terbaik untuk Aplikasi
- Praktik Terbaik untuk Komponen Media Foundation
- Ringkasan
- Topik terkait
Praktik Terbaik untuk Aplikasi
Di Media Foundation, pemrosesan asinkron dan panggilan balik ditangani oleh antrean kerja. Antrean kerja selalu memiliki utas multithreaded apartment (MTA), sehingga aplikasi akan memiliki implementasi yang lebih sederhana jika berjalan pada utas MTA juga. Oleh karena itu, disarankan untuk memanggil CoInitializeEx dengan bendera COINIT_MULTITHREADED.
Media Foundation tidak marshal objek apartemen berulir tunggal (STA) untuk bekerja utas antrean. Juga tidak memastikan bahwa invarian STA dipertahankan. Oleh karena itu, aplikasi STA harus berhati-hati untuk tidak meneruskan objek STA atau proksi ke API Media Foundation. Objek yang hanya STA tidak didukung di Media Foundation.
Jika Anda memiliki proksi STA ke objek MTA atau utas bebas, objek dapat dinaungi ke proksi MTA dengan menggunakan panggilan balik antrean kerja. Fungsi CoCreateInstance dapat mengembalikan pointer mentah atau proksi STA, tergantung pada model objek yang ditentukan dalam registri untuk CLSID tersebut. Jika proksi STA dikembalikan, Anda tidak boleh meneruskan pointer ke MEDIA Foundation API.
Misalnya, Anda ingin meneruskan pointer IPropertyStore ke metode IMFSourceResolver::BeginCreateObjectFromURL. Anda dapat memanggil PSCreateMemoryPropertyStore untuk membuat pointer IPropertyStore . Jika Anda memanggil dari STA, Anda harus melakukan marshal penunjuk sebelum meneruskannya ke BeginCreateObjectFromURL.
Kode berikut menunjukkan cara melakukan marsekal proksi STA ke MEDIA Foundation API.
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;
};
Untuk informasi selengkapnya tentang tabel antarmuka global, lihat IGlobalInterfaceTable.
Jika Anda menggunakan Media Foundation dalam proses, objek yang dikembalikan dari metode dan fungsi Media Foundation adalah penunjuk langsung ke objek. Untuk Media Foundation lintas proses, objek-objek ini mungkin proksi MTA, dan harus dinamai ke dalam utas STA jika diperlukan di sana. Demikian pula, objek yang diperoleh di dalam panggilan balik — misalnya, topologi dari peristiwa MESessionTopologyStatus — adalah pointer langsung ketika Media Foundation digunakan dalam proses, tetapi merupakan proksi MTA ketika Media Foundation digunakan lintas proses.
Catatan
Skenario paling umum untuk menggunakan lintas proses Media Foundation adalah dengan Protected Media Path (PMP). Namun, pernyataan ini berlaku untuk situasi apa pun ketika API Media Foundation digunakan melalui RPC.
Semua implementasi IMFAsyncCallback harus kompatibel dengan MTA. Objek ini tidak perlu menjadi objek COM sama sekali. Tetapi jika mereka, mereka tidak dapat berjalan di STA. Fungsi IMFAsyncCallback::Invoke akan dipanggil pada utas antrean kerja MTA, dan objek IMFAsyncResult yang disediakan akan menjadi penunjuk objek langsung atau proksi MTA.
Praktik Terbaik untuk Komponen Media Foundation
Ada dua kategori objek Media Foundation yang perlu diperhatikan tentang COM. Beberapa komponen, seperti transformasi atau byte stream handler, adalah objek COM lengkap yang dibuat oleh CLSID. Objek-objek ini harus mengikuti aturan untuk apartemen COM, baik untuk Media Foundation dalam proses maupun lintas proses. Komponen Media Foundation lainnya bukan objek COM penuh, tetapi memerlukan proksi COM untuk pemutaran lintas proses. Objek dalam kategori ini mencakup sumber media dan objek aktivasi. Objek-objek ini dapat mengabaikan masalah apartemen jika hanya akan digunakan untuk Media Foundation dalam proses.
Meskipun tidak semua objek Media Foundation adalah objek COM, semua antarmuka Media Foundation berasal dari IUnknown. Oleh karena itu, semua objek Media Foundation harus mengimplementasikan IUnknown sesuai dengan spesifikasi COM, termasuk aturan untuk penghitungan referensi dan QueryInterface. Semua objek yang dihitung referensi juga harus memastikan bahwa DllCanUnloadNow tidak akan memungkinkan modul dibongkar saat objek masih bertahan.
Komponen Media Foundation tidak boleh berupa objek STA. Banyak objek Media Foundation tidak perlu menjadi objek COM sama sekali. Tetapi jika mereka, mereka tidak dapat berjalan di STA. Semua komponen Media Foundation harus aman untuk utas. Beberapa objek Media Foundation juga harus bebas utas atau netral apartemen. Tabel berikut menentukan persyaratan untuk implementasi antarmuka kustom:
Antarmuka | Kategori | Apartemen yang diperlukan |
---|---|---|
IMFActivate | Proksi lintas proses | Utas bebas atau netral |
IMFByteStreamHandler | Objek COM | MTA |
IMFContentProtectionManager | Proksi lintas proses | Utas bebas atau netral |
IMFQualityManager | Objek COM | Utas bebas atau netral |
IMFMediaSource | Proksi lintas proses | Utas bebas atau netral |
IMFSchemeHandler | Objek COM | MTA |
IMFTopoLoader | Objek COM | Utas bebas atau netral |
IMFTransform | Objek COM | MTA |
Mungkin ada persyaratan tambahan tergantung pada implementasinya. Misalnya, jika sink media mengimplementasikan antarmuka lain yang memungkinkan aplikasi melakukan panggilan fungsi langsung ke sink, sink harus berulir bebas atau netral, sehingga dapat menangani panggilan lintas proses langsung. Objek apa pun dapat di-utas bebas; tabel ini menentukan persyaratan minimum.
Cara yang disarankan untuk mengimplementasikan objek berulir bebas atau netral adalah dengan menggabungkan marshaler berulir bebas. Untuk detail selengkapnya, lihat CoCreateFreeThreadedMarshaler. Sesuai dengan persyaratan untuk tidak meneruskan objek STA atau proksi ke API Media Foundation, objek utas bebas tidak perlu khawatir tentang marshaling penunjuk input STA dalam komponen free-threaded.
Komponen yang menggunakan antrean kerja fungsi panjang (MFASYNC_CALLBACK_QUEUE_LONG_FUNCTION) harus melakukan lebih banyak perawatan. Utas dalam antrean kerja fungsi panjang membuat STA mereka sendiri. Komponen yang menggunakan antrean kerja fungsi panjang untuk panggilan balik harus menghindari pembuatan objek COM pada utas ini, dan perlu berhati-hati untuk marshal proksi ke STA seperlunya.
Ringkasan
Aplikasi akan memiliki waktu yang lebih mudah jika mereka berinteraksi dengan Media Foundation dari utas MTA, tetapi dimungkinkan dengan hati-hati untuk menggunakan Media Foundation dari utas STA. Media Foundation tidak menangani komponen STA, dan aplikasi harus berhati-hati untuk tidak meneruskan objek STA ke API Media Foundation. Beberapa objek memiliki persyaratan tambahan, terutama objek yang berjalan dalam situasi lintas proses. Mengikuti panduan ini akan membantu menghindari kesalahan COM, kebuntuan, dan penundaan tak terduga dalam pemrosesan media.
Topik terkait