मल्टी-कैमरा एपीआई

ध्यान दें: इस पेज पर Camera2 पैकेज के बारे में बताया गया है. अगर आपके ऐप्लिकेशन को Camera2 की खास और लो-लेवल सुविधाओं की ज़रूरत नहीं है, तो हमारा सुझाव है कि आप CameraX का इस्तेमाल करें. CameraX और Camera2, दोनों ही Android 5.0 (एपीआई लेवल 21) और इसके बाद के वर्शन पर काम करते हैं.

मल्टी-कैमरा की सुविधा, Android 9 (एपीआई लेवल 28) के साथ लॉन्च की गई थी. इसकी रिलीज़ के बाद से, बाज़ार में ऐसे डिवाइस आ गए हैं जो एपीआई के साथ काम करते हैं. मल्टी-कैमरा के इस्तेमाल के कई उदाहरण, किसी खास हार्डवेयर कॉन्फ़िगरेशन से जुड़े होते हैं. दूसरे शब्दों में, इस्तेमाल के सभी उदाहरण हर डिवाइस के साथ काम नहीं करते. इस वजह से, मल्टी-कैमरा की सुविधाएं Play Feature Delivery के लिए बेहतर विकल्प हैं.

इस्तेमाल के कुछ सामान्य उदाहरणों में ये शामिल हैं:

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

लॉजिकल और फ़िज़िकल कैमरों के बीच अंतर

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

फ़ोन बनाने वाली कई कंपनियां, फ़र्स्ट पार्टी कैमरा ऐप्लिकेशन बनाती हैं. आम तौर पर, ये ऐप्लिकेशन उनके डिवाइसों पर पहले से इंस्टॉल होते हैं. हार्डवेयर की सभी सुविधाओं का इस्तेमाल करने के लिए, वे निजी या छिपे हुए एपीआई का इस्तेमाल कर सकते हैं. इसके अलावा, उन्हें ड्राइवर को लागू करने के तरीके से खास सुविधाएं मिल सकती हैं. ये सुविधाएं, अन्य ऐप्लिकेशन के पास नहीं होती हैं. कुछ डिवाइसों में लॉजिकल कैमरे का कॉन्सेप्ट इस्तेमाल किया जाता है. इसके लिए, अलग-अलग फ़िज़िकल कैमरों से फ़्रेम की फ़्यूज़्ड स्ट्रीम उपलब्ध कराई जाती है. हालांकि, यह सुविधा सिर्फ़ कुछ खास ऐप्लिकेशन के लिए उपलब्ध होती है. आम तौर पर, फ़्रेमवर्क में सिर्फ़ एक फ़िज़िकल कैमरा दिखता है. Android 9 से पहले, तीसरे पक्ष के डेवलपर के लिए स्थिति को इस डायग्राम में दिखाया गया है:

कैमरे की सुविधाएं, आम तौर पर सिर्फ़ खास ऐप्लिकेशन के लिए उपलब्ध होती हैं
पहली इमेज. कैमरे की सुविधाएं, आम तौर पर सिर्फ़ खास ऐप्लिकेशन के लिए उपलब्ध होती हैं

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

Android 9 से, डेवलपर को सभी कैमरा डिवाइसों का पूरा ऐक्सेस मिलता है
दूसरी इमेज. Android 9 से, डेवलपर को सभी कैमरा डिवाइसों का पूरा ऐक्सेस मिलता है

लॉजिकल कैमरा क्या उपलब्ध कराता है, यह पूरी तरह से इस बात पर निर्भर करता है कि ओईएम ने कैमरा एचएएल को कैसे लागू किया है. उदाहरण के लिए, Pixel 3 जैसे डिवाइस में लॉजिकल कैमरे को इस तरह से लागू किया जाता है कि वह अनुरोध की गई फ़ोकल लेंथ और क्रॉप किए गए हिस्से के आधार पर, अपने फ़िज़िकल कैमरों में से किसी एक को चुनता है.

मल्टी-कैमरा एपीआई

एपीआई के नए वर्शन में ये नए कॉन्सटैंट, क्लास, और तरीके जोड़े गए हैं:

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

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

एक साथ कई स्ट्रीम

