कैमरा कैप्चर से जुड़े सेशन और अनुरोध

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

Android पर चलने वाले किसी डिवाइस में एक से ज़्यादा कैमरे हो सकते हैं. हर कैमरा CameraDevice, और CameraDevice एक साथ एक से ज़्यादा स्ट्रीम दे सकता है.

ऐसा करने की एक वजह यह है कि सिर्फ़ एक स्ट्रीम, क्रम में चलने वाले कैमरा फ़्रेम CameraDevice से, जिसे किसी ख़ास टास्क के लिए ऑप्टिमाइज़ किया गया है. जैसे, इसका इस्तेमाल फ़ोटो खींचने या वीडियो बनाने के लिए किया जा सकता है. रिकॉर्डिंग.स्ट्रीम, पैरलल पाइपलाइन की तरह काम करती हैं, जो रॉ फ़्रेम प्रोसेस करती हैं कैमरे से बाहर आती है,एक बार में एक फ़्रेम से बाहर निकलती है:

पहली इमेज. यूनिवर्सल कैमरा ऐप्लिकेशन बनाने से लिया गया इलस्ट्रेशन (Google I/O ‘18)

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

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

किसी प्रॉडक्ट को बनाने के लिए, CameraDevice का इस्तेमाल किया जा सकता है CameraCaptureSession, यह सिर्फ़ उस CameraDevice पर लागू होता है. CameraDevice को CameraCaptureSession का इस्तेमाल करके, हर रॉ फ़्रेम के लिए फ़्रेम कॉन्फ़िगरेशन. कॉन्टेंट बनाने कॉन्फ़िगरेशन से कैमरे के एट्रिब्यूट की जानकारी मिलती है. जैसे, ऑटोफ़ोकस, एपर्चर, इफ़ेक्ट, और एक्सपोज़र. हार्डवेयर की सीमाओं की वजह से, सिर्फ़ एक कॉन्फ़िगरेशन किसी भी समय कैमरा सेंसर में चालू रहता है. इसे active कॉन्फ़िगरेशन होना चाहिए.

हालांकि, स्ट्रीम के इस्तेमाल के उदाहरण CameraDevice इस्तेमाल करने के पिछले तरीकों को बेहतर बनाते हैं और उनमें बढ़ोतरी करते हैं का इस्तेमाल करके लाइव स्ट्रीम की जा सकती है. इससे कैमरे की स्ट्रीम को इस्तेमाल के उदाहरण के बारे में ज़्यादा जानें. उदाहरण के लिए, ऑप्टिमाइज़ करते समय यह बैटरी लाइफ़ बेहतर बना सकता है वीडियो कॉल.

CameraCaptureSession में उन सभी पाइपलाइन के बारे में बताया गया है जो CameraDevice. सेशन बनाने के बाद, न तो पाइपलाइन जोड़ी जा सकती हैं और न ही उन्हें हटाया जा सकता है. CameraCaptureSession ने इनकी पंक्ति बनाकर रखी है CaptureRequest जो ऐक्टिव कॉन्फ़िगरेशन बन जाते हैं.

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

बेहतर परफ़ॉर्मेंस के लिए, स्ट्रीम के इस्तेमाल के उदाहरण वाली सुविधा का इस्तेमाल करना

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

यह इससे कैमरा डिवाइस को कैमरा हार्डवेयर और सॉफ़्टवेयर पाइपलाइन को ऑप्टिमाइज़ करने में मदद मिलती है इसके लिए अलग-अलग फ़ॉर्मैट का इस्तेमाल करें. स्ट्रीम के इस्तेमाल के बारे में ज़्यादा जानकारी पाने के लिए केस, setStreamUseCase देखें.

