ضبط ویدیو HDR

توجه: این صفحه به بسته Camera2 اشاره دارد. توصیه می‌کنیم از CameraX استفاده کنید، مگراینکه برنامه‌تان به ویژگی‌های خاص و سطح پایین Camera2 نیاز داشته باشد. ‫CameraX و Camera2 هر دو از Android 5.0 (سطح میانای برنامه‌سازی کاربردی ۲۱) و بالاتر پشتیبانی می‌کنند.

Camera2 APIs از ضبط ویدیو با «دامنه پویای بالا» (HDR) پشتیبانی می‌کند که به شما امکان می‌دهد محتوای ویدیویی HDR را بااستفاده از دوربینتان پیش‌نمایش و ضبط کنید. درمقایسه با «دامنه پویای استاندارد» (SDR)، HDR طیف وسیع‌تری از رنگ‌ها را ارائه می‌دهد و دامنه پویای مؤلفه درخشندگی را افزایش می‌دهد (از ۱۰۰ cd/m2 فعلی به ۱۰۰۰ cd/m2). این امر منجر به کیفیت ویدیویی می‌شود که با رنگ‌های غنی‌تر، برجستگی‌های روشن‌تر، و سایه‌های تیره‌تر، بیشتر به واقعیت نزدیک است.

ببینید ویدیو HDR چگونه غروب آفتاب را با جزئیات زنده‌تری ضبط می‌کند.

شکل ۱. مقایسه کیفیت ویدیو SDR (بالا) درمقابل HDR (پایین).

پیش‌نیازهای دستگاه

همه دستگاه‌های Android از ضبط ویدیو HDR پشتیبانی نمی‌کنند. قبل‌از ضبط ویدیو HDR در برنامه‌تان، بررسی کنید که آیا دستگاهتان پیش‌نیازهای زیر را دارد یا نه:

  • Android 13 (میانای برنامه‌سازی کاربردی سطح ۳۳) را هدف‌یابی می‌کند.
  • حسگر دوربین با قابلیت ۱۰ بیت یا بالاتر داشته باشد. برای اطلاعات بیشتر درباره پشتیبانی HDR، به بررسی پشتیبانی HDR مراجعه کنید.

چون همه دستگاه‌ها پیش‌نیازها را ندارند، می‌توانید هنگام راه‌اندازی ضبط ویدیو HDR در برنامه‌تان، مسیر کد جداگانه‌ای اضافه کنید. این کار به برنامه‌تان اجازه می‌دهد در دستگاه‌های ناسازگار به SDR برگردد. همچنین، اضافه کردن گزینه میانای کاربر برای SDR را درنظر بگیرید. سپس کاربر می‌تواند برای نیازهای ضبط ویدیو خود، بین SDR و HDR جابه‌جا شود.

معماری ضبط HDR

نمودار زیر مؤلفه‌های اصلی معماری ضبط HDR را نشان می‌دهد.

نمودار معماری ضبط HDR.
شکل ۲. نمودار معماری ضبط HDR.

وقتی دستگاه دوربین قابی را در HDR ضبط می‌کند، چارچوب Camera2 میان‌گیری را اختصاص می‌دهد که خروجی پردازش‌شده حسگر دوربین را ذخیره می‌کند. همچنین، درصورت نیاز نمایه HDR، فراداده HDR مربوطه را پیوست می‌کند. سپس چارچوب Camera2 میان‌گیر پرشده را برای سطح خروجی ارجاع‌شده در CaptureRequest، مانند نمایشگر یا رمزگذار ویدیو، همان‌طور که در نمودار نشان داده شده است، در صف قرار می‌دهد.

بررسی پشتیبانی از HDR

قبل‌از ضبط ویدیو HDR در برنامه‌تان، بررسی کنید که آیا دستگاه از نمایه HDR موردنظرتان پشتیبانی می‌کند یا نه.

از روش CameraManager getCameraCharacteristics() برای دریافت نمونه CameraCharacteristics استفاده کنید که می‌توانید آن را برای قابلیت‌های HDR دستگاهتان پُرسمان کنید.

مراحل زیر بررسی می‌کند که آیا دستگاه از HLG10 پشتیبانی می‌کند یا نه. HLG10 استاندارد HDR پایه است که سازندگان دستگاه باید در دوربین‌های دارای خروجی ۱۰ بیتی از آن پشتیبانی کنند.

  1. ابتدا بررسی کنید که دستگاه از نمایه‌های ۱۰ بیتی (عمق بیت برای 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
    }
  2. سپس، بررسی کنید که آیا دستگاه از 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,
      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 تکراری برای پیش‌نمایش ضبط ارسال می‌کند:

کاتلین

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)

برای جزئیات بیشتر درباره پیاده‌سازی، به EncoderWrapper.kt برنامه نمونه Camera2Video مراجعه کنید.

قالب‌های HDR

از Android 13، دستگاه‌های دوربین با قابلیت‌های خروجی ۱۰ بیتی باید از HLG10 برای ضبط HDR و بازپخش پشتیبانی کنند. علاوه‌براین، سازندگان دستگاه می‌توانند هر قالب HDR را که می‌خواهند بااستفاده از معماری ضبط HDR فعال کنند.

جدول زیر قالب‌های HDR دردسترس و قابلیت‌های آن‌ها را برای ضبط ویدیو HDR خلاصه می‌کند.

قالب تابع انتقال (TF) فراداده کدک عمق بیت
HLG10 HLG نه HEVC ‫۱۰ بیتی
HDR10 PQ ثابت HEVC ‫۱۰ بیتی
HDR10+‎ PQ پویا HEVC ‫۱۰ بیتی
Dolby Vision 8.4 HLG پویا HEVC ‫۱۰ بیتی

منابع

برای برنامه‌ای که قابلیت ضبط ویدیو HDR دارد، نمونه Camera2Video را در GitHub ببینید.