कैमरा HAL3 बफर प्रबंधन API

एंड्रॉइड 10 वैकल्पिक कैमरा एचएएल 3 बफर प्रबंधन एपीआई पेश करता है जो आपको विभिन्न मेमोरी प्राप्त करने और कैमरा एचएएल कार्यान्वयन में विलंबता ट्रेडऑफ को कैप्चर करने के लिए बफर प्रबंधन तर्क को लागू करने की अनुमति देता है।

कैमरा एचएएल को अपनी पाइपलाइन में कतारबद्ध एन अनुरोधों (जहां एन पाइपलाइन की गहराई के बराबर है) की आवश्यकता होती है, लेकिन इसे अक्सर एक ही समय में आउटपुट बफर के सभी एन सेट की आवश्यकता नहीं होती है।

उदाहरण के लिए, एचएएल के पास पाइपलाइन में कतारबद्ध आठ अनुरोध हो सकते हैं, लेकिन पाइपलाइन के अंतिम चरण में दो अनुरोधों के लिए केवल आउटपुट बफ़र्स की आवश्यकता होती है। एंड्रॉइड 9 और उससे कम पर चलने वाले उपकरणों पर, कैमरा फ्रेमवर्क बफ़र्स को आवंटित करता है जब अनुरोध एचएएल में कतारबद्ध होता है, इसलिए एचएएल में बफ़र्स के छह सेट हो सकते हैं जो उपयोग में नहीं हैं। एंड्रॉइड 10 में, कैमरा एचएएल 3 बफर प्रबंधन एपीआई बफ़र्स के छह सेटों को मुक्त करने के लिए आउटपुट बफ़र्स को डिकूप करने की अनुमति देता है। इससे हाई-एंड डिवाइस पर सैकड़ों मेगाबाइट मेमोरी बचत हो सकती है और कम मेमोरी वाले डिवाइस के लिए भी फायदेमंद हो सकता है।

चित्र 1 Android 9 और उसके बाद के संस्करण चलाने वाले उपकरणों के लिए कैमरा HAL इंटरफ़ेस का आरेख दिखाता है। चित्र 2 Android 10 में कैमरा HAL3 बफर प्रबंधन API के साथ कैमरा HAL इंटरफ़ेस दिखाता है।

9 या उससे कम में बफर प्रबंधन

चित्रा 1. एंड्रॉइड 9 और उससे कम में कैमरा एचएएल इंटरफ़ेस

Android 10 . में बफर प्रबंधन

चित्रा 2. बफर प्रबंधन एपीआई का उपयोग कर एंड्रॉइड 10 में कैमरा एचएएल इंटरफ़ेस

बफर प्रबंधन एपीआई लागू करना

बफर प्रबंधन एपीआई को लागू करने के लिए, कैमरा एचएएल को यह करना होगा:

कैमरा एचएएल बफ़र्स का अनुरोध करने और वापस करने के लिए ICameraDeviceCallback.hal requestStreamBuffers returnStreamBuffers विधियों का उपयोग करता है। HAL को ICameraDeviceSession.hal में signalStreamFlush विधि को भी लागू करना चाहिए ताकि कैमरा HAL को बफ़र्स वापस करने के लिए संकेत दिया जा सके।

अनुरोधस्ट्रीमबफर

कैमरा फ्रेमवर्क से बफ़र्स का अनुरोध करने के लिए requestStreamBuffers विधि का उपयोग करें। कैमरा HAL3 बफर प्रबंधन API का उपयोग करते समय, कैमरा फ्रेमवर्क से कैप्चर अनुरोधों में आउटपुट बफ़र्स नहीं होते हैं, अर्थात, StreamBuffer bufferId 0 है। इसलिए, कैमरा एचएएल को कैमरा फ्रेमवर्क से बफ़र्स का अनुरोध करने के लिए requestStreamBuffers का उपयोग करना चाहिए।

requestStreamBuffers विधि कॉल करने वाले को एक ही कॉल में कई आउटपुट स्ट्रीम से कई बफ़र्स का अनुरोध करने की अनुमति देती है, जिससे कम HIDL IPC कॉल की अनुमति मिलती है। हालांकि, कॉल में अधिक समय लगता है जब एक ही समय में अधिक बफ़र्स का अनुरोध किया जाता है और यह कुल अनुरोध-से-परिणाम विलंबता को नकारात्मक रूप से प्रभावित कर सकता है। इसके अलावा, क्योंकि अनुरोध में requestStreamBuffers को कैमरा सेवा में क्रमबद्ध किया जाता है, यह अनुशंसा की जाती है कि कैमरा एचएएल बफ़र्स का अनुरोध करने के लिए एक समर्पित उच्च-प्राथमिकता वाले थ्रेड का उपयोग करें।

