تونل زنی چند رسانه ای

تونل‌سازی چندرسانه‌ای، که با نام حالت تونل نیز شناخته می‌شود، داده‌های ویدئویی فشرده‌شده را قادر می‌سازد تا از طریق یک رمزگشای ویدئویی سخت‌افزاری، مستقیماً به یک نمایشگر تونل بزنند، بدون اینکه توسط کد برنامه یا کد چارچوب اندروید پردازش شوند. کد مخصوص دستگاه در زیر پشته اندروید، با مقایسه مهرهای زمانی ارائه فریم ویدئو با یکی از انواع ساعت داخلی زیر، تعیین می‌کند که کدام فریم‌های ویدئویی به نمایشگر ارسال شوند و چه زمانی آنها را ارسال کنند:

  • برای پخش ویدیوی درخواستی در اندروید ۵ یا بالاتر، یک ساعت AudioTrack با مهرهای زمانی ارائه صوتی که توسط برنامه ارسال می‌شود، همگام‌سازی شده است.

  • برای پخش زنده در اندروید ۱۱ یا بالاتر، یک ساعت مرجع برنامه (PCR) یا ساعت زمان سیستم (STC) که توسط یک تیونر هدایت می‌شود

پیشینه

پخش ویدیوی حالت غیر تونلی در اندروید، هنگامی که یک فریم ویدیوی فشرده رمزگشایی شد، به برنامه اطلاع می‌دهد . سپس برنامه، فریم ویدیوی رمزگشایی شده را برای نمایش در همان زمان ساعت سیستم به عنوان فریم صوتی مربوطه منتشر می‌کند و نمونه‌های AudioTimestamp تاریخی را برای محاسبه زمان‌بندی صحیح بازیابی می‌کند .

از آنجا که پخش ویدیوی تونلی، کد برنامه را دور می‌زند و تعداد فرآیندهای فعال روی ویدیو را کاهش می‌دهد، می‌تواند رندر ویدیوی کارآمدتری را بسته به پیاده‌سازی OEM ارائه دهد. همچنین می‌تواند با اجتناب از مشکلات زمان‌بندی ناشی از انحراف احتمالی بین زمان‌بندی درخواست‌های اندروید برای رندر ویدیو و زمان‌بندی vsyncهای سخت‌افزاری واقعی، ریتم ویدیو و همگام‌سازی دقیق‌تری را با ساعت انتخاب‌شده (PRC، STC یا صدا) ارائه دهد. با این حال، تونلی همچنین می‌تواند پشتیبانی از جلوه‌های GPU مانند تار شدن یا گوشه‌های گرد در پنجره‌های تصویر در تصویر (PiP) را کاهش دهد، زیرا بافرها از پشته گرافیکی اندروید عبور می‌کنند.

نمودار زیر نشان می‌دهد که چگونه تونلینگ فرآیند پخش ویدئو را ساده می‌کند.

مقایسه حالت‌های سنتی و تونلی

شکل ۱. مقایسه فرآیندهای پخش ویدیوی تونلی و غیر تونلی.

برای توسعه‌دهندگان اپلیکیشن

از آنجا که اکثر توسعه‌دهندگان برنامه برای پیاده‌سازی پخش، از یک کتابخانه استفاده می‌کنند، در بیشتر موارد، پیاده‌سازی فقط نیاز به پیکربندی مجدد آن کتابخانه برای پخش تونلی دارد. برای پیاده‌سازی سطح پایین یک پخش‌کننده ویدیوی تونلی، از دستورالعمل‌های زیر استفاده کنید.

برای پخش ویدیوی درخواستی در اندروید ۵ یا بالاتر:

  1. یک نمونه SurfaceView ایجاد کنید.

  2. یک نمونه audioSessionId ایجاد کنید.

  3. نمونه‌های AudioTrack و MediaCodec را با نمونه audioSessionId ایجاد شده در مرحله 2 ایجاد کنید.

  4. داده‌های صوتی را با استفاده از مهر زمانی ارائه برای اولین فریم صوتی در داده‌های صوتی، در AudioTrack قرار دهید.

برای پخش زنده در اندروید ۱۱ یا بالاتر:

  1. یک نمونه SurfaceView ایجاد کنید.

  2. یک نمونه avSyncHwId از Tuner دریافت کنید.

  3. نمونه‌های AudioTrack و MediaCodec را با نمونه avSyncHwId ایجاد شده در مرحله 2 ایجاد کنید.

