ক্যামেরা ক্যাপচার সেশন এবং অনুরোধ

দ্রষ্টব্য: এই পৃষ্ঠাটি Camera2 প্যাকেজকে বোঝায়। আপনার অ্যাপের Camera2 থেকে নির্দিষ্ট, নিম্ন-স্তরের বৈশিষ্ট্যের প্রয়োজন না হলে, আমরা CameraX ব্যবহার করার পরামর্শ দিই। CameraX এবং Camera2 উভয়ই Android 5.0 (API স্তর 21) এবং উচ্চতর সমর্থন করে।

একটি একক Android-চালিত ডিভাইসে একাধিক ক্যামেরা থাকতে পারে। প্রতিটি ক্যামেরা একটি CameraDevice , এবং একটি CameraDevice একই সাথে একাধিক স্ট্রীম আউটপুট করতে পারে।

এটি করার একটি কারণ হল যাতে একটি স্ট্রীম, একটি CameraDevice থেকে আসা অনুক্রমিক ক্যামেরা ফ্রেমগুলি একটি নির্দিষ্ট কাজের জন্য অপ্টিমাইজ করা হয়, যেমন একটি ভিউফাইন্ডার প্রদর্শন করা, অন্যগুলি একটি ফটো তোলা বা একটি ভিডিও রেকর্ডিং করতে ব্যবহার করা হতে পারে৷ স্ট্রীমগুলি সমান্তরাল পাইপলাইন হিসাবে কাজ করে যা ক্যামেরা থেকে বেরিয়ে আসা কাঁচা ফ্রেমগুলিকে এক সময়ে একটি ফ্রেম প্রক্রিয়া করে:

