অডিও এবং এমএমএএপি

AAudio হল Android 8.0 রিলিজে প্রবর্তিত একটি অডিও API। অ্যান্ড্রয়েড 8.1 রিলিজে এমএপি সমর্থন করে এমন একটি HAL এবং ড্রাইভারের সাথে ব্যবহার করার সময় লেটেন্সি কমাতে বর্ধিতকরণ রয়েছে। এই নথিটি Android-এ AAudio-এর MMAP বৈশিষ্ট্য সমর্থন করার জন্য প্রয়োজনীয় হার্ডওয়্যার অ্যাবস্ট্রাকশন লেয়ার (HAL) এবং ড্রাইভার পরিবর্তনগুলি বর্ণনা করে৷

AAudio MMAP-এর জন্য সমর্থন প্রয়োজন:

  • HAL-এর MMAP ক্ষমতা রিপোর্ট করা
  • HAL-তে নতুন ফাংশন বাস্তবায়ন
  • ঐচ্ছিকভাবে এক্সক্লুসিভ মোড বাফারের জন্য একটি কাস্টম ioctl() বাস্তবায়ন করা হচ্ছে
  • একটি অতিরিক্ত হার্ডওয়্যার ডেটা পাথ প্রদান করে
  • MMAP বৈশিষ্ট্য সক্ষম করে এমন সিস্টেম বৈশিষ্ট্যগুলি সেট করা

অডিও আর্কিটেকচার

AAudio একটি নতুন নেটিভ সি এপিআই, যাতে Open SL বিভাগ: ইএস বিকল্প প্রদান করে। এটি অডিও স্ট্রিম তৈরি করতে একটি বিল্ডার ডিজাইন প্যাটার্ন ব্যবহার করে।

AAudio একটি কম লেটেন্সি ডেটা পাথ প্রদান করে। এক্সক্লুসিভ মোডে, বৈশিষ্ট্যটি ক্লায়েন্ট অ্যাপ্লিকেশন কোডকে সরাসরি একটি মেমরি ম্যাপ করা বাফারে লিখতে দেয় যা ALSA ড্রাইভারের সাথে ভাগ করা হয়। শেয়ারড মোডে, অডিও সার্ভারে চলমান একটি মিক্সার দ্বারা MMAP বাফার ব্যবহার করা হয়। এক্সক্লুসিভ মোডে, লেটেন্সি উল্লেখযোগ্যভাবে কম কারণ ডেটা মিক্সারকে বাইপাস করে।

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

নীচের চিত্রে, আমরা পালস-কোড মড্যুলেশন (পিসিএম) ডেটা এমএপি ফিফো এর মাধ্যমে ALSA ড্রাইভারের মধ্যে প্রবাহিত হতে দেখতে পাচ্ছি। টাইমস্ট্যাম্পগুলি পর্যায়ক্রমে AAudio পরিষেবা দ্বারা অনুরোধ করা হয় এবং তারপরে একটি পারমাণবিক বার্তা সারির মাধ্যমে ক্লায়েন্টের টাইমিং মডেলে প্রেরণ করা হয়।

পিসিএম ডেটা ফ্লো ডায়াগ্রাম।
চিত্র 1. পিসিএম ডেটা উদ্দেশ্যে ALSA করার FIFO মাধ্যমে প্রবাহিত

SHARED মোডে, একটি টাইমিং মডেলও ব্যবহার করা হয়, কিন্তু এটি AAudioService-এ থাকে।

অডিও ক্যাপচারের জন্য, একটি অনুরূপ মডেল ব্যবহার করা হয়, কিন্তু PCM ডেটা বিপরীত দিকে প্রবাহিত হয়।

HAL পরিবর্তন

TinyALSA এর জন্য দেখুন:

external/tinyalsa/include/tinyalsa/asoundlib.h
external/tinyalsa/include/tinyalsa/pcm.c
int pcm_start(struct pcm *pcm);
int pcm_stop(struct pcm *pcm);
int pcm_mmap_begin(struct pcm *pcm, void **areas,
           unsigned int *offset,
           unsigned int *frames);
int pcm_get_poll_fd(struct pcm *pcm);
int pcm_mmap_commit(struct pcm *pcm, unsigned int offset,
           unsigned int frames);
int pcm_mmap_get_hw_ptr(struct pcm* pcm, unsigned int *hw_ptr,
           struct timespec *tstamp);

উত্তরাধিকার HAL-এর জন্য, দেখুন:

hardware/libhardware/include/hardware/audio.h
hardware/qcom/audio/hal/audio_hw.c
int start(const struct audio_stream_out* stream);
int stop(const struct audio_stream_out* stream);
int create_mmap_buffer(const struct audio_stream_out *stream,
                        int32_t min_size_frames,
                        struct audio_mmap_buffer_info *info);
int get_mmap_position(const struct audio_stream_out *stream,
                        struct audio_mmap_position *position);

HIDL অডিও HAL এর জন্য:

hardware/interfaces/audio/2.0/IStream.hal
hardware/interfaces/audio/2.0/types.hal
hardware/interfaces/audio/2.0/default/Stream.h
start() generates (Result retval);
stop() generates (Result retval) ;
createMmapBuffer(int32_t minSizeFrames)
       generates (Result retval, MmapBufferInfo info);
getMmapPosition()
       generates (Result retval, MmapPosition position);

MMAP সমর্থন প্রতিবেদন করা

সিস্টেম প্রপার্টি "aaudio.mmap_policy" 2 (AAUDIO_POLICY_AUTO) এ সেট করা উচিত যাতে অডিও ফ্রেমওয়ার্ক জানে যে MMAP মোড অডিও HAL দ্বারা সমর্থিত। (নীচে "AAudio MMAP ডেটা পাথ সক্ষম করা" দেখুন।)

audio_policy_configuration.xml ফাইলটিতে অবশ্যই MMAP/NO IRQ মোডের জন্য নির্দিষ্ট একটি আউটপুট এবং ইনপুট প্রোফাইল থাকতে হবে যাতে অডিও নীতি পরিচালক জানতে পারে যে MMAP ক্লায়েন্ট তৈরি করা হলে কোন স্ট্রিমটি খুলতে হবে:

<mixPort name="mmap_no_irq_out" role="source"
            flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_MMAP_NOIRQ">
            <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                                samplingRates="48000"
                                channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
</mixPort>

<mixPort name="mmap_no_irq_in" role="sink" flags="AUDIO_INPUT_FLAG_MMAP_NOIRQ">
            <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                                samplingRates="48000"
                                channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
</mixPort>

একটি MMAP স্ট্রীম খোলা এবং বন্ধ করা হচ্ছে

createMmapBuffer(int32_t minSizeFrames)
            generates (Result retval, MmapBufferInfo info);

Tinyalsa ফাংশন কল করে MMAP স্ট্রীম খোলা এবং বন্ধ করা যেতে পারে।

MMAP অবস্থান জিজ্ঞাসা করা হচ্ছে

টাইমিং মডেলে ফিরে আসা টাইমস্ট্যাম্পটিতে একটি ফ্রেমের অবস্থান এবং ন্যানোসেকেন্ডে একটি মনোটোনিক সময় রয়েছে:

getMmapPosition()
        generates (Result retval, MmapPosition position);

HAL একটি নতুন Tinyalsa ফাংশন কল করে ALSA ড্রাইভার থেকে এই তথ্য পেতে পারে:

int pcm_mmap_get_hw_ptr(struct pcm* pcm,
                        unsigned int *hw_ptr,
                        struct timespec *tstamp);

শেয়ার্ড মেমরির জন্য ফাইল বর্ণনাকারী

AAudio MMAP ডেটা পাথ একটি মেমরি অঞ্চল ব্যবহার করে যা হার্ডওয়্যার এবং অডিও পরিষেবার মধ্যে ভাগ করা হয়। ভাগ করা মেমরি একটি ফাইল বর্ণনাকারী ব্যবহার করে উল্লেখ করা হয় যা ALSA ড্রাইভার দ্বারা তৈরি করা হয়।

কার্নেল পরিবর্তন

ফাইল বর্ণনাকারী সরাসরি একটি সাথে সম্পর্কিত হয় তবে /dev/snd/ চালক ফাইল, তারপর এটি ভাগ মোডে AAudio পরিষেবা দ্বারা ব্যবহার করা যাবে। কিন্তু বর্ণনাকারীকে এক্সক্লুসিভ মোডের জন্য ক্লায়েন্ট কোডে পাঠানো যাবে না। /dev/snd/ ফাইল বর্ণনাকারী, ক্লায়েন্ট অ্যাক্সেস খুবই বিস্তৃত প্রদান, তাই এটি SELinux- র দ্বারা অবরুদ্ধ করা আছে হবে।

অর্ডার এক্সক্লুসিভ মোড সমর্থন করার জন্য, এটা রূপান্তর করা প্রয়োজন /dev/snd/ একটি থেকে বর্ণনাকারী anon_inode:dmabuf ফাইল বর্ননাকারী। SELinux সেই ফাইল বর্ণনাকারীকে ক্লায়েন্টের কাছে পাঠানোর অনুমতি দেয়। এটি AAudioService দ্বারাও ব্যবহার করা যেতে পারে।

একটি anon_inode:dmabuf ফাইল বর্ণনাকারী অ্যান্ড্রয়েড আয়ন মেমরির লাইব্রেরি ব্যবহার উত্পন্ন করা যেতে পারে।

অতিরিক্ত তথ্যের জন্য, এই বাহ্যিক সংস্থানগুলি দেখুন:

  1. "অ্যান্ড্রয়েড ION মেমরির বরাদ্দকরণ" https://lwn.net/Articles/480055/
  2. "অ্যান্ড্রয়েড ION ওভারভিউ" https://wiki.linaro.org/BenjaminGaignard/ion
  3. "ION মেমরির বরাদ্দকরণ একীভূত" https://lwn.net/Articles/565469/

