مدخل إلى Media Foundation - فهم الواجهة من منظور COM
· آخر تحديث: · 小村 豪 · Media Foundation, COM, C++, تطوير Windows
سجل التعديلات (3 تحديثات، آخر تحديث 3 Sep، 2026)
سجل بالتغييرات التي أُجريت على هذا المقال. وحيثما حُفظت نسخة سابقة، تبقى متاحة للقراءة عبر رابط دائم يحمل معرّف DOI.
- أُضيفت روابط الاستشارة الموجودة في الأصل الياباني (consultation_services). ولم يتغيّر نصّ المقالة نفسه. قراءة النسخة السابقة لهذا التحديث (DOI: 10.5281/zenodo.22240805)
- أُعيدَت الترجمة العربية كترجمة كاملة عن النص الياباني الأصلي، وأُضيفَت خريطة المعرفة.
- أعيدت الترجمة كترجمة كاملة عن النص الياباني الأصلي. كانت النسخة العربية السابقة مختصراً يسقط أبواباً وجداول ورسوم Mermaid وتعليقات الأشكال وFAQ. أُعيدت هذه العناصر وفق الأصل الياباني، والادّعاءات التقنية مطابقة للنسخة اليابانية.
- النشر الأول
الاستشهاد بهذا المقال(DOI: 10.5281/zenodo.21621321)
هذا المقال محفوظ على Zenodo. يرد أدناه معرّف DOI الذي يشير دائمًا إلى أحدث نسخة، ومعرّف DOI المثبَّت على النسخة التي تقرؤها.
小村 豪 (2026). مدخل إلى Media Foundation - فهم الواجهة من منظور COM. شركة كومورا سوفت ذ.م.م.. https://doi.org/10.5281/zenodo.21621321 https://comcomponent.com/ar/blog/2026/03/09/002-media-foundation-why-it-feels-like-com/
- DOI (أحدث نسخة)
- 10.5281/zenodo.21621321
- DOI (هذه النسخة)
- 10.5281/zenodo.22279703
حين تبدأ لمس Media Foundation يسهل الإحساس أنّك «تستخدم واجهة فيديو وصوت في Windows، فإذا بحديث COM يزداد فجأة». يظهر دفعة واحدة CoInitializeEx و MFStartup و IMFSourceReader و IMFMediaType و IMFTransform و IMFActivate و HRESULT و GUID، فيصير المناخ فجأة أقرب إلى Win32 / COM، ويصعب رؤية ما هو Media Foundation.
هذا المقال لا يغطي Media Foundation كلّه كقاموس، بل يضيّق على ثلاث نقاط.
- لماذا يظهر حديث COM طبيعيّاً عند استخدام Media Foundation
- أين يشتدّ طابع COM
- من أين تبدأ أوّلاً بين Source Reader / Sink Writer / Media Session / MFT
أمثلة الشيفرة على أساس C++، لكنّ طريقة التفكير نفسها تقريباً حتّى عند اللمس من .NET عبر غلاف.
المحتويات
- الخلاصة أوّلاً (في جملة)
- الكلمات والصورة العامّة
- 2.1. كلمات يُضبَط معناها أوّلاً
- 2.2. الصورة العامّة لـ Media Foundation (رسم)
- المواضع التي يصير فيها لـ Media Foundation وجه COM
- 3.1. في التهيئة يصطفّ
CoInitializeExوMFStartup - 3.2. تسليم الكائنات مركزه الواجهات
- 3.3. الإعداد ومعلومات النوع مركزها
IMFAttributesو GUID - 3.4. يظهر Activation Object
- 3.5. التعامل مع غير المتزامن والـ callback والخيوط أيضاً بطابع COM
- 3.1. في التهيئة يصطفّ
- غير أنّ Media Foundation ليس مساوياً لـ COM
- من أين تلمس (اختيار المدخل)
- 5.1. حالة الدخول أوّلاً من Source Reader
- 5.2. إن كتبت إلى ملفّ فـ Sink Writer
- 5.3. إن تعاملت مع التشغيل والمزامنة فـ Media Session
- 5.4. إن أدرجت مكوّناً خاصّاً فـ MFT
- قائمة فحص في العمل
- الخلاصة
- مراجع
في المخطّط، يشير الخطّ المتّصل إلى علاقة قائمة دائماً، ويشير الخطّ المتقطّع إلى علاقة مشروطة (شروط قيامها مذكورة في شرح كلّ علاقة في الصفحة التفصيليّة). القائمة الكاملة للعلاقات (المجموع 21، مع الأدلّة ودرجة اليقين) وتعريفات المفاهيم الرئيسة مجمّعة في صفحة تفاصيل خريطة المعرفة (باليابانية). البيانات: JSON-LD / Turtle
1. الخلاصة أوّلاً (في جملة)
- Media Foundation منصّة للتعامل مع الفيديو والصوت، وسطح الواجهة بأكمله ليس COM خالصاً كما هو
- غير أنّ حدود source / transform / sink / activation / attributes / callback تُعبَّر عنها بواجهات COM، لذا يظهر أثناء الاستخدام حديث
IUnknownوHRESULTو GUID و apartment طبيعيّاً - ادخل أوّلاً من Source Reader / Sink Writer، وإن لزم التحكّم في التشغيل فإلى Media Session، وإن لزم محوّل خاصّ فإلى MFT؛ بهذا يسهل الترتيب
بعبارة أخرى: Media Foundation منصّة معالجة وسائط، وحدودها يدخلها COM بعمق.
ضبط هذا أوّلاً يحسّن كثيراً رؤية «لماذا يصير الوجه فجأة وجه COM».
flowchart TB
accTitle: علاقة Media Foundation و COM
accDescr: يبيّن أنّ جسم Media Foundation منصّة معالجة وسائط، وأنّ سطح الواجهة بأكمله ليس COM خالصاً، لكنّ حدود المكوّنات تُعبَّر عنها بواجهات COM فيظهر حديث IUnknown و HRESULT و GUID طبيعيّاً.
mf["Media Foundation"] --> plat["منصّة معالجة وسائط"]
mf --> border["حدود المكوّنات واجهات COM"]
border --> com["يظهر IUnknown و HRESULT و GUID"]
plat -.-> note["سطح الواجهة بأكمله ليس COM خالصاً"]
الشكل 1: الجسم منصّة معالجة وسائط، وحدودها يدخلها COM بعمق.
2. الكلمات والصورة العامّة
قبل دخول حديث COM نمرّ أوّلاً على الكلمات المستخدمة في هذا المقال والإطار الكبير لـ Media Foundation.
2.1. كلمات يُضبَط معناها أوّلاً
| المصطلح | معناه هنا |
|---|---|
| Media Source | مدخل إدخال بيانات الوسائط إلى خط الأنابيب. ملفّ، شبكة، جهاز التقاط، وغيرها |
| MFT | Media Foundation Transform. النموذج المشترك لمفكّك الترميز ومشفّره ومحوّل الصورة وغيرها |
| Media Sink | وجهة بيانات الوسائط. عرض على الشاشة، إخراج صوت، كتابة ملفّ، وغيرها |
| Media Session | آليّة تدير تدفّق خط الأنابيب بأكمله. تتولّى التشغيل والمزامنة |
| Topology | مخطّط وصل يبيّن كيف تُربَط source / transform / sink |
| Activation Object | كائن مساعد لصنع الجسم لاحقاً. يُعبَّر عنه بـ IMFActivate |
| Attributes | مخزن key/value مفتاحه GUID. يُستخدم بكثرة في Media Foundation كلّه |
| apartment | وحدة يجمع بها COM الخيوط. اتفاق «من أيّ خيط يجوز استدعاء هذا الكائن»، يُقرَّر بوسيط CoInitializeEx (3.1، 3.5) |
| STA / MTA | نوعا apartment. STA (Single-Threaded Apartment) مربوط بخيط واحد، واستدعاءات الخيوط الأخرى تُجلَب عبر مضخّة الرسائل. MTA (Multi-Threaded Apartment) تشترك فيه خيوط متعدّدة ويمكن الاستدعاء مباشرة. التفاصيل في أساسيات تجنّب التعليق بـ STA/MTA في COM |
| work queue | آليّة خيوط يملكها Media Foundation لإدارة المعالجة غير المتزامنة. يُستدعى الـ callback من خيط هنا (3.5) |
حمل هذه ككلمات أوّلاً يقلّل كثيراً التعثّر عند قراءة الوثائق.
apartment يصير الموضوع في 3.5، وهنا يكفي أن تحفظ أنّ «callback Media Foundation قد يأتي من خيط آخر (work queue في MTA) غير الخيط الذي استدعيت منه ReadSample».
2.2. الصورة العامّة لـ Media Foundation (رسم)
Media Foundation بالنظر الكبير حديث خط أنابيب وسائط. حديث COM مهمّ، لكنّ رؤية الصورة العامّة أوّلاً أسهل ترتيباً.
flowchart TB
subgraph Pipeline["نموذج يستخدم خط الأنابيب بأكمله"]
Source1["Media Source"] --> Transform1["MFT"]
Transform1 --> Sink1["Media Sink"]
Session["Media Session"] --- Source1
Session --- Transform1
Session --- Sink1
end
subgraph Direct["نموذج يتعامل فيه التطبيق مع البيانات مباشرة"]
Source2["Media Source"] --> Reader["Source Reader (+ decoder)"]
Reader --> App["التطبيق"]
App --> Writer["Sink Writer (+ encoder)"]
Writer --> Sink2["Media Sink"]
end
الشكل 2: طريقتا استخدام. نموذج يترك خط الأنابيب لـ Media Session، ونموذج يتعامل فيه التطبيق مع البيانات مباشرة بـ Reader / Writer.
لـ Media Foundation تقريباً طريقتا استخدام.
- نموذج يستخدم خط الأنابيب بأكمله
- تربط source / transform / sink، وتدير Media Session تدفّق البيانات ومزامنة الصوت والصورة
- نموذج يتعامل فيه التطبيق مع البيانات مباشرة
- تستخرج البيانات من source بـ Source Reader، وتدفعها إلى sink بـ Sink Writer
الأخير أسهل دخولاً حين تريد معالجة الإطارات أو العيّنات بنفسك. ومن جهة أخرى إن أردت ترك التشغيل والمزامنة أيضاً للمنصّة فالأوّل هو المسار الأصلي.
ما ينبغي ضبطه أنّ هويّة Media Foundation منصّة معالجة وسائط، والإحساس مختلف قليلاً عن لمس تجميع كائنات COM مباشرة.
غير أنّك إن بدأت النظر في حدود تلك المكوّنات اشتدّ وجه COM فجأة. في الفصل التالي ننظر في تلك المواضع بالترتيب.
3. المواضع التي يصير فيها لـ Media Foundation وجه COM
مواضع اشتداد طابع COM تُرتَّب تقريباً في خمسة.
| الموضع | ماذا يظهر | ما يُفهم أوّلاً |
|---|---|---|
| 3.1. التهيئة | CoInitializeEx, MFStartup |
تهيئة COM وتهيئة Media Foundation أمران مختلفان |
| 3.2. إنشاء الكائنات وتسليمها | IMFSourceReader, IMFMediaType, IMFTransform |
كثير منها مؤشّر واجهة + HRESULT |
| 3.3. الإعداد | IMFAttributes, GUID |
قيم الإعداد ومعلومات النوع تُعبَّر عنها بـ key/value + GUID |
| 3.4. التعداد والإنشاء المؤجَّل | IMFActivate, ActivateObject |
نتيجة التعداد قد لا تكون الجسم كما هو |
| 3.5. غير المتزامن | IMFSourceReaderCallback, work queue |
يلزم وعي الـ callback و apartment |
| (الفصل 4) التحكّم في التشغيل | topology, Media Session | تدفّق خط الأنابيب بأكمله مفهوم خاص بـ Media Foundation |
التحكّم في التشغيل الأخير وحده مختلف الطابع، وليس حديث COM عامّاً بل وظيفة Media Foundation نفسها. لذلك نفصله في الفصل 4.
فيما يلي ننظر بالترتيب. الشيفرة ليست عيّنة كاملة، بل مقتطفات تكفي لرؤية أين يصير الوجه وجه COM.
3.1. في التهيئة يصطفّ CoInitializeEx و MFStartup
هنا أوّل ما يشعر كثيرون بالغربة. قبل حديث فتح ملفّ أو الأخذ من كاميرا يظهر أوّلاً CoInitializeEx و MFStartup.
CoInitializeExتهيئة مكتبة COMMFStartupتهيئة منصّة Media Foundation
أي أنّ تهيئة COM وحدها لا تكفي، وتلزم تهيئة جانب Media Foundation أيضاً. هنا يتّضح أنّ «هذه ليست مجرّد واجهة فيديو، بل تحتها عقد قائم على COM إلى حدّ بعيد».
template <class T>
void SafeRelease(T** pp)
{
if (pp != nullptr && *pp != nullptr)
{
(*pp)->Release();
*pp = nullptr;
}
}
HRESULT InitializeMediaFoundationForCurrentThread()
{
HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
if (FAILED(hr))
{
return hr;
}
hr = MFStartup(MF_VERSION);
if (FAILED(hr))
{
CoUninitialize();
return hr;
}
return S_OK;
}
void UninitializeMediaFoundationForCurrentThread()
{
MFShutdown();
CoUninitialize();
}
هذا الشكل الذي يصطفّ فيه CoInitializeEx و MFStartup أوّل موضع يشتدّ فيه مناخ COM فجأة عند لمس Media Foundation.
flowchart TB
accTitle: التهيئة والإنهاء على مرحلتين
accDescr: يبيّن التهيئة على مرحلتين: تهيئة مكتبة COM بـ CoInitializeEx ثمّ تهيئة منصّة Media Foundation بـ MFStartup قبل الاستخدام، وعند الإنهاء استدعاء MFShutdown و CoUninitialize بالعكس.
co["CoInitializeEx (تهيئة COM)"] --> mfs["MFStartup (تهيئة MF)"]
mfs --> use["استخدام Media Foundation"]
use --> shut["MFShutdown"]
shut --> coun["CoUninitialize"]
الشكل 3: تهيئة COM وحدها لا تكفي. التهيئة على مرحلتين، والإنهاء بالعكس.
في العمل إن قرّرت عند هذه النقطة ما يلي سهل ما بعدها.
- أيّ خيط يستخدم Media Foundation
- هل تجعل ذلك الخيط STA أم MTA
- من يحمل مسؤوليّة
MFStartup/MFShutdownوCoInitializeEx/CoUninitialize
في التنفيذ قد تكون طبقة أخرى تتولّى تهيئة COM أصلاً. حتّى عندئذٍ أأمن أن تثبّت أوّلاً من يحمل المسؤوليّة. إن تقدّمت وهذا التصميم غامض، صعب الفهم لاحقاً عند الـ callback والتكامل مع الواجهة.
لاحظ أنّ شيفرة هذا المقال تكتب SafeRelease بنفسها وتدير مؤشّر الواجهة الخام. عيّنات وثائق Microsoft مكتوبة بهذا الشكل، فيظهر أين يعمل AddRef / Release. غير أنّ هذا ليس سبباً لعدم استخدام مؤشّر ذكي في شيفرة العمل. إن كتبت جديداً بـ C++ فأأمن الميل إلى أحدهما التاليين.
| الخيار | الكيان | ملاحظة |
|---|---|---|
Microsoft::WRL::ComPtr<T> |
<wrl/client.h> |
مضمَّن في Windows SDK بلا اعتماد إضافي. مؤشّر خام بـ Get()، وسيط out بـ GetAddressOf() / &، و QueryInterface بـ As<U>() |
wil::com_ptr<T> |
wil/com.h من WIL (Windows Implementation Libraries) |
يُدخَل على حدة عبر NuGet ونحوه. يُستخدم مع مساعدات تحوّل HRESULT إلى استثناء |
بالكتابة بـ ComPtr لا تلزم توليفة goto done; و SafeRelease الظاهرة في أواخر 3.1، ويُستدعى Release عند الخروج من النطاق. هذا المقال يبقي المؤشّر خاماً لإظهار أسلوب COM، لكنّ الشيفرة الجديدة يُفضَّل أن تبدأ من ComPtr.
flowchart TB
accTitle: تقسيم استخدام المؤشّر الخام والمؤشّر الذكي
accDescr: يبيّن أنّ شيفرة هذا المقال مكتوبة بمؤشّر خام و SafeRelease ليظهر أين يعمل AddRef و Release، لكنّ الشيفرة الجديدة في العمل إن مالت إلى ComPtr أو wil::com_ptr استُدعي Release عند الخروج من النطاق فصارت أأمن.
raw["مؤشّر خام و SafeRelease"] -.-> why["كتابة يظهر فيها موضع عمل Release"]
smart["ComPtr أو wil::com_ptr"] --> auto["Release عند الخروج من النطاق"]
auto --> rec["الشيفرة الجديدة تبدأ من ComPtr"]
الشكل 4: شيفرة المقال تبقي المؤشّر خاماً للتعلّم. الشيفرة الجديدة في العمل تميل إلى المؤشّر الذكي.
3.2. تسليم الكائنات مركزه الواجهات
بقراءة واجهة Media Foundation يتّضح أنّ كثيراً من القيم المُرجَعة ووسائط out واجهات COM.
IMFSourceReaderIMFMediaTypeIMFTransformIMFActivateIMFSampleIMFMediaBuffer
المميّز أنّ لا بيانات الجسم وحدها بل معلومات النوع وكائنات الإعداد أيضاً تُعبَّر عنها بواجهة.
مثلاً:
IMFTransformواجهة تمثّل MFTIMFAttributesمخزن key/valueIMFMediaType«وصف لشكل الوسائط» يرثIMFAttributes
حتّى شيء بطابع «بيانات إعداد» مثل media type يُحمَل بواجهة COM. هنا يدخل سياق IUnknown و QueryInterface و AddRef / Release و HRESULT طبيعيّاً.
flowchart TD
IUnknown["IUnknown"]
IUnknown --> IMFAttributes["IMFAttributes"]
IMFAttributes --> IMFMediaType["IMFMediaType"]
IMFAttributes --> IMFActivate["IMFActivate"]
IUnknown --> IMFSourceReader["IMFSourceReader"]
IUnknown --> IMFTransform["IMFTransform"]
الشكل 5: نسب الواجهات الرئيسة. حتّى الإعداد ومعلومات النوع تُعبَّر عنها بواجهات COM رأسها IUnknown.
عند هذا الحدّ يتّضح أنّ «Media Foundation واجهة وسائط، لكنّ طريقة التعبير عن الحدود COM إلى حدّ بعيد».
3.3. الإعداد ومعلومات النوع مركزها IMFAttributes و GUID
عند لمس Media Foundation ثمّة موضع يبدو فيه الإعداد فجأة غابة GUID. مركزه IMFAttributes، مخزن key/value مفتاحه GUID. يُستخدم كثيراً جدّاً في Media Foundation كلّه.
الأهمّ خصوصاً IMFMediaType الذي يرث IMFAttributes ويحمل معلومات شكل الوسائط كخصائص.
مثلاً معلومات كهذه.
- major type (صوت أم صورة)
- subtype (H.264، AAC، RGB32، PCM وغيرها)
- حجم الإطار
- معدّل الإطارات
- معدّل العيّنات
- عدد القنوات
flowchart LR
MediaType["IMFMediaType"] --> Major["MF_MT_MAJOR_TYPE"]
MediaType --> Subtype["MF_MT_SUBTYPE"]
MediaType --> Detail["الحجم / FPS / معدّل العيّنات وغيرها"]
الشكل 6: IMFMediaType مخزن خصائص يحمل معلومات الشكل مثل major type و subtype بمفتاح GUID.
يسهل الإحساس هنا بـ «غابة GUID»، لكنّ ما يُفعل في الواقع صريح إلى حدّ بعيد.
- حمل الإعداد بمخزن خصائص
- تمثيل media type أيضاً كمخزن خصائص
- بين source / transform / sink تُوافَق الأشكال بالنظر في تلك الخصائص
الحديث أنّ تمثيل الإعداد ومعلومات النوع يستخدم واجهة بطابع COM و GUID فحسب.
بالشيفرة حتّى هنا يصير كالتالي. مثال يقرأ إطاراً واحداً فقط من فيديو بـ Source Reader.
HRESULT ReadOneVideoSample(PCWSTR path)
{
IMFSourceReader* pReader = nullptr;
IMFMediaType* pType = nullptr;
IMFSample* pSample = nullptr;
HRESULT hr = MFCreateSourceReaderFromURL(path, nullptr, &pReader);
if (FAILED(hr)) goto done;
hr = MFCreateMediaType(&pType);
if (FAILED(hr)) goto done;
hr = pType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
if (FAILED(hr)) goto done;
hr = pType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32);
if (FAILED(hr)) goto done;
hr = pReader->SetCurrentMediaType(
MF_SOURCE_READER_FIRST_VIDEO_STREAM,
nullptr,
pType);
if (FAILED(hr)) goto done;
DWORD streamFlags = 0;
LONGLONG timestamp = 0;
hr = pReader->ReadSample(
MF_SOURCE_READER_FIRST_VIDEO_STREAM,
0,
nullptr,
&streamFlags,
×tamp,
&pSample);
if (FAILED(hr)) goto done;
// pSample から IMFMediaBuffer を取り出して処理する
done:
SafeRelease(&pSample);
SafeRelease(&pType);
SafeRelease(&pReader);
return hr;
}
ما يظهر هنا النقاط التالية.
- الـ reader و media type كلاهما واجهة COM
- الإعداد على أساس GUID
- القيمة المُرجَعة
HRESULT - في الوضع المتزامن يحجب
ReadSample
حتّى مع «أريد قراءة إطار واحد فقط» يصير الوجه عند حدود Media Foundation وجه COM إلى حدّ بعيد. حديث الوضع المتزامن الأخير يُعالَج في 3.5.
خطوات media type negotiation (بند من «الثلاثة التي تُنظَر أوّلاً» في قائمة فحص الفصل 6)
الشيفرة أعلاه تعلن فقط «أريد RGB32»، لذا في العمل الفعلي تلزم خطوات قبلها وبعدها. في حالة Source Reader التدفّق الذي تعرضه وثائق Microsoft أربع خطوات.
- تعداد الأنواع الأصليّة — استدعِ
IMFSourceReader::GetNativeMediaType(streamIndex, typeIndex, &pType)مع زيادةtypeIndexمن 0. عند تجاوز النطاق يُرجَعMF_E_NO_MORE_TYPES، وذلك نهاية التعداد (إن كانstreamIndexخارج النطاق فـMF_E_INVALIDSTREAMNUMBER). الملفّ غالباً نوع واحد لكلّ تيّار، أمّا كاميرا الويب فتحمل أشكالاً متعدّدة - تأكيد major type — اقرأ
MF_MT_MAJOR_TYPEمن media type الحاصل بالتعداد، واحكم أصوت هو أم صورة. إن تقدّمت بتثبيت دون النظر هنا رميت إعداد صورة على تيّار صوت - تجميع شكل الإخراج المطلوب وتعيينه — اصنع media type جديداً بـ
MFCreateMediaType، عيّنMF_MT_MAJOR_TYPEوMF_MT_SUBTYPE، واستدعِSetCurrentMediaType. إن أردت الاستلام مضغوطاً كما هو فمرّر النوع الحاصل في الخطوة 1 كما هو، وإن أردت فكّ الترميز فعيّن شكلاً غير مضغوط (MFVideoFormat_RGB32،MFAudioFormat_PCMوغيرها). يحمّل Source Reader المفكّك تلقائيّاً - إعادة قراءة الشكل المثبَّت — بعد
SetCurrentMediaTypeاستدعِGetCurrentMediaTypeواحصل على تفاصيل الشكل المثبَّت فعلاً (حجم الإطار، stride، معدّل العيّنات وغيرها). ما تمرّره في الخطوة 3 تعيين جزئي، لذا القيمة المثبَّتة تُقرأ هنا وهو الترتيب الصحيح
إن أسقطت هذه الخطوات الأربع وتقدّمت بـ «ربّما هذا الشكل» رُجع MF_E_INVALIDMEDIATYPE، أو مرّ الأمر لكنّك قرأت buffer بشكل غير متوقَّع.
flowchart TB
accTitle: الخطوات الأربع لـ media type negotiation
accDescr: يبيّن أربع خطوات: تعداد الأنواع الأصليّة بـ GetNativeMediaType، وتأكيد major type، وتجميع شكل الإخراج المطلوب وتعيينه بـ SetCurrentMediaType، وأخيراً قراءة الشكل المثبَّت بـ GetCurrentMediaType.
s1["التعداد بـ GetNativeMediaType"] --> s2["تأكيد major type"]
s2 --> s3["الشكل المطلوب بـ SetCurrentMediaType"]
s3 --> s4["قراءة القيمة المثبَّتة بـ GetCurrentMediaType"]
s1 -.-> stop["MF_E_NO_MORE_TYPES نهاية التعداد"]
الشكل 7: موافقة الشكل أربع خطوات. ما يُمرَّر تعيين جزئي، لذا تُقرأ القيمة المثبَّتة أخيراً.
3.4. يظهر Activation Object
حيث يظهر طابع COM في Media Foundation خصوصاً هو activation object.
IMFActivate كائن مساعد لصنع الجسم لاحقاً. الإحساس قريب من class factory في COM فيسهل فهمه كذلك.
في المواضع التي يظهر فيها قد لا تكون قيمة واجهة التعداد «جسماً يُستخدم كما هو» بل مصفوفة IMFActivate* أوّلاً.
ثمّ تُجسَّد ما يلزم فقط بـ ActivateObject.
sequenceDiagram
participant App as التطبيق
participant Enum as واجهة التعداد
participant Act as IMFActivate
participant Obj as IMFTransform / Sink وغيرها
App->>Enum: استدعاء التعداد
Enum-->>App: مصفوفة IMFActivate*
App->>Act: تأكيد الخصائص
App->>Act: ActivateObject(...)
Act-->>App: كائن COM الكيان
الشكل 8: ما ترجعه واجهة التعداد IMFActivate، ولا يُحصل على كائن COM الكيان إلّا بعد استدعاء ActivateObject.
هذا الشكل يتوافق جيّداً مع تصميم Media Foundation في العثور على مكوّنات قابلة للاستبدال لاحقاً وتركيبها.
ثمّ إنّ activation object نفسه يستطيع حمل attributes، فيسهل تدفّق «انظر أوّلاً في خصائص المرشّح» و«عيّن إن لزم» و«جسّد لاحقاً». هنا أيضاً طابع COM إلى حدّ بعيد.
عند تعداد MFT بـ MFTEnumEx وتجسيده يصير كالتالي.
HRESULT FindH264Decoder(IMFTransform** ppTransform)
{
*ppTransform = nullptr;
IMFActivate** ppActivate = nullptr;
UINT32 count = 0;
MFT_REGISTER_TYPE_INFO inputType = {};
inputType.guidMajorType = MFMediaType_Video;
inputType.guidSubtype = MFVideoFormat_H264;
HRESULT hr = MFTEnumEx(
MFT_CATEGORY_VIDEO_DECODER,
MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_LOCALMFT,
&inputType,
nullptr,
&ppActivate,
&count);
if (FAILED(hr))
{
return hr;
}
if (count == 0)
{
CoTaskMemFree(ppActivate);
return MF_E_TOPO_CODEC_NOT_FOUND;
}
hr = ppActivate[0]->ActivateObject(
__uuidof(IMFTransform),
reinterpret_cast<void**>(ppTransform));
for (UINT32 i = 0; i < count; ++i)
{
ppActivate[i]->Release();
}
CoTaskMemFree(ppActivate);
return hr;
}
نتيجة التعداد لا ترجع IMFTransform* من البداية بل IMFActivate**، ولا تأخذ IMFTransform الكيان إلّا بعد ActivateObject. هذا التدفّق يمثّل جيّداً إحساس Media Foundation بـ «يصير الوجه فجأة وجه COM».
flowchart TB
accTitle: التدفّق من MFTEnumEx إلى تجسيد المفكّك
accDescr: يبيّن التدفّق: تعداد مرشّحي المفكّك بـ MFTEnumEx يرجع مصفوفة IMFActivate، وإن لم يوجد مرشّح فـ MF_E_TOPO_CODEC_NOT_FOUND، وإن وُجد جُسِّد بـ ActivateObject للحصول على IMFTransform ثمّ Release لكلّ IMFActivate و CoTaskMemFree لمصفوفة الجسم.
enum["تعداد المرشّحين بـ MFTEnumEx"] --> arr["ترجع مصفوفة IMFActivate"]
arr --> q{"هل ثمّة مرشّح؟"}
q -->|"لا"| nf["MF_E_TOPO_CODEC_NOT_FOUND"]
q -->|"نعم"| act["التجسيد بـ ActivateObject"]
act --> obj["الحصول على IMFTransform"]
act -.-> free["Release لكلّ عنصر"]
free -.-> free2["المصفوفة بـ CoTaskMemFree"]
الشكل 9: تدفّق تعداد → تأكيد المرشّح → تجسيد → تحرير. نتيجة التعداد ليست جسماً يُستخدم كما هو.
3.5. التعامل مع غير المتزامن والـ callback والخيوط أيضاً بطابع COM
ما يسهل إغفاله في عمل Media Foundation المعالجة غير المتزامنة ونموذج الخيوط.
مثلاً Source Reader افتراضيّاً في الوضع المتزامن. في الوضع المتزامن يحجب ReadSample.
حسب حالة الملفّ أو الشبكة أو الجهاز قد يصير ذلك الانتظار زمناً مرئيّاً.
للوضع غير المتزامن تمرّر callback عند إنشاء Source Reader.
التدفّق: تعدّ كائناً ينفّذ IMFSourceReaderCallback، وتعيّنه في خاصّية MF_SOURCE_READER_ASYNC_CALLBACK، ثمّ تنشئ.
HRESULT CreateSourceReaderAsync(
PCWSTR path,
IMFSourceReaderCallback* pCallback,
IMFSourceReader** ppReader)
{
IMFAttributes* pAttributes = nullptr;
HRESULT hr = MFCreateAttributes(&pAttributes, 1);
if (FAILED(hr))
{
return hr;
}
hr = pAttributes->SetUnknown(MF_SOURCE_READER_ASYNC_CALLBACK, pCallback);
if (SUCCEEDED(hr))
{
hr = MFCreateSourceReaderFromURL(path, pAttributes, ppReader);
}
SafeRelease(&pAttributes);
return hr;
}
أي أنّ الشكل:
- الـ callback نفسه واجهة COM
- إعداد غير المتزامن عبر
IMFAttributes - الوضع يُقرَّر عند الإنشاء
ثمّ الأهمّ قليلاً apartment. تستخدم المعالجة غير المتزامنة في Media Foundation work queue، وخيط work queue هو MTA. لذا يبسّط التنفيذ إن تعامل جانب التطبيق أيضاً بـ MTA.
sequenceDiagram
participant App as خيط التطبيق
participant Reader as Source Reader
participant Queue as MF work queue (MTA)
participant Cb as IMFSourceReaderCallback
App->>Reader: ReadSample(...)
Reader-->>App: يعود فوراً
Reader->>Queue: معالجة داخليّة
Queue->>Cb: OnReadSample(...)
الشكل 10: ReadSample في الوضع غير المتزامن يعود فوراً، ويُستدعى OnReadSample من خيط work queue.
حول الـ callback ما ينبغي الانتباه إليه هذه النقاط.
- لا تلمس كائن STA لخيط الواجهة كما هو من جانب الـ callback
- اجعل تنفيذ الـ callback آمناً للخيوط
- إن لزم تحديث الواجهة فأعد النتيجة فقط إلى خيط الواجهة
- فكّر أوّلاً بتثبيت «من أيّ خيط يأتي callback Media Foundation»
Media Foundation لا يمتصّ من تلقاء نفسه مقتضيات كائن STA. لذا أسهل ترتيباً أن تميل العامل الذي يستخدم Media Foundation إلى MTA، وتمدّ جسراً صريحاً مع الواجهة.
flowchart TB
accTitle: طريقة مدّ الجسر بين الـ callback وخيط الواجهة
accDescr: يبيّن الترتيب: الـ callback يأتي من خيط work queue في MTA لذا يُجعل التنفيذ آمناً للخيوط، ولا تُلمَس كائنات واجهة STA مباشرة، وإن لزم تحديث الواجهة تُعاد النتيجة فقط إلى خيط الواجهة.
cb["الـ callback يأتي من work queue في MTA"] --> safe["اجعل التنفيذ آمناً للخيوط"]
cb -.-> ng["لا تلمس كائن واجهة STA مباشرة"]
safe --> bridge["أعد النتيجة فقط إلى خيط الواجهة"]
الشكل 11: مل العامل الذي يستخدم Media Foundation إلى MTA، ومدّ جسراً صريحاً مع الواجهة.
4. غير أنّ Media Foundation ليس مساوياً لـ COM
بقراءة حتّى هنا يسهل الظنّ أنّ «Media Foundation في النهاية COM نفسه». غير أنّ الأمر مختلف قليلاً.
لـ Media Foundation مفاهيم خاصّة بالمنصّة لا تُنهى بحديث COM عامّ.
MFStartup/MFShutdown- Media Session
- topology
- topology loader
- presentation clock
- Source Reader / Sink Writer
هذا تقريباً دور Media Foundation نفسه في كيف يُمرَّر خط أنابيب الوسائط.
مثلاً في Media Session يوجد تدفّق يمرّر فيه التطبيق partial topology فيكمّل topology loader التحويلات اللازمة ويحلّه إلى full topology. هذا أقرب إلى وظيفة يملكها Media Foundation كمنصّة معالجة وسائط منه إلى حديث COM عامّ.
flowchart LR
Partial["Partial Topology Source -> Output"] --> Loader["Topology Loader"]
Loader --> Full["Full Topology Source -> Decoder MFT -> Output"]
الشكل 12: إن مُرِّر partial topology كمّل topology loader التحويل اللازم وحلّه إلى full topology.
Media Foundation يعبّر عن عقد المكوّنات بـ COM، ويعمل فوق ذلك كمنصّة معالجة وسائط. النظر بهاتين المرحلتين يقلّل التيه.
flowchart TB
accTitle: مرحلتا طبقة COM وطبقة المنصّة
accDescr: يبيّن بنية مرحلتين: Media Foundation يعبّر عن عقد المكوّنات بـ COM، وفوق ذلك يملك آليّات خاصّة بخط أنابيب الوسائط مثل Media Session و topology و presentation clock.
com2["طبقة COM (تعبّر عن عقد المكوّنات)"] --> mf2["طبقة منصّة معالجة الوسائط"]
mf2 --> own["Media Session و topology وغيرها"]
own -.-> note2["مفاهيم خاصّة بـ MF لا تُنهى بحديث COM عامّ"]
الشكل 13: ليس إعادة طبخ لـ COM. فوق طبقة COM طبقة خاصّة بـ MF تمرّر خط الأنابيب.
5. من أين تلمس (اختيار المدخل)
عند تقرير المدخل الأوّل يكفي غالباً هذا الرسم.
flowchart TD
Start["ما تريد فعله"] --> Q1{"ما اللازم أوّلاً؟"}
Q1 -- "أريد قراءة إطارات / عيّنات" --> A1["Source Reader"]
Q1 -- "أريد الكتابة إلى ملفّ" --> A2["Sink Writer"]
Q1 -- "يلزم تحكّم في التشغيل أو مزامنة صوت وصورة" --> A3["Media Session"]
Q1 -- "أريد إدخال محوّل خاصّ" --> A4["MFT"]
الشكل 14: اختر المدخل ممّا يلزم أوّلاً. إن أردت القراءة فـ Reader، وإن أردت الكتابة فـ Writer، وإن أردت التشغيل فـ Session.
في جدول يصير هكذا.
| ما تريد فعله | ما تلمسه أوّلاً | كثافة COM | تكميل |
|---|---|---|---|
| استخراج إطارات / عيّنات من ملفّ أو كاميرا | Source Reader | متوسّطة | يتولّى decoder أيضاً إن لزم |
| كتابة صوت / صورة مولَّدة إلى ملفّ | Sink Writer | متوسّطة | يمكن التعامل مجتمعاً مع encoder و media sink إن لزم |
| التعامل حتّى التشغيل والإيقاف والبحث ومزامنة الصوت والصورة وضبط الجودة | Media Session | عالية | يلزم فهم topology و session |
| إدراج محوّل خاصّ أو مكوّن بطابع codec | MFT | عالية | فكّر أساساً بـ IMFTransform |
| النظر في مرشّحين مُعدَّدين ثمّ تجسيد ما يلزم فقط | IMFActivate |
عالية | ما يرجع قد يكون activation object لا الجسم |
5.1. حالة الدخول أوّلاً من Source Reader
Source Reader سهل الاستخدام إلى حدّ بعيد كمدخل حين تريد استخراج بيانات من ملفّ أو جهاز.
يناسبه مثلاً حالات كهذه.
- تريد استخراج إطارات من ملفّ فيديو
- تريد فكّ ترميز ملفّ صوت واستخراج عيّنات
- تريد استخراج إطارات من كاميرا
- تريد وصل source في Media Foundation بخط أنابيب معالجة خاصّ بك
يحمّل Source Reader decoder عند الحاجة ويمرّر البيانات إلى التطبيق. ومن جهة أخرى لا يتولّى إدارة ساعة العرض ولا مزامنة الصوت والصورة ولا الرسم على الشاشة نفسه.
أوضح أن تراه مدخلاً «لأخذ البيانات» لا «للتشغيل».
flowchart TB
accTitle: نطاق دور Source Reader
accDescr: يبيّن نطاق الدور: Source Reader يستخرج البيانات من ملفّ أو كاميرا ويحمّل decoder عند الحاجة ويمرّرها إلى التطبيق، لكنّه لا يتولّى إدارة ساعة العرض ولا مزامنة الصوت والصورة ولا الرسم على الشاشة.
src["source مثل ملفّ أو كاميرا"] --> sr["Source Reader"]
sr --> app["تمرير البيانات إلى التطبيق"]
sr -.-> dec["تحميل decoder إن لزم"]
sr -.-> not["لا يتولّى التشغيل والمزامنة"]
الشكل 15: Source Reader مدخل «لأخذ البيانات» لا «للتشغيل».
5.2. إن كتبت إلى ملفّ فـ Sink Writer
Sink Writer مدخل حين تريد كتابة صوت أو صورة إلى ملفّ.
الاستخدام النموذجي تقريباً هذا.
- تريد حفظ إطارات مولَّدة في ملفّ فيديو
- تريد تشفير عيّنات صوت وكتابتها
- تريد تحويل بيانات مستخرجة إلى شكل آخر وحفظها
يجد Sink Writer encoder عند الحاجة ويحمّله ويدير تدفّق البيانات إلى media sink. كثيراً ما يُجمع مع Source Reader، لكنّهما مكوّنان مستقلّان فلا يلزم استخدامهما كزوج حتماً.
flowchart TB
accTitle: نطاق دور Sink Writer
accDescr: يبيّن أنّ التطبيق يمرّر إطارات أو عيّنات صوت مولَّدة إلى Sink Writer فيجد encoder عند الحاجة ويحمّله ويدير تدفّق البيانات إلى media sink ويكتب إلى ملفّ.
app2["إطارات وصوت مولَّد في التطبيق"] --> sw["Sink Writer"]
sw -.-> enc["تحميل encoder إن لزم"]
sw --> sink["الكتابة إلى media sink"]
sw -.-> ind["مكوّن مستقلّ عن Source Reader"]
الشكل 16: Sink Writer مدخل يتولّى التشفير والكتابة. الاستخدام كزوج مع Reader ليس لازماً.
5.3. إن تعاملت مع التشغيل والمزامنة فـ Media Session
إن لم يكن المراد «الاستخراج من ملفّ» بل التشغيل على وجه سليم، فأصرح التفكير أساساً بـ Media Session.
يحين دور Media Session حين توجد متطلّبات كهذه.
- تريد التعامل مع التشغيل / الإيقاف / البحث
- تريد ترك مزامنة الصوت والصورة لجانب المنصّة
- تريد التعامل مع خط الأنابيب شاملاً ضبط الجودة وتغيير الشكل
- تريد تركيب تدفّق source / transform / sink بـ topology
بدخول هذه الطبقة تقترب من «جسم Media Foundation» أكثر من Source Reader / Sink Writer. وبذلك تزيد أيضاً مفاهيم خاصّة بـ Media Foundation مثل topology و session event.
flowchart TB
accTitle: حكم اختيار Media Session
accDescr: يبيّن أنّك إن أردت ترك التشغيل والإيقاف والبحث ومزامنة الصوت والصورة وضبط الجودة للمنصّة فكّرت أساساً بـ Media Session وركّبت التدفّق بـ topology، وبذلك تزيد المفاهيم الخاصّة بـ Media Foundation.
need["أريد ترك التشغيل والبحث والمزامنة"] --> ms["التفكير أساساً بـ Media Session"]
ms --> topo["تركيب source إلى sink بـ topology"]
ms -.-> deep["تزيد بذلك المفاهيم الخاصّة بـ MF"]
الشكل 17: إن لم يكن المراد «أخذ البيانات» بل «التشغيل على وجه سليم» فـ Media Session هو المسار الأصلي.
5.4. إن أدرجت مكوّناً خاصّاً فـ MFT
MFT هو النموذج المشترك لتحويل Media Foundation.
تدخل هنا في مواضع كهذه.
- تريد صنع مفكّك أو مشفّر خاصّ
- تريد إدراج مكوّن معالجة صورة أو صوت في خط الأنابيب
- تريد تعداد codec أو محوّل واختياره بنفسك
- تريد تحكّماً أعمق من الحلّ التلقائي الافتراضي
في عالم MFT يظهر في المقدّمة إلى حدّ بعيد عقد بطابع COM مثل IMFTransform و IMFActivate و media type negotiation وإدارة العيّنة / الـ buffer.
لذا أوضح أن تنظر أوّلاً في أيّ من Source Reader / Sink Writer / Media Session لازم حقّاً، لا أن تدخل إلى MFT فوراً كمدخل أوّل.
flowchart TB
accTitle: التأكيد قبل التقدّم إلى MFT
accDescr: يبيّن أنّك تتقدّم إلى MFT حين تريد إدراج مفكّك أو محوّل خاصّ في خط الأنابيب، لكنّ عقد COM يظهر في المقدّمة لذا يحسن التأكيد أوّلاً هل تكفي Source Reader أو Sink Writer أو Media Session.
first["انظر أوّلاً هل تكفي المداخل الثلاثة الأخرى"] --> q{"هل يلزم مكوّن تحويل خاصّ؟"}
q -->|"لا"| use3["التقدّم بـ Reader أو Writer أو Session"]
q -->|"نعم"| mft["التقدّم إلى MFT (IMFTransform)"]
mft -.-> heavy["عقد COM يظهر في المقدّمة"]
الشكل 18: MFT آخر مدخل. لا تدخل فوراً؛ تقدّم بعد التأكيد أنّ الثلاثة الأخرى لا تكفي.
6. قائمة فحص في العمل
أخيراً نجمع في ورقة واحدة النقاط التي يُراد النظر إليها أوّلاً في العمل.
| البند | ما يُنظَر إليه | ما يسهل وقوعه إن أُغفل |
|---|---|---|
| مسؤوليّة التهيئة | تقرير أين يُستدعى CoInitializeEx و MFStartup، وأين تُحمَل معالجة الإنهاء |
نقص التهيئة، اضطراب ترتيب الإنهاء |
| apartment | تقرير أوّلاً هل خيط لمس MF سيكون STA أم MTA | اضطراب حول الـ callback، تصادم مع الواجهة |
| وضع Source Reader | تقرير المتزامن أو غير المتزامن عند الإنشاء | ReadSample يحجب على غير المتوقَّع، ولا يمكن التبديل لاحقاً |
| media type negotiation | تعداد أشكال الإخراج والتصريح بالشكل المستخدم فعلاً. الخطوات هي الأربع في 3.3 (تعداد بـ GetNativeMediaType → تأكيد major type → SetCurrentMediaType → قراءة القيمة المثبَّتة بـ GetCurrentMediaType) |
MF_E_INVALIDMEDIATYPE، وصول شكل غير متوقَّع |
| عمر الكائن | توضيح مسؤوليّة Release و Unlock و ShutdownObject |
تسرّب ذاكرة، احتفاظ بـ buffer، عدم اتّساق عند الإنهاء |
| activation object | تمييز هل نتيجة التعداد جسم أم IMFActivate |
الفشل بظنّ أنّ QueryInterface ممكن |
| topology | إدراك هل تتعامل مع partial topology أم full topology | الانسداد بظنّ أنّ «الوصل يتمّ تلقائيّاً» |
| تأكيد الخطأ | النظر كلّ مرّة في HRESULT و stream flags و event |
إغفال فشل جزئي |
| التكامل مع الواجهة | لا تلمس الواجهة مباشرة من الـ callback، أعد النتيجة فقط إلى خيط الواجهة | تعليق، تعارض، خلل صعب الفهم |
الأعلى أولويّة خصوصاً هذه الثلاثة.
- عدم خطأ واجهة المدخل الأولى
- ميّز أوّلاً أيّ من Source Reader / Sink Writer / Media Session لازم حقّاً
- تقرير apartment أوّلاً
- إن خلطت واجهة STA و work queue في Media Foundation فقرّر أوّلاً طريقة مدّ الجسر
- عدم الاستسهال في media type negotiation
- التقدّم بـ «ربّما هذا الشكل» يصير لاحقاً صعب الفهم إلى حدّ بعيد
- الخطوات العينيّة مجمّعة في «خطوات media type negotiation» في 3.3
flowchart TB
accTitle: ثلاثة بنود ذات أولويّة عالية في قائمة الفحص
accDescr: يبيّن أنّ ثلاثة ذات أولويّة عالية خصوصاً: عدم خطأ واجهة المدخل الأولى، وتقرير apartment أوّلاً، وعدم الاستسهال في media type negotiation، وبهذا يُتجنَّب اضطراب التنفيذ لاحقاً.
c1["عدم خطأ واجهة المدخل"] --> ease["يمكن تجنّب اضطراب التنفيذ لاحقاً"]
c2["تقرير apartment أوّلاً"] --> ease
c3["عدم الاستسهال في موافقة الشكل"] --> ease
الشكل 19: من قائمة الفحص، ضبط هذه الثلاثة أوّلاً هو الذي ينفع.
7. الخلاصة
ازدياد حديث COM فجأة عند لمس Media Foundation ليس مصادفة.
- Media Foundation منصّة معالجة وسائط
- حدود source / transform / sink / activation / callback وغيرها تُعبَّر عنها بواجهات COM
- لذلك يظهر طبيعيّاً حديث
IUnknownوHRESULTو GUID و apartment و callback - غير أنّ جسم Media Foundation خط أنابيب وسائط يملك Media Session و topology، وليس مجرّد إعادة طبخ لـ COM
في العمل يسهل الترتيب كثيراً إن فكّرت بهذا الترتيب أوّلاً.
- ميّز أصلاً أيّ من Source Reader / Sink Writer / Media Session / MFT لازم
- قرّر أوّلاً سياسة apartment و callback
- تعامل بعناية مع media type negotiation وعمر الكائن
flowchart TB
accTitle: ترتيب التفكير في العمل
accDescr: يبيّن ترتيب الترتيب في العمل: ميّز أوّلاً أيّ مدخل لازم، ثمّ قرّر سياسة apartment و callback، وأخيراً تعامل بعناية مع media type negotiation وعمر الكائن.
o1["تمييز أيّ مدخل لازم"] --> o2["تقرير سياسة apartment و callback"]
o2 --> o3["موافقة الشكل والعمر بعناية"]
الشكل 20: ترتيب التفكير في العمل. قرّر بالترتيب اختيار المدخل، ثمّ سياسة الخيوط، ثمّ الشكل والعمر.
لا بأس إن لم تفهم الكلّ من البداية. إن رأيت أوّلاً أنّ «Media Foundation منصّة معالجة وسائط، و COM داخل حدودها بعمق» سهل تتبّع الوثائق والشيفرة كثيراً.
8. مراجع
- Media Foundation and COM - Microsoft Learn
- Overview of the Media Foundation Architecture - Microsoft Learn
- Initializing Media Foundation - Microsoft Learn
- Source Reader - Microsoft Learn
- Using the Source Reader to Process Media Data - Microsoft Learn
- Using the Source Reader in Asynchronous Mode - Microsoft Learn
- Sink Writer - Microsoft Learn
- Activation Objects - Microsoft Learn
- About Topologies - Microsoft Learn
- IMFAttributes interface - Microsoft Learn
- IMFMediaType interface - Microsoft Learn
- IMFTransform interface - Microsoft Learn
- MFTEnumEx function - Microsoft Learn
- IMFSourceReader::GetNativeMediaType - Microsoft Learn
- ComPtr Class (Microsoft::WRL) - Microsoft Learn
- أساسيات تجنّب التعليق بـ STA/MTA في COM - KomuraSoft Blog
- لماذا يُفضَّل صنع غلاف C++/CLI عند استخدام native DLL لـ C++ من C# - KomuraSoft Blog
مقالات ذات صلة
أحدث المقالات التي تشترك في نفس الوسوم. عمّق فهمك بمواضيع مرتبطة.
كيف تحرق صورة ونصّاً في إطارات MP4 بـ Media Foundation
نرتّب كيف تحرق صورة ونصّاً في كل إطار من فيديو MP4 بـ Media Foundation وتنتج MP4 جديداً، بتقسيم الأدوار بين Source Reader والرسم وتحويل ا...
كيفيّة تحويل YUV إلى RGB في Media Foundation
نرتّب هنا تحويل إطارات YUV إلى RGB في Media Foundation عبر مسارَي التحويل التلقائيّ في Source Reader والتحويل اليدويّ لـ NV12 و YUY2، مع ...
استخراج صورة ثابتة من MP4 عند زمن محدّد بـ Media Foundation
نلخّص خطوات التنفيذ لأخذ إطار قريب من زمن محدّد في MP4 عبر Source Reader، وترتيب stride و alpha في RGB32، ثم الحفظ PNG.
Time Travel Debugging ── تسجيل الأخطاء التي لا تتكرّر في التطبيقات طويلة التشغيل وإرجاعها
خطأ يظهر مرّة في الشهر لا يترك في تفريغ الانهيار سوى نتيجته. سجّل التنفيذ وأرجعه بـ WinDbg Time Travel Debugging (TTD): TTD.exe والمخزن ا...
لماذا تتعطّل الوسائط ── قواعد وسائط سطر أوامر Windows
في Windows لا توجد مصفوفة وسائط؛ يصل إلى CreateProcess سلسلة واحدة ويتولّى الطرف المستقبل تقسيمها. نشرح قواعد CommandLineToArgvW وCRT و.N...
أين يتصل هذا الموضوع
ترتبط هذه المقالة بشكل طبيعي بصفحات الخدمات التالية.
تطوير تطبيقات ويندوز
معالجة الوسائط في Windows التي تشمل Media Foundation وCOM وHRESULT قريبة من موضوعات التنفيذ التي تُعالَج ضمن تطوير تطبيقات Windows.
الاستشارات التقنية ومراجعة التصميم
إن أردت أولاً ترتيب الحدود ذات الطابع COM وترتيب التهيئة، فيمكن الدخول من جانب التصميم ضمن الاستشارة التقنية ومراجعة التصميم.
الأسئلة الشائعة
أسئلة شائعة حول موضوع هذه المقالة.
- ما هو Media Foundation؟ هل يختلف عن COM؟
- Media Foundation منصّة معالجة وسائط للتعامل مع الفيديو والصوت على Windows، وسطح الواجهة بأكمله ليس COM خالصاً كما هو. غير أنّ حدود المكوّنات مثل source / transform / sink / activation / attributes / callback تُعبَّر عنها بواجهات COM، لذا يظهر أثناء الاستخدام حديث IUnknown و HRESULT و GUID و apartment طبيعيّاً. الأدقّ أن تراه «منصّة معالجة وسائط، وحدودها يدخلها COM بعمق».
- لماذا تلزم MFStartup و CoInitializeEx معاً؟
- لأنّ الدور مختلف. CoInitializeEx تهيئة مكتبة COM، و MFStartup تهيئة منصّة Media Foundation. تهيئة COM وحدها لا تكفي، وتلزم تهيئة جانب Media Foundation أيضاً. في العمل إن قرّرت أوّلاً أيّ خيط يستخدم Media Foundation، و STA أم MTA، ومن يحمل مسؤوليّة MFStartup / MFShutdown و CoInitializeEx / CoUninitialize، سهل لاحقاً الـ callback والتكامل مع واجهة المستخدم.
- كيف تُقسَّم Source Reader و Sink Writer و Media Session و MFT؟
- إن أردت استخراج إطارات أو عيّنات من ملفّ أو كاميرا فمدخل Source Reader، وإن أردت كتابة صوت أو صورة مولَّدة إلى ملفّ فمدخل Sink Writer. إن أردت ترك التشغيل والإيقاف والبحث ومزامنة الصوت والصورة وضبط الجودة للمنصّة فكّر أساساً بـ Media Session. تتقدّم إلى MFT حين تريد إدراج مفكّك أو محوّل خاصّ في خط الأنابيب، لكنّ عقد COM يظهر في المقدّمة، لذا يُفضَّل النظر أوّلاً في أيّ من الثلاثة السابقة لازم حقّاً.
- ما الذي ينبغي الانتباه إليه في callback غير المتزامن لـ Media Foundation؟
- تستخدم المعالجة غير المتزامنة في Media Foundation work queue، وخيطها MTA، لذا يبسّط التنفيذ إن مال جانب التطبيق أيضاً إلى MTA. اجعل تنفيذ IMFSourceReaderCallback آمناً للخيوط، ولا تلمس كائن STA لخيط الواجهة مباشرة من جانب الـ callback. إن لزم تحديث الواجهة فأعد النتيجة فقط إلى خيط الواجهة. وانتبه أيضاً أنّ وضع Source Reader المتزامن أو غير المتزامن يُقرَّر عند الإنشاء ولا يمكن تبديله لاحقاً.
الملف الشخصي للمؤلف
صفحة الملف الشخصي لمؤلف المقالة.
غو كومورا
مؤسّس شركة كومورا سوفت ذ.م.م.
يركّز على تطوير برامج ويندوز، والاستشارات التقنية، والتحقيق في الأخطاء، ويتميّز في المشاريع التي تبقى فيها الأصول القديمة ناشطة، وفي تشخيص الأعطال التي يصعب تحديد سببها.