চিত্র 1. একটি ইউনিভার্সাল ক্যামেরা অ্যাপ তৈরির চিত্র (Google I/O '18)

সমান্তরাল প্রক্রিয়াকরণ পরামর্শ দেয় যে সিপিইউ, জিপিইউ বা অন্যান্য প্রসেসর থেকে উপলব্ধ প্রক্রিয়াকরণ শক্তির উপর নির্ভর করে কর্মক্ষমতা সীমা থাকতে পারে। যদি একটি পাইপলাইন ইনকামিং ফ্রেমের সাথে তাল মিলিয়ে চলতে না পারে, তাহলে এটি সেগুলিকে ফেলে দিতে শুরু করে।

প্রতিটি পাইপলাইনের নিজস্ব আউটপুট বিন্যাস আছে। প্রতিটি পাইপলাইনের সাথে যুক্ত অন্তর্নিহিত যুক্তি দ্বারা স্বয়ংক্রিয়ভাবে উপযুক্ত আউটপুট বিন্যাসে আসা কাঁচা ডেটা স্বয়ংক্রিয়ভাবে রূপান্তরিত হয়। এই পৃষ্ঠার কোড নমুনা জুড়ে ব্যবহৃত CameraDevice অ-নির্দিষ্ট, তাই আপনি এগিয়ে যাওয়ার আগে প্রথমে সমস্ত উপলব্ধ ক্যামেরা গণনা করুন

আপনি একটি CameraCaptureSession তৈরি করতে CameraDevice ব্যবহার করতে পারেন, যা সেই CameraDevice এর জন্য নির্দিষ্ট। CameraCaptureSession ব্যবহার করে একটি CameraDevice প্রতিটি কাঁচা ফ্রেমের জন্য একটি ফ্রেম কনফিগারেশন পেতে হবে। কনফিগারেশন ক্যামেরা বৈশিষ্ট্য যেমন অটোফোকাস, অ্যাপারচার, প্রভাব এবং এক্সপোজার নির্দিষ্ট করে। হার্ডওয়্যার সীমাবদ্ধতার কারণে, যে কোনো সময়ে ক্যামেরা সেন্সরে শুধুমাত্র একটি কনফিগারেশন সক্রিয় থাকে, যেটিকে সক্রিয় কনফিগারেশন বলা হয়।

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

একটি CameraCaptureSession CameraDevice সাথে আবদ্ধ সমস্ত সম্ভাব্য পাইপলাইন বর্ণনা করে। যখন একটি সেশন তৈরি করা হয়, আপনি পাইপলাইন যোগ করতে বা অপসারণ করতে পারবেন না। CameraCaptureSession CaptureRequest s এর একটি সারি বজায় রাখে, যা সক্রিয় কনফিগারেশনে পরিণত হয়।

একটি CaptureRequest সারিতে একটি কনফিগারেশন যোগ করে এবং CameraDevice থেকে একটি ফ্রেম পেতে একটি, একাধিক বা উপলব্ধ পাইপলাইনগুলির মধ্যে একটি নির্বাচন করে। আপনি একটি ক্যাপচার সেশনের জীবনে অনেক ক্যাপচার অনুরোধ পাঠাতে পারেন। প্রতিটি অনুরোধ সক্রিয় কনফিগারেশন এবং আউটপুট পাইপলাইনের সেট পরিবর্তন করতে পারে যা কাঁচা চিত্র গ্রহণ করে।

আরও ভালো পারফরম্যান্সের জন্য স্ট্রিম ব্যবহারের ক্ষেত্রে ব্যবহার করুন

স্ট্রিম ব্যবহারের ক্ষেত্রে ক্যামেরা2 ক্যাপচার সেশনের কর্মক্ষমতা উন্নত করার একটি উপায়। তারা হার্ডওয়্যার ডিভাইসটিকে প্যারামিটারগুলি সুর করার জন্য আরও তথ্য দেয়, যা আপনার নির্দিষ্ট কাজের জন্য একটি ভাল ক্যামেরা অভিজ্ঞতা প্রদান করে।

এটি ক্যামেরা ডিভাইসটিকে প্রতিটি স্ট্রীমের জন্য ব্যবহারকারীর পরিস্থিতির উপর ভিত্তি করে ক্যামেরা হার্ডওয়্যার এবং সফ্টওয়্যার পাইপলাইন অপ্টিমাইজ করার অনুমতি দেয়। স্ট্রীম ব্যবহারের ক্ষেত্রে আরও তথ্যের জন্য, setStreamUseCase দেখুন।

CameraDevice.createCaptureRequest() এ একটি টেমপ্লেট সেট করার পাশাপাশি স্ট্রিম ব্যবহারের ক্ষেত্রে আপনাকে নির্দিষ্ট ক্যামেরা স্ট্রীম কীভাবে আরও বিস্তারিতভাবে ব্যবহার করা হয় তা উল্লেখ করতে দেয়। এটি ক্যামেরা হার্ডওয়্যারকে নির্দিষ্ট ব্যবহারের ক্ষেত্রে উপযুক্ত গুণমান বা লেটেন্সি ট্রেডঅফের উপর ভিত্তি করে টিউনিং, সেন্সর মোড বা ক্যামেরা সেন্সর সেটিংসের মতো প্যারামিটারগুলি অপ্টিমাইজ করতে দেয়৷

স্ট্রিম ব্যবহারের ক্ষেত্রে অন্তর্ভুক্ত:

  • DEFAULT : সমস্ত বিদ্যমান অ্যাপ্লিকেশন আচরণ কভার করে। এটি কোনো স্ট্রিম ব্যবহারের ক্ষেত্রে সেট না করার সমতুল্য।

  • PREVIEW : ভিউফাইন্ডার বা ইন-অ্যাপ ইমেজ বিশ্লেষণের জন্য প্রস্তাবিত।

  • STILL_CAPTURE : উচ্চ-মানের উচ্চ-রেজোলিউশন ক্যাপচারের জন্য অপ্টিমাইজ করা হয়েছে, এবং প্রিভিউ-এর মতো ফ্রেম রেট বজায় রাখার প্রত্যাশিত নয়৷

  • VIDEO_RECORD : ডিভাইস দ্বারা সমর্থিত এবং অ্যাপ্লিকেশন দ্বারা সক্ষম হলে উচ্চ-মানের চিত্র স্থিতিশীলতা সহ উচ্চ-মানের ভিডিও ক্যাপচারের জন্য অপ্টিমাইজ করা হয়েছে। সর্বোচ্চ মানের স্থিতিশীলতা বা অন্যান্য প্রক্রিয়াকরণের জন্য এই বিকল্পটি রিয়েল টাইম থেকে যথেষ্ট ব্যবধান সহ আউটপুট ফ্রেম তৈরি করতে পারে।

  • VIDEO_CALL : দীর্ঘমেয়াদী ক্যামেরা ব্যবহারের জন্য প্রস্তাবিত যেখানে পাওয়ার ড্রেন একটি উদ্বেগের বিষয়।

  • PREVIEW_VIDEO_STILL : সোশ্যাল মিডিয়া অ্যাপ বা একক স্ট্রিম ব্যবহারের ক্ষেত্রে প্রস্তাবিত৷ এটি একটি বহুমুখী প্রবাহ।

  • VENDOR_START : OEM-সংজ্ঞায়িত ব্যবহারের ক্ষেত্রে ব্যবহৃত হয়।

একটি ক্যামেরা ক্যাপচার সেশন তৈরি করুন

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

নিম্নলিখিত কোড স্নিপেটটি দেখায় কিভাবে আপনি দুটি আউটপুট বাফার সহ একটি ক্যামেরা সেশন প্রস্তুত করতে পারেন, একটি SurfaceView এবং অন্যটি একটি ImageReader সাথে। PREVIEW স্ট্রীম ইউজ কেস previewSurface এবং STILL_CAPTURE স্ট্রিম ইউজ কেস imReaderSurface এ যোগ করা ডিভাইস হার্ডওয়্যারকে এই স্ট্রীমগুলিকে আরও অপ্টিমাইজ করতে দেয়৷

কোটলিন


// 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)
}

