मल्टीमीडिया टनलिंग

मल्टीमीडिया टनलिंग की मदद से, कंप्रेस किए गए वीडियो डेटा को सीधे तौर पर हार्डवेयर वीडियो डिकोडर से डिस्प्ले तक टनल किया जा सकता है. इसके लिए, ऐप्लिकेशन कोड या Android फ़्रेमवर्क कोड से प्रोसेस करने की ज़रूरत नहीं होती. Android स्टैक के नीचे मौजूद डिवाइस के हिसाब से कोड यह तय करता है कि डिसप्ले को कौनसे वीडियो फ़्रेम भेजने हैं और उन्हें कब भेजना है. इसके लिए, वह वीडियो फ़्रेम प्रज़ेंटेशन के टाइमस्टैंप की तुलना, यहां दी गई किसी एक तरह की इंटरनल क्लॉक से करता है:

  • Android 5 या इसके बाद के वर्शन में, मांग पर वीडियो चलाने के लिए, AudioTrack घड़ी का ऑडियो प्रज़ेंटेशन के टाइमस्टैंप के साथ सिंक होना ज़रूरी है. इसे ऐप्लिकेशन में पास किया गया है

  • Android 11 या इसके बाद के वर्शन में लाइव ब्रॉडकास्ट चलाने के लिए, प्रोग्राम रेफ़रंस क्लॉक (पीसीआर) या सिस्टम टाइम क्लॉक (एसटीसी) की ज़रूरत होती है. ये क्लॉक, ट्यूनर से चलती हैं

बैकग्राउंड

Android पर वीडियो चलाने की सुविधा, कंप्रेस किए गए वीडियो फ़्रेम को डिकोड किए जाने पर ऐप्लिकेशन को सूचना देती है. इसके बाद, ऐप्लिकेशन डिकोड किए गए वीडियो फ़्रेम को डिसप्ले के लिए रिलीज़ करता है, ताकि उसे उसी सिस्टम क्लॉक टाइम पर रेंडर किया जा सके जिस पर ऑडियो फ़्रेम रेंडर किया गया था. इसके लिए, ऐप्लिकेशन पिछले AudioTimestamps इंस्टेंस को फिर से हासिल करता है, ताकि सही समय का हिसाब लगाया जा सके.

टनल किए गए वीडियो प्लेबैक में, ऐप्लिकेशन कोड को बायपास किया जाता है. साथ ही, वीडियो पर काम करने वाली प्रोसेस की संख्या कम हो जाती है. इसलिए, ओईएम के लागू करने के तरीके के आधार पर, यह वीडियो को ज़्यादा बेहतर तरीके से रेंडर कर सकता है. यह वीडियो कैडेंस और चुने गए क्लॉक (पीआरसी, एसटीडी या ऑडियो) के साथ सिंक्रनाइज़ेशन को ज़्यादा सटीक बना सकता है. ऐसा इसलिए, क्योंकि यह Android के वीडियो रेंडर करने के अनुरोध के समय और हार्डवेयर के सही वर्टिकल सिंक के समय के बीच संभावित अंतर की वजह से होने वाली टाइमिंग की समस्याओं से बचता है. हालांकि, टनलिंग की वजह से, जीपीयू इफ़ेक्ट के लिए भी सहायता कम हो सकती है. जैसे, पिक्चर में पिक्चर (पीआईपी) विंडो में ब्लर करने या गोल कोनों वाले इफ़ेक्ट. ऐसा इसलिए होता है, क्योंकि बफ़र, Android ग्राफ़िक्स स्टैक को बायपास कर देते हैं.

इस डायग्राम में दिखाया गया है कि टनलिंग की मदद से, वीडियो चलाने की प्रोसेस को कैसे आसान बनाया जाता है.

ट्रेडिशन और टनल मोड की तुलना

पहली इमेज. वीडियो चलाने की पारंपरिक और टनल वाली प्रोसेस की तुलना

ऐप्लिकेशन डेवलपर के लिए जानकारी