HAL পরিবর্তন

AAudio সেবা চাহিদা যদি এই জানতে anon_inode:dmabuf সমর্থিত। অ্যান্ড্রয়েড 10.0 এর আগে, এটি করার একমাত্র উপায় ছিল MMAP বাফারের আকারকে নেতিবাচক সংখ্যা হিসাবে পাস করা, যেমন। -2048 এর পরিবর্তে 2048, যদি সমর্থিত হয়। অ্যান্ড্রয়েড 10.0 এবং তোমার সাথে পরে সেট করতে পারেন AUDIO_MMAP_APPLICATION_SHAREABLE পতাকা।

mmapBufferInfo |= AUDIO_MMAP_APPLICATION_SHAREABLE;

অডিও সাবসিস্টেম পরিবর্তন

AAudio-এর জন্য অডিও সাবসিস্টেমের অডিও ফ্রন্ট এন্ডে একটি অতিরিক্ত ডেটা পাথ প্রয়োজন যাতে এটি মূল AudioFlinger পাথের সাথে সমান্তরালভাবে কাজ করতে পারে। সেই উত্তরাধিকার পথটি অন্যান্য সমস্ত সিস্টেম শব্দ এবং অ্যাপ্লিকেশন শব্দের জন্য ব্যবহৃত হয়। এই কার্যকারিতা ডিএসপিতে একটি সফ্টওয়্যার মিক্সার বা SOC-তে একটি হার্ডওয়্যার মিক্সার দ্বারা সরবরাহ করা যেতে পারে।

AAudio MMAP ডেটা পাথ সক্ষম করা হচ্ছে

MMAP সমর্থিত না হলে বা কোনো স্ট্রীম খুলতে ব্যর্থ হলে AAudio লিগ্যাসি AudioFlinger ডেটা পাথ ব্যবহার করবে। তাই AAudio একটি অডিও ডিভাইসের সাথে কাজ করবে যা MMAP/NOIRQ পাথ সমর্থন করে না।

AAudio-এর জন্য MMAP সমর্থন পরীক্ষা করার সময়, আপনি আসলে MMAP ডেটা পাথ পরীক্ষা করছেন নাকি শুধুমাত্র উত্তরাধিকার ডেটা পাথ পরীক্ষা করছেন তা জানা গুরুত্বপূর্ণ। নিম্নলিখিতগুলি বর্ণনা করে যে কীভাবে নির্দিষ্ট ডেটা পাথগুলিকে সক্ষম বা জোর করতে হয় এবং কীভাবে একটি স্ট্রীম দ্বারা ব্যবহৃত পাথটি অনুসন্ধান করতে হয়।

পদ্ধতির বৈশিষ্ট্য

আপনি সিস্টেম বৈশিষ্ট্যের মাধ্যমে MMAP নীতি সেট করতে পারেন:

  • 1 = AAUDIO_POLICY_NEVER - শুধুমাত্র লিগ্যাসি পাথ ব্যবহার করুন৷ এমনকি MMAP ব্যবহার করার চেষ্টা করবেন না।
  • 2 = AAUDIO_POLICY_AUTO - MMAP ব্যবহার করার চেষ্টা করুন। যদি এটি ব্যর্থ হয় বা উপলব্ধ না হয়, তাহলে উত্তরাধিকার পথ ব্যবহার করুন।
  • 3 = AAUDIO_POLICY_ALWAYS - শুধুমাত্র MMAP পাথ ব্যবহার করুন৷ উত্তরাধিকারের পথে ফিরে যাবেন না।

এগুলি মেকফাইল ডিভাইসে সেট করা হতে পারে, যেমন:

# Enable AAudio MMAP/NOIRQ data path.
# 2 is AAUDIO_POLICY_AUTO so it will try MMAP then fallback to Legacy path.
PRODUCT_PROPERTY_OVERRIDES += aaudio.mmap_policy=2
# Allow EXCLUSIVE then fall back to SHARED.
PRODUCT_PROPERTY_OVERRIDES += aaudio.mmap_exclusive_policy=2

ডিভাইস বুট হওয়ার পরে আপনি এই মানগুলি ওভাররাইড করতে পারেন। পরিবর্তনটি কার্যকর করার জন্য আপনাকে অডিও সার্ভার পুনরায় চালু করতে হবে। উদাহরণস্বরূপ, MMAP এর জন্য অটো মোড সক্ষম করতে:

adb root
adb shell setprop aaudio.mmap_policy 2
adb shell killall audioserver

সেখানে সরবরাহ করা ফাংশন হয় ndk/sysroot/usr/include/aaudio/AAudioTesting.h আপনি mmap পথ ব্যবহার করার জন্য নীতিটি ওভাররাইড করতে মঞ্জুরি দিন:

aaudio_result_t AAudio_setMMapPolicy(aaudio_policy_t policy);

একটি স্ট্রীম MMAP পাথ ব্যবহার করছে কিনা তা জানতে, কল করুন:

bool AAudioStream_isMMapUsed(AAudioStream* stream);