यदि बफर अनुरोध विफल हो जाता है, तो कैमरा एचएएल को गैर-घातक त्रुटियों को ठीक से संभालने में सक्षम होना चाहिए। निम्न सूची सामान्य कारणों का वर्णन करती है कि बफर अनुरोध विफल हो जाते हैं और उन्हें कैमरा एचएएल द्वारा कैसे नियंत्रित किया जाना चाहिए।

  • ऐप आउटपुट स्ट्रीम से डिस्कनेक्ट हो जाता है: यह एक गैर-घातक त्रुटि है। कैमरा एचएएल को डिस्कनेक्टेड स्ट्रीम को लक्षित करने वाले किसी भी कैप्चर अनुरोध के लिए ERROR_REQUEST भेजना चाहिए और सामान्य रूप से बाद के अनुरोधों को संसाधित करने के लिए तैयार रहना चाहिए।
  • टाइमआउट: यह तब हो सकता है जब कोई ऐप कुछ बफ़र्स को होल्ड करते हुए गहन प्रसंस्करण करने में व्यस्त हो। कैमरा एचएएल को कैप्चर अनुरोधों के लिए ERROR_REQUEST भेजना चाहिए जो टाइमआउट त्रुटि के कारण पूरा नहीं किया जा सकता है और सामान्य रूप से बाद के अनुरोधों को संसाधित करने के लिए तैयार रहना चाहिए।
  • कैमरा फ्रेमवर्क एक नया स्ट्रीम कॉन्फ़िगरेशन तैयार कर रहा है: कैमरा एचएएल को तब तक इंतजार करना चाहिए जब तक कि अगला configureStreams कॉल पूरा न हो जाए, फिर से requestStreamBuffers को कॉल करने से पहले।
  • कैमरा एचएएल अपनी बफर सीमा ( maxBuffers फ़ील्ड) तक पहुँच गया है: कैमरा एचएएल को तब तक प्रतीक्षा करनी चाहिए जब तक कि वह फिर से requestStreamBuffers को कॉल करने से पहले स्ट्रीम के कम से कम एक बफर को वापस न कर दे।

रिटर्नस्ट्रीमबफर

कैमरा फ्रेमवर्क में अतिरिक्त बफ़र्स वापस करने के लिए returnStreamBuffers विधि का उपयोग करें। कैमरा एचएएल आम तौर पर प्रक्रिया कैप्चर processCaptureResult विधि के माध्यम से कैमरे के ढांचे में बफर लौटाता है, लेकिन यह केवल कैमरा एचएएल को भेजे गए कैप्चर अनुरोधों के लिए जिम्मेदार हो सकता है। requestStreamBuffers विधि के साथ, कैमरा एचएएल कार्यान्वयन के लिए कैमरा फ्रेमवर्क द्वारा अनुरोधित की तुलना में अधिक बफ़र्स बनाए रखना संभव है। यह तब होता है जब returnStreamBuffers विधि का उपयोग किया जाना चाहिए। यदि एचएएल कार्यान्वयन कभी भी अनुरोध से अधिक बफ़र्स नहीं रखता है, तो कैमरा एचएएल कार्यान्वयन को returnStreamBuffers विधि को कॉल करने की आवश्यकता नहीं है।

सिग्नलस्ट्रीमफ्लश

कैमरा एचएएल को सभी बफ़र्स को हाथ में वापस करने के लिए सूचित करने के लिए कैमरा फ्रेमवर्क द्वारा signalStreamFlush विधि को कॉल किया जाता है। इसे आम तौर पर तब कहा जाता है जब कैमरा फ्रेमवर्क configureStreams को कॉल करने वाला होता है और कैमरा कैप्चर पाइपलाइन को खत्म करना चाहिए। returnStreamBuffers विधि के समान, यदि कैमरा एचएएल कार्यान्वयन अनुरोध से अधिक बफर नहीं रखता है, तो इस विधि का खाली कार्यान्वयन संभव है।