'स्ट्रीम के इस्तेमाल के उदाहरण' सुविधा की मदद से, यह तय किया जा सकता है कि किसी खास स्ट्रीम का इस्तेमाल कैसे किया जाए ज़्यादा जानकारी के लिए, टेंप्लेट में टेंप्लेट सेट करने के अलावा CameraDevice.createCaptureRequest(). इससे कैमरे का हार्डवेयर ऑप्टिमाइज़ हो जाता है जैसे, ट्यूनिंग, सेंसर मोड या कैमरा सेंसर सेटिंग. इस्तेमाल के खास उदाहरणों के मुताबिक, क्वालिटी और इंतज़ार के समय में बदलाव.

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

  • DEFAULT: इसमें ऐप्लिकेशन के सभी मौजूदा व्यवहार शामिल हैं. यह 'नहीं' के बराबर है स्ट्रीम के इस्तेमाल का उदाहरण सेट कर सकते हैं.

  • PREVIEW: व्यूफ़ाइंडर या ऐप्लिकेशन में इमेज के विश्लेषण के लिए इसका सुझाव दिया जाता है.

  • STILL_CAPTURE: इसे अच्छी क्वालिटी वाले अच्छी क्वालिटी के वीडियो रिकॉर्ड करने के लिए ऑप्टिमाइज़ किया गया है. हालांकि, इसे कैप्चर करने के लिए नहीं बनाया गया है झलक जैसे फ़्रेम रेट बनाए रखने की उम्मीद की जाती है.

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

  • VIDEO_CALL: लंबे समय तक चलने वाले कैमरे के इस्तेमाल का सुझाव तब दिया जाता है, जब बैटरी तेज़ी से खर्च होती है चिंता.

  • PREVIEW_VIDEO_STILL: सोशल मीडिया ऐप्लिकेशन या एक स्ट्रीम के इस्तेमाल के लिए सुझाया गया मामले. यह अलग-अलग कामों में इस्तेमाल होने वाली स्ट्रीम है.

  • VENDOR_START: इसका इस्तेमाल, OEM के तय किए गए इस्तेमाल के उदाहरणों के लिए किया जाता है.

कैमरा कैप्चर सेशन बनाना

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

नीचे दिया गया कोड स्निपेट बताता है कि दो अलग-अलग तरीकों का इस्तेमाल करके, एक कैमरा सेशन कैसे तैयार किया जा सकता है आउटपुट बफ़र, एक SurfaceView और अन्य ImageReader. PREVIEW के स्ट्रीम इस्तेमाल के उदाहरण को previewSurface और STILL_CAPTURE स्ट्रीम का इस्तेमाल केस imReaderSurface से डिवाइस का हार्डवेयर इन स्ट्रीम को भी ऑप्टिमाइज़ कर सकता है आगे.

Kotlin


// Retrieve the target surfaces, which might be coming from a number of places:
// 1. SurfaceView, if you want to display the image directly to the user
// 2. ImageReader, if you want to read each frame or perform frame-by-frame
// analysis
// 3. OpenGL Texture or TextureView, although discouraged for maintainability
      reasons
// 4. RenderScript.Allocation, if you want to do parallel processing
val surfaceView = findViewById<SurfaceView>(...)
val imageReader = ImageReader.newInstance(...)

// Remember to call this only *after* SurfaceHolder.Callback.surfaceCreated()
val previewSurface = surfaceView.holder.surface
val imReaderSurface = imageReader.surface
val targets = listOf(previewSurface, imReaderSurface)

// Create a capture session using the predefined targets; this also involves
// defining the session state callback to be notified of when the session is
// ready
// Setup Stream Use Case while setting up your Output Configuration.
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
fun configureSession(device: CameraDevice, targets: List<Surface>){
    val configs = mutableListOf<OutputConfiguration>()
    val streamUseCase = CameraMetadata
        .SCALER_AVAILABLE_STREAM_USE_CASES_PREVIEW_VIDEO_STILL

    targets.forEach {
        val config = OutputConfiguration(it)
        config.streamUseCase = streamUseCase.toLong()
        configs.add(config)
    }
    ...
    device.createCaptureSession(session)
}

Java


// Retrieve the target surfaces, which might be coming from a number of places:
// 1. SurfaceView, if you want to display the image directly to the user
// 2. ImageReader, if you want to read each frame or perform frame-by-frame
      analysis
