মাল্টিমিডিয়া টানেলিং

মাল্টিমিডিয়া টানেলিং, যা টানেল মোড নামেও পরিচিত, সংকুচিত ভিডিও ডেটাকে অ্যাপ কোড বা অ্যান্ড্রয়েড ফ্রেমওয়ার্ক কোড দ্বারা প্রক্রিয়াজাত না হয়েই একটি হার্ডওয়্যার ভিডিও ডিকোডারের মধ্য দিয়ে সরাসরি ডিসপ্লেতে পাঠাতে সক্ষম করে। অ্যান্ড্রয়েড স্ট্যাকের নিচের ডিভাইস-নির্দিষ্ট কোডটি, ভিডিও ফ্রেম উপস্থাপনের টাইমস্ট্যাম্পগুলোকে নিম্নলিখিত ধরনের অভ্যন্তরীণ ঘড়িগুলোর কোনো একটির সাথে তুলনা করে নির্ধারণ করে যে কোন ভিডিও ফ্রেমগুলো ডিসপ্লেতে পাঠাতে হবে এবং কখন পাঠাতে হবে।

  • অ্যান্ড্রয়েড ৫ বা তার উচ্চতর সংস্করণে অন-ডিমান্ড ভিডিও প্লেব্যাকের জন্য, অ্যাপ থেকে পাঠানো অডিও প্রেজেন্টেশন টাইমস্ট্যাম্পের সাথে সিঙ্ক্রোনাইজ করা একটি AudioTrack ঘড়ি ব্যবহৃত হয়।

  • অ্যান্ড্রয়েড ১১ বা তার পরবর্তী সংস্করণে লাইভ সম্প্রচার প্লেব্যাকের জন্য, একটি টিউনার দ্বারা চালিত প্রোগ্রাম রেফারেন্স ক্লক (PCR) বা সিস্টেম টাইম ক্লক (STC) প্রয়োজন হয়।

পটভূমি

অ্যান্ড্রয়েডে নন-টানেল মোডে ভিডিও প্লেব্যাকের সময়, একটি কম্প্রেসড ভিডিও ফ্রেম ডিকোড হয়ে গেলে অ্যাপটিকে জানানো হয় । এরপর অ্যাপটি সঠিক সময় গণনা করার জন্য পূর্ববর্তী AudioTimestamp ইনস্ট্যান্সগুলো সংগ্রহ করে , ডিকোড করা ভিডিও ফ্রেমটিকে সংশ্লিষ্ট অডিও ফ্রেমের সাথে একই সিস্টেম ক্লক টাইমে ডিসপ্লেতে রেন্ডার করার জন্য প্রকাশ করে।

যেহেতু টানেলড ভিডিও প্লেব্যাক অ্যাপ কোডকে বাইপাস করে এবং ভিডিওর উপর কাজ করা প্রসেসের সংখ্যা কমিয়ে দেয়, তাই OEM বাস্তবায়নের উপর নির্ভর করে এটি আরও কার্যকর ভিডিও রেন্ডারিং প্রদান করতে পারে। এটি অ্যান্ড্রয়েডের ভিডিও রেন্ডার করার অনুরোধের টাইমিং এবং প্রকৃত হার্ডওয়্যার vsync-এর টাইমিংয়ের মধ্যে সম্ভাব্য অসামঞ্জস্যের কারণে সৃষ্ট টাইমিং সমস্যা এড়িয়ে, নির্বাচিত ক্লকের (PRC, STC, বা অডিও) সাথে আরও নির্ভুল ভিডিও ক্যাডেন্স এবং সিনক্রোনাইজেশনও প্রদান করতে পারে। তবে, টানেলিং পিকচার-ইন-পিকচার (PiP) উইন্ডোতে ব্লারিং বা গোলাকার কোণার মতো GPU ইফেক্টের সমর্থনও কমিয়ে দিতে পারে, কারণ বাফারগুলো অ্যান্ড্রয়েড গ্রাফিক্স স্ট্যাককে বাইপাস করে।

