إنشاء نفق للوسائط المتعددة

يسمح النقل عبر الأنفاق للوسائط المتعددة، المعروف أيضًا باسم "وضع النقل عبر الأنفاق"، بنقل بيانات الفيديو المضغوطة عبر برنامج فك ترميز الفيديو في الجهاز مباشرةً إلى شاشة العرض، بدون أن تتم معالجتها بواسطة رمز التطبيق أو رمز إطار عمل Android. يحدّد الرمز البرمجي الخاص بالجهاز أسفل حزمة Android الإطارات التي سيتم إرسالها إلى شاشة العرض ووقت إرسالها من خلال مقارنة الطوابع الزمنية لعرض إطارات الفيديو بأحد الأنواع التالية من الساعات الداخلية:

  • لتشغيل الفيديو عند الطلب في Android 5 أو إصدار أحدث، يتم استخدام AudioTrack ساعة تتم مزامنتها مع الطوابع الزمنية لعرض الصوت التي يمرّرها التطبيق

  • لتشغيل البث المباشر في Android 11 أو إصدار أحدث، يتم استخدام ساعة مرجعية للبرنامج (PCR) أو ساعة وقت النظام (STC) يتم تشغيلها بواسطة جهاز استقبال .

خلفية

عند تشغيل الفيديو في وضع غير "النقل عبر الأنفاق" على Android، يتم إشعار التطبيق عند فك ترميز إطار فيديو مضغوط. بعد ذلك، يعرض التطبيق إطار الفيديو الذي تم فك ترميزه على شاشة العرض ليتم عرضه في الوقت نفسه على ساعة النظام الذي يتم فيه عرض إطار الصوت المقابل، ويستردّ التطبيق مثيلات AudioTimestamp السابقة لحساب التوقيت الصحيح.

بما أنّ تشغيل الفيديو المنقول عبر الأنفاق يتجاوز رمز التطبيق ويقلّل عدد العمليات التي يتم تنفيذها على الفيديو، يمكن أن يوفّر عرضًا أكثر فعالية للفيديو استنادًا إلى تنفيذ الشركة المصنّعة للمعدات الأصلية. ويمكن أن يوفّر أيضًا إيقاعًا ومزامنة أكثر دقة للفيديو مع الساعة التي تم اختيارها (ساعة مرجعية للبرنامج أو ساعة وقت النظام أو ساعة الصوت) من خلال تجنُّب مشاكل التوقيت الناتجة عن الانحراف المحتمَل بين توقيت طلبات Android لعرض الفيديو وتوقيت عمليات المزامنة العمودية الحقيقية في الجهاز. ومع ذلك، يمكن أن يؤدي النقل عبر الأنفاق أيضًا إلى تقليل إمكانية استخدام تأثيرات وحدة معالجة الرسومات، مثل التمويه أو الزوايا المستديرة في نوافذ "نافذة ضمن النافذة"، لأنّ المخازن المؤقتة تتجاوز حزمة الرسومات في Android.

يوضّح الرسم البياني التالي كيف يسهّل الاتصال النفَقي عملية تشغيل الفيديو.

مقارنة بين الوضعَين التقليدي والنفق

الشكل 1: مقارنة بين عمليتَي تشغيل الفيديو في وضعَي "غير النقل عبر الأنفاق" و"النقل عبر الأنفاق"

لمطوّري التطبيقات

بما أنّ معظم مطوّري التطبيقات يدمجون مكتبة لتنفيذ التشغيل، لا يتطلّب التنفيذ في معظم الحالات سوى إعادة ضبط هذه المكتبة لتشغيل الفيديو المنقول عبر الأنفاق. للتنفيذ على مستوى منخفض لمشغّل فيديو منقول عبر الأنفاق، اتّبِع التعليمات التالية.

لتشغيل الفيديو عند الطلب في Android 5 أو إصدار أحدث:

  1. أنشئ مثيلاً من SurfaceView.

  2. أنشئ مثيلاً من audioSessionId.

  3. أنشئ مثيلَين من AudioTrack وMediaCodec باستخدام مثيل audioSessionId الذي تم إنشاؤه في الخطوة 2.

  4. ضَع بيانات الصوت في قائمة الانتظار في AudioTrack باستخدام الطابع الزمني للعرض الخاص بإطار الصوت الأول في بيانات الصوت.