জাভা


// 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 হতে হবে। অ্যানড্রয়েড ফ্রেমওয়ার্ক জানে কিভাবে সক্রিয় কনফিগারেশনে একটি কাঁচা ছবিকে প্রতিটি টার্গেটের জন্য উপযুক্ত ফর্ম্যাটে রূপান্তর করতে হয়। রূপান্তরটি নির্দিষ্ট Surface পিক্সেল বিন্যাস এবং আকার দ্বারা নিয়ন্ত্রিত হয়।

ফ্রেমওয়ার্ক তার সর্বোত্তম কাজ করার চেষ্টা করে, কিন্তু কিছু Surface কনফিগারেশন সমন্বয় কাজ নাও করতে পারে, যার ফলে সেশন তৈরি না হওয়া, আপনি একটি অনুরোধ পাঠানোর সময় রানটাইম ত্রুটি বা কর্মক্ষমতা অবনতির মতো সমস্যা সৃষ্টি করতে পারে। ফ্রেমওয়ার্ক ডিভাইস, পৃষ্ঠ এবং অনুরোধের পরামিতিগুলির নির্দিষ্ট সমন্বয়ের জন্য গ্যারান্টি প্রদান করে। createCaptureSession() এর জন্য ডকুমেন্টেশন আরও তথ্য প্রদান করে।

একক ক্যাপচার অনুরোধ

প্রতিটি ফ্রেমের জন্য ব্যবহৃত কনফিগারেশন একটি CaptureRequest এ এনকোড করা হয়, যা ক্যামেরায় পাঠানো হয়। একটি ক্যাপচার অনুরোধ তৈরি করতে, আপনি পূর্বনির্ধারিত টেমপ্লেটগুলির একটি ব্যবহার করতে পারেন, অথবা আপনি সম্পূর্ণ নিয়ন্ত্রণের জন্য TEMPLATE_MANUAL ব্যবহার করতে পারেন৷ আপনি যখন একটি টেমপ্লেট চয়ন করেন, আপনাকে অনুরোধের সাথে ব্যবহার করার জন্য এক বা একাধিক আউটপুট বাফার সরবরাহ করতে হবে। আপনি শুধুমাত্র বাফারগুলি ব্যবহার করতে পারেন যা আপনি ব্যবহার করতে চান এমন ক্যাপচার সেশনে ইতিমধ্যে সংজ্ঞায়িত করা হয়েছে।

ক্যাপচার অনুরোধগুলি একটি বিল্ডার প্যাটার্ন ব্যবহার করে এবং ডেভেলপারদের অটো-এক্সপোজার , অটো-ফোকাস এবং লেন্স অ্যাপারচার সহ বিভিন্ন বিকল্প সেট করার সুযোগ দেয়। একটি ক্ষেত্র সেট করার আগে, CameraCharacteristics.getAvailableCaptureRequestKeys() কল করে ডিভাইসের জন্য নির্দিষ্ট বিকল্পটি উপলব্ধ আছে কিনা নিশ্চিত করুন এবং উপযুক্ত ক্যামেরা বৈশিষ্ট্য যেমন উপলব্ধ স্বয়ংক্রিয়-এক্সপোজার মোডগুলি পরীক্ষা করে পছন্দসই মানটি সমর্থিত।

কোনো পরিবর্তন ছাড়াই পূর্বরূপের জন্য ডিজাইন করা টেমপ্লেট ব্যবহার করে SurfaceView এর জন্য ক্যাপচার অনুরোধ তৈরি করতে, CameraDevice.TEMPLATE_PREVIEW ব্যবহার করুন:

কোটলিন

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

জাভা

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

একটি ক্যাপচার অনুরোধ সংজ্ঞায়িত করে, আপনি এখন এটি ক্যামেরা সেশনে প্রেরণ করতে পারেন:

কোটলিন

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)