एक साथ कई कैमरा स्ट्रीम इस्तेमाल करना: इसमें एक ही कैमरे में एक साथ कई स्ट्रीम इस्तेमाल करने के नियम शामिल हैं. एक से ज़्यादा कैमरों के लिए भी यही नियम लागू होते हैं. हालांकि, इसमें एक अहम बदलाव किया गया है. CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA में, लॉजिकल YUV_420_888 या रॉ स्ट्रीम को दो फ़िज़िकल स्ट्रीम से बदलने का तरीका बताया गया है. इसका मतलब है कि YUV या RAW टाइप की हर स्ट्रीम को, एक जैसे टाइप और साइज़ की दो स्ट्रीम से बदला जा सकता है. सिंगल-कैमरा डिवाइसों के लिए, यहां दिए गए कॉन्फ़िगरेशन की कैमरा स्ट्रीम से शुरुआत की जा सकती है:

  • स्ट्रीम 1: YUV टाइप, लॉजिकल कैमरा id = 0 से MAXIMUM साइज़

इसके बाद, एक से ज़्यादा कैमरे इस्तेमाल करने की सुविधा वाले डिवाइस पर, लॉजिकल YUV स्ट्रीम को दो फ़िज़िकल स्ट्रीम से बदलकर सेशन बनाया जा सकता है:

  • स्ट्रीम 1: YUV टाइप, फ़िज़िकल कैमरे id = 1 से MAXIMUM साइज़
  • स्ट्रीम 2: YUV टाइप, फ़िज़िकल कैमरे id = 2 से MAXIMUM साइज़

YUV या RAW स्ट्रीम को दो मिलती-जुलती स्ट्रीम से सिर्फ़ तब बदला जा सकता है, जब वे दोनों कैमरे, लॉजिकल कैमरा ग्रुपिंग का हिस्सा हों. यह ग्रुपिंग, CameraCharacteristics.getPhysicalCameraIds() में मौजूद होती है.

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

एक से ज़्यादा फ़िज़िकल कैमरों के साथ सेशन बनाना

एक से ज़्यादा कैमरे वाले डिवाइस पर फ़िज़िकल कैमरों का इस्तेमाल करते समय, एक CameraDevice (लॉजिकल कैमरा) खोलें और एक ही सेशन में उससे इंटरैक्ट करें. एपीआई CameraDevice.createCaptureSession(SessionConfiguration config) का इस्तेमाल करके, सिंगल सेशन बनाएं. इसे एपीआई लेवल 28 में जोड़ा गया था. सेशन कॉन्फ़िगरेशन में कई आउटपुट कॉन्फ़िगरेशन होते हैं. इनमें से हर एक में आउटपुट टारगेट का एक सेट होता है. साथ ही, इसमें चुने गए फ़िज़िकल कैमरे का आईडी भी शामिल हो सकता है.

SessionConfiguration और OutputConfiguration मॉडल
तीसरी इमेज. SessionConfiguration और OutputConfiguration मॉडल

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

दो फ़िज़िकल कैमरों का इस्तेमाल करना

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

/**
 * Helper class used to encapsulate a logical camera and two underlying
 * physical cameras
 */
data class DualCamera(val logicalId: String, val physicalId1: String, val physicalId2: String)

fun findDualCameras(manager: CameraManager, facing: Int? = null): List<DualCamera> {
    val dualCameras = mutableListOf<DualCamera>()

    // Iterate over all the available camera characteristics.
    manager.cameraIdList.map {
        Pair(manager.getCameraCharacteristics(it), it)
    }.filter {
        // Filter by cameras facing the requested direction.
        facing == null || it.first.get(CameraCharacteristics.LENS_FACING) == facing
    }.filter {
        // Filter by logical cameras.
        // CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA requires API >= 28.
        it.first.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES)?.contains(
            CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA
        ) ?: false
    }.forEach {
        // All possible pairs from the list of physical cameras are valid results.
        // NOTE: There could be N physical cameras as part of a logical camera grouping.
        // getPhysicalCameraIds() requires API >= 28.
        val physicalCameras = it.first.physicalCameraIds.toTypedArray()
        for (idx1 in 0 until physicalCameras.size) {
            for (idx2 in (idx1 + 1) until physicalCameras.size) {
                dualCameras.add(
                    DualCamera(
                        it.second, physicalCameras[idx1], physicalCameras[idx2]
                    )
                )
            }
        }
    }

    return dualCameras
}

फ़िज़िकल कैमरों की स्थिति को लॉजिकल कैमरा कंट्रोल करता है. "ड्यूअल कैमरा" खोलने के लिए, फ़िज़िकल कैमरे से जुड़ा लॉजिकल कैमरा खोलें:

