mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Support MediaCodec tonemapping in CompositionPlayer
PiperOrigin-RevId: 708995517
This commit is contained in:
parent
f22d91d9e5
commit
515de89973
@ -691,7 +691,9 @@ public final class CompositionPlayer extends SimpleBasePlayer
|
|||||||
playbackAudioGraphWrapper,
|
playbackAudioGraphWrapper,
|
||||||
playbackVideoGraphWrapper.getSink(),
|
playbackVideoGraphWrapper.getSink(),
|
||||||
imageDecoderFactory,
|
imageDecoderFactory,
|
||||||
/* inputIndex= */ i)
|
/* inputIndex= */ i,
|
||||||
|
/* requestToneMapping= */ composition.hdrMode
|
||||||
|
== Composition.HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_MEDIACODEC)
|
||||||
: SequenceRenderersFactory.createForAudio(
|
: SequenceRenderersFactory.createForAudio(
|
||||||
context, editedMediaItemSequence, playbackAudioGraphWrapper, /* inputIndex= */ i);
|
context, editedMediaItemSequence, playbackAudioGraphWrapper, /* inputIndex= */ i);
|
||||||
ExoPlayer.Builder playerBuilder =
|
ExoPlayer.Builder playerBuilder =
|
||||||
|
@ -23,6 +23,7 @@ import static androidx.media3.exoplayer.DefaultRenderersFactory.MAX_DROPPED_VIDE
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
|
import android.media.MediaFormat;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
@ -33,6 +34,7 @@ import androidx.media3.common.MimeTypes;
|
|||||||
import androidx.media3.common.PlaybackException;
|
import androidx.media3.common.PlaybackException;
|
||||||
import androidx.media3.common.Timeline;
|
import androidx.media3.common.Timeline;
|
||||||
import androidx.media3.common.util.ConstantRateTimestampIterator;
|
import androidx.media3.common.util.ConstantRateTimestampIterator;
|
||||||
|
import androidx.media3.common.util.Util;
|
||||||
import androidx.media3.exoplayer.ExoPlaybackException;
|
import androidx.media3.exoplayer.ExoPlaybackException;
|
||||||
import androidx.media3.exoplayer.Renderer;
|
import androidx.media3.exoplayer.Renderer;
|
||||||
import androidx.media3.exoplayer.RenderersFactory;
|
import androidx.media3.exoplayer.RenderersFactory;
|
||||||
@ -66,6 +68,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
@Nullable private final VideoSink videoSink;
|
@Nullable private final VideoSink videoSink;
|
||||||
@Nullable private final ImageDecoder.Factory imageDecoderFactory;
|
@Nullable private final ImageDecoder.Factory imageDecoderFactory;
|
||||||
private final int inputIndex;
|
private final int inputIndex;
|
||||||
|
private final boolean requestToneMapping;
|
||||||
|
|
||||||
/** Creates a renderers factory for a player that will play video, image and audio. */
|
/** Creates a renderers factory for a player that will play video, image and audio. */
|
||||||
public static SequenceRenderersFactory create(
|
public static SequenceRenderersFactory create(
|
||||||
@ -74,9 +77,16 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
PlaybackAudioGraphWrapper playbackAudioGraphWrapper,
|
PlaybackAudioGraphWrapper playbackAudioGraphWrapper,
|
||||||
VideoSink videoSink,
|
VideoSink videoSink,
|
||||||
ImageDecoder.Factory imageDecoderFactory,
|
ImageDecoder.Factory imageDecoderFactory,
|
||||||
int inputIndex) {
|
int inputIndex,
|
||||||
|
boolean requestToneMapping) {
|
||||||
return new SequenceRenderersFactory(
|
return new SequenceRenderersFactory(
|
||||||
context, sequence, playbackAudioGraphWrapper, videoSink, imageDecoderFactory, inputIndex);
|
context,
|
||||||
|
sequence,
|
||||||
|
playbackAudioGraphWrapper,
|
||||||
|
videoSink,
|
||||||
|
imageDecoderFactory,
|
||||||
|
inputIndex,
|
||||||
|
requestToneMapping);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Creates a renderers factory that for a player that will only play audio. */
|
/** Creates a renderers factory that for a player that will only play audio. */
|
||||||
@ -91,7 +101,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
playbackAudioGraphWrapper,
|
playbackAudioGraphWrapper,
|
||||||
/* videoSink= */ null,
|
/* videoSink= */ null,
|
||||||
/* imageDecoderFactory= */ null,
|
/* imageDecoderFactory= */ null,
|
||||||
inputIndex);
|
inputIndex,
|
||||||
|
/* requestToneMapping= */ false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SequenceRenderersFactory(
|
private SequenceRenderersFactory(
|
||||||
@ -100,13 +111,15 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
PlaybackAudioGraphWrapper playbackAudioGraphWrapper,
|
PlaybackAudioGraphWrapper playbackAudioGraphWrapper,
|
||||||
@Nullable VideoSink videoSink,
|
@Nullable VideoSink videoSink,
|
||||||
@Nullable ImageDecoder.Factory imageDecoderFactory,
|
@Nullable ImageDecoder.Factory imageDecoderFactory,
|
||||||
int inputIndex) {
|
int inputIndex,
|
||||||
|
boolean requestToneMapping) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.sequence = sequence;
|
this.sequence = sequence;
|
||||||
this.playbackAudioGraphWrapper = playbackAudioGraphWrapper;
|
this.playbackAudioGraphWrapper = playbackAudioGraphWrapper;
|
||||||
this.videoSink = videoSink;
|
this.videoSink = videoSink;
|
||||||
this.imageDecoderFactory = imageDecoderFactory;
|
this.imageDecoderFactory = imageDecoderFactory;
|
||||||
this.inputIndex = inputIndex;
|
this.inputIndex = inputIndex;
|
||||||
|
this.requestToneMapping = requestToneMapping;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -133,7 +146,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
eventHandler,
|
eventHandler,
|
||||||
videoRendererEventListener,
|
videoRendererEventListener,
|
||||||
sequence,
|
sequence,
|
||||||
videoSink));
|
videoSink,
|
||||||
|
requestToneMapping));
|
||||||
renderers.add(
|
renderers.add(
|
||||||
new SequenceImageRenderer(sequence, checkStateNotNull(imageDecoderFactory), videoSink));
|
new SequenceImageRenderer(sequence, checkStateNotNull(imageDecoderFactory), videoSink));
|
||||||
}
|
}
|
||||||
@ -266,8 +280,12 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static final class SequenceVideoRenderer extends MediaCodecVideoRenderer {
|
private static final class SequenceVideoRenderer extends MediaCodecVideoRenderer {
|
||||||
|
|
||||||
|
private static final String TAG = "SequenceVideoRenderer";
|
||||||
|
|
||||||
private final EditedMediaItemSequence sequence;
|
private final EditedMediaItemSequence sequence;
|
||||||
private final VideoSink videoSink;
|
private final VideoSink videoSink;
|
||||||
|
private final boolean requestToneMapping;
|
||||||
|
|
||||||
@Nullable private ImmutableList<Effect> pendingEffect;
|
@Nullable private ImmutableList<Effect> pendingEffect;
|
||||||
@Nullable private EditedMediaItem currentEditedMediaItem;
|
@Nullable private EditedMediaItem currentEditedMediaItem;
|
||||||
@ -278,7 +296,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
Handler eventHandler,
|
Handler eventHandler,
|
||||||
VideoRendererEventListener videoRendererEventListener,
|
VideoRendererEventListener videoRendererEventListener,
|
||||||
EditedMediaItemSequence sequence,
|
EditedMediaItemSequence sequence,
|
||||||
VideoSink videoSink) {
|
VideoSink videoSink,
|
||||||
|
boolean requestToneMapping) {
|
||||||
super(
|
super(
|
||||||
context,
|
context,
|
||||||
MediaCodecAdapter.Factory.getDefault(context),
|
MediaCodecAdapter.Factory.getDefault(context),
|
||||||
@ -292,6 +311,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
videoSink);
|
videoSink);
|
||||||
this.sequence = sequence;
|
this.sequence = sequence;
|
||||||
this.videoSink = videoSink;
|
this.videoSink = videoSink;
|
||||||
|
this.requestToneMapping = requestToneMapping;
|
||||||
experimentalEnableProcessedStreamChangedAtStart();
|
experimentalEnableProcessedStreamChangedAtStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -313,6 +333,29 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
super.onStreamChanged(formats, startPositionUs, offsetUs, mediaPeriodId);
|
super.onStreamChanged(formats, startPositionUs, offsetUs, mediaPeriodId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected MediaFormat getMediaFormat(
|
||||||
|
Format format,
|
||||||
|
String codecMimeType,
|
||||||
|
CodecMaxValues codecMaxValues,
|
||||||
|
float codecOperatingRate,
|
||||||
|
boolean deviceNeedsNoPostProcessWorkaround,
|
||||||
|
int tunnelingAudioSessionId) {
|
||||||
|
MediaFormat mediaFormat =
|
||||||
|
super.getMediaFormat(
|
||||||
|
format,
|
||||||
|
codecMimeType,
|
||||||
|
codecMaxValues,
|
||||||
|
codecOperatingRate,
|
||||||
|
deviceNeedsNoPostProcessWorkaround,
|
||||||
|
tunnelingAudioSessionId);
|
||||||
|
if (requestToneMapping && Util.SDK_INT >= 31) {
|
||||||
|
mediaFormat.setInteger(
|
||||||
|
MediaFormat.KEY_COLOR_TRANSFER_REQUEST, MediaFormat.COLOR_TRANSFER_SDR_VIDEO);
|
||||||
|
}
|
||||||
|
return mediaFormat;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected long getBufferTimestampAdjustmentUs() {
|
protected long getBufferTimestampAdjustmentUs() {
|
||||||
return offsetToCompositionTimeUs;
|
return offsetToCompositionTimeUs;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user