AAudio এবং MMAP

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

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

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

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

AAudio হল একটি নতুন নেটিভ C API যা ওপেন SL ES-এর বিকল্প প্রদান করে। এটি অডিও স্ট্রিম তৈরি করতে একটি বিল্ডার ডিজাইন প্যাটার্ন ব্যবহার করে।

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

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

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

PCM ডেটা ফ্লো ডায়াগ্রাম।
চিত্র 1. FIFO-এর মাধ্যমে ALSA-তে PCM ডেটা প্রবাহ

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 পরিষেবা দ্বারা SHARED মোডে ব্যবহার করা যেতে পারে। কিন্তু বর্ণনাকারীকে এক্সক্লুসিভ মোডের জন্য ক্লায়েন্ট কোডে পাঠানো যাবে না। /dev/snd/ ফাইলের বর্ণনাকারী ক্লায়েন্টকে খুব বিস্তৃত অ্যাক্সেস প্রদান করবে, তাই এটি SELinux দ্বারা ব্লক করা হয়েছে।

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

একটি anon_inode:dmabuf ফাইল বর্ণনাকারী Android Ion মেমরি লাইব্রেরি ব্যবহার করে তৈরি করা যেতে পারে।

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

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

HAL পরিবর্তন

AAudio পরিষেবাটি জানতে হবে যে এই anon_inode:dmabuf সমর্থিত কিনা। Android 10.0 এর আগে, এটি করার একমাত্র উপায় ছিল MMAP বাফারের আকারকে একটি ঋণাত্মক সংখ্যা হিসাবে পাস করা, যেমন। -2048 এর পরিবর্তে 2048, যদি সমর্থিত হয়। Android 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);