Sử dụng bộ sưu tập để sắp xếp ngăn nắp các trang
Lưu và phân loại nội dung dựa trên lựa chọn ưu tiên của bạn.
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 vùng sáng nhất và vùng tối nhất, nhờ đó chất lượng video gần giống hơn với những gì mắt thường nhìn thấy.
Bạn có thể thiết lập chế độ 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 của mình. 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ợ chế độ 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 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à truy cập vào màn hình hỗ trợ HDR.
Kiểm tra xem thiết bị có hỗ trợ phát HDR hay không
Sử dụng Display.getHdrCapabilities() để truy vấn các chức năng HDR của màn hình. Phương thức này trả về thông tin về các cấu hình HDR được hỗ trợ và dải độ chói cho màn hình.
Đoạn mã sau đây kiểm tra xem thiết bị có hỗ trợ chế độ 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ó khả năng phát nội dung HDR:
Kotlin
// Check if display supports the HDR typevalcapabilities=display?.hdrCapabilities?.supportedHdrTypes?:intArrayOf()if(!capabilities.contains(HDR_TYPE_HLG)){throwRuntimeException("Display does not support desired HDR type");}
Java
// Check if display supports the HDR typeint[]list=getDisplay().getHdrCapabilities().getSupportedHdrTypes();Listcapabilities=Arrays.stream(list).boxed().collect(Collectors.toList());if(!capabilities.contains(HDR_TYPE_HLG)){thrownewRuntimeException("Display does not support desired HDR type");}
Thiết lập chế độ 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 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 cách dùng SurfaceView. Nhờ đó, bạn có thể hiển thị nội dung video HDR mà không cần xử lý đặc biệt cho quá trình 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 cách sử dụng SurfaceView:
Kotlin
// Check if there's a codec that supports the specific HDR profilevallist=MediaCodecList(MediaCodecList.REGULAR_CODECS)varformat=MediaFormat()/* media format from the container */;format.setInteger(MediaFormat.KEY_PROFILE,MediaCodecInfo.CodecProfileLevel.AV1ProfileMain10)valcodecName=list.findDecoderForFormat(format)?:throwRuntimeException("No codec supports the format")// Here is a standard MediaCodec playback flowvalcodec:MediaCodec=MediaCodec.createByCodecName(codecName);valsurface:Surface=surfaceView.holder.surfacevalcallback:MediaCodec.Callback=(object:MediaCodec.Callback(){overridefunonInputBufferAvailable(codec:MediaCodec,index:Int){queue.offer(index)}overridefunonOutputBufferAvailable(codec:MediaCodec,index:Int,info:MediaCodec.BufferInfo){codec.releaseOutputBuffer(index,timestamp)}overridefunonError(codec:MediaCodec,e:MediaCodec.CodecException){// handle error}overridefunonOutputFormatChanged(codec:MediaCodec,format:MediaFormat){// handle format change}})codec.setCallback(callback)codec.configure(format,surface,crypto,0/* flags */)codec.start()while(/* until EOS */){valindex=queue.poll()valbuffer=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 profileMediaCodecListlist=newMediaCodecList(MediaCodecList.REGULAR_CODECS);MediaFormatformat=/* media format from the container */;format.setInteger(MediaFormat.KEY_PROFILE,CodecProfileLevel.AV1ProfileMain10);StringcodecName=list.findDecoderForFormat(format);if(codecName==null){thrownewRuntimeException("No codec supports the format");}// Below is a standard MediaCodec playback flowMediaCodeccodec=MediaCodec.getCodecByName(codecName);Surfacesurface=surfaceView.getHolder().getSurface();MediaCodec.Callbackcallback=newMediaCodec.Callback(){@OverridevoidonInputBufferAvailable(MediaCodeccodec,intindex){queue.offer(index);}@OverridevoidonOutputBufferAvailable(MediaCodeccodec,intindex){// release the buffer for rendercodec.releaseOutputBuffer(index,timestamp);}@OverridevoidonOutputFormatChanged(MediaCodeccodec,MediaFormatformat){// handle format change}@OverridevoidonError(MediaCodeccodec,MediaCodec.CodecExceptionex){// handle error}};codec.setCallback(callback);codec.configure(format,surface,crypto,0/* flags */);codec.start();while(/* until EOS */){intindex=queue.poll();ByteBufferbuffer=codec.getInputBuffer(index);buffer.put(/* write bitstream */);codec.queueInputBuffer(index,offset,size,timestamp,flags);}codec.stop();codec.release();
Để biết thêm các cách triển khai MediaCodec bằng SurfaceView, hãy xem các mẫu Camera Android.
Tài nguyên
Để biết thêm thông tin liên quan đến chế độ phát HDR, hãy xem các tài nguyên sau:
HDR
Quay video HDR: tìm hiểu cách thiết lập tính năng quay video HDR bằng Camera2 API.
ExoPlayer: tìm hiểu cách thiết lập ứng dụng bằng thư viện ExoPlayer.
Nội dung và mã mẫu trên trang này phải tuân thủ các giấy phép như mô tả trong phần Giấy phép nội dung. Java và OpenJDK là nhãn hiệu hoặc nhãn hiệu đã đăng ký của Oracle và/hoặc đơn vị liên kết của Oracle.
Cập nhật lần gần đây nhất: 2025-08-27 UTC.
[[["Dễ hiểu","easyToUnderstand","thumb-up"],["Giúp tôi giải quyết được vấn đề","solvedMyProblem","thumb-up"],["Khác","otherUp","thumb-up"]],[["Thiếu thông tin tôi cần","missingTheInformationINeed","thumb-down"],["Quá phức tạp/quá nhiều bước","tooComplicatedTooManySteps","thumb-down"],["Đã lỗi thời","outOfDate","thumb-down"],["Vấn đề về bản dịch","translationIssue","thumb-down"],["Vấn đề về mẫu/mã","samplesCodeIssue","thumb-down"],["Khác","otherDown","thumb-down"]],["Cập nhật lần gần đây nhất: 2025-08-27 UTC."],[],[],null,["# HDR video playback\n\nHDR, or High Dynamic Range, provides a wider range of colors and greater\ncontrast between the brightest whites and darkest shadows, resulting in video\nquality that more closely resembles what the naked eye perceives.\n\nYou can set up HDR video playback in your app to preview and play back HDR video\ncontent.\n\nThis article assumes that you've already added basic video playback support to\nyour app. See the [ExoPlayer](/guide/topics/media/exoplayer) documentation for\nmore details on playback.\n\nDevice prerequisites\n--------------------\n\nNot all Android devices support HDR playback. Before playing back HDR\nvideo content in your app, determine if your device meets the following\nprerequisites:\n\n- Targets Android 7.0 or higher (API layer 24).\n- Has a HDR-capable decoder and access to a HDR-capable display.\n\nCheck for HDR playback support\n------------------------------\n\nUse [`Display.getHdrCapabilities()`](/reference/android/view/Display#getHdrCapabilities()) to query a display's HDR capabilities. The method returns information about the supported HDR profiles and luminance range for the display.\n\nThe following code checks if the device supports HLG10 playback. Starting in Android 13, HLG10 is the minimum standard that device makers must support if the device is capable of HDR playback: \n\n### Kotlin\n\n```kotlin\n// Check if display supports the HDR type\nval capabilities = display?.hdrCapabilities?.supportedHdrTypes ?: intArrayOf()\nif (!capabilities.contains(HDR_TYPE_HLG)) {\n throw RuntimeException(\"Display does not support desired HDR type\");\n}\n```\n\n### Java\n\n```java\n// Check if display supports the HDR type\nint[] list = getDisplay().getHdrCapabilities().getSupportedHdrTypes();\nList capabilities = Arrays.stream(list).boxed().collect(Collectors.toList());\nif (!capabilities.contains(HDR_TYPE_HLG)) {\n throw new RuntimeException(\"Display does not support desired HDR type\");\n}\n```\n\nSet up HDR playback in your app\n-------------------------------\n\nIf your app uses [ExoPlayer](https://exoplayer.dev/), it supports HDR playback by default. See [Check for HDR playback support](#check_for_hdr_playback_support) for next steps.\n\nIf your app does not use ExoPlayer, set up HDR playback using `MediaCodec` via `SurfaceView`.\n| **Note:** HDR playback has limited support on [`TextureView`](/reference/android/view/TextureView) in Android 13 (API layer 33) and higher. When playing back HDR video content, `TextureView` transcodes the video from HDR to SDR, resulting in playback with possible loss of detail including clipped colors and video banding. If at all possible, you should use `SurfaceView` for HDR playback.\n\n### Set up MediaCodec using SurfaceView\n\nSet up a standard [`MediaCodec`](/reference/android/media/MediaCodec) playback flow using [`SurfaceView`](https://developer.android.com/reference/android/view/SurfaceView). This allows you to display HDR video content without any special handling for HDR playback:\n\n- `MediaCodec`: Decodes HDR video content.\n- `SurfaceView`: Displays HDR video content.\n\nThe following code checks if the codec supports the HDR profile, then sets up `MediaCodec` using `SurfaceView`: \n\n### Kotlin\n\n```kotlin\n// Check if there's a codec that supports the specific HDR profile\nval list = MediaCodecList(MediaCodecList.REGULAR_CODECS) var format = MediaFormat() /* media format from the container */;\nformat.setInteger(MediaFormat.KEY_PROFILE, MediaCodecInfo.CodecProfileLevel.AV1ProfileMain10)\nval codecName = list.findDecoderForFormat (format) ?: throw RuntimeException (\"No codec supports the format\")\n\n// Here is a standard MediaCodec playback flow\nval codec: MediaCodec = MediaCodec.createByCodecName(codecName);\nval surface: Surface = surfaceView.holder.surface\nval callback: MediaCodec.Callback = (object : MediaCodec.Callback() {\n override fun onInputBufferAvailable(codec: MediaCodec, index: Int) {\n queue.offer(index)\n }\n\n override fun onOutputBufferAvailable(\n codec: MediaCodec,\n index: Int,\n info: MediaCodec.BufferInfo\n ) {\n codec.releaseOutputBuffer(index, timestamp)\n }\n\n override fun onError(codec: MediaCodec, e: MediaCodec.CodecException) {\n // handle error\n }\n\n override fun onOutputFormatChanged(\n codec: MediaCodec, format: MediaFormat\n ) {\n // handle format change\n }\n})\n\ncodec.setCallback(callback)\ncodec.configure(format, surface, crypto, 0 /* flags */)\ncodec.start()\nwhile (/* until EOS */) {\n val index = queue.poll()\n val buffer = codec.getInputBuffer(index)\n buffer?.put(/* write bitstream */)\n codec.queueInputBuffer(index, offset, size, timestamp, flags)\n}\ncodec.stop()\ncodec.release()\n```\n\n### Java\n\n```java\n// Check if there's a codec that supports the specific HDR profile\nMediaCodecList list = new MediaCodecList(MediaCodecList.REGULAR_CODECS);\nMediaFormat format = /* media format from the container */;\nformat.setInteger(\n MediaFormat.KEY_PROFILE, CodecProfileLevel.AV1ProfileMain10);\nString codecName = list.findDecoderForFormat(format);\nif (codecName == null) {\n throw new RuntimeException(\"No codec supports the format\");\n}\n\n// Below is a standard MediaCodec playback flow\nMediaCodec codec = MediaCodec.getCodecByName(codecName);\nSurface surface = surfaceView.getHolder().getSurface();\nMediaCodec.Callback callback = new MediaCodec.Callback() {\n @Override\n void onInputBufferAvailable(MediaCodec codec, int index) {\n queue.offer(index);\n }\n\n @Override\n void onOutputBufferAvailable(MediaCodec codec, int index) {\n // release the buffer for render\n codec.releaseOutputBuffer(index, timestamp);\n }\n\n @Override\n void onOutputFormatChanged(MediaCodec codec, MediaFormat format) {\n // handle format change\n }\n\n @Override\n void onError(MediaCodec codec, MediaCodec.CodecException ex) {\n // handle error\n }\n\n};\ncodec.setCallback(callback);\ncodec.configure(format, surface, crypto, 0 /* flags */);\ncodec.start();\nwhile (/* until EOS */) {\n int index = queue.poll();\n ByteBuffer buffer = codec.getInputBuffer(index);\n buffer.put(/* write bitstream */);\n codec.queueInputBuffer(index, offset, size, timestamp, flags);\n}\ncodec.stop();\ncodec.release();\n```\n\nFor more `MediaCodec` implementations using `SurfaceView`, see the [Android Camera samples](https://github.com/android/camera-samples).\n| **Note:** Android takes screenshots in SDR. HDR content is tonemapped to SDR in screenshots.\n\nResources\n---------\n\nFor more information related to HDR playback, see the following resources:\n\n### HDR\n\n- [HDR video capture](/training/camera2/hdr-video-capture): learn how to set up HDR video capture using the Camera2 APIs.\n- [Camera2Video sample on Github](https://github.com/android/camera-samples/tree/main/Camera2Video): see a working app with HDR capture and playback functionality.\n\n### Media\n\n- [Media API reference](/reference/android/media/package-summary): learn more about the Media APIs.\n- [ExoPlayer](https://exoplayer.dev/): learn how to set up your app with the ExoPlayer library."]]