הערה: הדף הזה מתייחס לחבילה Camera2. אם האפליקציה לא דורשת תכונות ספציפיות ברמה נמוכה מ-Camera2, מומלץ להשתמש ב-CameraX. גם CameraX וגם Camera2 תומכים ב-Android מגרסה 5.0 (רמת API 21) ואילך.
ממשקי ה-API של Camera2 תומכים בצילום וידאו בטווח דינמי גבוה (HDR), שמאפשר לכם לצפות בתצוגה מקדימה של קטע וידאו ב-HDR ולצלם אותו באמצעות המצלמה. בהשוואה לטווח דינמי סטנדרטי (SDR), טווח דינמי גבוה (HDR) מציע מגוון רחב יותר של צבעים ומגדיל את הטווח הדינמי של רכיב הבהירות (מ-100 cd/m2 כרגע לאלפי cd/m2). כך מתקבלת איכות וידאו שקרובה יותר למציאות, עם צבעים עשירים יותר, אזורים בהירים יותר וצללים כהים יותר.
תראו איך סרטון HDR מתעד שקיעה עם פרטים עשירים יותר.
דרישות מקדימות למכשיר
לא כל מכשירי Android תומכים בצילום וידאו ב-HDR. לפני שאתם מצלמים סרטון HDR באפליקציה, אתם צריכים לבדוק אם המכשיר שלכם עומד בדרישות המוקדמות הבאות:
- מטרגטת ל-Android 13 (רמת API 33).
- חיישן מצלמה של 10 ביט או יותר. מידע נוסף על תמיכה ב-HDR זמין במאמר בדיקת התמיכה ב-HDR.
לא כל המכשירים עומדים בדרישות המוקדמות, לכן אתם יכולים להוסיף נתיב קוד נפרד כשאתם מגדירים צילום וידאו ב-HDR באפליקציה. כך האפליקציה תוכל לחזור ל-SDR במכשירים לא תואמים. כדאי גם להוסיף אפשרות SDR לממשק המשתמש. המשתמש יכול לעבור בין SDR ל-HDR בהתאם לצרכים שלו בצילום הסרטון.
ארכיטקטורת צילום ב-HDR
בתרשים הבא מוצגים הרכיבים העיקריים של ארכיטקטורת הצילום ב-HDR.
כשמצלמים פריים ב-HDR, מסגרת Camera2 מקצה מאגר נתונים ששומר את הפלט המעובד של חיישן המצלמה. הוא גם מצרף את המטא-נתונים המתאימים של HDR אם הם נדרשים על ידי פרופיל ה-HDR. לאחר מכן, מסגרת Camera2 מוסיפה את המאגר המאוכלס לתור של משטח הפלט שאליו מפנה CaptureRequest, כמו מסך או מקודד וידאו, כפי שמוצג בתרשים.
איך בודקים אם יש תמיכה ב-HDR
לפני שאתם מצלמים סרטון HDR באפליקציה, אתם צריכים לבדוק אם המכשיר תומך בפרופיל ה-HDR שבחרתם.
משתמשים ב-method 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 chosen 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() בודק קודם שהמכשיר פועל עם Android 13. לאחר מכן, הוא מגדיר את CameraCaptureSession עם פרופיל ה-HDR שנתמך במכשיר בתור OutputConfiguration:
/**
* Creates a [CameraCaptureSession] with a dynamic range profile.
*/
private fun setupSessionWithDynamicRangeProfile(
dynamicRange: Long,
device: CameraDevice,
targets: List<Surface>,
handler: Handler? = null,
stateCallback: CameraCaptureSession.StateCallback
): Boolean {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU) {
val outputConfigs = mutableListOf<OutputConfiguration>()
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.
קודם כל, מקבלים את הפלט Surface, שממופה למאגר שבו מאוחסנים נתוני הווידאו הגולמיים. בשביל 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 | PQ | סטטי | HEVC | 10 ביט |
| HDR10+ | PQ | דינמי | HEVC | 10 ביט |
| Dolby Vision 8.4 | HLG | דינמי | HEVC | 10 ביט |
משאבים
כדי לראות אפליקציה פעילה עם פונקציונליות של צילום וידאו ב-HDR, עיינו בדוגמה של Camera2Video ב-GitHub.