لتشغيل البث المباشر في Android 11 أو إصدار أحدث:

  1. أنشئ مثيلاً من SurfaceView.

  2. احصل على مثيل avSyncHwId من Tuner.

  3. أنشئ مثيلَين من AudioTrack وMediaCodec باستخدام مثيل avSyncHwId الذي تم إنشاؤه في الخطوة 2.

يظهر مسار طلب بيانات من واجهة برمجة التطبيقات في مقتطفات الرمز البرمجي التالية:

aab.setContentType(AudioAttributes.CONTENT_TYPE_MOVIE);

// configure for audio clock sync
aab.setFlag(AudioAttributes.FLAG_HW_AV_SYNC);
// or, for tuner clock sync (Android 11 or higher)
new tunerConfig = TunerConfiguration(0, avSyncId);
aab.setTunerConfiguration(tunerConfig);
if (codecName == null) {
  return FAILURE;
}

// configure for audio clock sync
mf.setInteger(MediaFormat.KEY_AUDIO_SESSION_ID, audioSessionId);
// or, for tuner clock sync (Android 11 or higher)
mf.setInteger(MediaFormat.KEY_HARDWARE_AV_SYNC_ID, avSyncId);

سلوك تشغيل الفيديو عند الطلب

بما أنّ تشغيل الفيديو عند الطلب المنقول عبر الأنفاق مرتبط ضمنيًا بتشغيل AudioTrack، قد يعتمد سلوك تشغيل الفيديو المنقول عبر الأنفاق على سلوك تشغيل الصوت.

  • على معظم الأجهزة، لا يتم تلقائيًا عرض إطار الفيديو إلى أن يبدأ تشغيل الصوت. ومع ذلك، قد يحتاج التطبيق إلى عرض إطار فيديو قبل بدء تشغيل الصوت، مثلاً لعرض موضع الفيديو الحالي للمستخدم أثناء البحث.

    • للإشارة إلى أنّه يجب عرض إطار الفيديو الأول الذي تم وضعه في قائمة الانتظار فور فك ترميزه، اضبط المَعلمة PARAMETER_KEY_TUNNEL_PEEK على 1. عند إعادة ترتيب إطارات الفيديو المضغوطة في قائمة الانتظار (مثلما يحدث عند توفر إطارات B )، يعني ذلك أنّ إطار الفيديو الأول الذي يتم عرضه يجب أن يكون دائمًا إطارًا I.

    • إذا لم تكن تريد عرض إطار الفيديو الأول الذي تم وضعه في قائمة الانتظار إلى أن يبدأ تشغيل الصوت، اضبط هذه المَعلمة على 0.

    • إذا لم يتم ضبط هذه المَعلمة، تحدّد الشركة المصنّعة للمعدات الأصلية السلوك الخاص بالجهاز.

  • عندما لا يتم توفير بيانات الصوت إلى AudioTrack وتكون المخازن المؤقتة فارغة (نقص في بيانات الصوت)، يتوقّف تشغيل الفيديو إلى أن تتم كتابة المزيد من بيانات الصوت لأنّ ساعة الصوت لم تعُد تتقدّم.

  • أثناء التشغيل، قد تظهر انقطاعات في الطوابع الزمنية لعرض الصوت لا يمكن للتطبيق تصحيحها. عند حدوث ذلك، تصحّح الشركة المصنّعة للمعدات الأصلية الفجوات السلبية من خلال إيقاف إطار الفيديو الحالي مؤقتًا، والفجوات الإيجابية من خلال إما حذف إطارات الفيديو أو إدراج إطارات صوت صامتة (استنادًا إلى تنفيذ الشركة المصنّعة للمعدات الأصلية). لا يزداد موضع إطار AudioTimestamp لإطارات الصوت الصامتة التي تم إدراجها.

مسار تسلسل البحث الدقيق

يتيح لك البحث الدقيق العثور على موضع معيّن في فيديو. على عكس البحث عن الإطارات الرئيسية، الذي ينتقل فقط إلى أقرب إطار I ويمكن أن ينحرف عن الموضع المستهدَف بعدة ثوانٍ، يعرض البحث الدقيق الفيديو في الطابع الزمني المطلوب تمامًا. يسمح الالتزام بتسلسل واجهة برمجة التطبيقات المحدّد هذا للتطبيق بتنفيذ عملية التحميل المسبق قبل عرض الإعلان ومزامنة التوقيت بسلاسة في الخلفية. ويضمن ذلك عرض الإطار المستهدَف على الفور عند استئناف التشغيل.

