ملاحظة: تشير هذه الصفحة إلى حزمة camera2. ننصحك باستخدام cameraX ما لم يكن تطبيقك يتطلب ميزات محدّدة ومنخفضة المستوى من Camera2. يتوافق كل من CameraX و Camera2 مع الإصدار Android 5.0 (المستوى 21 من واجهة برمجة التطبيقات) والإصدارات الأحدث.
تتيح واجهات برمجة تطبيقات Camera2 إمكانية التقاط الفيديو بنطاق عالي الديناميكية (HDR)، ما يمكّنك من معاينة محتوى فيديو بنطاق عالي الديناميكية وتسجيله باستخدام الكاميرا. مقارنةً بالنطاق الديناميكي العادي (SDR)، يوفّر النطاق العالي الديناميكية مجموعة أكبر من الألوان ويزيد من النطاق الديناميكي لمكوِّن السطوع (من 100 قرص مضغوط/متر مربّع حاليًا إلى 1,000 ثانية من القرص المضغوط/المتر المربّع). يؤدي ذلك إلى جودة الفيديو التي تتطابق بشكل وثيق مع الحياة الواقعية، من خلال ألوان أكثر ثراءً وتظليلًا أكثر سطوعًا وظلالاً داكنة.
يمكنك الاطّلاع على مزيد من التفاصيل النابضة بالحياة حول كيفية التقاط فيديو بنطاق عالي الديناميكية (HDR).
![](https://developer.android.com/static/images/training/camera/camera2/sdr_comparison.png?authuser=8&hl=ar)
![](https://developer.android.com/static/images/training/camera/camera2/hdr_comparison.png?authuser=8&hl=ar)
المتطلبات الأساسية للأجهزة
لا تتيح بعض أجهزة Android إمكانية التقاط الفيديو بنطاق عالي الديناميكية. قبل التقاط فيديو بنطاق عالي الديناميكية في تطبيقك، عليك تحديد ما إذا كان جهازك يستوفي المتطلّبات الأساسية التالية:
- يستهدف Android 13 (المستوى 33 من واجهة برمجة التطبيقات).
- يتضمّن مستشعر كاميرا 10 بت أو أعلى. لمزيد من المعلومات حول دعم النطاق العالي الديناميكية (HDR)، راجع التحقق من توفّر دعم بنطاق عالي الديناميكية (HDR).
بما أنّ بعض الأجهزة لا تلبّي المتطلّبات الأساسية، يمكنك إضافة مسار رمز منفصل عند إعداد التقاط فيديو بنطاق عالي الديناميكية في تطبيقك. يتيح ذلك لتطبيقك استخدام النطاق العادي الديناميكية (SDR) على الأجهزة غير المتوافقة. يمكنك أيضًا إضافة خيار واجهة المستخدم لنطاق SDR. يمكن للمستخدم بعد ذلك التبديل بين النطاق العادي الديناميكية والنطاق العالي الديناميكية لاحتياجات تسجيل الفيديو.
بنية التقاط الصور بنطاق عالي الديناميكية (HDR)
يعرض المخطّط التالي المكوّنات الرئيسية لبنية التقاط الصور بنطاق عالي الديناميكية (HDR).
![مخطّط لبنية التقاط المحتوى بنطاق عالي الديناميكية (HDR)](https://developer.android.com/static/images/training/camera/camera2/hdr_capture_architecture_diagram.png?authuser=8&hl=ar)
عندما يلتقط جهاز الكاميرا إطارًا بنطاق عالي الديناميكية، يخصّص إطار عمل Camera2
مخزنًا مؤقتًا يخزّن البيانات التي تمّت معالجتها لأداة استشعار الكاميرا.
وتُرفِق أيضًا بيانات النطاق الوصفية ذات الصلة بالبيانات الوصفية ذات الصلة إذا كان ذلك مطلوبًا في ملف تعريف النطاق العالي الديناميكية (HDR).
يضع إطار عمل Camera2 في قائمة انتظار المخزن المؤقت المعبأ لواجهة الإخراج
المشار إليها في CaptureRequest
، مثل جهاز عرض أو
برنامج ترميز فيديو، كما هو موضّح في الرسم البياني.
التحقّق من توفّر تقنية النطاق العالي الديناميكية
قبل التقاط فيديو بنطاق عالي الديناميكية في تطبيقك، عليك تحديد ما إذا كان الجهاز متوافقًا مع الملف الشخصي الذي تريده بنطاق عالي الديناميكية (HDR).
استخدِم طريقة CameraManager
getCameraCharacteristics()
للحصول على مثيل
CameraCharacteristics
الذي يمكنك الاستعلام فيه عن إمكانات النطاق العالي الديناميكية (HDR) في جهازك.
تحدِّد الخطوات التالية ما إذا كان الجهاز متوافقًا مع تقنية HLG10. HLG10 هو معيار النطاق العالي الديناميكية الأساسي الذي يجب على صنّاع الأجهزة اعتماده في الكاميرات ذات إخراج 10 بت.
أولاً، عليك التأكّد مما إذا كان الجهاز متوافقًا مع الملفات الشخصية بتردد 10 بت (عمق البت لتقنية HLG10):
Kotlin
private fun isTenBitProfileSupported(cameraId: String): Boolean { val cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId) val availableCapabilities = cameraCharacteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES) for (capability in availableCapabilities!!) { if (capability == CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT) { return true } } return false }
بعد ذلك، تحقَّق مما إذا كان الجهاز متوافقًا مع HLG10 (أو ملف شخصي آخر متوافق):
Kotlin
@RequiresApi(api = 33) private fun isHLGSupported(cameraId: String): Boolean { if (isTenBitProfileSupported(cameraId)) { Val cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId) val availableProfiles = cameraCharacteristics .get(CameraCharacteristics.REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES)!! .getSupportedProfiles() // Checks for the desired profile, in this case HLG10 return availableProfiles.contains(DynamicRangeProfiles.HLG10) } return false; }
إذا كان الجهاز متوافقًا مع تقنية HDR، يجب أن تعرض السمة isHLGSupported()
دائمًا true
.
لمزيد من المعلومات، اطّلِع على المستندات المرجعية
CameraCharacteristics
.
إعداد التقاط نطاق عالي الديناميكية
بعد التأكّد من أنّ جهازك متوافق مع تقنية HDR، يجب إعداد التطبيق لالتقاط
بث فيديو مباشر بنطاق عالي الديناميكية من الكاميرا.
استخدِم setDynamicRangeProfile()
لتزويد OutputConfiguration
البث بملف شخصي بنطاق عالي الديناميكية متوافق مع الأجهزة، ويتم تمريره بعد ذلك إلى CameraCaptureSession
عند الإنشاء.
راجع قائمة الملفات الشخصية المتوافقة ذات النطاق العالي الديناميكية (HDR) المتوافقة.
في الرمز النموذجي التالي، يتحقّق setupSessionDynamicRangeProfile()
أولاً
من أنّ الجهاز يعمل بنظام التشغيل Android 13.
بعد ذلك، يتم ضبط CameraCaptureSession
مع ملف شخصي بنطاق عالي الديناميكية
متوافق مع الجهاز على أنّه OutputConfiguration
:
Kotlin
/** * Creates a [CameraCaptureSession] with a dynamic range profile. */ private fun setupSessionWithDynamicRangeProfile( dynamicRange: Long, device: CameraDevice, targets: List, handler: Handler? = null, stateCallback: CameraCaptureSession.StateCallback ): Boolean { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU) { val outputConfigs = mutableListOf () for (target in targets) { val outputConfig = OutputConfiguration(target) //sets the dynamic range profile, for example DynamicRangeProfiles.HLG10 outputConfig.setDynamicRangeProfile(dynamicRange) outputConfigs.add(outputConfig) } device.createCaptureSessionByOutputConfigurations( outputConfigs, stateCallback, handler) return true } else { device.createCaptureSession(targets, stateCallback, handler) return false } }
}
عندما يبدأ تطبيق الكاميرا تشغيل الكاميرا، يرسل رمز CaptureRequest
متكرر لمعاينة التسجيل:
Kotlin
session.setRepeatingRequest(previewRequest, null, cameraHandler)
ولبدء تسجيل الفيديو أيضًا، يُرجى اتّباع الخطوات التالية:
Kotlin
// Start recording repeating requests, which stops the ongoing preview // repeating requests without having to explicitly call // `session.stopRepeating` session.setRepeatingRequest(recordRequest, object : CameraCaptureSession.CaptureCallback() { override fun onCaptureCompleted(session: CameraCaptureSession, request: CaptureRequest, result: TotalCaptureResult) { if (currentlyRecording) { encoder.frameAvailable() } } }, cameraHandler)
ترميز بث الكاميرا بنطاق عالي الديناميكية
لترميز بث كاميرا HDR ونقل الملف على القرص، استخدِم MediaCodec
.
أولاً، احصل على OutputSurface
الذي يرتبط بمخزن مؤقت يخزّن بيانات الفيديو الأوّلية.
بالنسبة إلى MediaCodec
،
استخدِم createInputSurface()
.
لإعداد MediaCodec
، يجب أن ينشئ التطبيق MediaFormat
بملف شخصي محدد في برنامج الترميز، ومساحة لونية، ونطاق لون، ودالة نقل:
Kotlin
val mimeType = when { dynamicRange == DynamicRangeProfiles.STANDARD -> MediaFormat.MIMETYPE_VIDEO_AVC dynamicRange < DynamicRangeProfiles.PUBLIC_MAX -> MediaFormat.MIMETYPE_VIDEO_HEVC else -> throw IllegalArgumentException("Unknown dynamic range format") } val codecProfile = when { dynamicRange == DynamicRangeProfiles.HLG10 -> MediaCodecInfo.CodecProfileLevel.HEVCProfileMain10 dynamicRange == DynamicRangeProfiles.HDR10 -> MediaCodecInfo.CodecProfileLevel.HEVCProfileMain10HDR10 dynamicRange == DynamicRangeProfiles.HDR10_PLUS -> MediaCodecInfo.CodecProfileLevel.HEVCProfileMain10HDR10Plus else -> -1 } // Failing to correctly set color transfer causes quality issues // for example, washout and color clipping val transferFunction = when (codecProfile) { MediaCodecInfo.CodecProfileLevel.HEVCProfileMain10 -> MediaFormat.COLOR_TRANSFER_HLG MediaCodecInfo.CodecProfileLevel.HEVCProfileMain10HDR10 -> MediaFormat.COLOR_TRANSFER_ST2084 MediaCodecInfo.CodecProfileLevel.HEVCProfileMain10HDR10Plus -> MediaFormat.COLOR_TRANSFER_ST2084 else -> MediaFormat.COLOR_TRANSFER_SDR_VIDEO } val format = MediaFormat.createVideoFormat(mimeType, width, height) // Set some properties. Failing to specify some of these can cause the MediaCodec // configure() call to throw an exception. format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface) format.setInteger(MediaFormat.KEY_BIT_RATE, bitRate) format.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate) format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL) if (codecProfile != -1) { format.setInteger(MediaFormat.KEY_PROFILE, codecProfile) format.setInteger(MediaFormat.KEY_COLOR_STANDARD, MediaFormat.COLOR_STANDARD_BT2020) format.setInteger(MediaFormat.KEY_COLOR_RANGE, MediaFormat.COLOR_RANGE_LIMITED) format.setInteger(MediaFormat.KEY_COLOR_TRANSFER, transferFunction) format.setFeatureEnabled(MediaCodecInfo.CodecCapabilities.FEATURE_HdrEditing, true) } mediaCodec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE)
لمزيد من التفاصيل حول عملية التنفيذ، يُرجى الاطّلاع على نموذج تطبيق Camera2Video
EncoderWrapper.kt
.
تنسيقات النطاق العالي الديناميكية
بدءًا من نظام التشغيل Android 13، يجب أن تكون الكاميرات المزوّدة بإمكانيات الإخراج 10 بت متوافقة مع تقنية HLG10 لالتقاط صور بدقة عالية وتشغيل بنطاق عالي الديناميكية. بالإضافة إلى ذلك، يمكن للشركات المصنّعة للأجهزة تفعيل أي تنسيق نطاق عالي الديناميكية من اختيارهم، باستخدام بنية الالتقاط بنطاق عالي الديناميكية.
يلخّص الجدول التالي تنسيقات النطاق العالي الديناميكية المتاحة وإمكاناتها في التقاط فيديو بنطاق عالي الديناميكية.
التنسيق | وظيفة النقل (TF) | البيانات الوصفية | برنامج الترميز | عمق البت |
---|---|---|---|---|
تقنية HLG10 | تقنية HLG | لا | تنسيق HEVC | 10 وحدات بت |
نطاق عالي الديناميكية (HDR10) | جودة الهواء (PQ) | ثابت | تنسيق HEVC | 10 وحدات بت |
+HDR10 | جودة الهواء (PQ) | ديناميكي | تنسيق HEVC | 10 وحدات بت |
تقنية Dolby Vision 8.4 | تقنية HLG | ديناميكي | تنسيق HEVC | 10 وحدات بت |
المَراجع
للحصول على تطبيق يعمل مع وظيفة التقاط فيديو بنطاق عالي الديناميكية، يمكنك الاطّلاع على نموذج Camera2Video على GitHub.