הערה: הדף הזה מתייחס לחבילה camera2. מומלץ להשתמש ב-CameraX, אלא אם לאפליקציה שלך נדרשים תכונות ספציפיות ברמה נמוכה. גם CameraX וגם Camera2 תומכים ב-Android 5.0 (רמת API 21) ואילך.
תמיכה בממשקי API של Camera2 צילום וידאו עם טווח דינמי גבוה (HDR), שמאפשר לראות תצוגה מקדימה לצלם תוכן של סרטוני HDR באמצעות המצלמה. בהשוואה לדינמיקה רגילה Range (SDR), באיכות HDR יש מגוון רחב יותר של צבעים ומגבירים את הדינמיקה. הטווח של רכיב הבהירות (החל מ- 100 cd/m2 עד 1,000s של cd/m2). התוצאה היא איכות וידאו שקרובה יותר לחיים האמיתיים, צבעים עשירים יותר, אזורים בהירים יותר וצלליות כהות יותר.
אפשר לראות איך סרטון HDR מצלמים את השקיעה בצורה מרהיבה יותר.


דרישות מוקדמות למכשירים
לא כל מכשירי Android תומכים בצילום סרטונים באיכות HDR. לפני צילום סרטון HDR באפליקציה, כדאי לבדוק אם המכשיר עומד בדרישות הדרישות המוקדמות הבאות:
- מוגדר טירגוט ל-Android 13 (רמת API 33).
- כולל חיישן מצלמה עם יכולות של 10 ביט ומעלה. למידע נוסף על HDR כאן תוכלו לקרוא איך בודקים אם יש תמיכה ב-HDR.
לא כל המכשירים עומדים בדרישות המוקדמות, ולכן ניתן להוסיף קוד נפרד נתיב בזמן ההגדרה של צילום וידאו באיכות HDR באפליקציה. כך האפליקציה תוכל לחזור ל-SDR במכשירים לא תואמים. כדאי גם להוסיף אפשרות בממשק המשתמש ל-SDR. המשתמש יכול להחליף מצב בין SDR ל-HDR בהתאם לצרכים שלהם לגבי הקלטת וידאו.
ארכיטקטורת צילום HDR
בתרשים הבא מוצגים הרכיבים העיקריים בארכיטקטורת צילום HDR.

כשמכשיר מצלמה מצלם פריים ב-HDR, ה-framework של Camera2 מקצה
מאגר נתונים זמני שמאחסן את הפלט של חיישן המצלמה המעובד.
הוא גם מצרף את המטא-נתונים המתאימים של HDR, אם הדבר נדרש על ידי פרופיל ה-HDR.
לאחר מכן, ה-framework של מצלמה2 מוסיף את מאגר הנתונים הזמני המאוכלס למשטח הפלט.
שיש הפניה אליו ב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()
בודק קודם
שמותקנת במכשיר Android 13.
לאחר מכן, הוא מגדיר את CameraCaptureSession
עם המכשיר שנתמך
פרופיל HDR כOutputConfiguration
:
/**
* Creates a [CameraCaptureSession] with a dynamic range profile.
*/
private fun setupSessionWithDynamicRangeProfile(
dynamicRange: Long,
device: CameraDevice,
targets: List
כשאפליקציית המצלמה מפעילה את המצלמה, היא שולחת
חוזר
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)
לפרטים נוספים על ההטמעה, ראו את האפליקציה לדוגמה של Camera2Video
EncoderWrapper.kt
פורמטים של HDR
החל מ-Android 13, מכשירי מצלמה עם יכולות פלט של 10 ביט חייבת לתמוך ב-HLG10 לצילום HDR הפעלה. בנוסף, יצרני המכשירים יכולים להפעיל כל פורמט HDR לפי בחירתם באמצעות ארכיטקטורת צילום HDR.
הטבלה הבאה מסכמת את הפורמטים הזמינים של HDR והיכולות שלהם לצילום סרטונים באיכות HDR.
פורמט | שיטת העברה (TF) | Metadata | קודק | עומק ביט |
---|---|---|---|---|
HLG10 | איכות חיים (HLG) | לא | מק"ט HEVC | 10-ביט |
HDR10 | PQ | סטטי | מק"ט HEVC | 10-ביט |
HDR10+ | PQ | דינמי | מק"ט HEVC | 10-ביט |
Dolby Vision 8.4 | איכות חיים (HLG) | דינמי | מק"ט HEVC | 10-ביט |
משאבים
לאפליקציה פעילה עם פונקציית צילום וידאו ב-HDR: דוגמה של Camera2Video ב-GitHub.