لإجراء بحث دقيق، اتّبِع ترتيب التنفيذ الموضّح في الشكل 2:

مسار تسلسل البحث

الشكل 2: مسار التسلسل لتحقيق البحث الدقيق

تشمل التفاصيل الرئيسية ما يلي:

  • التنفيذ المتوازي: يمكنك تنفيذ الخطوات ضمن مربّع par واحد في الوقت نفسه. على سبيل المثال، تكون طلبات الفيديو MediaCodec مستقلة عن AudioTrack.

  • التبعيات التسلسلية: استدعِ جميع العمليات ضمن مربّع par الأول قبل الانتقال إلى مربّع par الثاني. على وجه التحديد، يجب أن يضمن التطبيق وضع AudioTrack.write والمخازن المؤقتة في MediaCodec للفيديو في قائمة الانتظار قبل استدعاء AudioTrack.play.

مسار تسلسل تشغيل الفيديو بسرعة متغيّرة

يتيح لك تشغيل الفيديو بسرعة متغيّرة تشغيل الفيديو بمعدّل أسرع أو أبطأ من السرعة العادية. تستخدم التطبيقات هذه الميزة عادةً للسماح للمستخدمين باستهلاك المحتوى بشكل أسرع (مثل تشغيل المحاضرات التعليمية أو البودكاست بسرعة 1.5x أو 2.0x لتوفير الوقت) أو أبطأ (مثل تحليل الألعاب الرياضية أو الفيديوهات التعليمية بسرعة 0.5x).

لضبط السرعة، اتّبِع ترتيب التنفيذ الموضّح في الشكل 3:

تسلسل السرعة

الشكل 3: مسار التسلسل لضبط السرعة

لا يتم تسجيل السلوكيات والمتطلبات الفنية التالية في مخطط تسلسل الشكل 3:

  • AudioTrack.getTimestamp تعرض قيمة framePosition استنادًا إلى معدّل إدخال الصوت الأصلي. على سبيل المثال، عند إدخال بيانات بمعدّل 44100 هرتز وسرعة تشغيل 2.0x، بعد تشغيل الصوت لمدة ثانيتَين، تعرض الدالة AudioTrack.getTimestamp قيمة framePosition تبلغ 176400.

  • إذا استدعى التطبيق الدالة setSpeed(1.5) ونجحت، ثم استدعى التطبيق الدالة setSpeed(30) وفشلت، يظل التشغيل بسرعة 1.5x.

  • إذا تم كتم الصوت (باستخدام setVolume)، لا يزال مطلوبًا من التطبيق إرسال مخازن مؤقتة للصوت لأنّه يتم عرض إطارات الفيديو استنادًا إلى موضع الصوت.

  • يتم الحفاظ على درجة الصوت عند تغيير السرعة.

  • لا تتأثر سرعة التشغيل بإجراءات التشغيل الأخرى.

    • المثال 1: إذا كانت سرعة التشغيل 1.5x وتم إيقاف AudioTrack مؤقتًا، تظل السرعة 1.5x بعد استئناف AudioTrack.

    • المثال 2: إذا كانت سرعة التشغيل 1.5x وانتقل المستخدم إلى طابع زمني مختلف للعرض، يظل التشغيل بسرعة 1.5x باتّباع الشكل 2.

  • للمساعدة في ضمان فك ترميز جميع الإطارات في الوقت المناسب لعرضها بالسرعة التي تم اختيارها، اضبط KEY_OPERATING_RATE على أن تتطابق مع ناتج عدد اللقطات في الثانية للفيديو وسرعة التشغيل. إذا لم يتم ضبط KEY_OPERATING_RATE على قيمة عالية بما يكفي، قد لا يتمكّن برنامج الترميز من فك ترميز الإطارات بسرعة كافية، ما يؤدي إلى حذف إطارات غير مقصود أثناء التشغيل.

    • مثال: إذا كان عدد اللقطات في الثانية الأصلي للمحتوى 60، وكانت سرعة التشغيل 2x، اضبط KEY_OPERATING_RATE على 120.
  • لا يجب أن يؤدي ضبط السرعة بشكل متكرّر باستخدام سرعات مختلفة متوافقة إلى ظهور أي أخطاء، ويجب أن يكون سلوك التشغيل بعد آخر استدعاء هو نفسه كما لو تم ضبط السرعة مرة واحدة فقط، على أحدث إعداد للسرعة.