कैमरा फ्रेमवर्क signalStreamFlush को कॉल करने के बाद, फ्रेमवर्क कैमरा एचएएल को नए कैप्चर अनुरोध भेजना बंद कर देता है जब तक कि सभी बफर कैमरा फ्रेमवर्क में वापस नहीं आ जाते। जब सभी बफ़र्स वापस आ जाते हैं, तो requestStreamBuffers विधि कॉल विफल हो जाती है, और कैमरा फ्रेमवर्क एक स्वच्छ स्थिति में अपना काम जारी रख सकता है। कैमरा फ्रेमवर्क तब या तो configureStreams या processCaptureRequest विधि को कॉल करता है। यदि कैमरा फ्रेमवर्क configureStreams विधि को कॉल करता है, तो configureStreams कॉल सफलतापूर्वक वापस आने के बाद कैमरा HAL बफ़र्स के लिए फिर से अनुरोध करना शुरू कर सकता है। यदि कैमरा फ्रेमवर्क processCaptureRequest विधि को कॉल करता है, तो कैमरा HAL, processCaptureRequest कॉल के दौरान बफ़र्स का अनुरोध करना शुरू कर सकता है।

signalStreamFlush विधि और flush विधि के लिए अर्थशास्त्र अलग हैं। जब flush विधि को कॉल किया जाता है, तो HAL पाइपलाइन को जल्द से जल्द निकालने के लिए ERROR_REQUEST के साथ लंबित कैप्चर अनुरोधों को रोक सकता है। जब signalStreamFlush विधि को कॉल किया जाता है, तो एचएएल को सभी लंबित कैप्चर अनुरोधों को सामान्य रूप से पूरा करना होगा और सभी बफ़र्स को कैमरा फ्रेमवर्क में वापस करना होगा।

signalStreamFlush विधि और अन्य विधियों के बीच एक और अंतर यह है कि signalStreamFlush एक तरफा एचआईडीएल विधि है, जिसका अर्थ है कि एचएएल को signalStreamFlush कॉल प्राप्त होने से पहले कैमरा फ्रेमवर्क अन्य अवरुद्ध एपीआई में कॉल कर सकता है। इसका मतलब यह है कि signalStreamFlush विधि और अन्य विधियां (विशेष रूप से configureStreams विधि) कैमरे के एचएएल में कैमरे के ढांचे में बुलाए गए क्रम से अलग क्रम में पहुंच सकती हैं। इस अतुल्यकालिक समस्या को हल करने के लिए, streamConfigCounter फ़ील्ड को StreamConfiguration में जोड़ा गया था और signalStreamFlush विधि के लिए एक तर्क के रूप में जोड़ा गया था। कैमरा एचएएल कार्यान्वयन को यह निर्धारित करने के लिए streamConfigCounter तर्क का उपयोग करना चाहिए कि क्या signalStreamFlush कॉल इसके संबंधित configureStreams कॉल के बाद आता है। उदाहरण के लिए चित्र 3 देखें।

देर से आने वाले कॉल को हैंडल करना

चित्रा 3. कैमरा एचएएल को देर से आने वाले सिग्नलस्ट्रीमफ्लश कॉल का पता लगाना और संभालना चाहिए

बफ़र प्रबंधन API को लागू करते समय व्यवहार में परिवर्तन

