Skip to content

Commit

Permalink
Throw if tone-mapping is requested but not enabled
Browse files Browse the repository at this point in the history
In the case where this check fails, the downstream frame processor chain won't be able to handle the incoming (SDR) data anyway as we've already set it up for HDR.

PiperOrigin-RevId: 465584814
  • Loading branch information
andrewlewis authored and marcbaechinger committed Oct 19, 2022
1 parent d90d7d3 commit 0e99d28
Showing 1 changed file with 39 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.google.android.exoplayer2.transformer;

import static com.google.android.exoplayer2.util.Assertions.checkArgument;
import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
import static com.google.android.exoplayer2.util.Assertions.checkState;
import static com.google.android.exoplayer2.util.Assertions.checkStateNotNull;
Expand All @@ -27,14 +28,17 @@
import android.media.MediaCrypto;
import android.media.MediaFormat;
import android.view.Surface;
import androidx.annotation.DoNotInline;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.annotation.VisibleForTesting;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
import com.google.android.exoplayer2.util.MediaFormatUtil;
import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.TraceUtil;
import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.video.ColorInfo;
import com.google.common.base.Ascii;
import com.google.common.collect.ImmutableList;
Expand All @@ -54,12 +58,8 @@ public final class DefaultCodec implements Codec {
private final MediaFormat configurationMediaFormat;

private final Format configurationFormat;
/** The expected {@link ColorInfo} output from the codec. */
@Nullable private final ColorInfo configuredOutputColor;

private final MediaCodec mediaCodec;
@Nullable private final Surface inputSurface;

private final boolean decoderNeedsFrameDroppingWorkaround;

private @MonotonicNonNull Format outputFormat;
Expand Down Expand Up @@ -101,8 +101,18 @@ public DefaultCodec(
@Nullable MediaCodec mediaCodec = null;
@Nullable Surface inputSurface = null;
try {
boolean requestedHdrToneMapping =
Util.SDK_INT >= 29 && Api29.isSdrToneMappingEnabled(configurationMediaFormat);
mediaCodec = MediaCodec.createByCodecName(mediaCodecName);
configureCodec(mediaCodec, configurationMediaFormat, isDecoder, outputSurface);
if (SDK_INT >= 29 && requestedHdrToneMapping) {
// The MediaCodec input format reflects whether tone-mapping is possible after configure().
// See
// https://developer.android.com/reference/android/media/MediaFormat#KEY_COLOR_TRANSFER_REQUEST.
checkArgument(
Api29.isSdrToneMappingEnabled(mediaCodec.getInputFormat()),
"Tone-mapping requested but not supported by the decoder");
}
if (isVideo && !isDecoder) {
inputSurface = mediaCodec.createInputSurface();
}
Expand All @@ -119,12 +129,6 @@ public DefaultCodec(
e, configurationMediaFormat, isVideo, isDecoder, mediaCodecName);
}
this.mediaCodec = mediaCodec;
boolean toneMapRequested =
SDK_INT >= 31
&& isDecoder
&& (configurationMediaFormat.getInteger(MediaFormat.KEY_COLOR_TRANSFER_REQUEST, 0)
== MediaFormat.COLOR_TRANSFER_SDR_VIDEO);
configuredOutputColor = toneMapRequested ? null : configurationFormat.colorInfo;
this.inputSurface = inputSurface;
decoderNeedsFrameDroppingWorkaround = decoderNeedsFrameDroppingWorkaround(context);
}
Expand Down Expand Up @@ -281,11 +285,7 @@ public void release() {
*/
@Override
public String getName() {
if (SDK_INT >= 29) {
return mediaCodec.getCanonicalName();
}

return mediaCodec.getName();
return SDK_INT >= 29 ? Api29.getCanonicalName(mediaCodec) : mediaCodec.getName();
}

@VisibleForTesting
Expand Down Expand Up @@ -318,15 +318,19 @@ private boolean maybeDequeueOutputBuffer(boolean setOutputBuffer) throws Transfo
if (outputBufferIndex < 0) {
if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
outputFormat = convertToFormat(mediaCodec.getOutputFormat());
if (!areColorTransfersEqual(configuredOutputColor, outputFormat.colorInfo)) {
boolean isToneMappingEnabled =
SDK_INT >= 29 && Api29.isSdrToneMappingEnabled(configurationMediaFormat);
ColorInfo expectedColorInfo =
isToneMappingEnabled ? ColorInfo.SDR_BT709_LIMITED : configurationFormat.colorInfo;
if (!areColorTransfersEqual(expectedColorInfo, outputFormat.colorInfo)) {
// TODO(b/237674316): These exceptions throw when the container ColorInfo doesn't match
// the video ColorInfo. Instead of throwing when seeing unexpected ColorInfos, consider
// reconfiguring downstream components (ex. FrameProcessor and encoder) when different
// ColorInfo values are output.
throw createTransformationException(
new IllegalStateException(
"Codec output color format does not match configured color format. Configured: "
+ configuredOutputColor
"Codec output color format does not match configured color format. Expected: "
+ expectedColorInfo
+ ". Actual: "
+ outputFormat.colorInfo));
}
Expand Down Expand Up @@ -478,4 +482,21 @@ private static boolean decoderNeedsFrameDroppingWorkaround(Context context) {
return SDK_INT < 29
|| context.getApplicationContext().getApplicationInfo().targetSdkVersion < 29;
}

@RequiresApi(29)
private static final class Api29 {
@DoNotInline
public static String getCanonicalName(MediaCodec mediaCodec) {
return mediaCodec.getCanonicalName();
}

@DoNotInline
public static boolean isSdrToneMappingEnabled(MediaFormat mediaFormat) {
// MediaFormat.getInteger(String, int) was added in API 29 but applying a color transfer
// request is only possible from API 31.
return SDK_INT >= 31
&& mediaFormat.getInteger(MediaFormat.KEY_COLOR_TRANSFER_REQUEST, /* defaultValue= */ 0)
== MediaFormat.COLOR_TRANSFER_SDR_VIDEO;
}
}
}

0 comments on commit 0e99d28

Please sign in to comment.