لمصنّعي الأجهزة

الإعداد

على الشركات المصنّعة للمعدات الأصلية إنشاء برنامج فك ترميز فيديو منفصل لدعم تشغيل الفيديو المنقول عبر الأنفاق. يجب أن يعلن برنامج فك الترميز هذا عن قدرته على تشغيل الفيديو المنقول عبر الأنفاق في ملف media_codecs.xml:

<Feature name="tunneled-playback" required="true"/>

عند ضبط مثيل MediaCodec منقول عبر الأنفاق باستخدام رقم تعريف جلسة صوتية، يستعلم عن AudioFlinger عن رقم تعريف HW_AV_SYNC هذا:

if (entry.getKey().equals(MediaFormat.KEY_AUDIO_SESSION_ID)) {
    int sessionId = 0;
    try {
        sessionId = (Integer)entry.getValue();
    }
    catch (Exception e) {
        throw new IllegalArgumentException("Wrong Session ID Parameter!");
    }
    keys[i] = "audio-hw-sync";
    values[i] = AudioSystem.getAudioHwSyncForSession(sessionId);
}

أثناء هذا الاستعلام، AudioFlinger يستردّ رقم تعريف HW_AV_SYNC من جهاز الصوت الأساسي ويربطه داخليًا برقم تعريف الجلسة الصوتية:

audio_hw_device_t *dev = mPrimaryHardwareDev->hwDevice();
char *reply = dev->get_parameters(dev, AUDIO_PARAMETER_HW_AV_SYNC);
AudioParameter param = AudioParameter(String8(reply));
int hwAVSyncId;
param.getInt(String8(AUDIO_PARAMETER_HW_AV_SYNC), hwAVSyncId);

إذا سبق أن تم إنشاء مثيل AudioTrack، يتم تمرير رقم تعريف HW_AV_SYNC إلى مجموعة البث الناتجة باستخدام رقم تعريف الجلسة الصوتية نفسه. إذا لم يتم إنشاء مثيل AudioTrack بعد، يتم تمرير رقم تعريف HW_AV_SYNC إلى مجموعة البث الناتجة أثناء إنشاء AudioTrack. يتم ذلك بواسطة سلسلة محادثات التشغيل:

mOutput->stream->common.set_parameters(&mOutput->stream->common, AUDIO_PARAMETER_STREAM_HW_AV_SYNC, hwAVSyncId);

يتم تمرير رقم تعريف HW_AV_SYNC، سواء كان يتوافق مع مصدر إخراج الصوت أو إعداد Tuner، إلى المكوِّن OMX أو Codec2 حتى يتمكّن رمز المصنّع الأصلي للجهاز من ربط برنامج ترميز بمصدر إخراج الصوت أو مجموعة بث جهاز الاستقبال.

أثناء ضبط المكوّن، يجب أن يعرض مكوّن OMX أو Codec2 مقبضًا للنطاق الجانبي يمكن استخدامه لربط برنامج الترميز بطبقة Hardware Composer (HWC). عندما يربط التطبيق سطحًا بـ MediaCodec، يتم تمرير مقبض النطاق الجانبي هذا إلى HWC من خلال SurfaceFlinger، الذي يضبط الطبقة كطبقة نطاق جانبي.

err = native_window_set_sideband_stream(nativeWindow.get(), sidebandHandle);
if (err != OK) {
  ALOGE("native_window_set_sideband_stream(%p) failed! (err %d).", sidebandHandle, err);
  return err;
}

يكون HWC مسؤولاً عن تلقّي المخازن المؤقتة الجديدة للصور من ناتج برنامج الترميز في الوقت المناسب، إما تتم مزامنتها مع مصدر إخراج الصوت المرتبط أو الساعة المرجعية لبرنامج جهاز الاستقبال، ودمج المخازن المؤقتة مع المحتويات الحالية للطبقات الأخرى، وعرض الصورة الناتجة. يحدث ذلك بشكل مستقل عن دورة الإعداد والضبط العادية. لا تحدث طلبات الإعداد والضبط إلا عند تغيير الطبقات الأخرى أو عند تغيير خصائص طبقة النطاق الجانبي (مثل الموضع أو الحجم).