बफर प्रबंधन तर्क को लागू करने के लिए बफर प्रबंधन एपीआई का उपयोग करते समय, कैमरा और कैमरा एचएएल कार्यान्वयन में निम्नलिखित संभावित व्यवहार परिवर्तनों पर विचार करें:

  • कैप्चर अनुरोध कैमरे पर तेजी से और अधिक बार आते हैं: बफर प्रबंधन एपीआई के बिना, कैमरा फ्रेमवर्क कैमरा एचएएल को कैप्चर अनुरोध भेजने से पहले प्रत्येक कैप्चर अनुरोध के लिए आउटपुट बफर का अनुरोध करता है। बफर प्रबंधन एपीआई का उपयोग करते समय, कैमरा फ्रेमवर्क को अब बफ़र्स की प्रतीक्षा करने की आवश्यकता नहीं होती है और इसलिए कैमरा एचएएल को पहले कैप्चर अनुरोध भेज सकता है।

    इसके अलावा, बफर प्रबंधन एपीआई के बिना, कैमरा फ्रेमवर्क कैप्चर अनुरोध भेजना बंद कर देता है यदि कैप्चर अनुरोध के आउटपुट स्ट्रीम में से एक बफ़र्स की अधिकतम संख्या तक पहुँच जाता है जिसे एचएएल एक समय में पकड़ सकता है (यह मान कैमरा एचएएल द्वारा निर्दिष्ट किया गया है। HalStream::maxBuffers फ़ील्ड configureStreams कॉल के रिटर्न वैल्यू में)। बफर प्रबंधन एपीआई के साथ, यह थ्रॉटलिंग व्यवहार अब मौजूद नहीं है और एचएएल के पास बहुत से कैप्चर अनुरोध कतारबद्ध होने पर कैमरा एचएएल कार्यान्वयन processCaptureRequest कैप्चर अनुरोध कॉल स्वीकार नहीं करना चाहिए।

  • requestStreamBuffers कॉल विलंबता महत्वपूर्ण रूप से भिन्न होती है: ऐसे कई कारण हैं requestStreamBuffers कॉल में औसत से अधिक समय लग सकता है। उदाहरण के लिए:

    • नई बनाई गई स्ट्रीम के पहले कुछ बफ़र्स के लिए, कॉल में अधिक समय लग सकता है क्योंकि डिवाइस को मेमोरी आवंटित करने की आवश्यकता होती है।
    • प्रत्येक कॉल में अनुरोधित बफ़र्स की संख्या के अनुपात में अपेक्षित विलंबता बढ़ जाती है।
    • ऐप में बफ़र्स हैं और प्रोसेसिंग में व्यस्त है। इससे बफ़र अनुरोध धीमा हो सकता है या बफ़र्स की कमी या व्यस्त CPU के कारण टाइमआउट हिट हो सकता है।

बफर प्रबंधन रणनीतियाँ

बफर प्रबंधन एपीआई विभिन्न प्रकार की बफर प्रबंधन रणनीतियों को लागू करने की अनुमति देता है। कुछ उदाहरण निम्न हैं:

  • पिछड़ा संगत: एचएएल processCaptureRequest कैप्चर अनुरोध कॉल के दौरान कैप्चर अनुरोध के लिए बफर का अनुरोध करता है। यह रणनीति कोई मेमोरी बचत प्रदान नहीं करती है, लेकिन बफर प्रबंधन एपीआई के पहले कार्यान्वयन के रूप में काम कर सकती है, जिसके लिए मौजूदा कैमरा एचएएल में बहुत कम कोड परिवर्तन की आवश्यकता होती है।
  • अधिकतम मेमोरी बचत: कैमरा एचएएल केवल आउटपुट बफ़र्स को भरने के लिए आवश्यक होने से ठीक पहले अनुरोध करता है। यह रणनीति अधिकतम मेमोरी बचत की अनुमति देती है। संभावित नकारात्मक पक्ष अधिक कैमरा पाइपलाइन जंक है जब बफर अनुरोधों को समाप्त होने में असामान्य रूप से लंबा समय लगता है।
  • कैश्ड: कैमरा एचएएल कुछ बफ़र्स को कैश करता है ताकि कभी-कभार धीमे बफर अनुरोध से इसके प्रभावित होने की संभावना कम हो।

कैमरा एचएएल विशेष उपयोग के मामलों के लिए विभिन्न रणनीतियों को अपना सकता है, उदाहरण के लिए, उपयोग के मामलों के लिए अधिकतम मेमोरी सेविंग रणनीति का उपयोग करना जो बहुत अधिक मेमोरी का उपयोग करते हैं और अन्य उपयोग के मामलों के लिए पिछड़े-संगत रणनीति का उपयोग करते हैं।

बाहरी कैमरे में नमूना कार्यान्वयन एचएएल

बाहरी कैमरा एचएएल को एंड्रॉइड 9 में पेश किया गया था और इसे hardware/interfaces/camera/device/3.5/ पर सोर्स ट्री में पाया जा सकता है। Android 10 में, इसे ExternalCameraDeviceSession.cpp शामिल करने के लिए अद्यतन किया गया है, जो बफर प्रबंधन API का कार्यान्वयन है। यह बाहरी कैमरा एचएएल बफर प्रबंधन रणनीतियों में उल्लिखित अधिकतम मेमोरी बचत रणनीति को सी ++ कोड की कुछ सौ पंक्तियों में लागू करता है।