নিম্নোক্ত চিত্রটিতে দেখানো হয়েছে কীভাবে টানেলিং ভিডিও প্লেব্যাক প্রক্রিয়াকে সহজ করে তোলে।

ঐতিহ্যবাহী এবং টানেল মোডের তুলনা

চিত্র ১. নন-টানেলড এবং টানেলড ভিডিও প্লেব্যাক প্রক্রিয়ার তুলনা।

অ্যাপ ডেভেলপারদের জন্য

যেহেতু বেশিরভাগ অ্যাপ ডেভেলপার প্লেব্যাক বাস্তবায়নের জন্য একটি লাইব্রেরি ব্যবহার করেন, তাই অধিকাংশ ক্ষেত্রে টানেলড প্লেব্যাকের জন্য শুধু সেই লাইব্রেরিটি পুনরায় কনফিগার করার প্রয়োজন হয়। একটি টানেলড ভিডিও প্লেয়ারের নিম্ন-স্তরের বাস্তবায়নের জন্য, নিম্নলিখিত নির্দেশাবলী ব্যবহার করুন।

অ্যান্ড্রয়েড ৫ বা তার উচ্চতর সংস্করণে চাহিদা অনুযায়ী ভিডিও দেখার জন্য:

  1. একটি SurfaceView ইনস্ট্যান্স তৈরি করুন।

  2. একটি audioSessionId ইনস্ট্যান্স তৈরি করুন।

  3. ধাপ ২-এ তৈরি করা audioSessionId ইনস্ট্যান্সটি ব্যবহার করে AudioTrack এবং MediaCodec ইনস্ট্যান্স তৈরি করুন।

  4. অডিও ডেটার প্রথম ফ্রেমের প্রেজেন্টেশন টাইমস্ট্যাম্প ব্যবহার করে AudioTrack এ অডিও ডেটা কিউ করুন।

অ্যান্ড্রয়েড ১১ বা তার পরবর্তী সংস্করণে লাইভ সম্প্রচার দেখার জন্য:

  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 -তে সেট করুন।

    • এই প্যারামিটারটি সেট করা না থাকলে, OEM ডিভাইসটির আচরণ নির্ধারণ করে।

  • যখন AudioTrack এ অডিও ডেটা সরবরাহ করা হয় না এবং বাফারগুলি খালি থাকে (অডিও আন্ডাররান), তখন আরও অডিও ডেটা লেখা না হওয়া পর্যন্ত ভিডিও প্লেব্যাক থেমে যায়, কারণ অডিও ক্লক আর অগ্রসর হয় না।

  • প্লেব্যাকের সময়, অডিও উপস্থাপনার টাইমস্ট্যাম্পে এমন অসংগতি দেখা যেতে পারে যা অ্যাপটি সংশোধন করতে পারে না। যখন এমনটা ঘটে, তখন OEM নেতিবাচক ফাঁকগুলো সংশোধন করে বর্তমান ভিডিও ফ্রেমটিকে থামিয়ে দিয়ে, এবং ইতিবাচক ফাঁকগুলো সংশোধন করে হয় ভিডিও ফ্রেম বাদ দিয়ে অথবা নীরব অডিও ফ্রেম যোগ করে (যা OEM-এর বাস্তবায়নের উপর নির্ভর করে)। যোগ করা নীরব অডিও ফ্রেমগুলোর জন্য AudioTimestamp এর ফ্রেম পজিশন বাড়ে না।

সুনির্দিষ্ট অনুসন্ধানের ক্রম প্রবাহ

প্রিসাইজ সিক আপনাকে ভিডিওর একটি নির্দিষ্ট স্থান খুঁজে পেতে সাহায্য করে। কীফ্রেম সিকিং-এর বিপরীতে, যা কেবল নিকটতম আই-ফ্রেমে চলে যায় এবং লক্ষ্য অবস্থান থেকে কয়েক সেকেন্ড পর্যন্ত বিচ্যুত হতে পারে, প্রিসাইজ সিকিং ভিডিওটিকে ঠিক অনুরোধ করা টাইমস্ট্যাম্পে রেন্ডার করে। এই নির্দিষ্ট এপিআই ক্রমটি অনুসরণ করার ফলে অ্যাপটি নির্বিঘ্নে ব্যাকগ্রাউন্ড প্রি-রোলিং এবং টাইমিং সিনক্রোনাইজেশন সম্পাদন করতে পারে। এটি নিশ্চিত করে যে প্লেব্যাক পুনরায় শুরু হলে লক্ষ্য ফ্রেমটি সঙ্গে সঙ্গে প্রদর্শিত হয়।

