การจับภาพวิดีโอ HDR

หมายเหตุ: หน้านี้เกี่ยวข้องกับแพ็กเกจ camera2 เราขอแนะนำให้ใช้ cameraX เว้นแต่ว่าแอปของคุณต้องใช้ฟีเจอร์ระดับต่ำที่เฉพาะเจาะจงจาก Camera2 ทั้ง CameraX และ Camera2 รองรับ Android 5.0 (API ระดับ 21) ขึ้นไป

การรองรับ camera2 API การบันทึกวิดีโอ High Dynamic Range (HDR) ซึ่งช่วยให้คุณดูตัวอย่างและ บันทึกเนื้อหาวิดีโอ HDR โดยใช้กล้อง เทียบกับไดนามิกมาตรฐาน ช่วง (SDR) HDR มีช่วงสีที่กว้างกว่าและเพิ่มไดนามิก ช่วงของคอมโพเนนต์ความสว่าง (ตั้งแต่ 100 cd/m2 ในปัจจุบัน ถึง 1,000 วินาทีของ cd/m2) วิธีนี้ทำให้คุณภาพวิดีโอใกล้เคียงกับในชีวิตจริงมากขึ้น โดย สีที่เข้มขึ้น ไฮไลต์ที่สว่างขึ้น และเงาที่เข้มขึ้น

ดูวิธีที่วิดีโอ HDR บันทึกพระอาทิตย์ตกแบบละเอียดมากขึ้น

วันที่
รูปที่ 1 การเปรียบเทียบคุณภาพวิดีโอแบบ SDR (ด้านบน) กับ HDR (ด้านล่าง)

ข้อกำหนดเบื้องต้นของอุปกรณ์

อุปกรณ์ Android บางรุ่นไม่รองรับการจับภาพวิดีโอ HDR ก่อนจับภาพวิดีโอ HDR ในแอป ให้ตรวจสอบว่าอุปกรณ์ของคุณเป็นไปตามข้อกำหนดหรือไม่ ข้อกำหนดเบื้องต้นต่อไปนี้

  • กำหนดเป้าหมายเป็น Android 13 (API ระดับ 33)
  • มีเซ็นเซอร์กล้องที่รองรับความละเอียด 10 บิตขึ้นไป ดูข้อมูลเพิ่มเติมเกี่ยวกับ HDR โปรดดูการสนับสนุนที่หัวข้อตรวจหาการรองรับ HDR

เนื่องจากอุปกรณ์บางเครื่องมีคุณสมบัติไม่ตรงตามเกณฑ์เบื้องต้น คุณจึงใส่รหัสแยกต่างหากได้ เมื่อตั้งค่าการจับภาพวิดีโอ HDR ในแอป ซึ่งจะช่วยให้แอปของคุณกลับไปใช้ SDR ในอุปกรณ์ที่เข้ากันไม่ได้ นอกจากนี้ ให้พิจารณาเพิ่มตัวเลือก UI สำหรับ SDR ด้วย จากนั้นผู้ใช้จึงจะสลับ ระหว่าง SDR และ HDR เมื่อต้องการบันทึกวิดีโอ

สถาปัตยกรรมการจับภาพ HDR

แผนภาพต่อไปนี้แสดงส่วนประกอบหลักของสถาปัตยกรรมการจับภาพ HDR

วันที่ แผนภาพสถาปัตยกรรมการจับภาพ HDR
รูปที่ 2 แผนภาพสถาปัตยกรรมการจับภาพ HDR

เมื่ออุปกรณ์กล้องจับภาพเฟรมในรูปแบบ HDR เฟรมเวิร์ก Camera2 จะจัดสรร บัฟเฟอร์ที่จัดเก็บเอาต์พุตของเซ็นเซอร์กล้องที่ประมวลผลแล้ว นอกจากนี้จะแนบข้อมูลเมตา HDR ที่เกี่ยวข้องมาด้วย หากโปรไฟล์ HDR กำหนดไว้ จากนั้นเฟรมเวิร์ก Camera2 จะจัดคิวบัฟเฟอร์ที่มีอยู่สำหรับแพลตฟอร์มเอาต์พุต ที่กล่าวถึงในCaptureRequest เช่น จอแสดงผลหรือ โปรแกรมเปลี่ยนไฟล์วิดีโอ ดังที่แสดงในแผนภาพ

ตรวจสอบการรองรับ HDR

ก่อนจับภาพวิดีโอ HDR ในแอป ให้ตรวจสอบว่าอุปกรณ์รองรับหรือไม่ โปรไฟล์ HDR ที่คุณต้องการได้

ใช้เมธอด CameraManager getCameraCharacteristics() เพื่อดู CameraCharacteristics ซึ่งคุณสามารถค้นหาความสามารถ HDR ของอุปกรณ์ได้

ขั้นตอนต่อไปนี้ตรวจสอบว่าอุปกรณ์รองรับ HLG10 หรือไม่ HLG10 เป็นมาตรฐาน HDR พื้นฐานที่ผู้ผลิตอุปกรณ์ต้องรองรับ ในกล้องที่มีเอาต์พุต 10 บิต

  1. ก่อนอื่น ให้ตรวจสอบว่าอุปกรณ์รองรับโปรไฟล์ 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
    }
    
  2. ถัดไป ให้ตรวจสอบว่าอุปกรณ์รองรับ 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

หลังจากที่ตรวจสอบแล้วว่าอุปกรณ์รองรับ HDR ให้ตั้งค่าแอปเพื่อจับภาพ สตรีมวิดีโอ HDR ดิบจากกล้อง ใช้ setDynamicRangeProfile() เพื่อระบุ OutputConfiguration ของสตรีม ด้วยโปรไฟล์ HDR ที่อุปกรณ์รองรับ ซึ่งจะมีการส่งผ่าน ไปยัง CameraCaptureSession ขณะสร้าง ดูรายการโปรไฟล์ HDR ที่รองรับ

ในตัวอย่างโค้ดต่อไปนี้ setupSessionDynamicRangeProfile() จะตรวจสอบก่อน ว่าอุปกรณ์ใช้ Android 13 จากนั้นตั้งค่า CameraCaptureSession ด้วยอุปกรณ์ที่ระบบรองรับ โปรไฟล์ HDR ในรูปแบบ 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

วิธีเข้ารหัสสตรีมจากกล้อง 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

รูปแบบ 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