ملاحظة: تشير هذه الصفحة إلى حزمة Camera2. ننصحك باستخدام الكاميراX ما لم يكن تطبيقك يتطلب ميزات محدَّدة منخفضة المستوى من تطبيق Camera2. يتوافق كل من CameraX و Camera2 مع نظام التشغيل Android 5.0 (المستوى 21 لواجهة برمجة التطبيقات) والإصدارات الأحدث.
يمكن أن يتضمّن جهاز واحد يعمل بنظام التشغيل Android عدة كاميرات. كل كاميرا عبارة عن
CameraDevice
,
ويمكن لـ CameraDevice
إخراج أكثر من مصدر بيانات واحد في الوقت نفسه.
إنّ السبب الوحيد لإجراء ذلك هو إطلاق بث واحد وإطارات الكاميرا المتسلسلة.
من CameraDevice
، محسّنة لمهمة محدّدة، مثل عرض
عدسة الكاميرا، بينما يمكن استخدام الآخرين لالتقاط صورة أو إنشاء فيديو
التسجيل.تعمل مجموعات البث كمسارات متوازية تعالج الإطارات الأولية
تخرج من الكاميرا، لقطة واحدة في كل مرة:
تشير المعالجة المتوازية إلى إمكانية وضع حدود للأداء استنادًا إلى طاقة المعالجة المتاحة من وحدة المعالجة المركزية (CPU) أو وحدة معالجة الرسومات (GPU) أو معالج آخر. إذا مسار الإطارات الشبكية الواردة، فقد بدأ في إسقاطها.
لكل مسار تنسيق الإخراج الخاص به. البيانات الأولية الواردة هي
يتم تحويلها تلقائيًا إلى الطريقة المناسبة
تنسيق الناتج من خلال المنطق الضمني
المرتبطة بكل مسار. إنّ CameraDevice
المستخدمة في هذه الصفحة
نماذج التعليمات البرمجية غير محددة، لذلك عليك أولاً تعداد
جميع الكاميرات المتاحة قبل المتابعة.
يمكنك استخدام CameraDevice
لإنشاء
CameraCaptureSession
,
الخاص بـ CameraDevice
. يجب أن يتلقّى CameraDevice
إعدادات الإطار لكل إطار أولي باستخدام CameraCaptureSession
. تشير رسالة الأشكال البيانية
سمات الكاميرا مثل التركيز التلقائي وفتحة العدسة والتأثيرات
ومدى التعرّض للأصوات. وبسبب قيود الأجهزة، لا يتم إجراء سوى تهيئة واحدة
نشطًا في أداة استشعار الكاميرا في أي وقت، وهو ما يسمى
نشط.
مع ذلك، تساعد حالات استخدام البث في تحسين الطرق السابقة لاستخدام CameraDevice
وتوسيع نطاقها.
لبث جلسات التصوير، ما يتيح لك تحسين بث الكاميرا
في حالة استخدام معينة. على سبيل المثال، يمكنها تحسين عمر البطارية عند التحسين
مكالمات فيديو.
تصف السمة CameraCaptureSession
جميع المسارات المحتملة المرتبطة بنموذج
CameraDevice
عند إنشاء جلسة، لا يمكنك إضافة مسارات التعلّم أو إزالتها.
يحتفظ CameraCaptureSession
بقائمة انتظار
CaptureRequest
،
والتي تصبح هي التهيئة النشطة.
يضيف CaptureRequest
إعدادًا إلى قائمة الانتظار ويختار إعدادًا، أكثر من
واحد، أو كل المسارات المتاحة لتلقي إطار من
CameraDevice
يمكنك إرسال العديد من طلبات الالتقاط طوال فترة التقاط الصورة.
جلسة المراجعة. يمكن لكل طلب تغيير الإعداد النشط ومجموعة النتائج
الممرات التي تتلقى الصورة الأولية.
الاستفادة من حالات الاستخدام في البث لتحقيق أداء أفضل
"حالات استخدام البث" هي وسيلة لتحسين أداء التقاط الصور بالكاميرا 2. الجلسات. فهي تعطي الجهاز المزيد من المعلومات لضبط المعاملات، التي تقدّم تجربة أفضل للكاميرا لإنجاز مهمتك المحدّدة.
هذا النمط
تسمح لجهاز الكاميرا بتحسين أجهزة الكاميرا ومسارات البرامج.
استنادًا إلى سيناريوهات كل بث مباشر لمزيد من المعلومات حول استخدام البث
الطلبات، يُرجى الاطّلاع على setStreamUseCase
.
تتيح لك حالات الاستخدام للبث المباشر تحديد كيفية استخدام بث كاميرا معيّن في
بمزيد من التفصيل، بالإضافة إلى إعداد قالب في
CameraDevice.createCaptureRequest()
يسمح هذا الإجراء لأجهزة الكاميرا بتحسين
مثل الضبط أو وضع أداة الاستشعار أو إعدادات أداة استشعار الكاميرا، بناءً على
مفاضلات الجودة ووقت الاستجابة مناسبة لحالات استخدام معيّنة.
تشمل حالات الاستخدام لساحة المشاركات ما يلي:
DEFAULT
: تشمل هذه السياسة جميع سلوكيات التطبيقات الحالية. تعادل عدم وإعداد أي حالة استخدام للبث.PREVIEW
: يُنصح به لتحليل عدسة الكاميرا أو الصور داخل التطبيق.STILL_CAPTURE
: محسَّنة لالتقاط صور عالية الجودة عالية الجودة، بدلاً من من المتوقع الحفاظ على عدد اللقطات في الثانية الذي يشبه المعاينة.VIDEO_RECORD
: خيار محسَّن لتسجيل الفيديو بجودة عالية، بما في ذلك الجودة العالية تثبيت الصورة، إذا كان الجهاز متوافقًا مع الميزة وفعّلها التطبيق. قد يؤدي هذا الخيار إلى إنتاج إطارات مُخرجة مع تأخُّر كبير عن الوقت الفعلي، للسماح بالتثبيت بأعلى جودة أو المعالجة الأخرى.VIDEO_CALL
: يُنصح به لاستخدامات الكاميرا لفترات طويلة حيث يتم استنزاف الطاقة المشكلة.PREVIEW_VIDEO_STILL
: يُنصح بهذا الخيار لتطبيقات وسائل التواصل الاجتماعي أو للاستخدام في بث واحد. الحالات. إنّه بث متعدد الأغراض.VENDOR_START
: يُستخدَم في حالات الاستخدام التي يحدّدها المصنّع الأصلي للجهاز.
إنشاء جلسة تسجيل الكاميرا
لإنشاء جلسة كاميرا، عليك تزويدها بمورد احتياطي واحد أو أكثر للمخرجات. لتطبيقك كتابة إطارات الإخراج. يمثل كل مورد احتياطي خطًا. يجب القيام بذلك قبل البدء في استخدام الكاميرا حتى يمكن لإطار العمل تهيئة المسارات الداخلية للجهاز وتخصيص مخازن مؤقتة لإرسال الإطارات إلى أهداف المخرجات المطلوبة.
يوضح مقتطف الرمز التالي كيفية تحضير جلسة كاميرا مع اثنين
الموارد الاحتياطية للمخرجات التي تنتمي إلى
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
، وهو
إرسال إلى الكاميرا. لإنشاء طلب تسجيل، يمكنك استخدام أحد
محدّدة مسبقًا
templates
أو يمكنك استخدام 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
أيضًا للمستخدمين بالتقاط الفيديو من الكاميرا عن طريق إرسال
تكرار CaptureRequests
كما هو موضّح في ذلك
نموذج Camera2
على جيت هب. ويمكنها أيضًا عرض فيديو بالتصوير البطيء من خلال التقاط
فيديو عالي السرعة (تصوير بطيء) باستخدام صور متسلسلة متكررة 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 هو طلب التقاط لقطة واحدة، وهذه هي الطريقة التي تعالج الجلسة قائمة انتظار الطلبات:
ليس هناك أي ضمانات بشأن وقت الاستجابة بين آخر طلب متكرر من أ قبل تفعيل الطلب ب وفي المرة التالية التي يتم فيها استخدام الحرف أ مرة أخرى، لذلك قد تواجه بعض الإطارات التي تم تخطيها. هناك بعض الأشياء التي يمكنك فعله للتخفيف من هذه المشكلة:
أضِف استهدافات الناتج من الطلب أ إلى الطلب ب. بهذه الطريقة، عندما إطار B جاهز، ويتم نسخه إلى استهدافات الإخراج A. على سبيل المثال، يُعد هذا أمرًا ضروريًا عند تصوير لقطات فيديو للحفاظ على عدد ثابت للقطات في الثانية. في التعليمة البرمجية السابقة، يمكنك إضافة
singleRequest.addTarget(previewSurface)
قبل إنشاء الطلب.استخدم مجموعة من القوالب المصممة للعمل لهذا السيناريو المحدد، مثل عدم الفاصل الإعلاني