সঠিকভাবে অনুসন্ধান (seek) করার জন্য, চিত্র ২-এ প্রদর্শিত কার্য সম্পাদনের ক্রম অনুসরণ করুন:

ক্রম প্রবাহ সন্ধান করুন

চিত্র ২. নির্ভুল অনুসন্ধান অর্জনের জন্য অনুক্রম প্রবাহ।

মূল বিবরণগুলির মধ্যে রয়েছে:

  • সমান্তরাল সম্পাদন: আপনি একটিমাত্র par বক্সের মধ্যে থাকা ধাপগুলো একই সাথে সম্পাদন করতে পারেন। উদাহরণস্বরূপ, ভিডিও MediaCodec কলগুলো AudioTrack থেকে স্বাধীন।

  • ক্রমিক নির্ভরতা: দ্বিতীয় par বক্সে যাওয়ার আগে প্রথম par বক্সের মধ্যে থাকা সমস্ত অপারেশন কল করুন। বিশেষত, অ্যাপটিকে অবশ্যই নিশ্চিত করতে হবে যে AudioTrack.play কল করার আগে AudioTrack.write এবং ভিডিও MediaCodec এর বাফারগুলি কিউতে যুক্ত করা হয়েছে।

পরিবর্তনশীল গতির প্লেব্যাকের ক্রম প্রবাহ

পরিবর্তনশীল গতির প্লেব্যাক আপনাকে স্বাভাবিক গতির চেয়ে দ্রুত বা ধীর গতিতে ভিডিও চালাতে দেয়। এই বৈশিষ্ট্যটি সাধারণত অ্যাপগুলো ব্যবহার করে থাকে, যাতে ব্যবহারকারীরা দ্রুত (যেমন সময় বাঁচাতে শিক্ষামূলক বক্তৃতা বা পডকাস্ট ১.৫x বা ২.০x গতিতে চালানো) অথবা ধীর গতিতে (যেমন খেলার কৌশল বিশ্লেষণ বা নির্দেশনামূলক ভিডিও ০.৫x গতিতে) কন্টেন্ট উপভোগ করতে পারেন।

গতি নির্ধারণ করতে, চিত্র ৩-এ প্রদর্শিত কার্য সম্পাদনের ক্রম অনুসরণ করুন:

গতি ক্রম প্রবাহ

চিত্র ৩. গতি নির্ধারণের জন্য ক্রমিক প্রবাহ।