OMX

يجب أن يتيح مكوّن برنامج فك ترميز منقول عبر الأنفاق ما يلي:

  • ضبط المَعلمة الموسّعة OMX.google.android.index.configureVideoTunnelMode، التي تستخدم بنية ConfigureVideoTunnelModeParams لتمرير رقم تعريف HW_AV_SYNC المرتبط بمصدر إخراج الصوت.

  • ضبط المَعلمة OMX_IndexConfigAndroidTunnelPeek التي تُعلم برنامج الترميز بعرض إطار الفيديو الأول الذي تم فك ترميزه أو عدم عرضه، بغض النظر عمّا إذا بدأ تشغيل الصوت.

  • إرسال الحدث OMX_EventOnFirstTunnelFrameReady عندما يتم فك ترميز إطار الفيديو الأول المنقول عبر الأنفاق ويكون جاهزًا للعرض.

يضبط تنفيذ AOSP وضع النقل عبر الأنفاق في ACodec من خلال OMXNodeInstance كما هو موضّح في مقتطف الرمز البرمجي التالي:

OMX_INDEXTYPE index;
OMX_STRING name = const_cast<OMX_STRING>(
        "OMX.google.android.index.configureVideoTunnelMode");

OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);

ConfigureVideoTunnelModeParams tunnelParams;
InitOMXParams(&tunnelParams);
tunnelParams.nPortIndex = portIndex;
tunnelParams.bTunneled = tunneled;
tunnelParams.nAudioHwSync = audioHwSync;
err = OMX_SetParameter(mHandle, index, &tunnelParams);
err = OMX_GetParameter(mHandle, index, &tunnelParams);
sidebandHandle = (native_handle_t*)tunnelParams.pSidebandWindow;

إذا كان المكوّن يتيح هذا الإعداد، يجب أن يخصّص مقبض نطاق جانبي لبرنامج الترميز هذا ويمرّره مرة أخرى من خلال العضو pSidebandWindow حتى يتمكّن HWC من تحديد برنامج الترميز المرتبط. إذا كان المكوّن لا يتيح هذا الإعداد، يجب ضبط bTunneled على OMX_FALSE.

Codec2

في Android 11 أو إصدار أحدث، يتيح Codec2 تشغيل الفيديو المنقول عبر الأنفاق. يجب أن يتيح مكوّن برنامج فك الترميز ما يلي:

  • ضبط C2PortTunneledModeTuning، الذي يضبط وضع النفق ويمرّر رقم تعريف HW_AV_SYNC الذي تم استرداده من مصدر إخراج الصوت أو إعداد جهاز الاستقبال.

  • الاستعلام عن C2_PARAMKEY_OUTPUT_TUNNEL_HANDLE لتخصيص مؤشر النطاق الجانبي لـ HWC واسترداده.

  • التعامل مع C2_PARAMKEY_TUNNEL_HOLD_RENDER عند إرفاقه بـ C2Work، الذي يطلب من برنامج الترميز فك ترميز العمل والإشارة إلى اكتماله، ولكن عدم عرض المخزن المؤقت الناتج إلى أن يتم إما 1) توجيه برنامج الترميز لاحقًا لعرضه أو 2) بدء تشغيل الصوت.

  • التعامل مع C2_PARAMKEY_TUNNEL_START_RENDER، الذي يطلب من برنامج الترميز عرض الإطار الذي تم وضع علامة C2_PARAMKEY_TUNNEL_HOLD_RENDER عليه على الفور، حتى إذا لم يبدأ تشغيل الصوت.

  • اترك debug.stagefright.ccodec_delayed_params غير مضبوط (إجراء ننصح به). إذا ضبطته، اضبطه على false.

يضبط تنفيذ AOSP وضع النقل عبر الأنفاق في CCodec من خلال C2PortTunnelModeTuning، كما هو موضّح في مقتطف الرمز البرمجي التالي:

if (msg->findInt32("audio-hw-sync", &tunneledPlayback->m.syncId[0])) {
    tunneledPlayback->m.syncType =
            C2PortTunneledModeTuning::Struct::sync_type_t::AUDIO_HW_SYNC;
} else if (msg->findInt32("hw-av-sync-id", &tunneledPlayback->m.syncId[0])) {
    tunneledPlayback->m.syncType =
            C2PortTunneledModeTuning::Struct::sync_type_t::HW_AV_SYNC;
} else {
    tunneledPlayback->m.syncType =
            C2PortTunneledModeTuning::Struct::sync_type_t::REALTIME;
    tunneledPlayback->setFlexCount(0);
}
c2_status_t c2err = comp->config({ tunneledPlayback.get() }, C2_MAY_BLOCK,
        failures);
std::vector<std::unique_ptr<C2Param>> params;
c2err = comp->query({}, {C2PortTunnelHandleTuning::output::PARAM_TYPE},
        C2_DONT_BLOCK, &params);
if (c2err == C2_OK && params.size() == 1u) {
    C2PortTunnelHandleTuning::output *videoTunnelSideband =
            C2PortTunnelHandleTuning::output::From(params[0].get());
    return OK;
}

إذا كان المكوّن يتيح هذا الإعداد، يجب أن يخصّص مقبض نطاق جانبي لبرنامج الترميز هذا ويمرّره مرة أخرى من خلال C2PortTunnelHandlingTuning حتى يتمكّن HWC من تحديد برنامج الترميز المرتبط.

Audio HAL

لتشغيل الفيديو عند الطلب، يتلقّى Audio HAL الطوابع الزمنية لعرض الصوت مضمّنة مع بيانات الصوت بتنسيق big-endian داخل رأس في بداية كل كتلة من بيانات الصوت التي يكتبها التطبيق:

struct TunnelModeSyncHeader {
  // The 32-bit data to identify the sync header (0x55550002)
  int32 syncWord;
  // The size of the audio data following the sync header before the next sync
  // header might be found.
  int32 sizeInBytes;
  // The presentation timestamp of the first audio sample following the sync
  // header.
  int64 presentationTimestamp;
  // The number of bytes to skip after the beginning of the sync header to find the
  // first audio sample (20 bytes for compressed audio, or larger for PCM, aligned
  // to the channel count and sample size).
  int32 offset;
}

لكي يعرض HWC إطارات الفيديو بالتزامن مع إطارات الصوت المقابلة، يجب أن يحلّل Audio HAL رأس المزامنة ويستخدم الطابع الزمني للعرض لإعادة مزامنة ساعة التشغيل مع عرض الصوت. لإعادة المزامنة عند تشغيل الصوت المضغوط، قد يحتاج Audio HAL إلى تحليل البيانات الوصفية داخل بيانات الصوت المضغوطة لتحديد مدة تشغيلها.

إتاحة الإيقاف المؤقت

لا يتضمّن Android 5 أو إصدار أقدم إمكانية الإيقاف المؤقت. لا يمكنك إيقاف التشغيل المنقول عبر الأنفاق مؤقتًا إلا من خلال نقص بيانات الصوت والفيديو، ولكن إذا كان المخزن المؤقت الداخلي للفيديو كبيرًا (مثلاً، إذا كان هناك ثانية واحدة من البيانات في مكوّن OMX)، يبدو الإيقاف المؤقت غير مستجيب.

في Android 5.1 أو إصدار أحدث، يتيح AudioFlinger الإيقاف المؤقت والاستئناف لمجموعات بث الصوت المباشرة (المنقولة عبر الأنفاق). إذا نفّذت طبقة HAL الإيقاف المؤقت والاستئناف، يتم إعادة توجيه الإيقاف المؤقت والاستئناف للمقطع الصوتي إلى طبقة HAL.

يتم الالتزام بتسلسل استدعاء الإيقاف المؤقت والإفراغ والاستئناف من خلال تنفيذ طلبات HAL في سلسلة محادثات التشغيل (مثلما يحدث في عملية نقل المعالجة).

اقتراحات التنفيذ

Audio HAL

بالنسبة إلى Android 11، يمكن استخدام رقم تعريف مزامنة الجهاز من ساعة مرجعية للبرنامج أو ساعة وقت النظام لمزامنة الصوت والفيديو، لذا يتم إتاحة مجموعة بث الفيديو فقط.

