Phát video HDR

HDR hay Dải động cao (High Dynamic Range) cung cấp dải màu rộng hơn và độ tương phản cao hơn giữa màu trắng sáng nhất và bóng tối nhất, mang lại chất lượng video gần giống với những gì mắt thường nhìn thấy.

Bạn có thể thiết lập tính năng phát video HDR trong ứng dụng của mình để xem trước và phát lại nội dung video HDR.

Bài viết này giả định rằng bạn đã thêm tính năng hỗ trợ phát video cơ bản vào ứng dụng. Hãy xem tài liệu về ExoPlayer để biết thêm thông tin chi tiết về cách phát.

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

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

  • Nhắm đến Android 7.0 trở lên (API lớp 24).
  • Có bộ giải mã hỗ trợ HDR và quyền truy cập vào màn hình hỗ trợ HDR.

Kiểm tra xem có hỗ trợ tính năng phát HDR hay không

Sử dụng Display.getHdrCapabilities() để truy vấn tính năng HDR của màn hình. Phương thức này sẽ trả về thông tin về các cấu hình HDR được hỗ trợ và phạm vi chiếu sáng cho màn hình.

Mã sau đây sẽ kiểm tra xem thiết bị có hỗ trợ tính năng phát HLG10 hay không. Kể từ Android 13, HLG10 là tiêu chuẩn tối thiểu mà các nhà sản xuất thiết bị phải hỗ trợ nếu thiết bị có khả năng phát HDR:

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

Thiết lập chế độ phát HDR trong ứng dụng

Nếu sử dụng ExoPlayer, ứng dụng của bạn sẽ hỗ trợ chế độ phát HDR theo mặc định. Hãy xem bài viết Kiểm tra xem có hỗ trợ tính năng phát HDR hay không để biết các bước tiếp theo.

Nếu ứng dụng của bạn không sử dụng ExoPlayer, hãy thiết lập chế độ phát HDR bằng MediaCodec qua SurfaceView.

Thiết lập MediaCodec bằng SurfaceView

Thiết lập quy trình phát MediaCodec tiêu chuẩn bằng SurfaceView. Tính năng này cho phép bạn hiển thị nội dung video HDR mà không cần xử lý đặc biệt nào để phát HDR:

  • MediaCodec: Giải mã nội dung video HDR.
  • SurfaceView: Hiển thị nội dung video HDR.

Mã sau đây sẽ kiểm tra xem bộ mã hoá và giải mã có hỗ trợ hồ sơ HDR hay không, sau đó thiết lập MediaCodec bằng 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();

Để biết thêm thông tin về cách triển khai MediaCodec bằng SurfaceView, hãy xem mẫu Máy ảnh Android.

Tài nguyên

Để biết thêm thông tin liên quan đến việc phát HDR, hãy xem các tài nguyên sau:

HDR

Nội dung nghe nhìn