চিত্র ৩-এর ক্রমিক চিত্রে নিম্নলিখিত আচরণসমূহ এবং প্রযুক্তিগত প্রয়োজনীয়তাগুলো অন্তর্ভুক্ত করা হয়নি:

  • AudioTrack.getTimestamp মূল অডিও ইনপুট ফ্রিকোয়েন্সির উপর ভিত্তি করে framePosition রিটার্ন করে। উদাহরণস্বরূপ, 44100 Hz ইনপুট এবং প্লে স্পিড 2.0x হলে, 2 সেকেন্ড প্লে হওয়ার পর AudioTrack.getTimestamp 176400 framePosition রিটার্ন করে।

  • যদি অ্যাপটি setSpeed(1.5) কল করে এবং সেটি সফল হয়, এবং তারপর setSpeed(30) কল করে এবং সেটি ব্যর্থ হয়, তাহলে প্লেব্যাক 1.5x গতিতেই থাকবে।

  • যদি setVolume ব্যবহার করে অডিও মিউট করা হয়, তবুও অ্যাপটিকে অডিও বাফার পাঠাতে হয়, কারণ ভিডিও ফ্রেমগুলো অডিওর অবস্থানের ওপর ভিত্তি করে রেন্ডার করা হয়।

  • গতি পরিবর্তন করা হলেও অডিওর পিচ অপরিবর্তিত থাকে।

  • অন্যান্য প্লেব্যাক কার্যক্রমের দ্বারা প্লেব্যাকের গতি প্রভাবিত হয় না।

    • উদাহরণ ১: যদি প্লেব্যাক স্পিড 1.5x হয় এবং AudioTrack পজ করা হয়, তাহলে AudioTrack পুনরায় চালু করার পরেও স্পিড 1.5x-ই থাকবে।

    • উদাহরণ ২: যদি প্লেব্যাকের গতি 1.5x হয় এবং ব্যবহারকারী চিত্র ২ অনুসরণ করে একটি ভিন্ন PTS-এ যান, তাহলে প্লেব্যাকের গতি 1.5x-ই থাকবে।

  • নির্বাচিত গতিতে রেন্ডার করার জন্য সমস্ত ফ্রেম যেন সময়মতো ডিকোড হয়, তা নিশ্চিত করতে KEY_OPERATING_RATE ভিডিও ফ্রেম রেট এবং প্লেব্যাক স্পিডের গুণফলের সমান করে সেট করুন। যদি KEY_OPERATING_RATE যথেষ্ট বেশি সেট করা না হয়, তাহলে কোডেক হয়তো ফ্রেমগুলো যথেষ্ট দ্রুত ডিকোড করতে পারবে না, যার ফলে প্লেব্যাকের সময় অনাকাঙ্ক্ষিত ফ্রেম ড্রপ হতে পারে।

    • উদাহরণস্বরূপ: যদি কন্টেন্টের আসল ফ্রেম রেট 60 fps হয় এবং প্লেব্যাক স্পিড 2x হয়, তাহলে KEY_OPERATING_RATE 120 তে সেট করুন।
  • বারবার বিভিন্ন সমর্থিত গতিতে স্পিড সেট করলে কোনো ত্রুটি দেখা দেওয়ার কথা নয়, এবং শেষবার সেট করার পর প্লেব্যাকের আচরণ এমন হওয়া উচিত, যেন স্পিডটি শুধুমাত্র একবারই সর্বশেষ সেট করা হয়েছে।

ডিভাইস প্রস্তুতকারকদের জন্য

কনফিগারেশন

টানেলড ভিডিও প্লেব্যাক সমর্থন করার জন্য OEM-দের একটি পৃথক ভিডিও ডিকোডার তৈরি করা উচিত। এই ডিকোডারটির media_codecs.xml ফাইলে এটি টানেলড প্লেব্যাকে সক্ষম বলে উল্লেখ করা উচিত:

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

যখন একটি টানেলড MediaCodec ইনস্ট্যান্স একটি অডিও সেশন আইডি দিয়ে কনফিগার করা হয়, তখন এটি এই HW_AV_SYNC ID-টির জন্য 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 ID-টি সংগ্রহ করে এবং অভ্যন্তরীণভাবে এটিকে অডিও সেশন ID-র সাথে সংযুক্ত করে:

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 ID-টি একই অডিও সেশন ID সহ আউটপুট স্ট্রিমে পাঠানো হয়। যদি এটি এখনও তৈরি না হয়ে থাকে, তাহলে AudioTrack তৈরির সময় HW_AV_SYNC ID-টি আউটপুট স্ট্রিমে পাঠানো হয়। এই কাজটি প্লেব্যাক থ্রেড দ্বারা করা হয়।

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

HW_AV_SYNC ID-টি, তা কোনো অডিও আউটপুট স্ট্রিম বা Tuner কনফিগারেশনের সাথেই সম্পর্কিত হোক না কেন, OMX বা Codec2 কম্পোনেন্টে পাঠানো হয়, যাতে OEM কোডটি কোডেকটিকে সংশ্লিষ্ট অডিও আউটপুট স্ট্রিম বা টিউনার স্ট্রিমের সাথে যুক্ত করতে পারে।