fun openDualCamera(
    cameraManager: CameraManager,
    dualCamera: DualCamera,
    executor: Executor,
    callback: (CameraDevice) -> Unit
) {

    // openCamera() requires API >= 28.
    cameraManager.openCamera(
        dualCamera.logicalId, executor,
        object : CameraDevice.StateCallback() {
            override fun onOpened(device: CameraDevice) = callback(device)
            // Omitting for brevity...
            override fun onError(device: CameraDevice, error: Int) = onDisconnected(device)
            override fun onDisconnected(device: CameraDevice) = device.close()
        }
    )
}

कौनसा कैमरा खोलना है, यह चुनने के अलावा, कैमरा खोलने की प्रोसेस Android के पिछले वर्शन जैसी ही है. नए सेशन कॉन्फ़िगरेशन एपीआई का इस्तेमाल करके कैप्चर सेशन बनाने से, फ़्रेमवर्क को कुछ टारगेट को खास फ़िज़िकल कैमरा आईडी से जोड़ने का निर्देश मिलता है:

/**
 * Helper type definition that encapsulates 3 sets of output targets:
 *
 * 1. Logical camera
 * 2. First physical camera
 * 3. Second physical camera
 */
typealias DualCameraOutputs =
    Triple<MutableList<Surface>?, MutableList<Surface>?, MutableList<Surface>?>

fun createDualCameraSession(
    cameraManager: CameraManager,
    dualCamera: DualCamera,
    targets: DualCameraOutputs,
    executor: Executor,
    callback: (CameraCaptureSession) -> Unit
) {

    // Create 3 sets of output configurations: one for the logical camera, and
    // one for each of the physical cameras.
    val outputConfigsLogical = targets.first?.map { OutputConfiguration(it) }
    val outputConfigsPhysical1 = targets.second?.map {
        OutputConfiguration(it).apply { setPhysicalCameraId(dualCamera.physicalId1) }
    }
    val outputConfigsPhysical2 = targets.third?.map {
        OutputConfiguration(it).apply { setPhysicalCameraId(dualCamera.physicalId2) }
    }

    // Put all the output configurations into a single flat array.
    val outputConfigsAll = arrayOf(
        outputConfigsLogical, outputConfigsPhysical1, outputConfigsPhysical2
    )
        .filterNotNull().flatMap { it }

    // Instantiate a session configuration that can be used to create a session.
    val sessionConfiguration = SessionConfiguration(
        SessionConfiguration.SESSION_REGULAR,
        outputConfigsAll, executor,
        object : CameraCaptureSession.StateCallback() {
            override fun onConfigured(session: CameraCaptureSession) = callback(session)
            // Omitting for brevity...
            override fun onConfigureFailed(session: CameraCaptureSession) = session.device.close()
        }
    )

    // Open the logical camera using the previously defined function.
    openDualCamera(cameraManager, dualCamera, executor = executor) {

        // Finally create the session and return using the callback.
        it.createCaptureSession(sessionConfiguration)
    }
}

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

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

Zoom के इस्तेमाल का उदाहरण

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

ज़ूम करने के लेवल के इस्तेमाल के उदाहरण के लिए, कैमरे बदलने का उदाहरण
चौथी इमेज. ज़ूम करने के लेवल के इस्तेमाल के उदाहरण के लिए, कैमरे बदलने का उदाहरण (Pixel 3 के विज्ञापन से)

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

fun findShortLongCameraPair(manager: CameraManager, facing: Int? = null): DualCamera? {

    return findDualCameras(manager, facing).map {
        val characteristics1 = manager.getCameraCharacteristics(it.physicalId1)
        val characteristics2 = manager.getCameraCharacteristics(it.physicalId2)

        // Query the focal lengths advertised by each physical camera.
        val focalLengths1 = characteristics1.get(
            CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS
        ) ?: floatArrayOf(0F)
        val focalLengths2 = characteristics2.get(
            CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS
        ) ?: floatArrayOf(0F)

        // Compute the largest difference between min and max focal lengths between cameras.
        val focalLengthsDiff1 = (focalLengths2.maxOrNull() ?: 0f) - (focalLengths1.minOrNull() ?: 0f)
        val focalLengthsDiff2 = (focalLengths1.maxOrNull() ?: 0f) - (focalLengths2.minOrNull() ?: 0f)

        // Return the pair of camera IDs and the difference between min and max focal lengths.
        if (focalLengthsDiff1 < focalLengthsDiff2) {
            Pair(DualCamera(it.logicalId, it.physicalId1, it.physicalId2), focalLengthsDiff1)
        } else {
            Pair(DualCamera(it.logicalId, it.physicalId2, it.physicalId1), focalLengthsDiff2)
        }

        // Return only the pair with the largest difference, or null if no pairs are found.
    }.maxByOrNull { it.second }?.first
}

