توجه: این صفحه به پکیج Camera2 اشاره دارد. توصیه میکنیم از CameraX استفاده کنید، مگر اینکه برنامه شما به ویژگیهای خاص و سطح پایین Camera2 نیاز داشته باشد. هر دو CameraX و Camera2 از اندروید 5.0 (سطح API 21) و بالاتر پشتیبانی می کنند.
API های Camera2 از فیلم برداری با محدوده دینامیکی بالا (HDR) پشتیبانی می کنند، که به شما امکان می دهد با استفاده از دوربین خود، پیش نمایش و ضبط محتوای ویدیوی HDR را داشته باشید. در مقایسه با محدوده دینامیکی استاندارد (SDR)، HDR طیف وسیع تری از رنگ ها را ارائه می دهد و محدوده دینامیکی جزء روشنایی را افزایش می دهد (از 100 cd/m2 فعلی تا 1000s cd/m2). این منجر به کیفیت ویدیویی می شود که بیشتر با زندگی واقعی مطابقت دارد، با رنگ های غنی تر، هایلایت روشن تر و سایه های تیره تر.
ببینید چگونه ویدیوی HDR با جزئیات پر جنب و جوش غروب خورشید را ثبت می کند.
پیش نیاز دستگاه
همه دستگاه های اندرویدی از فیلم برداری HDR پشتیبانی نمی کنند. قبل از ضبط ویدیوی HDR در برنامه خود، تعیین کنید که آیا دستگاه شما شرایط زیر را دارد یا خیر:
- اندروید 13 (سطح API 33) را هدف قرار می دهد.
- دارای سنسور دوربین 10 بیتی یا بالاتر. برای اطلاعات بیشتر درباره پشتیبانی HDR، به بررسی پشتیبانی HDR مراجعه کنید.
از آنجایی که همه دستگاهها پیشنیازها را برآورده نمیکنند، میتوانید هنگام تنظیم فیلمبرداری HDR در برنامه خود یک مسیر کد جداگانه اضافه کنید. این به برنامه شما امکان میدهد در دستگاههای ناسازگار به SDR برگردد. همچنین، اضافه کردن یک گزینه UI برای SDR را در نظر بگیرید. سپس کاربر می تواند برای نیازهای ضبط ویدیوی خود بین SDR و HDR جابجا شود.
معماری عکاسی HDR
نمودار زیر اجزای اصلی معماری ضبط HDR را نشان می دهد.
هنگامی که یک دستگاه دوربین یک فریم را در HDR می گیرد، چارچوب Camera2 بافری را اختصاص می دهد که خروجی سنسور دوربین پردازش شده را ذخیره می کند. همچنین در صورت نیاز نمایه HDR، متادیتای HDR مربوطه را پیوست میکند. سپس چارچوب Camera2 بافر پر شده را برای سطح خروجی که در CaptureRequest
ارجاع داده شده است، مانند صفحه نمایش یا رمزگذار ویدیو، همانطور که در نمودار نشان داده شده است، در صف قرار می دهد.
پشتیبانی از HDR را بررسی کنید
قبل از ضبط ویدیوی HDR در برنامه خود، تعیین کنید که آیا دستگاه از نمایه HDR مورد نظر شما پشتیبانی می کند یا خیر.
از روش CameraManager
getCameraCharacteristics()
برای به دست آوردن یک نمونه CameraCharacteristics
استفاده کنید، که می توانید قابلیت های HDR دستگاه خود را پرس و جو کنید.
مراحل زیر بررسی کنید که آیا دستگاهی از HLG10 پشتیبانی می کند یا خیر. HLG10 استاندارد پایه HDR است که سازندگان دستگاه باید در دوربینهایی با خروجی 10 بیت از آن پشتیبانی کنند.
ابتدا بررسی کنید که آیا دستگاه از پروفایل های 10 بیتی پشتیبانی می کند (عمق بیت برای HLG10):
کاتلین
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 (یا پروفایل پشتیبانی شده دیگری ) پشتیبانی می کند:
کاتلین
@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 را تنظیم کنید
پس از اطمینان از اینکه دستگاه شما از HDR پشتیبانی می کند، برنامه خود را طوری تنظیم کنید که یک جریان ویدیوی HDR خام را از دوربین ضبط کند. از setDynamicRangeProfile()
استفاده کنید تا OutputConfiguration
جریان را با یک نمایه HDR پشتیبانی شده توسط دستگاه ارائه دهید، که پس از ایجاد به CameraCaptureSession
ارسال می شود. لیست نمایه های HDR پشتیبانی شده را ببینید.
در نمونه کد زیر، setupSessionDynamicRangeProfile()
ابتدا بررسی می کند که دستگاه اندروید 13 را اجرا می کند. سپس CameraCaptureSession
با نمایه HDR پشتیبانی شده توسط دستگاه به عنوان یک OutputConfiguration
راه اندازی می کند:
کاتلین
/** * 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
تکراری برای پیش نمایش ضبط ارسال می کند:
کاتلین
session.setRepeatingRequest(previewRequest, null, cameraHandler)
و همچنین برای شروع ضبط ویدیو:
کاتلین
// 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 را رمزگذاری کنید
برای رمزگذاری جریان دوربین HDR و نوشتن فایل روی دیسک، از MediaCodec
استفاده کنید.
ابتدا OutputSurface
دریافت کنید، که به بافری که دادههای ویدیوی خام را ذخیره میکند، نگاشت میشود. برای MediaCodec
، از createInputSurface()
استفاده کنید.
برای مقداردهی اولیه MediaCodec
، یک برنامه باید یک MediaFormat
با نمایه کدک مشخص، فضای رنگ، محدوده رنگ و تابع انتقال ایجاد کند:
کاتلین
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)
برای جزئیات بیشتر در مورد پیاده سازی، به EncoderWrapper.kt
برنامه نمونه Camera2Video مراجعه کنید.
فرمت های HDR
از Android 13، دستگاههای دوربین با قابلیت خروجی 10 بیتی باید از HLG10 برای ضبط و پخش HDR پشتیبانی کنند. علاوه بر این، سازندگان دستگاهها میتوانند هر فرمت HDR را با استفاده از معماری ضبط HDR فعال کنند.
جدول زیر فرمت های HDR موجود و قابلیت های آن ها برای فیلم برداری HDR را خلاصه می کند.
قالب | تابع انتقال (TF) | فراداده | کدک | عمق بیت |
---|---|---|---|---|
HLG10 | HLG | خیر | HEVC | 10 بیتی |
HDR10 | پی کیو | استاتیک | HEVC | 10 بیتی |
HDR10+ | پی کیو | پویا | HEVC | 10 بیتی |
Dolby Vision 8.4 | HLG | پویا | HEVC | 10 بیتی |
منابع
برای یک برنامه کاربردی با قابلیت ضبط ویدیوی HDR، نمونه Camera2Video را در GitHub ببینید.