Enable per-mediaItem effect in CompositionPlayer

Currently the effects are applied one frame too early. This will be fixed in
a later CL.

PiperOrigin-RevId: 573773074
This commit is contained in:
claincly 2023-10-16 04:38:22 -07:00 committed by Copybara-Service
parent 35121a2d3d
commit 37c86f3c15
3 changed files with 61 additions and 16 deletions

View File

@ -139,6 +139,14 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
} }
} }
@Override
public void setPendingVideoEffects(List<Effect> videoEffects) {
this.videoEffects = videoEffects;
if (isInitialized()) {
checkStateNotNull(videoSinkImpl).setPendingVideoEffects(videoEffects);
}
}
@Override @Override
public void setStreamOffsetUs(long streamOffsetUs) { public void setStreamOffsetUs(long streamOffsetUs) {
checkStateNotNull(videoSinkImpl).setStreamOffsetUs(streamOffsetUs); checkStateNotNull(videoSinkImpl).setStreamOffsetUs(streamOffsetUs);
@ -477,11 +485,19 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
renderedFirstFrame = false; renderedFirstFrame = false;
} }
/** Sets the {@linkplain Effect video effects}. */ /** Sets the {@linkplain Effect video effects} to apply immediately. */
public void setVideoEffects(List<Effect> videoEffects) { public void setVideoEffects(List<Effect> videoEffects) {
setPendingVideoEffects(videoEffects);
maybeRegisterInputStream();
}
/**
* Sets the {@linkplain Effect video effects} to apply when the next stream is {@linkplain
* #registerInputStream(int, Format) registered}.
*/
public void setPendingVideoEffects(List<Effect> videoEffects) {
this.videoEffects.clear(); this.videoEffects.clear();
this.videoEffects.addAll(videoEffects); this.videoEffects.addAll(videoEffects);
maybeRegisterInputStream();
} }
public void setStreamOffsetUs(long streamOffsetUs) { public void setStreamOffsetUs(long streamOffsetUs) {

View File

@ -801,8 +801,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer implements Video
case MSG_SET_VIDEO_EFFECTS: case MSG_SET_VIDEO_EFFECTS:
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
List<Effect> videoEffects = (List<Effect>) checkNotNull(message); List<Effect> videoEffects = (List<Effect>) checkNotNull(message);
videoSinkProvider.setVideoEffects(videoEffects); setVideoEffects(videoEffects);
hasEffects = true;
break; break;
case MSG_SET_VIDEO_OUTPUT_RESOLUTION: case MSG_SET_VIDEO_OUTPUT_RESOLUTION:
Size outputResolution = (Size) checkNotNull(message); Size outputResolution = (Size) checkNotNull(message);
@ -1130,6 +1129,16 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer implements Video
hasInitializedPlayback = true; hasInitializedPlayback = true;
} }
/** Sets the {@linkplain Effect video effects} to apply. */
public void setVideoEffects(List<Effect> effects) {
videoSinkProvider.setVideoEffects(effects);
hasEffects = true;
}
protected final VideoSinkProvider getVideoSinkProvider() {
return videoSinkProvider;
}
@Override @Override
protected void onCodecInitialized( protected void onCodecInitialized(
String name, String name,
@ -1238,19 +1247,31 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer implements Video
new VideoSize(width, height, unappliedRotationDegrees, pixelWidthHeightRatio); new VideoSize(width, height, unappliedRotationDegrees, pixelWidthHeightRatio);
frameReleaseHelper.onFormatChanged(format.frameRate); frameReleaseHelper.onFormatChanged(format.frameRate);
if (videoSink != null) { if (videoSink != null && mediaFormat != null) {
videoSink.registerInputStream( onReadyToRegisterVideoSinkInputStream();
/* inputType= */ VideoSink.INPUT_TYPE_SURFACE, checkNotNull(videoSink)
format .registerInputStream(
.buildUpon() /* inputType= */ VideoSink.INPUT_TYPE_SURFACE,
.setWidth(width) format
.setHeight(height) .buildUpon()
.setRotationDegrees(unappliedRotationDegrees) .setWidth(width)
.setPixelWidthHeightRatio(pixelWidthHeightRatio) .setHeight(height)
.build()); .setRotationDegrees(unappliedRotationDegrees)
.setPixelWidthHeightRatio(pixelWidthHeightRatio)
.build());
} }
} }
/**
* Called when ready to {@linkplain VideoSink#registerInputStream(int, Format) register} an input
* stream when {@linkplain #setVideoEffects video effects} are enabled.
*
* <p>The default implementation is a no-op.
*/
protected void onReadyToRegisterVideoSinkInputStream() {
// do nothing.
}
@Override @Override
@TargetApi(29) // codecHandlesHdr10PlusOutOfBandMetadata is false if Util.SDK_INT < 29 @TargetApi(29) // codecHandlesHdr10PlusOutOfBandMetadata is false if Util.SDK_INT < 29
protected void handleInputBufferSupplementalData(DecoderInputBuffer buffer) protected void handleInputBufferSupplementalData(DecoderInputBuffer buffer)

View File

@ -20,10 +20,12 @@ import android.view.Surface;
import androidx.media3.common.Effect; import androidx.media3.common.Effect;
import androidx.media3.common.Format; import androidx.media3.common.Format;
import androidx.media3.common.util.Size; import androidx.media3.common.util.Size;
import androidx.media3.common.util.UnstableApi;
import java.util.List; import java.util.List;
/** A provider of {@link VideoSink VideoSinks}. */ /** A provider of {@link VideoSink VideoSinks}. */
/* package */ interface VideoSinkProvider { @UnstableApi
public interface VideoSinkProvider {
/** /**
* Initializes the provider for video frame processing. Can be called up to one time and only * Initializes the provider for video frame processing. Can be called up to one time and only
@ -43,9 +45,15 @@ import java.util.List;
/** Returns a {@link VideoSink} to forward video frames for processing. */ /** Returns a {@link VideoSink} to forward video frames for processing. */
VideoSink getSink(); VideoSink getSink();
/** Sets video effects on this provider. */ /** Sets video effects on this provider to apply immediately. */
void setVideoEffects(List<Effect> videoEffects); void setVideoEffects(List<Effect> videoEffects);
/**
* Sets video effects on this provider to apply when the next stream is {@linkplain
* VideoSink#registerInputStream(int, Format) registered} on the {@link #getSink() VideoSink}.
*/
void setPendingVideoEffects(List<Effect> videoEffects);
/** /**
* Sets the offset, in microseconds, that is added to the video frames presentation timestamps * Sets the offset, in microseconds, that is added to the video frames presentation timestamps
* from the player. * from the player.