تشغيل فيديو بنطاق عالي الديناميكية (HDR)

توفّر تقنية HDR أو النطاق العالي الديناميكية نطاقًا أوسع من الألوان وتباينًا أكبر بين درجات اللون الأبيض الأكثر سطوعًا والظلال الداكنة، ما يؤدي إلى تحسين جودة الفيديو التي تشبه إلى حدّ كبير ما ترصده العين المجردة.

يمكنك إعداد ميزة تشغيل الفيديو بنطاق HDR في تطبيقك لمعاينة محتوى الفيديو وتشغيله باستخدام تقنية HDR.

تفترض هذه المقالة أنك أضفت الدعم الأساسي لتشغيل الفيديو إلى تطبيقك. راجِع مستندات ExoPlayer للحصول على مزيد من التفاصيل حول التشغيل.

المتطلبات الأساسية للأجهزة

لا تتيح بعض أجهزة Android تشغيل المحتوى بنطاق عالي الديناميكية. قبل تشغيل محتوى فيديو HDR في تطبيقك، حدِّد ما إذا كان جهازك يستوفي المتطلبات الأساسية التالية:

  • يستهدف الإصدار 7.0 من نظام التشغيل Android أو الإصدارات الأحدث (طبقة واجهة برمجة التطبيقات 24).
  • تتوفّر فيه أداة فك ترميز متوافقة مع النطاق العالي الديناميكية وإمكانية الوصول إلى شاشة متوافقة مع النطاق العالي الديناميكية.

التأكّد من توفّر إمكانية تشغيل الفيديوهات بنطاق عالي الديناميكية

استخدِم Display.getHdrCapabilities() للبحث عن إمكانات نطاق عالي الديناميكية (HDR) على الشاشة. تعرض الطريقة معلومات حول ملفات تعريف النطاق العالي الديناميكية (HDR) المتوافقة ونطاق سطوع الشاشة.

يتحقّق الرمز التالي مما إذا كان الجهاز متوافقًا مع تشغيل تقنية HLG10. بدءًا من نظام التشغيل Android 13، معيار HLG10 هو الحد الأدنى من المعايير التي يجب أن يتوافق معها صنّاع الأجهزة إذا كان الجهاز قادرًا على تشغيل المحتوى بنطاق عالي الديناميكية:

Kotlin

// Check if display supports the HDR type
val capabilities = display?.hdrCapabilities?.supportedHdrTypes ?: intArrayOf()
if (!capabilities.contains(HDR_TYPE_HLG)) {
  throw RuntimeException("Display does not support desired HDR type");
}

Java

// Check if display supports the HDR type
int[] list = getDisplay().getHdrCapabilities().getSupportedHdrTypes();
List capabilities = Arrays.stream(list).boxed().collect(Collectors.toList());
if (!capabilities.contains(HDR_TYPE_HLG)) {
 throw new RuntimeException("Display does not support desired HDR type");
}

إعداد ميزة "التشغيل باستخدام النطاق العالي الديناميكية" في تطبيقك

إذا كان تطبيقك يستخدم ExoPlayer، سيكون متوافقًا مع التشغيل بنطاق عالي الديناميكية (HDR) بشكل تلقائي. لمعرفة الخطوات التالية، يُرجى الاطّلاع على القسم التحقّق من توفّر إمكانية تشغيل الفيديوهات بنطاق عالي الديناميكية (HDR).

إذا كان تطبيقك لا يستخدم ExoPlayer، يمكنك إعداد ميزة "التشغيل باستخدام النطاق العالي الديناميكية" باستخدام "MediaCodec" من خلال "SurfaceView".

إعداد MediaCodec باستخدام SurfaceView

يمكنك إعداد مسار تشغيل عادي على MediaCodec باستخدام SurfaceView. يتيح لك ذلك عرض محتوى الفيديو بنطاق عالي الديناميكية بدون أي معالجة خاصة للتشغيل بنطاق عالي الديناميكية:

  • MediaCodec: فك ترميز محتوى الفيديو بنطاق عالي الديناميكية (HDR)
  • SurfaceView: لعرض محتوى الفيديو بنطاق عالي الديناميكية (HDR)