جریان فراخوانی API در قطعه کد زیر نشان داده شده است:

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 تنظیم کنید.

    • اگر این پارامتر تنظیم نشده باشد، سازنده اصلی (OEM) رفتار دستگاه را تعیین می‌کند.

  • وقتی داده‌های صوتی به AudioTrack ارائه نشود و بافرها خالی باشند (صدا با تأخیر اجرا شود)، پخش ویدیو تا زمانی که داده‌های صوتی بیشتری نوشته شود، متوقف می‌شود زیرا ساعت صوتی دیگر پیشرفت نمی‌کند.

  • در حین پخش، ممکن است ناپیوستگی‌هایی که برنامه نمی‌تواند آنها را اصلاح کند، در مهرهای زمانی ارائه صوتی ظاهر شوند. وقتی این اتفاق می‌افتد، OEM شکاف‌های منفی را با متوقف کردن فریم ویدیوی فعلی و شکاف‌های مثبت را با حذف فریم‌های ویدیویی یا وارد کردن فریم‌های صوتی بی‌صدا (بسته به پیاده‌سازی OEM) اصلاح می‌کند. موقعیت فریم AudioTimestamp برای فریم‌های صوتی بی‌صدای وارد شده افزایش نمی‌یابد.

جریان توالی جستجوی دقیق

جستجوی دقیق به شما امکان می‌دهد یک نقطه خاص در یک ویدیو را پیدا کنید. برخلاف جستجوی فریم کلیدی که فقط به نزدیکترین فریم I پرش می‌کند و می‌تواند چند ثانیه از موقعیت هدف منحرف شود، جستجوی دقیق، ویدیو را دقیقاً در زمان درخواست شده رندر می‌کند. رعایت این توالی API خاص به برنامه اجازه می‌دهد تا پیش‌نمایش پس‌زمینه و همگام‌سازی زمان‌بندی را به طور یکپارچه انجام دهد. این امر تضمین می‌کند که فریم هدف بلافاصله پس از از سرگیری پخش نمایش داده شود.

برای انجام یک جستجوی دقیق، ترتیب اجرای نشان داده شده در شکل 2 را دنبال کنید:

جستجوی جریان توالی

شکل ۲. جریان توالی برای دستیابی به جستجوی دقیق.

جزئیات کلیدی شامل موارد زیر است:

  • اجرای موازی: شما می‌توانید مراحل درون یک جعبه par را به طور همزمان اجرا کنید. برای مثال، فراخوانی‌های ویدیویی MediaCodec مستقل از AudioTrack هستند.

  • وابستگی‌های ترتیبی: قبل از پیشروی به سمت جعبه par دوم، تمام عملیات درون جعبه par اول را فراخوانی کنید. به طور خاص، برنامه باید اطمینان حاصل کند که AudioTrack.write و بافرها در MediaCodec ویدیو قبل از فراخوانی AudioTrack.play در صف قرار گرفته‌اند.

جریان متوالی پخش با سرعت متغیر

پخش با سرعت متغیر به شما امکان می‌دهد ویدیو را با سرعتی سریع‌تر یا کندتر از سرعت عادی پخش کنید. این ویژگی معمولاً توسط برنامه‌ها استفاده می‌شود تا به کاربران امکان دهد محتوا را سریع‌تر (مانند پخش سخنرانی‌های آموزشی یا پادکست‌ها با سرعت ۱.۵ برابر یا ۲ برابر برای صرفه‌جویی در زمان) یا کندتر (مانند تجزیه و تحلیل بازی‌های ورزشی یا ویدیوهای آموزشی با سرعت ۰.۵ برابر) مشاهده کنند.

برای تنظیم سرعت، ترتیب اجرای نشان داده شده در شکل 3 را دنبال کنید:

جریان توالی سرعت

شکل ۳. جریان توالی برای تنظیم سرعت.