কম্পোনেন্ট কনফিগারেশনের সময়, OMX বা Codec2 কম্পোনেন্টটির একটি সাইডব্যান্ড হ্যান্ডেল রিটার্ন করা উচিত, যা কোডেকটিকে একটি হার্ডওয়্যার কম্পোজার (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 এক্সটেন্ডেড প্যারামিটারটি সেট করা, যা অডিও আউটপুট ডিভাইসের সাথে যুক্ত HW_AV_SYNC ID পাস করার জন্য ConfigureVideoTunnelModeParams স্ট্রাকচারটি ব্যবহার করে।

  • OMX_IndexConfigAndroidTunnelPeek প্যারামিটারটি কনফিগার করা, যা অডিও প্লেব্যাক শুরু হয়েছে কি না তা নির্বিশেষে, প্রথম ডিকোড করা ভিডিও ফ্রেমটি রেন্ডার করবে কি না তা কোডেককে বলে দেয়।

  • প্রথম টানেল করা ভিডিও ফ্রেমটি ডিকোড হয়ে গেলে এবং রেন্ডার করার জন্য প্রস্তুত হলে OMX_EventOnFirstTunnelFrameReady ইভেন্টটি পাঠানো হয়।

নিম্নলিখিত কোড স্নিপেটে দেখানো অনুযায়ী, AOSP ইমপ্লিমেন্টেশনটি OMXNodeInstance এর মাধ্যমে ACodec এ টানেল মোড কনফিগার করে:

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 পাস করে।

  • HWC-এর জন্য সাইডব্যান্ড হ্যান্ডেল বরাদ্দ ও পুনরুদ্ধার করতে C2_PARAMKEY_OUTPUT_TUNNEL_HANDLE কোয়েরি করা হচ্ছে।

  • C2Work এর সাথে সংযুক্ত থাকা অবস্থায় C2_PARAMKEY_TUNNEL_HOLD_RENDER হ্যান্ডলিং, যা কোডেককে ডিকোড করতে এবং কাজ সমাপ্তির সংকেত দিতে নির্দেশ দেয়, কিন্তু আউটপুট বাফারটি রেন্ডার করতে নিষেধ করে যতক্ষণ না 1) কোডেককে পরে এটি রেন্ডার করার নির্দেশ দেওয়া হয় অথবা 2) অডিও প্লেব্যাক শুরু হয়।

  • C2_PARAMKEY_TUNNEL_START_RENDER হ্যান্ডলিং, যা কোডেককে নির্দেশ দেয় C2_PARAMKEY_TUNNEL_HOLD_RENDER দ্বারা চিহ্নিত ফ্রেমটি অবিলম্বে রেন্ডার করতে, এমনকি যদি অডিও প্লেব্যাক শুরু না হয়ে থাকে।

  • debug.stagefright.ccodec_delayed_params কনফিগার না করাই ভালো। যদি কনফিগার করতে চান, তবে এর false সেট করুন।

AOSP ইমপ্লিমেন্টেশনটি CCodecC2PortTunnelModeTuning এর মাধ্যমে টানেল মোড কনফিগার করে, যেমনটি নিম্নলিখিত কোড স্নিপেটে দেখানো হয়েছে:

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) অডিও ডেটার সাথে ইনলাইনে বিগ-এন্ডিয়ান ফরম্যাটে অডিও প্রেজেন্টেশন টাইমস্ট্যাম্পগুলো গ্রহণ করে।

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-কে এর প্লেব্যাকের সময়কাল নির্ধারণ করতে কম্প্রেসড অডিও ডেটার ভেতরের মেটাডেটা পার্স করার প্রয়োজন হতে পারে।

বিরতি সমর্থন

অ্যান্ড্রয়েড ৫ বা তার নিচের সংস্করণগুলোতে পজ সাপোর্ট নেই। টানেলড প্লেব্যাক শুধুমাত্র এ/ভি স্টারভেশনের মাধ্যমে পজ করা যায়, কিন্তু ভিডিওর অভ্যন্তরীণ বাফার বড় হলে (উদাহরণস্বরূপ, OMX কম্পোনেন্টে এক সেকেন্ডের ডেটা থাকলে), পজ করার সময় প্রতিক্রিয়াহীন মনে হয়।