// 3. RenderScript.Allocation, if you want to do parallel processing
// 4. OpenGL Texture or TextureView, although discouraged for maintainability
      reasons
Surface surfaceView = findViewById<SurfaceView>(...);
ImageReader imageReader = ImageReader.newInstance(...);

// Remember to call this only *after* SurfaceHolder.Callback.surfaceCreated()
Surface previewSurface = surfaceView.getHolder().getSurface();
Surface imageSurface = imageReader.getSurface();
List<Surface> targets = Arrays.asList(previewSurface, imageSurface);

// Create a capture session using the predefined targets; this also involves defining the
// session state callback to be notified of when the session is ready
private void configureSession(CameraDevice device, List<Surface> targets){
    ArrayList<OutputConfiguration> configs= new ArrayList()
    String streamUseCase=  CameraMetadata
        .SCALER_AVAILABLE_STREAM_USE_CASES_PREVIEW_VIDEO_STILL

    for(Surface s : targets){
        OutputConfiguration config = new OutputConfiguration(s)
        config.setStreamUseCase(String.toLong(streamUseCase))
        configs.add(config)
}

device.createCaptureSession(session)
}

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

इनपुट पर उनके बफ़र में लिखे जाने पर ट्रांसफ़ॉर्मेशन ऐक्शन लागू होता है हर टारगेट के टाइप से तय होता है, जो कि Surface. Android फ़्रेमवर्क सक्रिय कॉन्फ़िगरेशन में किसी रॉ इमेज को हर टारगेट पर लागू होती है. रूपांतरण पिक्सेल प्रारूप और इसके आकार से नियंत्रित होता है खास तौर पर Surface.

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

एक कैप्चर अनुरोध

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

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

टेंप्लेट का इस्तेमाल करके, SurfaceView के लिए कैप्चर करने का अनुरोध बनाने के लिए बिना किसी संशोधन के पूर्वावलोकन के लिए डिज़ाइन किया गया है, तो इसका उपयोग करें CameraDevice.TEMPLATE_PREVIEW:

Kotlin

val session: CameraCaptureSession = ...  // from CameraCaptureSession.StateCallback
val captureRequest = session.device.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW)
captureRequest.addTarget(previewSurface)

Java

CameraCaptureSession session = ...;  // from CameraCaptureSession.StateCallback
CaptureRequest.Builder captureRequest =
    session.getDevice().createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
captureRequest.addTarget(previewSurface);

कैप्चर अनुरोध निर्धारित करके, अब आप डिस्पैच कर सकते हैं उसे कैमरा सत्र पर लाने के लिए:

Kotlin

val session: CameraCaptureSession = ...  // from CameraCaptureSession.StateCallback
val captureRequest: CaptureRequest = ...  // from CameraDevice.createCaptureRequest()

// The first null argument corresponds to the capture callback, which you
// provide if you want to retrieve frame metadata or keep track of failed capture
// requests that can indicate dropped frames; the second null argument
// corresponds to the Handler used by the asynchronous callback, which falls
// back to the current thread's looper if null
session.capture(captureRequest.build(), null, null)

Java

CameraCaptureSession session = ...;  // from CameraCaptureSession.StateCallback
CaptureRequest captureRequest = ...;  // from CameraDevice.createCaptureRequest()

// The first null argument corresponds to the capture callback, which you
// provide if you want to retrieve frame metadata or keep track of failed
// capture
// requests that can indicate dropped frames; the second null argument
// corresponds to the Handler used by the asynchronous callback, which falls
// back to the current thread's looper if null
session.capture(captureRequest.build(), null, null);

जब किसी आउटपुट फ़्रेम को तय बफ़र में रखा जाता है, तो कैप्चर करें कॉलबैक ट्रिगर होता है. कई मामलों में अतिरिक्त कॉलबैक, जैसे ImageReader.OnImageAvailableListener, तब ट्रिगर होता है, जब उसमें मौजूद फ़्रेम प्रोसेस हो जाता है. यह इस समय पर है इस पॉइंट से तय करें कि बताए गए बफ़र से इमेज का डेटा वापस मिल सकता है.