ज़्यादातर ऐप्लिकेशन डेवलपर, वीडियो चलाने की सुविधा लागू करने के लिए किसी लाइब्रेरी के साथ इंटिग्रेट करते हैं. इसलिए, ज़्यादातर मामलों में टनल किए गए वीडियो चलाने की सुविधा लागू करने के लिए, सिर्फ़ उस लाइब्रेरी को फिर से कॉन्फ़िगर करना होता है. टनल किए गए वीडियो प्लेयर को कम लेवल पर लागू करने के लिए, यहां दिया गया तरीका अपनाएं.

Android 5 या इसके बाद के वर्शन वाले डिवाइसों पर, मांग पर वीडियो चलाने के लिए:

  1. SurfaceView इंस्टेंस बनाएं.

  2. audioSessionId इंस्टेंस बनाएं.

  3. दूसरे चरण में बनाए गए audioSessionId इंस्टेंस का इस्तेमाल करके, AudioTrack और MediaCodec इंस्टेंस बनाएं.

  4. ऑडियो डेटा को AudioTrack में शामिल करने के लिए, ऑडियो डेटा के पहले ऑडियो फ़्रेम के लिए प्रज़ेंटेशन टाइमस्टैंप का इस्तेमाल करें.

Android 11 या इसके बाद के वर्शन वाले डिवाइसों पर लाइव ब्रॉडकास्ट चलाने के लिए:

  1. SurfaceView इंस्टेंस बनाएं.

  2. Tuner से avSyncHwId इंस्टेंस पाएं.

  3. दूसरे चरण में बनाए गए avSyncHwId इंस्टेंस की मदद से, AudioTrack और MediaCodec इंस्टेंस बनाएं.

एपीआई कॉल फ़्लो को यहां दिए गए कोड स्निपेट में दिखाया गया है:

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 में जोड़े गए साइलेंट ऑडियो फ़्रेम के लिए, फ़्रेम की पोज़िशन नहीं बढ़ती.

डिवाइस बनाने वाली कंपनियों के लिए

कॉन्फ़िगरेशन

ओईएम को टनल किए गए वीडियो चलाने की सुविधा के लिए, एक अलग वीडियो डिकोडर बनाना चाहिए. इस डिकोडर को यह जानकारी देनी चाहिए कि यह media_codecs.xml फ़ाइल में टनल किए गए प्लेबैक की सुविधा दे सकता है:

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

जब ऑडियो सेशन आईडी के साथ टनल किए गए MediaCodec इंस्टेंस को कॉन्फ़िगर किया जाता है, तो यह इस HW_AV_SYNC आईडी के लिए AudioFlinger से क्वेरी करता है:

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 आईडी को OMX या Codec2 कॉम्पोनेंट में पास किया जाता है. यह आईडी, ऑडियो आउटपुट स्ट्रीम या Tuner कॉन्फ़िगरेशन से जुड़ा होता है. इससे OEM कोड, कोडेक को ऑडियो आउटपुट स्ट्रीम या ट्यूनर स्ट्रीम से जोड़ सकता है.

कॉम्पोनेंट कॉन्फ़िगरेशन के दौरान, OMX या Codec2 कॉम्पोनेंट को एक साइडबैंड हैंडल दिखाना चाहिए. इसका इस्तेमाल, कोडेक को हार्डवेयर कंपोज़र (एचडब्ल्यूसी) लेयर से जोड़ने के लिए किया जा सकता है. जब ऐप्लिकेशन, किसी सरफेस को 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;
}

एचडब्ल्यूसी की ज़िम्मेदारी है कि वह कोडेक आउटपुट से नए इमेज बफ़र को सही समय पर हासिल करे. ये बफ़र, ऑडियो आउटपुट स्ट्रीम या ट्यूनर प्रोग्राम के रेफ़रंस क्लॉक के साथ सिंक किए जाते हैं. साथ ही, एचडब्ल्यूसी इन बफ़र को अन्य लेयर के मौजूदा कॉन्टेंट के साथ कंपोज़ करता है और नतीजे के तौर पर मिली इमेज को दिखाता है. यह सामान्य तौर पर, तैयारी करने और सेट करने के साइकल से अलग होता है. तैयार करने और सेट करने के कॉल सिर्फ़ तब किए जाते हैं, जब अन्य लेयर में बदलाव होता है या साइडबैंड लेयर की प्रॉपर्टी (जैसे कि पोज़िशन या साइज़) में बदलाव होता है.