इसके लिए, दो SurfaceViews का इस्तेमाल करना सही रहेगा. हर स्ट्रीम के लिए एक. उपयोगकर्ता के इंटरैक्शन के आधार पर, ये SurfaceViews स्वैप हो जाते हैं, ताकि किसी भी समय सिर्फ़ एक ही दिखे.

यहां दिए गए कोड से, लॉजिकल कैमरा खोलने, कैमरा आउटपुट कॉन्फ़िगर करने, कैमरा सेशन बनाने, और दो झलक वाली स्ट्रीम शुरू करने का तरीका पता चलता है:

val cameraManager: CameraManager = ...
val cameraExecutor: Executor = ...  // owned by your activity / fragment

// Get the two output targets from the activity / fragment.
val surface1 = ...  // from SurfaceView
val surface2 = ...  // from SurfaceView

val dualCamera = findShortLongCameraPair(cameraManager) ?: return
val outputTargets = DualCameraOutputs(
    null, mutableListOf(surface1), mutableListOf(surface2)
)

// Here you open the logical camera, configure the outputs and create a session.
createDualCameraSession(
    cameraManager, dualCamera, targets = outputTargets, executor = cameraExecutor
) { session ->

    // Create a single request which has one target for each physical camera.
    // NOTE: Each target receive frames from only its associated physical camera.
    val requestTemplate = CameraDevice.TEMPLATE_PREVIEW
    val captureRequest = session.device.createCaptureRequest(requestTemplate).apply {
        arrayOf(surface1, surface2).forEach { addTarget(it) }
    }.build()

    // Set the sticky request for the session and you are done.
    session.setRepeatingRequest(captureRequest, null, null)
}

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

लेंस डिस्टॉर्शन

सभी लेंस से ली गई फ़ोटो में कुछ हद तक डिस्टॉर्शन होता है. Android में, CameraCharacteristics.LENS_DISTORTION का इस्तेमाल करके, लेंस से होने वाले डिस्टॉर्शन के बारे में क्वेरी की जा सकती है. यह CameraCharacteristics.LENS_RADIAL_DISTORTION की जगह लेता है, जो अब काम नहीं करता. लॉजिकल कैमरों के लिए, डिस्टॉर्शन कम से कम होता है. साथ ही, आपका ऐप्लिकेशन फ़्रेम को कम या ज़्यादा इस्तेमाल कर सकता है, जैसा कि वे कैमरे से आते हैं. फ़िज़िकल कैमरों के लिए, लेंस के कॉन्फ़िगरेशन काफ़ी अलग हो सकते हैं. खास तौर पर, वाइड लेंस के लिए.

कुछ डिवाइसों में, CaptureRequest.DISTORTION_CORRECTION_MODE का इस्तेमाल करके, डिस्टॉर्शन को अपने-आप ठीक करने की सुविधा लागू की जा सकती है. ज़्यादातर डिवाइसों के लिए, डिस्टॉर्शन सुधार की सुविधा डिफ़ॉल्ट रूप से चालू होती है.

val cameraSession: CameraCaptureSession = ...

// Use still capture template to build the capture request.
val captureRequest = cameraSession.device.createCaptureRequest(
    CameraDevice.TEMPLATE_STILL_CAPTURE
)

// Determine if this device supports distortion correction.
val characteristics: CameraCharacteristics = ...
val supportsDistortionCorrection = characteristics.get(
    CameraCharacteristics.DISTORTION_CORRECTION_AVAILABLE_MODES
)?.contains(
    CameraMetadata.DISTORTION_CORRECTION_MODE_HIGH_QUALITY
) ?: false

if (supportsDistortionCorrection) {
    captureRequest.set(
        CaptureRequest.DISTORTION_CORRECTION_MODE,
        CameraMetadata.DISTORTION_CORRECTION_MODE_HIGH_QUALITY
    )
}

// Add output target, set other capture request parameters...

// Dispatch the capture request.
cameraSession.capture(captureRequest.build(), ...)

इस मोड में कैप्चर करने का अनुरोध सेट करने से, कैमरे से जनरेट होने वाले फ़्रेम रेट पर असर पड़ सकता है. आपके पास डिस्टॉर्शन सुधार की सुविधा को सिर्फ़ स्टिल इमेज कैप्चर करने के लिए सेट करने का विकल्प होता है.