بالنسبة إلى Android 10 أو إصدار أقدم، يجب أن تتضمّن الأجهزة التي تتيح تشغيل الفيديو المنقول عبر الأنفاق ملفًا واحدًا على الأقل لإعداد مجموعة بث ناتجة لمصدر إخراج الصوت مع علامتَي FLAG_HW_AV_SYNC وAUDIO_OUTPUT_FLAG_DIRECT في ملف audio_policy.conf. تُستخدم هاتان العلامتان لضبط ساعة النظام من ساعة الصوت.

OMX

على مصنّعي الأجهزة توفير مكوّن OMX منفصل لتشغيل الفيديو المنقول عبر الأنفاق (يمكن أن يكون لدى المصنّعين مكوّنات OMX إضافية لأنواع أخرى من تشغيل الصوت والفيديو، مثل التشغيل الآمن). يجب أن يتيح المكوّن المنقول عبر الأنفاق ما يلي:

  • تحديد 0 مخزن مؤقت (nBufferCountMin وnBufferCountActual) في منفذ الإخراج.

  • تنفيذ الإضافة OMX.google.android.index.prepareForAdaptivePlayback setParameter.

  • تحديد إمكاناته في ملف media_codecs.xml والإعلان عن ميزة التشغيل المنقول عبر الأنفاق. يجب أيضًا توضيح أي قيود على حجم الإطار أو المحاذاة أو معدّل نقل البيانات. في ما يلي مثال:

    <MediaCodec name="OMX.OEM_NAME.VIDEO.DECODER.AVC.tunneled"
    type="video/avc" >
        <Feature name="adaptive-playback" />
        <Feature name="tunneled-playback" required=true />
        <Limit name="size" min="32x32" max="3840x2160" />
        <Limit name="alignment" value="2x2" />
        <Limit name="bitrate" range="1-20000000" />
            ...
    </MediaCodec>
    

إذا تم استخدام مكوّن OMX نفسه لدعم فك الترميز المنقول عبر الأنفاق وغير المنقول عبر الأنفاق، يجب أن يترك ميزة التشغيل المنقول عبر الأنفاق غير مطلوبة. بعد ذلك، يكون لكل من برامج فك الترميز المنقولة عبر الأنفاق وغير المنقولة عبر الأنفاق القيود نفسها على الإمكانات. في ما يلي مثال:

<MediaCodec name="OMX._OEM\_NAME_.VIDEO.DECODER.AVC" type="video/avc" >
    <Feature name="adaptive-playback" />
    <Feature name="tunneled-playback" />
    <Limit name="size" min="32x32" max="3840x2160" />
    <Limit name="alignment" value="2x2" />
    <Limit name="bitrate" range="1-20000000" />
        ...
</MediaCodec>

Hardware Composer (HWC)

عندما تكون هناك طبقة منقولة عبر الأنفاق (طبقة لها compositionType بقيمة HWC_SIDEBAND) على شاشة عرض، يكون sidebandStream للطبقة هو مقبض النطاق الجانبي الذي خصّصه مكوّن OMX للفيديو.

يزامن HWC إطارات الفيديو التي تم فك ترميزها (من مكوّن OMX المنقول عبر الأنفاق) مع المقطع الصوتي المرتبط (باستخدام رقم تعريف audio-hw-sync). عندما يصبح إطار فيديو جديد هو الإطار الحالي، يدمجه HWC مع المحتويات الحالية لجميع الطبقات التي تم تلقّيها أثناء آخر طلب إعداد أو ضبط، ويعرض الصورة الناتجة. لا تحدث طلبات الإعداد أو الضبط إلا عند تغيير الطبقات الأخرى أو عند تغيير خصائص طبقة النطاق الجانبي (مثل الموضع أو الحجم).

يمثّل الشكل التالي HWC الذي يعمل مع برنامج المزامنة في الجهاز (أو النواة أو برنامج التشغيل) لدمج إطارات الفيديو (7b) مع أحدث عملية دمج (7a) لعرضها في الوقت الصحيح، استنادًا إلى الصوت (7c).

دمج إطارات الفيديو المستند إلى الصوت باستخدام HWC

الشكل 4: برنامج مزامنة HWC في الجهاز (أو النواة أو برنامج التشغيل)