অ্যান্ড্রয়েড ৫.১ বা তার উচ্চতর সংস্করণে, AudioFlinger সরাসরি (টানেলড) অডিও আউটপুটের জন্য পজ এবং রিজুম সমর্থন করে। যদি HAL পজ এবং রিজুম বাস্তবায়ন করে, তবে ট্র্যাকের পজ এবং রিজুম HAL-এ ফরোয়ার্ড করা হয়।

পজ, ফ্লাশ, এবং রিজুম কল সিকোয়েন্সটি প্লেব্যাক থ্রেডে (অফলোডের মতোই) HAL কলগুলো এক্সিকিউট করার মাধ্যমে অনুসরণ করা হয়।

বাস্তবায়নের পরামর্শ

অডিও এইচএএল

অ্যান্ড্রয়েড ১১-এর ক্ষেত্রে, অডিও-ভিডিও সিঙ্কের জন্য PCR বা STC থেকে প্রাপ্ত হার্ডওয়্যার সিঙ্ক আইডি ব্যবহার করা যায়, ফলে শুধুমাত্র ভিডিও স্ট্রিম সমর্থিত হয়।

অ্যান্ড্রয়েড ১০ বা তার নিচের সংস্করণের জন্য, টানেলড ভিডিও প্লেব্যাক সমর্থনকারী ডিভাইসগুলোর audio_policy.conf ফাইলে FLAG_HW_AV_SYNC এবং AUDIO_OUTPUT_FLAG_DIRECT ফ্ল্যাগসহ অন্তত একটি অডিও আউটপুট স্ট্রিম প্রোফাইল থাকা আবশ্যক। এই ফ্ল্যাগগুলো অডিও ক্লক থেকে সিস্টেম ক্লক সেট করতে ব্যবহৃত হয়।

ওএমএক্স

ডিভাইস প্রস্তুতকারকদের টানেলড ভিডিও প্লেব্যাকের জন্য একটি পৃথক 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)

যখন কোনো ডিসপ্লেতে একটি টানেলড লেয়ার ( HWC_SIDEBAND compositionType যুক্ত একটি লেয়ার) থাকে, তখন লেয়ারটির sidebandStream হয় OMX ভিডিও কম্পোনেন্ট দ্বারা বরাদ্দকৃত সাইডব্যান্ড হ্যান্ডেল।

HWC, টানেল করা OMX কম্পোনেন্ট থেকে ডিকোড করা ভিডিও ফ্রেমগুলোকে, audio-hw-sync ID যুক্ত অডিও ট্র্যাকের সাথে সিঙ্ক্রোনাইজ করে। যখন একটি নতুন ভিডিও ফ্রেম কারেন্ট হয়, তখন HWC সেটিকে শেষ prepare বা set কলের সময় প্রাপ্ত সমস্ত লেয়ারের বর্তমান কন্টেন্টের সাথে কম্পোজিট করে এবং ফলস্বরূপ ছবিটি প্রদর্শন করে। prepare বা set কলগুলো কেবল তখনই ঘটে যখন অন্যান্য লেয়ার পরিবর্তিত হয়, অথবা যখন সাইডব্যান্ড লেয়ারের প্রোপার্টি (যেমন পজিশন বা সাইজ) পরিবর্তিত হয়।

নিম্নলিখিত চিত্রটি হার্ডওয়্যার (বা কার্নেল বা ড্রাইভার) সিঙ্ক্রোনাইজারের সাথে HWC-এর কাজকে উপস্থাপন করে, যা অডিও (7c)-এর উপর ভিত্তি করে সঠিক সময়ে প্রদর্শনের জন্য ভিডিও ফ্রেম (7b)-কে সর্বশেষ কম্পোজিশন (7a)-এর সাথে একত্রিত করে।

HWC অডিওর উপর ভিত্তি করে ভিডিও ফ্রেম একত্রিত করে

চিত্র ৪. HWC হার্ডওয়্যার (বা কার্নেল বা ড্রাইভার) সিঙ্ক্রোনাইজার।