OMX

टनल किए गए डिकोडर कॉम्पोनेंट में ये सुविधाएं होनी चाहिए:

  • OMX.google.android.index.configureVideoTunnelMode extended पैरामीटर सेट करना. यह पैरामीटर, 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 सदस्य के ज़रिए वापस पास करना चाहिए, ताकि एचडब्ल्यूसी इससे जुड़े कोडेक की पहचान कर सके. अगर कॉम्पोनेंट इस कॉन्फ़िगरेशन के साथ काम नहीं करता है, तो उसे bTunneled को OMX_FALSE पर सेट करना चाहिए.

Codec2

Android 11 या इसके बाद के वर्शन में, Codec2 टनल किए गए प्लेबैक के साथ काम करता है. डिकोडर कॉम्पोनेंट में ये सुविधाएं होनी चाहिए:

  • C2PortTunneledModeTuning को कॉन्फ़िगर करना. यह टनल मोड को कॉन्फ़िगर करता है और ऑडियो आउटपुट डिवाइस या ट्यूनर कॉन्फ़िगरेशन से वापस लाए गए HW_AV_SYNC में पास होता है.

  • एचडब्ल्यूसी के लिए साइडबैंड हैंडल को असाइन और वापस पाने के लिए, C2_PARAMKEY_OUTPUT_TUNNEL_HANDLE से क्वेरी करना.

  • C2Work को C2Work से अटैच करने पर, कोडेक को डिकोड करने और काम पूरा होने का सिग्नल देने का निर्देश मिलता है. हालांकि, आउटपुट बफ़र को तब तक रेंडर नहीं किया जाता, जब तक कि 1) कोडेक को बाद में इसे रेंडर करने का निर्देश न दिया जाए या 2) ऑडियो चलाने की प्रोसेस शुरू न हो जाए.C2_PARAMKEY_TUNNEL_HOLD_RENDER

  • C2_PARAMKEY_TUNNEL_START_RENDER को हैंडल करना. इससे कोडेक को C2_PARAMKEY_TUNNEL_HOLD_RENDER के तौर पर मार्क किए गए फ़्रेम को तुरंत रेंडर करने का निर्देश मिलता है. भले ही, ऑडियो चलना शुरू न हुआ हो.

  • debug.stagefright.ccodec_delayed_params को कॉन्फ़िगर न करें (हमारा सुझाव है). अगर आपने इसे कॉन्फ़िगर किया है, तो इसे false पर सेट करें.

AOSP लागू करने की सुविधा, C2PortTunnelModeTuning के ज़रिए CCodec में टनल मोड को कॉन्फ़िगर करती है. इसे नीचे दिए गए कोड स्निपेट में दिखाया गया है:

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 के ज़रिए वापस पास करना चाहिए, ताकि एचडब्ल्यूसी इससे जुड़े कोडेक की पहचान कर सके.

ऑडियो एचएएल

मांग पर वीडियो चलाने के लिए, ऑडियो एचएएल को ऑडियो प्रज़ेंटेशन के टाइमस्टैंप मिलते हैं. ये टाइमस्टैंप, ऑडियो डेटा के साथ इनलाइन होते हैं. ऑडियो डेटा, बिग-एंडियन फ़ॉर्मैट में होता है. यह हेडर में मौजूद होता है. हेडर, ऑडियो डेटा के हर ब्लॉक की शुरुआत में मिलता है. यह ब्लॉक, ऐप्लिकेशन लिखता है:

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;
}

एचडब्ल्यूसी को वीडियो फ़्रेम को ऑडियो फ़्रेम के साथ सिंक करके रेंडर करने के लिए, ऑडियो एचएएल को सिंक हेडर पार्स करना चाहिए. साथ ही, प्रज़ेंटेशन टाइमस्टैंप का इस्तेमाल करके, प्लेबैक क्लॉक को ऑडियो रेंडरिंग के साथ फिर से सिंक करना चाहिए. कंप्रेस किया गया ऑडियो चलाने के दौरान फिर से सिंक करने के लिए, Audio HAL को कंप्रेस किए गए ऑडियो डेटा में मौजूद मेटाडेटा को पार्स करने की ज़रूरत पड़ सकती है. इससे, वह ऑडियो चलाने की अवधि का पता लगा सकता है.