رفتارها و الزامات فنی زیر در نمودار توالی شکل 3 نشان داده نشده‌اند:

  • AudioTrack.getTimestamp framePosition بر اساس فرکانس ورودی صدای اصلی برمی‌گرداند. برای مثال، با ورودی ۴۴۱۰۰ هرتز و سرعت پخش ۲.۰x، پس از ۲ ثانیه پخش، AudioTrack.getTimestamp framePosition را ۱۷۶۴۰۰ برمی‌گرداند.

  • اگر برنامه تابع setSpeed(1.5) فراخوانی کند و موفق شود، و سپس تابع setSpeed(30) را فراخوانی کند و ناموفق باشد، پخش با سرعت ۱.۵x باقی می‌ماند.

  • اگر صدا قطع شده باشد (با استفاده از setVolume )، برنامه همچنان ملزم به ارسال بافرهای صوتی است زیرا فریم‌های ویدیویی بر اساس موقعیت صدا رندر می‌شوند.

  • زیر و بمی صدا هنگام تغییر سرعت حفظ می‌شود.

  • سرعت پخش تحت تأثیر سایر اقدامات پخش قرار نمی‌گیرد.

    • مثال ۱: اگر سرعت پخش ۱.۵ برابر باشد و AudioTrack متوقف شود، پس از از سرگیری AudioTrack ، سرعت روی ۱.۵ برابر باقی می‌ماند.

    • مثال ۲: اگر سرعت پخش ۱.۵ برابر باشد و کاربر به دنبال PTS متفاوتی باشد، طبق شکل ۲، پخش در ۱.۵ برابر باقی می‌ماند.

  • برای اطمینان از اینکه همه فریم‌ها به موقع رمزگشایی می‌شوند تا با سرعت انتخاب شده رندر شوند، KEY_OPERATING_RATE را طوری تنظیم کنید که با حاصلضرب نرخ فریم ویدیو و سرعت پخش مطابقت داشته باشد. اگر KEY_OPERATING_RATE به اندازه کافی بالا تنظیم نشود، ممکن است کدک فریم‌ها را به اندازه کافی سریع رمزگشایی نکند و باعث افت فریم ناخواسته در حین پخش شود.

    • مثال: اگر نرخ فریم اصلی محتوا ۶۰ فریم بر ثانیه و سرعت پخش ۲ برابر باشد، KEY_OPERATING_RATE را روی 120 تنظیم کنید.
  • تنظیم مکرر سرعت با سرعت‌های پشتیبانی‌شده‌ی مختلف نباید هیچ خطایی ایجاد کند، و رفتار پخش پس از آخرین فراخوانی باید مانند زمانی باشد که سرعت فقط یک بار تنظیم شده باشد، یعنی روی آخرین تنظیم سرعت.

برای تولیدکنندگان دستگاه

پیکربندی

تولیدکنندگان تجهیزات اصلی (OEM) باید یک رمزگشای ویدیوی جداگانه برای پشتیبانی از پخش ویدیوی تونلی ایجاد کنند. این رمزگشا باید در فایل 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 با همان شناسه جلسه صوتی به جریان خروجی منتقل می‌شود. اگر هنوز ایجاد نشده باشد، شناسه 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 ارسال می‌شود تا کد OEM بتواند کدک را با جریان خروجی صدای مربوطه یا جریان تیونر مرتبط کند.

در طول پیکربندی کامپوننت، کامپوننت OMX یا Codec2 باید یک دسته باند جانبی را برگرداند که می‌تواند برای مرتبط کردن کدک با یک لایه Hardware Composer (HWC) استفاده شود. هنگامی که برنامه یک سطح را با MediaCodec مرتبط می‌کند، این دسته باند جانبی از طریق SurfaceFlinger به HWC منتقل می‌شود که لایه را به عنوان یک لایه باند جانبی پیکربندی می‌کند.

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.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 از پخش تونلی پشتیبانی می‌کند. کامپوننت رمزگشا باید از موارد زیر پشتیبانی کند:

  • پیکربندی C2PortTunneledModeTuning ، که حالت تونل را پیکربندی می‌کند و HW_AV_SYNC بازیابی شده از دستگاه خروجی صدا یا پیکربندی تیونر را ارسال می‌کند.

  • پرس و جو از C2_PARAMKEY_OUTPUT_TUNNEL_HANDLE ، برای تخصیص و بازیابی دسته باند جانبی برای HWC.

  • مدیریت C2_PARAMKEY_TUNNEL_HOLD_RENDER هنگام اتصال به C2Work ، که به کدک دستور می‌دهد رمزگشایی کند و اتمام کار را اعلام کند، اما بافر خروجی را رندر نکند تا زمانی که ۱) کدک بعداً دستور رندر آن را دریافت کند یا ۲) پخش صدا شروع شود.

  • مدیریت 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 بتواند کدک مرتبط را شناسایی کند.