জাভা

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 , ট্রিগার হয় যখন এটিতে থাকা ফ্রেমটি প্রক্রিয়া করা হয়। এই মুহুর্তে আপনি নির্দিষ্ট বাফার থেকে ইমেজ ডেটা পুনরুদ্ধার করতে পারেন।

ক্যাপচার রিকোয়েস্টের পুনরাবৃত্তি করুন

একক ক্যামেরার অনুরোধগুলি করা সহজ, কিন্তু একটি লাইভ প্রিভিউ বা ভিডিও প্রদর্শনের জন্য, সেগুলি খুব একটা উপযোগী নয়৷ এই ক্ষেত্রে, আপনাকে ফ্রেমের একটি অবিচ্ছিন্ন স্ট্রিম গ্রহণ করতে হবে, শুধুমাত্র একটি একক নয়। নিম্নলিখিত কোড স্নিপেট দেখায় কিভাবে সেশনে একটি পুনরাবৃত্তি অনুরোধ যোগ করতে হয়:

কোটলিন

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)

জাভা

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 পাঠিয়ে যেমনটি GitHub-এ এই Camera2 নমুনা সংগ্রহস্থলে দেখা যায়। এটি GitHub-এ Camera2 স্লো মোশন ভিডিও নমুনা অ্যাপে দেখানো হিসাবে পুনরাবৃত্তি করা বার্স্ট CaptureRequests ব্যবহার করে একটি উচ্চ-গতির (ধীর গতি) ভিডিও ক্যাপচার করে ধীর গতির ভিডিও রেন্ডার করতে পারে।

ইন্টারলিভ ক্যাপচার অনুরোধ

পুনরাবৃত্তি করা ক্যাপচার অনুরোধ সক্রিয় থাকাকালীন একটি দ্বিতীয় ক্যাপচার অনুরোধ পাঠাতে, যেমন একটি ভিউফাইন্ডার প্রদর্শন করা এবং ব্যবহারকারীদের একটি ফটো ক্যাপচার করতে দেওয়া, আপনাকে চলমান পুনরাবৃত্তির অনুরোধটি বন্ধ করতে হবে না। পরিবর্তে, আপনি একটি নন-রিপিটিং ক্যাপচার রিকোয়েস্ট ইস্যু করেন যখন রিপিটিং রিকোয়েস্ট চলতে থাকে।

যে কোনো আউটপুট বাফার ব্যবহার করা হলে ক্যামেরা সেশনের অংশ হিসেবে কনফিগার করা প্রয়োজন যখন সেশনটি প্রথম তৈরি করা হয়। একক-ফ্রেম বা বার্স্ট অনুরোধের তুলনায় পুনরাবৃত্তির অনুরোধের অগ্রাধিকার কম থাকে, যা নিম্নলিখিত নমুনাকে কাজ করতে সক্ষম করে:

কোটলিন

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)

জাভা

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 হয় একক-ফ্রেম ক্যাপচার অনুরোধ, তাহলে এইভাবে সেশনটি অনুরোধ সারি প্রক্রিয়া করে:

চিত্র 2. চলমান ক্যামেরা সেশনের জন্য একটি অনুরোধ সারির চিত্র

অনুরোধ B সক্রিয় হওয়ার আগে A থেকে শেষ পুনরাবৃত্তি করা অনুরোধ এবং পরের বার যখন A আবার ব্যবহার করা হচ্ছে এর মধ্যে বিলম্বের কোনো গ্যারান্টি নেই, তাই আপনি কিছু এড়িয়ে যাওয়া ফ্রেম অনুভব করতে পারেন। এই সমস্যাটি প্রশমিত করার জন্য আপনি কিছু করতে পারেন:

  • অনুরোধ A থেকে B অনুরোধ করতে আউটপুট লক্ষ্য যোগ করুন। এইভাবে, যখন B এর ফ্রেম প্রস্তুত হয়, এটি A এর আউটপুট লক্ষ্যগুলিতে অনুলিপি করা হয়। উদাহরণস্বরূপ, একটি স্থির ফ্রেম রেট বজায় রাখতে ভিডিও স্ন্যাপশট করার সময় এটি অপরিহার্য। পূর্ববর্তী কোডে, আপনি অনুরোধটি তৈরি করার আগে singleRequest.addTarget(previewSurface) যোগ করুন।

  • এই নির্দিষ্ট পরিস্থিতিতে কাজ করার জন্য ডিজাইন করা টেমপ্লেটগুলির সংমিশ্রণ ব্যবহার করুন, যেমন শূন্য-শাটার-ল্যাগ।