सहायता को रोकना

Android 5 या इससे पहले के वर्शन में, वीडियो को रोकने की सुविधा नहीं होती. सिर्फ़ ए/वी स्टार्वेशन की वजह से, टनल किए गए प्लेबैक को रोका जा सकता है. हालांकि, अगर वीडियो के लिए इंटरनल बफ़र बड़ा है (उदाहरण के लिए, ओएमएक्स कॉम्पोनेंट में एक सेकंड का डेटा है), तो इससे वीडियो रुकने पर कोई जवाब नहीं मिलता.

Android 5.1 या इसके बाद के वर्शन में, AudioFlinger सीधे (टनल किए गए) ऑडियो आउटपुट के लिए, ऑडियो को रोकने और फिर से चलाने की सुविधा देता है. अगर HAL में रोकने और फिर से शुरू करने की सुविधा लागू की जाती है, तो रोकने और फिर से शुरू करने की सुविधा से जुड़ी जानकारी HAL को भेजी जाती है.

HAL कॉल को प्लेबैक थ्रेड में (ऑफ़लोड की तरह) लागू करके, रोकने, फ़्लश करने, और फिर से शुरू करने के कॉल के क्रम का पालन किया जाता है.

लागू करने के सुझाव

ऑडियो एचएएल

Android 11 के लिए, पीसीआर या एसटीडी से मिले एचडब्ल्यू सिंक आईडी का इस्तेमाल ए/वी सिंक के लिए किया जा सकता है. इसलिए, सिर्फ़ वीडियो स्ट्रीम की सुविधा काम करती है.

Android 10 या इससे पहले के वर्शन वाले डिवाइसों के लिए, टनल किए गए वीडियो प्लेबैक की सुविधा वाले डिवाइसों में कम से कम एक ऑडियो आउटपुट स्ट्रीम प्रोफ़ाइल होनी चाहिए. साथ ही, इसकी audio_policy.conf फ़ाइल में FLAG_HW_AV_SYNC और AUDIO_OUTPUT_FLAG_DIRECT फ़्लैग होने चाहिए. इन फ़्लैग का इस्तेमाल, ऑडियो क्लॉक से सिस्टम क्लॉक को सेट करने के लिए किया जाता है.

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>

हार्डवेयर कंपोज़र (एचडब्ल्यूसी)

जब डिसप्ले पर टनल वाली लेयर (HWC_SIDEBAND compositionType वाली लेयर) होती है, तो लेयर का sidebandStream, OMX वीडियो कॉम्पोनेंट से असाइन किया गया साइडबैंड हैंडल होता है.

एचडब्ल्यूसी, डिकोड किए गए वीडियो फ़्रेम (टनल किए गए ओएमएक्स कॉम्पोनेंट से) को audio-hw-sync आईडी वाले ऑडियो ट्रैक के साथ सिंक करता है. जब कोई नया वीडियो फ़्रेम चालू होता है, तो एचडब्ल्यूसी उसे उन सभी लेयर के मौजूदा कॉन्टेंट के साथ कंपोज़ करता है जो उसे पिछले prepare या set कॉल के दौरान मिले थे. इसके बाद, वह कंपोज़ की गई इमेज दिखाता है. तैयार करने या सेट करने की प्रोसेस सिर्फ़ तब होती है, जब अन्य लेयर में बदलाव होता है या साइडबैंड लेयर की प्रॉपर्टी (जैसे, जगह या साइज़) में बदलाव होता है.

इस इमेज में दिखाया गया है कि एचडब्ल्यूसी, हार्डवेयर (या कर्नल या ड्राइवर) सिंक्रनाइज़र के साथ मिलकर कैसे काम करता है. इससे वीडियो फ़्रेम (7b) को ऑडियो (7c) के आधार पर सही समय पर दिखाने के लिए, लेटेस्ट कंपोज़िशन (7a) के साथ जोड़ा जा सकता है.

ऑडियो के आधार पर वीडियो फ़्रेम को मिलाकर एचडब्ल्यूसी बनाना

दूसरी इमेज. एचडब्ल्यूसी हार्डवेयर (या कर्नल या ड्राइवर) सिंक्रनाइज़र