Skip to content

Commit

Permalink
HDR: Implement ForceInterpretHdrVideoAsSdr
Browse files Browse the repository at this point in the history
Also, document that we tone map when no HDR features are explicitly set

PiperOrigin-RevId: 487310971
  • Loading branch information
dway123 authored and microkatz committed Nov 10, 2022
1 parent d6c8e3a commit 8bdd278
Show file tree
Hide file tree
Showing 12 changed files with 226 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ public final class ConfigurationActivity extends AppCompatActivity {
public static final String ENABLE_FALLBACK = "enable_fallback";
public static final String ENABLE_DEBUG_PREVIEW = "enable_debug_preview";
public static final String ENABLE_REQUEST_SDR_TONE_MAPPING = "enable_request_sdr_tone_mapping";
public static final String FORCE_INTERPRET_HDR_VIDEO_AS_SDR = "force_interpret_hdr_video_as_sdr";
public static final String ENABLE_HDR_EDITING = "enable_hdr_editing";
public static final String DEMO_EFFECTS_SELECTIONS = "demo_effects_selections";
public static final String PERIODIC_VIGNETTE_CENTER_X = "periodic_vignette_center_x";
Expand Down Expand Up @@ -153,6 +154,7 @@ public final class ConfigurationActivity extends AppCompatActivity {
private @MonotonicNonNull CheckBox enableFallbackCheckBox;
private @MonotonicNonNull CheckBox enableDebugPreviewCheckBox;
private @MonotonicNonNull CheckBox enableRequestSdrToneMappingCheckBox;
private @MonotonicNonNull CheckBox forceInterpretHdrVideoAsSdrCheckBox;
private @MonotonicNonNull CheckBox enableHdrEditingCheckBox;
private @MonotonicNonNull Button selectDemoEffectsButton;
private boolean @MonotonicNonNull [] demoEffectsSelections;
Expand Down Expand Up @@ -248,6 +250,8 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
enableRequestSdrToneMappingCheckBox = findViewById(R.id.request_sdr_tone_mapping_checkbox);
enableRequestSdrToneMappingCheckBox.setEnabled(isRequestSdrToneMappingSupported());
findViewById(R.id.request_sdr_tone_mapping).setEnabled(isRequestSdrToneMappingSupported());
forceInterpretHdrVideoAsSdrCheckBox =
findViewById(R.id.force_interpret_hdr_video_as_sdr_checkbox);
enableHdrEditingCheckBox = findViewById(R.id.hdr_editing_checkbox);

demoEffectsSelections = new boolean[DEMO_EFFECTS.length];
Expand Down Expand Up @@ -306,6 +310,7 @@ protected void onNewIntent(Intent intent) {
"enableFallbackCheckBox",
"enableDebugPreviewCheckBox",
"enableRequestSdrToneMappingCheckBox",
"forceInterpretHdrVideoAsSdrCheckBox",
"enableHdrEditingCheckBox",
"demoEffectsSelections"
})
Expand Down Expand Up @@ -346,6 +351,8 @@ private void startTransformation(View view) {
bundle.putBoolean(ENABLE_DEBUG_PREVIEW, enableDebugPreviewCheckBox.isChecked());
bundle.putBoolean(
ENABLE_REQUEST_SDR_TONE_MAPPING, enableRequestSdrToneMappingCheckBox.isChecked());
bundle.putBoolean(
FORCE_INTERPRET_HDR_VIDEO_AS_SDR, forceInterpretHdrVideoAsSdrCheckBox.isChecked());
bundle.putBoolean(ENABLE_HDR_EDITING, enableHdrEditingCheckBox.isChecked());
bundle.putBooleanArray(DEMO_EFFECTS_SELECTIONS, demoEffectsSelections);
bundle.putInt(COLOR_FILTER_SELECTION, colorFilterSelection);
Expand Down Expand Up @@ -585,6 +592,7 @@ private void controlPeriodicVignetteSettings() {
"rotateSpinner",
"enableDebugPreviewCheckBox",
"enableRequestSdrToneMappingCheckBox",
"forceInterpretHdrVideoAsSdrCheckBox",
"enableHdrEditingCheckBox",
"selectDemoEffectsButton"
})
Expand All @@ -606,6 +614,7 @@ private void onRemoveAudio(View view) {
"rotateSpinner",
"enableDebugPreviewCheckBox",
"enableRequestSdrToneMappingCheckBox",
"forceInterpretHdrVideoAsSdrCheckBox",
"enableHdrEditingCheckBox",
"selectDemoEffectsButton"
})
Expand All @@ -626,6 +635,7 @@ private void onRemoveVideo(View view) {
"rotateSpinner",
"enableDebugPreviewCheckBox",
"enableRequestSdrToneMappingCheckBox",
"forceInterpretHdrVideoAsSdrCheckBox",
"enableHdrEditingCheckBox",
"selectDemoEffectsButton"
})
Expand All @@ -638,6 +648,7 @@ private void enableTrackSpecificOptions(boolean isAudioEnabled, boolean isVideoE
enableDebugPreviewCheckBox.setEnabled(isVideoEnabled);
enableRequestSdrToneMappingCheckBox.setEnabled(
isRequestSdrToneMappingSupported() && isVideoEnabled);
forceInterpretHdrVideoAsSdrCheckBox.setEnabled(isVideoEnabled);
enableHdrEditingCheckBox.setEnabled(isVideoEnabled);
selectDemoEffectsButton.setEnabled(isVideoEnabled);

Expand All @@ -648,6 +659,7 @@ private void enableTrackSpecificOptions(boolean isAudioEnabled, boolean isVideoE
findViewById(R.id.rotate).setEnabled(isVideoEnabled);
findViewById(R.id.request_sdr_tone_mapping)
.setEnabled(isRequestSdrToneMappingSupported() && isVideoEnabled);
findViewById(R.id.force_interpret_hdr_video_as_sdr).setEnabled(isVideoEnabled);
findViewById(R.id.hdr_editing).setEnabled(isVideoEnabled);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,8 @@ private Transformer createTransformer(@Nullable Bundle bundle, String filePath)

requestBuilder.setEnableRequestSdrToneMapping(
bundle.getBoolean(ConfigurationActivity.ENABLE_REQUEST_SDR_TONE_MAPPING));
requestBuilder.experimental_setForceInterpretHdrVideoAsSdr(
bundle.getBoolean(ConfigurationActivity.FORCE_INTERPRET_HDR_VIDEO_AS_SDR));
requestBuilder.experimental_setEnableHdrEditing(
bundle.getBoolean(ConfigurationActivity.ENABLE_HDR_EDITING));
transformerBuilder
Expand Down
10 changes: 10 additions & 0 deletions demos/transformer/src/main/res/layout/configuration_activity.xml
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,16 @@
android:id="@+id/hdr_editing_checkbox"
android:layout_gravity="end" />
</TableRow>
<TableRow
android:layout_weight="1">
<TextView
android:layout_gravity="center_vertical"
android:id="@+id/force_interpret_hdr_video_as_sdr"
android:text="@string/force_interpret_hdr_video_as_sdr" />
<CheckBox
android:id="@+id/force_interpret_hdr_video_as_sdr_checkbox"
android:layout_gravity="end" />
</TableRow>
</TableLayout>
</androidx.core.widget.NestedScrollView>
<Button
Expand Down
3 changes: 2 additions & 1 deletion demos/transformer/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
<string name="enable_debug_preview" translatable="false">Enable debug preview</string>
<string name="trim" translatable="false">Trim</string>
<string name="request_sdr_tone_mapping" translatable="false">Request SDR tone-mapping (API 31+)</string>
<string name="hdr_editing" translatable="false">[Experimental] HDR editing</string>
<string name="force_interpret_hdr_video_as_sdr" translatable="false">[Experimental] Force interpret HDR video as SDR (API 29+)</string>
<string name="hdr_editing" translatable="false">[Experimental] HDR editing (API 31+)</string>
<string name="select_demo_effects" translatable="false">Add demo effects</string>
<string name="periodic_vignette_options" translatable="false">Periodic vignette options</string>
<string name="no_media_pipe_error" translatable="false">Failed to load MediaPipe processor. Check the README for instructions.</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,14 @@
import android.content.Context;
import android.os.Build;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.mediacodec.MediaCodecInfo;
import com.google.android.exoplayer2.mediacodec.MediaCodecUtil;
import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.video.ColorInfo;
import com.google.common.collect.ImmutableList;
import java.io.File;
import java.io.FileWriter;
Expand Down Expand Up @@ -86,6 +88,19 @@ public final class AndroidTestUtil {

public static final String MP4_ASSET_1080P_4_SECOND_HDR10 =
"https://storage.googleapis.com/exoplayer-test-media-1/mp4/samsung-s21-hdr-hdr10.mp4";
public static final Format MP4_ASSET_1080P_4_SECOND_HDR10_FORMAT =
new Format.Builder()
.setSampleMimeType(VIDEO_H265)
.setWidth(1920)
.setHeight(1080)
.setFrameRate(23.517f)
.setColorInfo(
new ColorInfo(
C.COLOR_SPACE_BT2020,
C.COLOR_RANGE_LIMITED,
C.COLOR_TRANSFER_ST2084,
/* hdrStaticInfo= */ null))
.build();
public static final String MP4_ASSET_1080P_1_SECOND_HDR10_VIDEO_SDR_CONTAINER =
"asset:///media/mp4/hdr10-video-with-sdr-container.mp4";

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2.transformer.mh;

import static com.google.android.exoplayer2.transformer.AndroidTestUtil.MP4_ASSET_1080P_4_SECOND_HDR10;
import static com.google.android.exoplayer2.transformer.AndroidTestUtil.MP4_ASSET_1080P_4_SECOND_HDR10_FORMAT;
import static com.google.android.exoplayer2.transformer.mh.analysis.FileUtil.assertFileHasColorTransfer;

import android.content.Context;
import android.net.Uri;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.transformer.AndroidTestUtil;
import com.google.android.exoplayer2.transformer.TransformationException;
import com.google.android.exoplayer2.transformer.TransformationRequest;
import com.google.android.exoplayer2.transformer.TransformationTestResult;
import com.google.android.exoplayer2.transformer.Transformer;
import com.google.android.exoplayer2.transformer.TransformerAndroidTestRunner;
import com.google.android.exoplayer2.util.Log;
import org.junit.Test;
import org.junit.runner.RunWith;

/**
* {@link Transformer} instrumentation test for {@linkplain
* TransformationRequest#forceInterpretHdrVideoAsSdr forcing HDR contents to be interpreted as SDR}.
*/
@RunWith(AndroidJUnit4.class)
public class SetForceInterpretHdrVideoAsSdrTest {
public static final String TAG = "SetForceInterpretHdrVideoAsSdrTest";

@Test
public void forceInterpretHdrVideoAsSdrTest_hdr10File_transformsOrThrows() throws Exception {
String testId = "forceInterpretHdrVideoAsSdrTest_hdr10File_transformsOrThrows";
Context context = ApplicationProvider.getApplicationContext();

if (AndroidTestUtil.skipAndLogIfInsufficientCodecSupport(
context,
testId,
/* decodingFormat= */ MP4_ASSET_1080P_4_SECOND_HDR10_FORMAT,
/* encodingFormat= */ null)) {
return;
}

Transformer transformer =
new Transformer.Builder(context)
.setTransformationRequest(
new TransformationRequest.Builder()
.experimental_setForceInterpretHdrVideoAsSdr(true)
.build())
.build();
try {
TransformationTestResult transformationTestResult =
new TransformerAndroidTestRunner.Builder(context, transformer)
.build()
.run(testId, MediaItem.fromUri(Uri.parse(MP4_ASSET_1080P_4_SECOND_HDR10)));
assertFileHasColorTransfer(transformationTestResult.filePath, C.COLOR_TRANSFER_SDR);
Log.i(TAG, "Transformed.");
} catch (TransformationException exception) {
if (exception.errorCode != TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED
&& exception.errorCode != TransformationException.ERROR_CODE_HDR_DECODING_UNSUPPORTED) {
throw exception;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public void transform_noRequestedTranscode_hdr10File_transformsOrThrows() throws
Log.i(TAG, checkNotNull(exception.getCause()).toString());
assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
assertThat(exception.errorCode)
.isEqualTo(TransformationException.ERROR_CODE_HDR_EDITING_UNSUPPORTED);
.isEqualTo(TransformationException.ERROR_CODE_HDR_ENCODING_UNSUPPORTED);
}
}

Expand Down Expand Up @@ -156,7 +156,7 @@ public void onFallbackApplied(
assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
assertThat(exception.errorCode)
.isAnyOf(
TransformationException.ERROR_CODE_HDR_EDITING_UNSUPPORTED,
TransformationException.ERROR_CODE_HDR_ENCODING_UNSUPPORTED,
TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
assertThat(isFallbackListenerInvoked.get()).isFalse();
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public void onFallbackApplied(
assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
assertThat(exception.errorCode)
.isAnyOf(
TransformationException.ERROR_CODE_HDR_EDITING_UNSUPPORTED,
TransformationException.ERROR_CODE_HDR_ENCODING_UNSUPPORTED,
TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
return;
}
Expand Down Expand Up @@ -126,7 +126,7 @@ public void onFallbackApplied(
assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
assertThat(exception.errorCode)
.isAnyOf(
TransformationException.ERROR_CODE_HDR_EDITING_UNSUPPORTED,
TransformationException.ERROR_CODE_HDR_ENCODING_UNSUPPORTED,
TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public final class TransformationException extends Exception {
ERROR_CODE_ENCODER_INIT_FAILED,
ERROR_CODE_ENCODING_FAILED,
ERROR_CODE_OUTPUT_FORMAT_UNSUPPORTED,
ERROR_CODE_HDR_EDITING_UNSUPPORTED,
ERROR_CODE_HDR_ENCODING_UNSUPPORTED,
ERROR_CODE_FRAME_PROCESSING_FAILED,
ERROR_CODE_MUXING_FAILED,
})
Expand Down Expand Up @@ -137,6 +137,8 @@ public final class TransformationException extends Exception {
public static final int ERROR_CODE_DECODING_FAILED = 3002;
/** Caused by trying to decode content whose format is not supported. */
public static final int ERROR_CODE_DECODING_FORMAT_UNSUPPORTED = 3003;
/** Caused by the decoder not supporting HDR formats. */
public static final int ERROR_CODE_HDR_DECODING_UNSUPPORTED = 3004;

// Encoding errors (4xxx).

Expand All @@ -152,7 +154,7 @@ public final class TransformationException extends Exception {
*/
public static final int ERROR_CODE_OUTPUT_FORMAT_UNSUPPORTED = 4003;
/** Caused by the encoder not supporting HDR formats. */
public static final int ERROR_CODE_HDR_EDITING_UNSUPPORTED = 4004;
public static final int ERROR_CODE_HDR_ENCODING_UNSUPPORTED = 4004;

// Video editing errors (5xxx).

Expand All @@ -178,10 +180,11 @@ public final class TransformationException extends Exception {
.put("ERROR_CODE_DECODER_INIT_FAILED", ERROR_CODE_DECODER_INIT_FAILED)
.put("ERROR_CODE_DECODING_FAILED", ERROR_CODE_DECODING_FAILED)
.put("ERROR_CODE_DECODING_FORMAT_UNSUPPORTED", ERROR_CODE_DECODING_FORMAT_UNSUPPORTED)
.put("ERROR_CODE_HDR_DECODING_UNSUPPORTED", ERROR_CODE_HDR_DECODING_UNSUPPORTED)
.put("ERROR_CODE_ENCODER_INIT_FAILED", ERROR_CODE_ENCODER_INIT_FAILED)
.put("ERROR_CODE_ENCODING_FAILED", ERROR_CODE_ENCODING_FAILED)
.put("ERROR_CODE_OUTPUT_FORMAT_UNSUPPORTED", ERROR_CODE_OUTPUT_FORMAT_UNSUPPORTED)
.put("ERROR_CODE_HDR_EDITING_UNSUPPORTED", ERROR_CODE_HDR_EDITING_UNSUPPORTED)
.put("ERROR_CODE_HDR_ENCODING_UNSUPPORTED", ERROR_CODE_HDR_ENCODING_UNSUPPORTED)
.put("ERROR_CODE_FRAME_PROCESSING_FAILED", ERROR_CODE_FRAME_PROCESSING_FAILED)
.put("ERROR_CODE_MUXING_FAILED", ERROR_CODE_MUXING_FAILED)
.buildOrThrow();
Expand Down
Loading

0 comments on commit 8bdd278

Please sign in to comment.