Only set HDR transcoder flags for HDR content.

This commit is contained in:
Greyson Parrelli
2026-02-19 10:42:17 -05:00
committed by Michelle Tang
parent 701bed970b
commit 5c6962082a
3 changed files with 40 additions and 14 deletions

View File

@@ -13,6 +13,7 @@ import androidx.annotation.RequiresApi;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.video.interfaces.MediaInput;
import org.thoughtcrime.securesms.video.videoconverter.utils.MediaCodecCompat;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@@ -88,19 +89,25 @@ final class VideoThumbnailsExtractor {
outputSurface = new OutputSurface(outputWidthRotated, outputHeightRotated, true);
decoder = MediaCodec.createDecoderByType(mime);
if (Build.VERSION.SDK_INT >= 31) {
final String VENDOR_DOLBY_CODEC_TRANSFER_PARAMKEY = "vendor.dolby.codec.transfer.value";
MediaCodec.ParameterDescriptor descriptor = decoder.getParameterDescriptor(VENDOR_DOLBY_CODEC_TRANSFER_PARAMKEY);
if (descriptor != null) {
Bundle transferBundle = new Bundle();
transferBundle.putString(VENDOR_DOLBY_CODEC_TRANSFER_PARAMKEY, "transfer.sdr.normal");
decoder.setParameters(transferBundle);
} else {
mediaFormat.setInteger(MediaFormat.KEY_COLOR_TRANSFER_REQUEST, MediaFormat.COLOR_TRANSFER_SDR_VIDEO);
}
final boolean isHdr = MediaCodecCompat.isHdrVideo(mediaFormat);
if (Build.VERSION.SDK_INT >= 31 && isHdr) {
mediaFormat.setInteger(MediaFormat.KEY_COLOR_TRANSFER_REQUEST, MediaFormat.COLOR_TRANSFER_SDR_VIDEO);
}
decoder.configure(mediaFormat, outputSurface.getSurface(), null, 0);
decoder.start();
if (Build.VERSION.SDK_INT >= 31 && isHdr) {
try {
final String VENDOR_DOLBY_CODEC_TRANSFER_PARAMKEY = "vendor.dolby.codec.transfer.value";
MediaCodec.ParameterDescriptor descriptor = decoder.getParameterDescriptor(VENDOR_DOLBY_CODEC_TRANSFER_PARAMKEY);
if (descriptor != null) {
Bundle transferBundle = new Bundle();
transferBundle.putString(VENDOR_DOLBY_CODEC_TRANSFER_PARAMKEY, "transfer.sdr.normal");
decoder.setParameters(transferBundle);
}
} catch (IllegalStateException e) {
Log.w(TAG, "Failed to set Dolby Vision transfer parameter", e);
}
}
long duration = 0;
@@ -217,4 +224,5 @@ final class VideoThumbnailsExtractor {
}
Log.i(TAG, "doExtract finished");
}
}

View File

@@ -481,14 +481,16 @@ final class VideoTrackConverter {
final Pair<MediaCodec, MediaFormat> decoderPair = MediaCodecCompat.findDecoder(inputFormat);
final MediaCodec decoder = decoderPair.getFirst();
// Try to use the Dolby Vision decoder, but if it doesn't support the transfer parameter, the decoded video buffer
// is HLG and in-app tone mapping has to be used instead
if (Build.VERSION.SDK_INT >= 31) {
// For HDR video, request SDR tone-mapping from the decoder. Only do this for HDR content
// (PQ or HLG transfer), as some hardware decoders (e.g. Qualcomm HEVC) crash when this is
// set on non-HDR video.
final boolean isHdr = MediaCodecCompat.isHdrVideo(decoderPair.getSecond());
if (Build.VERSION.SDK_INT >= 31 && isHdr) {
decoderPair.getSecond().setInteger(MediaFormat.KEY_COLOR_TRANSFER_REQUEST, MediaFormat.COLOR_TRANSFER_SDR_VIDEO);
}
decoder.configure(decoderPair.getSecond(), surface, null, 0);
decoder.start();
if (Build.VERSION.SDK_INT >= 31) {
if (Build.VERSION.SDK_INT >= 31 && isHdr) {
try {
MediaCodec.ParameterDescriptor descriptor = decoder.getParameterDescriptor(VENDOR_DOLBY_CODEC_TRANSFER_PARAMKEY);
if (descriptor != null) {

View File

@@ -149,4 +149,20 @@ object MediaCodecCompat {
} else {
null
}
/**
* Returns true if the given [MediaFormat] describes an HDR video (PQ or HLG color transfer).
* Some hardware decoders crash when tone-mapping parameters are set on non-HDR video.
*/
@JvmStatic
fun isHdrVideo(format: MediaFormat): Boolean {
return try {
val colorTransfer = format.getInteger(MediaFormat.KEY_COLOR_TRANSFER)
colorTransfer == MediaFormat.COLOR_TRANSFER_ST2084 || colorTransfer == MediaFormat.COLOR_TRANSFER_HLG
} catch (e: NullPointerException) {
false
} catch (e: ClassCastException) {
false
}
}
}