Phát video HDR

HDR (Dải động cao) 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, nhờ đó chất lượng video giống với hình ảnh mà mắt thường nhìn thấy hơn.

Bạn có thể thiết lập tính năng phát video HDR trong ứng dụng để xem trước và phát 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ề tính năng phát.

Đ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 phát HDR. Trước khi phát nội dung video HDR trong ứng dụng, 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 không:

  • Nhắm đến Android 7.0 trở lên (lớp API 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 thiết bị có hỗ trợ tính năng phát HDR không

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

Mã sau đây kiểm tra xem thiết bị có hỗ trợ phát HLG10 hay không. Kể từ Android 13, HLG10 là tiêu chuẩn tối thiểu mà nhà sản xuất thiết bị phải hỗ trợ nếu thiết bị có thể 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 tính năng phát HDR trong ứng dụng

Nếu ứng dụng của bạn sử dụng ExoPlayer, thì ứng dụng đó sẽ hỗ trợ chế độ phát HDR theo mặc định. Hãy xem phần Kiểm tra khả năng hỗ trợ phát HDR để 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 thông 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. Điều 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 để phát HDR:

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

Mã sau đây 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 các mẫu Máy ảnh Android.

Tài nguyên

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

HDR

Nội dung nghe nhìn