कैप्चरअनुरोध दोहराएं

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

Kotlin

val session: CameraCaptureSession = ...  // from CameraCaptureSession.StateCallback
val captureRequest: CaptureRequest = ...  // from CameraDevice.createCaptureRequest()

// This keeps sending the capture request as frequently as possible until
// the
// session is torn down or session.stopRepeating() is called
// session.setRepeatingRequest(captureRequest.build(), null, null)

Java

CameraCaptureSession session = ...;  // from CameraCaptureSession.StateCallback
CaptureRequest captureRequest = ...;  // from CameraDevice.createCaptureRequest()

// This keeps sending the capture request as frequently as possible until the
// session is torn down or session.stopRepeating() is called
// session.setRepeatingRequest(captureRequest.build(), null, null);

कैप्चर करने के बार-बार किए जाने वाले अनुरोध की वजह से, कैमरा डिवाइस लगातार वीडियो रिकॉर्ड करता रहता है दिए गए CaptureRequest में सेटिंग का इस्तेमाल करके इमेज. Camera2 API उपयोगकर्ताओं को CaptureRequests को दोहराएं, जैसा कि इसमें देखा गया है कैमरा2 सैंपल GitHub पर डेटा स्टोर करने की जगह. यह वीडियो कैप्चर करके, स्लो मोशन वाले वीडियो को रेंडर कर सकता है दोहराए जाने वाले बर्स्ट CaptureRequests का इस्तेमाल करके, हाई-स्पीड (स्लो मोशन) वीडियो जैसा कि Camera2 स्लो मोशन वीडियो सैंपल ऐप्लिकेशन में दिखाया गया है GitHub पर.

इंटरलीफ़ कैप्चर रिक्वेस्ट

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

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

Kotlin

val session: CameraCaptureSession = ...  // from CameraCaptureSession.StateCallback

// Create the repeating request and dispatch it
val repeatingRequest = session.device.createCaptureRequest(
CameraDevice.TEMPLATE_PREVIEW)
repeatingRequest.addTarget(previewSurface)
session.setRepeatingRequest(repeatingRequest.build(), null, null)

// Some time later...

// Create the single request and dispatch it
// NOTE: This can disrupt the ongoing repeating request momentarily
val singleRequest = session.device.createCaptureRequest(
CameraDevice.TEMPLATE_STILL_CAPTURE)
singleRequest.addTarget(imReaderSurface)
session.capture(singleRequest.build(), null, null)

Java

CameraCaptureSession session = ...;  // from CameraCaptureSession.StateCallback

// Create the repeating request and dispatch it
CaptureRequest.Builder repeatingRequest =
session.getDevice().createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
repeatingRequest.addTarget(previewSurface);
session.setRepeatingRequest(repeatingRequest.build(), null, null);

// Some time later...

// Create the single request and dispatch it
// NOTE: This can disrupt the ongoing repeating request momentarily
CaptureRequest.Builder singleRequest =
session.getDevice().createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
singleRequest.addTarget(imReaderSurface);
session.capture(singleRequest.build(), null, null);

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

दूसरी इमेज. मौजूदा कैमरा सेशन के लिए अनुरोध की सूची की इमेज

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

  • B का अनुरोध करने के लिए, अनुरोध A से आउटपुट टारगेट जोड़ें. इस तरह, जब B का फ़्रेम तैयार है, इसे A के आउटपुट टारगेट में कॉपी कर लिया गया है. उदाहरण के लिए, यह ज़रूरी है कि वीडियो के स्नैपशॉट को बनाए रखने के लिए, स्थिर फ़्रेम रेट. पिछले कोड में, आपने अनुरोध करने से पहले singleRequest.addTarget(previewSurface).

  • इस स्थिति में काम करने के लिए डिज़ाइन किए गए टेंप्लेट के कॉम्बिनेशन का इस्तेमाल करें, जैसे कि ज़ीरो-शटर-लैग.