Quay video HDR

Lưu ý: Trang này đề cập đến gói Camera2. Trừ phi ứng dụng của bạn yêu cầu các tính năng cụ thể ở cấp độ thấp từ Camera2, bạn nên sử dụng CameraX. Cả CameraX và Camera2 đều hỗ trợ Android 5.0 (API cấp 21) trở lên.

Hỗ trợ Camera2 API Quay video có Dải động cao (HDR), cho phép bạn xem trước và quay nội dung video HDR bằng máy ảnh của bạn. So với động chuẩn Phạm vi (SDR), HDR cung cấp dải màu rộng hơn và tăng độ động phạm vi của thành phần độ chói (từ 100 cd/m2 hiện tại đến 1000 cd/m2). Nhờ vậy, video có chất lượng gần giống với thực tế hơn, màu sắc phong phú hơn, vùng sáng sáng hơn và bóng tối hơn.

Xem video HDR chụp cảnh hoàng hôn chi tiết hơn như thế nào.

Hình 1. So sánh chất lượng video SDR (trên cùng) và HDR (ở dưới cùng).

Điều kiện tiên quyết đối với thiết bị

Không phải thiết bị Android nào cũng hỗ trợ tính năng quay video HDR. Trước khi quay video HDR trong ứng dụng, hãy xác định xem thiết bị của bạn có đáp ứng yêu cầu hay không các điều kiện tiên quyết sau:

Vì không phải tất cả thiết bị đều đáp ứng điều kiện tiên quyết, nên bạn có thể thêm một mã riêng khi thiết lập quay video HDR trong ứng dụng của bạn. Việc này sẽ khiến ứng dụng của bạn quay lại dùng SDR trên những thiết bị không tương thích. Ngoài ra, hãy cân nhắc việc thêm tuỳ chọn giao diện người dùng cho SDR. Sau đó, người dùng có thể bật/tắt giữa SDR và HDR để đáp ứng nhu cầu quay video của họ.

Cấu trúc chụp HDR

Sơ đồ dưới đây cho thấy các thành phần chính của cấu trúc chụp HDR.

Sơ đồ cấu trúc chụp HDR.
Hình 2. Sơ đồ cấu trúc chụp HDR.

Khi một thiết bị máy ảnh chụp một khung hình ở HDR, khung Camera2 sẽ phân bổ một vùng đệm lưu trữ đầu ra cảm biến của máy ảnh đã được xử lý. Chế độ này cũng đính kèm siêu dữ liệu HDR tương ứng nếu cấu hình HDR yêu cầu. Sau đó, khung Camera2 sẽ xếp hàng đợi bộ đệm điền sẵn cho bề mặt đầu ra được tham chiếu trong CaptureRequest, chẳng hạn như màn hình hoặc như minh hoạ trong biểu đồ.

Kiểm tra xem có hỗ trợ HDR không

Trước khi quay video HDR trong ứng dụng, hãy xác định xem thiết bị có hỗ trợ hay không hồ sơ HDR mong muốn của bạn.

Sử dụng phương thức CameraManager getCameraCharacteristics() để có được CameraCharacteristics mà bạn có thể truy vấn về tính năng HDR của thiết bị.

Các bước sau đây sẽ kiểm tra xem thiết bị có hỗ trợ HLG10 hay không. HLG10 là tiêu chuẩn HDR cơ sở mà các nhà sản xuất thiết bị phải hỗ trợ trên máy ảnh có đầu ra 10 bit.

  1. Trước tiên, hãy kiểm tra xem thiết bị có hỗ trợ cấu hình 10 bit (bit-depth cho HLG10) hay không:

    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. Tiếp theo, hãy kiểm tra xem thiết bị có hỗ trợ HLG10 (hoặc một hồ sơ khác được hỗ trợ) hay không:

    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;
    }
    

Nếu thiết bị hỗ trợ chế độ HDR thì isHLGSupported() sẽ luôn trả về true. Để biết thêm thông tin, hãy xem CameraCharacteristics tài liệu tham khảo.

Thiết lập tính năng chụp HDR

Sau khi đảm bảo rằng thiết bị của bạn hỗ trợ HDR, hãy thiết lập ứng dụng để chụp luồng video HDR thô từ máy ảnh. Sử dụng setDynamicRangeProfile() để cung cấp OutputConfiguration của sự kiện phát trực tiếp có hồ sơ HDR được thiết bị hỗ trợ, hồ sơ này sau đó được chuyển vào CameraCaptureSession khi tạo. Xem danh sách các cấu hình HDR được hỗ trợ.

Trong mã mẫu sau, đầu tiên setupSessionDynamicRangeProfile() sẽ kiểm tra rằng thiết bị đang chạy Android 13. Sau đó, thao tác này thiết lập CameraCaptureSession với thành phần được thiết bị hỗ trợ Cấu hình HDR với tư cách là 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
      }
  }

}

Khi ứng dụng máy ảnh của bạn khởi chạy máy ảnh, ứng dụng sẽ gửi một lặp lại CaptureRequest để xem trước bản ghi:

Kotlin

session.setRepeatingRequest(previewRequest, null, cameraHandler)

Cách bắt đầu quay video:

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)

Mã hoá luồng camera HDR

Để mã hoá luồng camera HDR và ghi tệp vào ổ đĩa, sử dụng MediaCodec.

Trước tiên, hãy tải OutputSurface, liên kết với một bộ đệm lưu trữ dữ liệu video thô. Đối với MediaCodec, sử dụng createInputSurface().

Để khởi chạy MediaCodec, ứng dụng phải tạo một MediaFormat với một thuộc tính cụ thể cấu hình bộ mã hoá và giải mã, hệ màu, dải màu và chức năng chuyển:

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)

Để biết thêm thông tin chi tiết về cách triển khai, hãy xem EncoderWrapper.kt.

Định dạng HDR

Kể từ Android 13, các thiết bị có camera có khả năng đầu ra 10 bit phải hỗ trợ HLG10 để chụp HDR và phát lại. Ngoài ra, các nhà sản xuất thiết bị có thể bật bất kỳ định dạng HDR nào họ chọn bằng cách sử dụng kiến trúc chụp HDR.

Bảng sau đây tóm tắt các định dạng HDR có sẵn và khả năng của chúng để quay video HDR.

Định dạng Hàm truyền (TF) Metadata Bộ mã hoá và giải mã Độ sâu bit
HLG10 HLG Không chuẩn HEVC 10 bit
HDR10 PQ Tĩnh chuẩn HEVC 10 bit
HDR10+ PQ Động chuẩn HEVC 10 bit
Dolby Vision 8.4 HLG Động chuẩn HEVC 10 bit

Tài nguyên

Đối với ứng dụng hoạt động có chức năng quay video HDR, hãy xem Mẫu Camera2Video trên GitHub.