يتحقّق الرمز التالي مما إذا كان برنامج الترميز يتوافق مع الملف الشخصي للنطاق العالي الديناميكية، ثم يتم إعداد MediaCodec باستخدام SurfaceView:

Kotlin

// Check if there's a codec that supports the specific HDR profile
val list = MediaCodecList(MediaCodecList.REGULAR_CODECS) var format = MediaFormat() /* media format from the container */;
format.setInteger(MediaFormat.KEY_PROFILE, MediaCodecInfo.CodecProfileLevel.AV1ProfileMain10)
val codecName = list.findDecoderForFormat (format) ?: throw RuntimeException ("No codec supports the format")

// Here is a standard MediaCodec playback flow
val codec: MediaCodec = MediaCodec.createByCodecName(codecName);
val surface: Surface = surfaceView.holder.surface
val callback: MediaCodec.Callback = (object : MediaCodec.Callback() {
   override fun onInputBufferAvailable(codec: MediaCodec, index: Int) {
      queue.offer(index)
   }

   override fun onOutputBufferAvailable(
      codec: MediaCodec,
      index: Int,
      info: MediaCodec.BufferInfo
   ) {
      codec.releaseOutputBuffer(index, timestamp)
   }

   override fun onError(codec: MediaCodec, e: MediaCodec.CodecException) {
      // handle error
   }

   override fun onOutputFormatChanged(
      codec: MediaCodec, format: MediaFormat
   ) {
      // handle format change
   }
})

codec.setCallback(callback)
codec.configure(format, surface, crypto, 0 /* flags */)
codec.start()
while (/* until EOS */) {
   val index = queue.poll()
   val buffer = codec.getInputBuffer(index)
   buffer?.put(/* write bitstream */)
   codec.queueInputBuffer(index, offset, size, timestamp, flags)
}
codec.stop()
codec.release()

Java

// Check if there's a codec that supports the specific HDR profile
MediaCodecList list = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
MediaFormat format = /* media format from the container */;
format.setInteger(
    MediaFormat.KEY_PROFILE, CodecProfileLevel.AV1ProfileMain10);
String codecName = list.findDecoderForFormat(format);
if (codecName == null) {
    throw new RuntimeException("No codec supports the format");
}

// Below is a standard MediaCodec playback flow
MediaCodec codec = MediaCodec.getCodecByName(codecName);
Surface surface = surfaceView.getHolder().getSurface();
MediaCodec.Callback callback = new MediaCodec.Callback() {
    @Override
    void onInputBufferAvailable(MediaCodec codec, int index) {
        queue.offer(index);
    }

    @Override
    void onOutputBufferAvailable(MediaCodec codec, int index) {
        // release the buffer for render
        codec.releaseOutputBuffer(index, timestamp);
    }

    @Override
    void onOutputFormatChanged(MediaCodec codec, MediaFormat format) {
        // handle format change
    }

    @Override
    void onError(MediaCodec codec, MediaCodec.CodecException ex) {
        // handle error
    }

};
codec.setCallback(callback);
codec.configure(format, surface, crypto, 0 /* flags */);
codec.start();
while (/* until EOS */) {
    int index = queue.poll();
    ByteBuffer buffer = codec.getInputBuffer(index);
    buffer.put(/* write bitstream */);
    codec.queueInputBuffer(index, offset, size, timestamp, flags);
}
codec.stop();
codec.release();

للمزيد من عمليات تنفيذ MediaCodec باستخدام SurfaceView، يمكنك الاطّلاع على نماذج كاميرا Android.

المراجع

لمزيد من المعلومات حول التشغيل بنطاق عالي الديناميكية (HDR)، يُرجى الاطّلاع على المراجع التالية:

نطاق HDR

الوسائط