หมายเหตุ: หน้านี้อ้างอิงถึงแพ็กเกจ Camera2 เราขอแนะนำให้ใช้ CameraX เว้นแต่ว่าแอปของคุณต้องใช้ฟีเจอร์ระดับต่ำที่เฉพาะเจาะจงจาก Camera2 ทั้ง CameraX และ Camera2 รองรับ Android 5.0 (API ระดับ 21) ขึ้นไป
Camera2 API รองรับการจับภาพวิดีโอ High Dynamic Range (HDR) ซึ่งช่วยให้คุณดูตัวอย่างและบันทึกเนื้อหาวิดีโอ HDR โดยใช้กล้องได้ เมื่อเทียบกับ Standard Dynamic Range (SDR) แล้ว HDR จะมีช่วงสีที่กว้างกว่าและเพิ่มช่วงไดนามิกของคอมโพเนนต์ความสว่าง (จากปัจจุบัน 100 cd/m2 เป็น 1,000 cd/m2) ซึ่งส่งผลให้คุณภาพวิดีโอใกล้เคียงกับชีวิตจริงมากขึ้น โดยมีสีสันที่สมบูรณ์ยิ่งขึ้น ไฮไลต์ที่สว่างขึ้น และเงาที่มืดลง
ดูว่าวิดีโอ HDR บันทึกภาพพระอาทิตย์ตกดินได้ละเอียดและมีสีสันสดใสมากขึ้นอย่างไร
ข้อกำหนดเบื้องต้นของอุปกรณ์
อุปกรณ์ Android บางรุ่นไม่รองรับการจับภาพวิดีโอ HDR ก่อนจับภาพวิดีโอ HDR ในแอป ให้ตรวจสอบว่าอุปกรณ์ของคุณมีคุณสมบัติตรงตามข้อกำหนดเบื้องต้นต่อไปนี้หรือไม่
- กำหนดเป้าหมายเป็น Android 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) ?: return false 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) ?: false } 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