صوتی 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 ممکن است نیاز به تجزیه فراداده درون داده‌های صوتی فشرده داشته باشد تا مدت زمان پخش آن را تعیین کند.

پشتیبانی را متوقف کنید

اندروید ۵ یا پایین‌تر شامل پشتیبانی از مکث (pause) نمی‌شود. شما می‌توانید پخش تونلی را فقط با قطع شدن صدا/تصویر (A/V starvation) متوقف کنید، اما اگر بافر داخلی ویدیو بزرگ باشد (برای مثال، یک ثانیه داده در کامپوننت OMX وجود داشته باشد)، مکث (pause) غیرفعال به نظر می‌رسد.

در اندروید ۵.۱ یا بالاتر، AudioFlinger از قابلیت مکث و از سرگیری برای خروجی‌های صوتی مستقیم (تونلی) پشتیبانی می‌کند. اگر HAL قابلیت مکث و از سرگیری را پیاده‌سازی کند، مکث و از سرگیری آهنگ به HAL ارسال می‌شود.

توالی فراخوانی مکث، شستشو، از سرگیری با اجرای فراخوانی‌های HAL در نخ پخش (همانند بارگذاری) رعایت می‌شود.

پیشنهادات اجرایی

صوتی HAL

برای اندروید ۱۱، شناسه همگام‌سازی HW از PCR یا STC می‌تواند برای همگام‌سازی A/V استفاده شود، بنابراین پخش فقط ویدیو پشتیبانی می‌شود.

برای اندروید ۱۰ یا پایین‌تر، دستگاه‌هایی که از پخش ویدیوی تونلی پشتیبانی می‌کنند، باید حداقل یک پروفایل جریان خروجی صدا با پرچم‌های FLAG_HW_AV_SYNC و AUDIO_OUTPUT_FLAG_DIRECT در فایل audio_policy.conf خود داشته باشند. این پرچم‌ها برای تنظیم ساعت سیستم از روی ساعت صوتی استفاده می‌شوند.

او ام ایکس

تولیدکنندگان دستگاه باید یک جزء OMX جداگانه برای پخش ویدیوی تونلی داشته باشند (سازندگان می‌توانند اجزای OMX اضافی برای انواع دیگر پخش صدا و تصویر، مانند پخش امن، داشته باشند). جزء تونلی باید:

  • تعداد بافرهای ( 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>

آهنگساز سخت‌افزار (HWC)

وقتی یک لایه تونلی (لایه‌ای با compositionType HWC_SIDEBAND ) روی صفحه نمایش وجود دارد، sidebandStream لایه، دسته sideband اختصاص داده شده توسط کامپوننت ویدیوی OMX است.

HWC فریم‌های ویدیویی رمزگشایی‌شده (از مؤلفه‌ی تونل‌شده‌ی OMX) را با تراک صوتی مرتبط (با شناسه‌ی audio-hw-sync ) همگام‌سازی می‌کند. هنگامی که یک فریم ویدیویی جدید جاری می‌شود، HWC آن را با محتوای فعلی تمام لایه‌های دریافت‌شده در طول آخرین فراخوانی آماده‌سازی یا تنظیم، ترکیب می‌کند و تصویر حاصل را نمایش می‌دهد. فراخوانی‌های آماده‌سازی یا تنظیم فقط زمانی اتفاق می‌افتند که لایه‌های دیگر تغییر کنند، یا زمانی که ویژگی‌های لایه‌ی باند جانبی (مانند موقعیت یا اندازه) تغییر کنند.

شکل زیر HWC را در حال کار با هماهنگ‌کننده سخت‌افزار (یا هسته یا درایور) نشان می‌دهد تا فریم‌های ویدیویی (7b) را با آخرین ترکیب (7a) برای نمایش در زمان صحیح، بر اساس صدا (7c) ترکیب کند.

HWC فریم‌های ویدیویی را بر اساس صدا ترکیب می‌کند

شکل ۴. هماهنگ‌کننده سخت‌افزار HWC (یا هسته یا درایور).