mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Remove setPendingVideoEffects from VideoSink.
VideoSink#onInputStreamChanged(int, Format, List<Effect>) should now be used to set video effects on a new input stream. PiperOrigin-RevId: 713627389
This commit is contained in:
parent
e1b57c130d
commit
8a709a7d76
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package androidx.media3.exoplayer.video;
|
package androidx.media3.exoplayer.video;
|
||||||
|
|
||||||
|
import static androidx.media3.common.util.Assertions.checkState;
|
||||||
import static androidx.media3.common.util.Assertions.checkStateNotNull;
|
import static androidx.media3.common.util.Assertions.checkStateNotNull;
|
||||||
|
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
@ -170,16 +171,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*
|
|
||||||
* <p>This method will always throw an {@link UnsupportedOperationException}.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void setPendingVideoEffects(List<Effect> videoEffects) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setStreamTimestampInfo(
|
public void setStreamTimestampInfo(
|
||||||
long streamStartPositionUs, long bufferTimestampAdjustmentUs, long lastResetPositionUs) {
|
long streamStartPositionUs, long bufferTimestampAdjustmentUs, long lastResetPositionUs) {
|
||||||
@ -212,8 +203,15 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
videoFrameReleaseControl.allowReleaseFirstFrameBeforeStarted();
|
videoFrameReleaseControl.allowReleaseFirstFrameBeforeStarted();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
|
* <p>{@code videoEffects} is required to be empty
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onInputStreamChanged(@InputType int inputType, Format format) {
|
public void onInputStreamChanged(
|
||||||
|
@InputType int inputType, Format format, List<Effect> videoEffects) {
|
||||||
|
checkState(videoEffects.isEmpty());
|
||||||
if (format.width != inputFormat.width || format.height != inputFormat.height) {
|
if (format.width != inputFormat.width || format.height != inputFormat.height) {
|
||||||
videoFrameRenderControl.onVideoSizeChanged(format.width, format.height);
|
videoFrameRenderControl.onVideoSizeChanged(format.width, format.height);
|
||||||
}
|
}
|
||||||
|
@ -1397,8 +1397,8 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer
|
|||||||
decodedVideoSize = new VideoSize(width, height, pixelWidthHeightRatio);
|
decodedVideoSize = new VideoSize(width, height, pixelWidthHeightRatio);
|
||||||
|
|
||||||
if (videoSink != null && pendingVideoSinkInputStreamChange) {
|
if (videoSink != null && pendingVideoSinkInputStreamChange) {
|
||||||
onReadyToChangeVideoSinkInputStream();
|
changeVideoSinkInputStream(
|
||||||
videoSink.onInputStreamChanged(
|
videoSink,
|
||||||
/* inputType= */ VideoSink.INPUT_TYPE_SURFACE,
|
/* inputType= */ VideoSink.INPUT_TYPE_SURFACE,
|
||||||
format
|
format
|
||||||
.buildUpon()
|
.buildUpon()
|
||||||
@ -1413,13 +1413,15 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when ready to {@linkplain VideoSink#onInputStreamChanged(int, Format) change} the input
|
* Called when ready to {@linkplain VideoSink#onInputStreamChanged(int, Format, List<Effect>)
|
||||||
* stream when {@linkplain #setVideoEffects video effects} are enabled.
|
* change} the input stream.
|
||||||
*
|
*
|
||||||
* <p>The default implementation is a no-op.
|
* <p>The default implementation applies this renderer's video effects.
|
||||||
*/
|
*/
|
||||||
protected void onReadyToChangeVideoSinkInputStream() {
|
protected void changeVideoSinkInputStream(
|
||||||
// do nothing.
|
VideoSink videoSink, @VideoSink.InputType int inputType, Format format) {
|
||||||
|
List<Effect> videoEffectsToApply = videoEffects != null ? videoEffects : ImmutableList.of();
|
||||||
|
videoSink.onInputStreamChanged(inputType, format, videoEffectsToApply);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -382,13 +382,15 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
|
|||||||
// We forward output size changes to the sink even if we are still flushing.
|
// We forward output size changes to the sink even if we are still flushing.
|
||||||
videoGraphOutputFormat =
|
videoGraphOutputFormat =
|
||||||
videoGraphOutputFormat.buildUpon().setWidth(width).setHeight(height).build();
|
videoGraphOutputFormat.buildUpon().setWidth(width).setHeight(height).build();
|
||||||
defaultVideoSink.onInputStreamChanged(INPUT_TYPE_SURFACE, videoGraphOutputFormat);
|
defaultVideoSink.onInputStreamChanged(
|
||||||
|
INPUT_TYPE_SURFACE, videoGraphOutputFormat, /* videoEffects= */ ImmutableList.of());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onOutputFrameRateChanged(float frameRate) {
|
public void onOutputFrameRateChanged(float frameRate) {
|
||||||
videoGraphOutputFormat = videoGraphOutputFormat.buildUpon().setFrameRate(frameRate).build();
|
videoGraphOutputFormat = videoGraphOutputFormat.buildUpon().setFrameRate(frameRate).build();
|
||||||
defaultVideoSink.onInputStreamChanged(INPUT_TYPE_SURFACE, videoGraphOutputFormat);
|
defaultVideoSink.onInputStreamChanged(
|
||||||
|
INPUT_TYPE_SURFACE, videoGraphOutputFormat, /* videoEffects= */ ImmutableList.of());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -685,7 +687,8 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInputStreamChanged(@InputType int inputType, Format format) {
|
public void onInputStreamChanged(
|
||||||
|
@InputType int inputType, Format format, List<Effect> videoEffects) {
|
||||||
checkState(isInitialized());
|
checkState(isInitialized());
|
||||||
switch (inputType) {
|
switch (inputType) {
|
||||||
case INPUT_TYPE_SURFACE:
|
case INPUT_TYPE_SURFACE:
|
||||||
@ -694,6 +697,7 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
|
|||||||
default:
|
default:
|
||||||
throw new UnsupportedOperationException("Unsupported input type " + inputType);
|
throw new UnsupportedOperationException("Unsupported input type " + inputType);
|
||||||
}
|
}
|
||||||
|
setPendingVideoEffects(videoEffects);
|
||||||
this.inputType = inputType;
|
this.inputType = inputType;
|
||||||
this.inputFormat = format;
|
this.inputFormat = format;
|
||||||
finalBufferPresentationTimeUs = C.TIME_UNSET;
|
finalBufferPresentationTimeUs = C.TIME_UNSET;
|
||||||
@ -729,15 +733,6 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setPendingVideoEffects(List<Effect> videoEffects) {
|
|
||||||
this.videoEffects =
|
|
||||||
new ImmutableList.Builder<Effect>()
|
|
||||||
.addAll(videoEffects)
|
|
||||||
.addAll(compositionEffects)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setStreamTimestampInfo(
|
public void setStreamTimestampInfo(
|
||||||
long streamStartPositionUs, long bufferTimestampAdjustmentUs, long lastResetPositionUs) {
|
long streamStartPositionUs, long bufferTimestampAdjustmentUs, long lastResetPositionUs) {
|
||||||
@ -887,6 +882,19 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
|
|||||||
|
|
||||||
// Private methods
|
// Private methods
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the pending video effects.
|
||||||
|
*
|
||||||
|
* <p>Effects are pending until a new input stream is registered.
|
||||||
|
*/
|
||||||
|
private void setPendingVideoEffects(List<Effect> newVideoEffects) {
|
||||||
|
this.videoEffects =
|
||||||
|
new ImmutableList.Builder<Effect>()
|
||||||
|
.addAll(newVideoEffects)
|
||||||
|
.addAll(compositionEffects)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
private void registerInputStream(Format inputFormat) {
|
private void registerInputStream(Format inputFormat) {
|
||||||
Format adjustedInputFormat =
|
Format adjustedInputFormat =
|
||||||
inputFormat
|
inputFormat
|
||||||
|
@ -187,8 +187,9 @@ public interface VideoSink {
|
|||||||
*
|
*
|
||||||
* <p>This method returns {@code true} if the end of the last input stream has been {@linkplain
|
* <p>This method returns {@code true} if the end of the last input stream has been {@linkplain
|
||||||
* #signalEndOfCurrentInputStream() signaled} and all the input frames have been rendered. Note
|
* #signalEndOfCurrentInputStream() signaled} and all the input frames have been rendered. Note
|
||||||
* that a new input stream can be {@linkplain #onInputStreamChanged(int, Format) signaled} even
|
* that a new input stream can be {@linkplain #onInputStreamChanged(int, Format, List<Effect>)
|
||||||
* when this method returns true (in which case the sink will not be ended anymore).
|
* signaled} even when this method returns true (in which case the sink will not be ended
|
||||||
|
* anymore).
|
||||||
*/
|
*/
|
||||||
boolean isEnded();
|
boolean isEnded();
|
||||||
|
|
||||||
@ -208,12 +209,6 @@ public interface VideoSink {
|
|||||||
/** Sets {@linkplain Effect video effects} to apply immediately. */
|
/** Sets {@linkplain Effect video effects} to apply immediately. */
|
||||||
void setVideoEffects(List<Effect> videoEffects);
|
void setVideoEffects(List<Effect> videoEffects);
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets {@linkplain Effect video effects} to apply after the next stream {@linkplain
|
|
||||||
* VideoSink#onInputStreamChanged(int, Format) change}.
|
|
||||||
*/
|
|
||||||
void setPendingVideoEffects(List<Effect> videoEffects);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets information about the timestamps of the current input stream.
|
* Sets information about the timestamps of the current input stream.
|
||||||
*
|
*
|
||||||
@ -250,20 +245,21 @@ public interface VideoSink {
|
|||||||
void enableMayRenderStartOfStream();
|
void enableMayRenderStartOfStream();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Informs the video sink that a new input stream will be queued.
|
* Informs the video sink that a new input stream will be queued with the given effects.
|
||||||
*
|
*
|
||||||
* <p>Must be called after the sink is {@linkplain #initialize(Format) initialized}.
|
* <p>Must be called after the sink is {@linkplain #initialize(Format) initialized}.
|
||||||
*
|
*
|
||||||
* @param inputType The {@link InputType} of the stream.
|
* @param inputType The {@link InputType} of the stream.
|
||||||
* @param format The {@link Format} of the stream.
|
* @param format The {@link Format} of the stream.
|
||||||
|
* @param videoEffects The {@link List<Effect>} to apply to the new stream.
|
||||||
*/
|
*/
|
||||||
void onInputStreamChanged(@InputType int inputType, Format format);
|
void onInputStreamChanged(@InputType int inputType, Format format, List<Effect> videoEffects);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles a video input frame.
|
* Handles a video input frame.
|
||||||
*
|
*
|
||||||
* <p>Must be called after the corresponding stream is {@linkplain #onInputStreamChanged(int,
|
* <p>Must be called after the corresponding stream is {@linkplain #onInputStreamChanged(int,
|
||||||
* Format) signaled}.
|
* Format, List<Effect>) signaled}.
|
||||||
*
|
*
|
||||||
* @param framePresentationTimeUs The frame's presentation time, in microseconds.
|
* @param framePresentationTimeUs The frame's presentation time, in microseconds.
|
||||||
* @param isLastFrame Whether this is the last frame of the video stream. This flag is set on a
|
* @param isLastFrame Whether this is the last frame of the video stream. This flag is set on a
|
||||||
@ -280,7 +276,7 @@ public interface VideoSink {
|
|||||||
* Handles an input {@link Bitmap}.
|
* Handles an input {@link Bitmap}.
|
||||||
*
|
*
|
||||||
* <p>Must be called after the corresponding stream is {@linkplain #onInputStreamChanged(int,
|
* <p>Must be called after the corresponding stream is {@linkplain #onInputStreamChanged(int,
|
||||||
* Format) signaled}.
|
* Format, List<Effect>) signaled}.
|
||||||
*
|
*
|
||||||
* @param inputBitmap The {@link Bitmap} to queue to the video sink.
|
* @param inputBitmap The {@link Bitmap} to queue to the video sink.
|
||||||
* @param timestampIterator The times within the current stream that the bitmap should be shown
|
* @param timestampIterator The times within the current stream that the bitmap should be shown
|
||||||
|
@ -15,20 +15,28 @@
|
|||||||
*/
|
*/
|
||||||
package androidx.media3.exoplayer.video;
|
package androidx.media3.exoplayer.video;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static org.junit.Assert.assertThrows;
|
import static org.junit.Assert.assertThrows;
|
||||||
import static org.mockito.ArgumentMatchers.anyInt;
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.view.Surface;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.media3.common.ColorInfo;
|
import androidx.media3.common.ColorInfo;
|
||||||
import androidx.media3.common.DebugViewProvider;
|
import androidx.media3.common.DebugViewProvider;
|
||||||
import androidx.media3.common.Effect;
|
import androidx.media3.common.Effect;
|
||||||
import androidx.media3.common.Format;
|
import androidx.media3.common.Format;
|
||||||
|
import androidx.media3.common.OnInputFrameProcessedListener;
|
||||||
import androidx.media3.common.PreviewingVideoGraph;
|
import androidx.media3.common.PreviewingVideoGraph;
|
||||||
|
import androidx.media3.common.SurfaceInfo;
|
||||||
import androidx.media3.common.VideoFrameProcessor;
|
import androidx.media3.common.VideoFrameProcessor;
|
||||||
import androidx.media3.common.VideoGraph;
|
import androidx.media3.common.VideoGraph;
|
||||||
|
import androidx.media3.common.util.TimestampIterator;
|
||||||
import androidx.test.core.app.ApplicationProvider;
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@ -51,17 +59,40 @@ public final class PlaybackVideoGraphWrapperTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void initializeSink_calledTwice_throws() throws VideoSink.VideoSinkException {
|
public void initializeSink_calledTwice_throws() throws VideoSink.VideoSinkException {
|
||||||
PlaybackVideoGraphWrapper provider = createPlaybackVideoGraphWrapper();
|
PlaybackVideoGraphWrapper playbackVideoGraphWrapper =
|
||||||
VideoSink sink = provider.getSink();
|
createPlaybackVideoGraphWrapper(new FakeVideoFrameProcessor());
|
||||||
|
VideoSink sink = playbackVideoGraphWrapper.getSink();
|
||||||
sink.initialize(new Format.Builder().build());
|
sink.initialize(new Format.Builder().build());
|
||||||
|
|
||||||
assertThrows(IllegalStateException.class, () -> sink.initialize(new Format.Builder().build()));
|
assertThrows(IllegalStateException.class, () -> sink.initialize(new Format.Builder().build()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PlaybackVideoGraphWrapper createPlaybackVideoGraphWrapper() {
|
@Test
|
||||||
|
public void onInputStreamChanged_setsVideoSinkVideoEffects() throws VideoSink.VideoSinkException {
|
||||||
|
ImmutableList<Effect> firstEffects = ImmutableList.of(Mockito.mock(Effect.class));
|
||||||
|
ImmutableList<Effect> secondEffects =
|
||||||
|
ImmutableList.of(Mockito.mock(Effect.class), Mockito.mock(Effect.class));
|
||||||
|
FakeVideoFrameProcessor videoFrameProcessor = new FakeVideoFrameProcessor();
|
||||||
|
PlaybackVideoGraphWrapper playbackVideoGraphWrapper =
|
||||||
|
createPlaybackVideoGraphWrapper(videoFrameProcessor);
|
||||||
|
Format format = new Format.Builder().build();
|
||||||
|
VideoSink sink = playbackVideoGraphWrapper.getSink();
|
||||||
|
|
||||||
|
sink.initialize(format);
|
||||||
|
|
||||||
|
sink.onInputStreamChanged(VideoSink.INPUT_TYPE_SURFACE, format, firstEffects);
|
||||||
|
assertThat(videoFrameProcessor.registeredEffects).isEqualTo(firstEffects);
|
||||||
|
sink.onInputStreamChanged(VideoSink.INPUT_TYPE_SURFACE, format, secondEffects);
|
||||||
|
assertThat(videoFrameProcessor.registeredEffects).isEqualTo(secondEffects);
|
||||||
|
sink.onInputStreamChanged(VideoSink.INPUT_TYPE_SURFACE, format, ImmutableList.of());
|
||||||
|
assertThat(videoFrameProcessor.registeredEffects).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PlaybackVideoGraphWrapper createPlaybackVideoGraphWrapper(
|
||||||
|
VideoFrameProcessor videoFrameProcessor) {
|
||||||
Context context = ApplicationProvider.getApplicationContext();
|
Context context = ApplicationProvider.getApplicationContext();
|
||||||
return new PlaybackVideoGraphWrapper.Builder(context, createVideoFrameReleaseControl())
|
return new PlaybackVideoGraphWrapper.Builder(context, createVideoFrameReleaseControl())
|
||||||
.setPreviewingVideoGraphFactory(new TestPreviewingVideoGraphFactory())
|
.setPreviewingVideoGraphFactory(new TestPreviewingVideoGraphFactory(videoFrameProcessor))
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,12 +125,73 @@ public final class PlaybackVideoGraphWrapperTest {
|
|||||||
context, frameTimingEvaluator, /* allowedJoiningTimeMs= */ 0);
|
context, frameTimingEvaluator, /* allowedJoiningTimeMs= */ 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class FakeVideoFrameProcessor implements VideoFrameProcessor {
|
||||||
|
|
||||||
|
List<Effect> registeredEffects = ImmutableList.of();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean queueInputBitmap(Bitmap inputBitmap, TimestampIterator timestampIterator) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean queueInputTexture(int textureId, long presentationTimeUs) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setOnInputFrameProcessedListener(OnInputFrameProcessedListener listener) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setOnInputSurfaceReadyListener(Runnable listener) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Surface getInputSurface() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerInputStream(
|
||||||
|
@InputType int inputType, Format format, List<Effect> effects, long offsetToAddUs) {
|
||||||
|
registeredEffects = effects;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean registerInputFrame() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getPendingInputFrameCount() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setOutputSurfaceInfo(@Nullable SurfaceInfo outputSurfaceInfo) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderOutputFrame(long renderTimeNs) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void signalEndOfInput() {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void flush() {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void release() {}
|
||||||
|
}
|
||||||
|
|
||||||
private static class TestPreviewingVideoGraphFactory implements PreviewingVideoGraph.Factory {
|
private static class TestPreviewingVideoGraphFactory implements PreviewingVideoGraph.Factory {
|
||||||
// Using a mock but we don't assert mock interactions. If needed to assert interactions, we
|
// Using a mock but we don't assert mock interactions. If needed to assert interactions, we
|
||||||
// should a fake instead.
|
// should a fake instead.
|
||||||
private final PreviewingVideoGraph previewingVideoGraph =
|
private final PreviewingVideoGraph previewingVideoGraph =
|
||||||
Mockito.mock(PreviewingVideoGraph.class);
|
Mockito.mock(PreviewingVideoGraph.class);
|
||||||
private final VideoFrameProcessor videoFrameProcessor = Mockito.mock(VideoFrameProcessor.class);
|
private final VideoFrameProcessor videoFrameProcessor;
|
||||||
|
|
||||||
|
public TestPreviewingVideoGraphFactory(VideoFrameProcessor videoFrameProcessor) {
|
||||||
|
this.videoFrameProcessor = videoFrameProcessor;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PreviewingVideoGraph create(
|
public PreviewingVideoGraph create(
|
||||||
@ -111,7 +203,6 @@ public final class PlaybackVideoGraphWrapperTest {
|
|||||||
List<Effect> compositionEffects,
|
List<Effect> compositionEffects,
|
||||||
long initialTimestampOffsetUs) {
|
long initialTimestampOffsetUs) {
|
||||||
when(previewingVideoGraph.getProcessor(anyInt())).thenReturn(videoFrameProcessor);
|
when(previewingVideoGraph.getProcessor(anyInt())).thenReturn(videoFrameProcessor);
|
||||||
when(videoFrameProcessor.registerInputFrame()).thenReturn(true);
|
|
||||||
return previewingVideoGraph;
|
return previewingVideoGraph;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -176,11 +176,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
executeOrDelay(videoSink -> videoSink.setVideoEffects(videoEffects));
|
executeOrDelay(videoSink -> videoSink.setVideoEffects(videoEffects));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setPendingVideoEffects(List<Effect> videoEffects) {
|
|
||||||
executeOrDelay(videoSink -> videoSink.setPendingVideoEffects(videoEffects));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setStreamTimestampInfo(
|
public void setStreamTimestampInfo(
|
||||||
long streamStartPositionUs, long bufferTimestampAdjustmentUs, long lastResetPositionUs) {
|
long streamStartPositionUs, long bufferTimestampAdjustmentUs, long lastResetPositionUs) {
|
||||||
@ -211,8 +206,9 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInputStreamChanged(@InputType int inputType, Format format) {
|
public void onInputStreamChanged(
|
||||||
executeOrDelay(videoSink -> videoSink.onInputStreamChanged(inputType, format));
|
@InputType int inputType, Format format, List<Effect> videoEffects) {
|
||||||
|
executeOrDelay(videoSink -> videoSink.onInputStreamChanged(inputType, format, videoEffects));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -287,7 +287,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
private final VideoSink videoSink;
|
private final VideoSink videoSink;
|
||||||
private final boolean requestToneMapping;
|
private final boolean requestToneMapping;
|
||||||
|
|
||||||
@Nullable private ImmutableList<Effect> pendingEffect;
|
private ImmutableList<Effect> pendingEffects;
|
||||||
@Nullable private EditedMediaItem currentEditedMediaItem;
|
@Nullable private EditedMediaItem currentEditedMediaItem;
|
||||||
private long offsetToCompositionTimeUs;
|
private long offsetToCompositionTimeUs;
|
||||||
|
|
||||||
@ -312,6 +312,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
this.sequence = sequence;
|
this.sequence = sequence;
|
||||||
this.videoSink = videoSink;
|
this.videoSink = videoSink;
|
||||||
this.requestToneMapping = requestToneMapping;
|
this.requestToneMapping = requestToneMapping;
|
||||||
|
this.pendingEffects = ImmutableList.of();
|
||||||
experimentalEnableProcessedStreamChangedAtStart();
|
experimentalEnableProcessedStreamChangedAtStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -329,7 +330,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
// previous one.
|
// previous one.
|
||||||
currentEditedMediaItem = getRepeatedEditedMediaItem(sequence, mediaItemIndex);
|
currentEditedMediaItem = getRepeatedEditedMediaItem(sequence, mediaItemIndex);
|
||||||
offsetToCompositionTimeUs = getOffsetToCompositionTimeUs(sequence, mediaItemIndex, offsetUs);
|
offsetToCompositionTimeUs = getOffsetToCompositionTimeUs(sequence, mediaItemIndex, offsetUs);
|
||||||
pendingEffect = sequence.editedMediaItems.get(mediaItemIndex).effects.videoEffects;
|
pendingEffects = sequence.editedMediaItems.get(mediaItemIndex).effects.videoEffects;
|
||||||
super.onStreamChanged(formats, startPositionUs, offsetUs, mediaPeriodId);
|
super.onStreamChanged(formats, startPositionUs, offsetUs, mediaPeriodId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,12 +371,9 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onReadyToChangeVideoSinkInputStream() {
|
protected void changeVideoSinkInputStream(
|
||||||
@Nullable ImmutableList<Effect> pendingEffect = this.pendingEffect;
|
VideoSink videoSink, @VideoSink.InputType int inputType, Format format) {
|
||||||
if (pendingEffect != null) {
|
videoSink.onInputStreamChanged(inputType, format, pendingEffects);
|
||||||
videoSink.setPendingVideoEffects(pendingEffect);
|
|
||||||
this.pendingEffect = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -519,7 +517,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
long positionUs, long elapsedRealtimeUs, Bitmap outputImage, long timeUs) {
|
long positionUs, long elapsedRealtimeUs, Bitmap outputImage, long timeUs) {
|
||||||
if (inputStreamPending) {
|
if (inputStreamPending) {
|
||||||
checkState(streamStartPositionUs != C.TIME_UNSET);
|
checkState(streamStartPositionUs != C.TIME_UNSET);
|
||||||
videoSink.setPendingVideoEffects(videoEffects);
|
|
||||||
videoSink.setStreamTimestampInfo(
|
videoSink.setStreamTimestampInfo(
|
||||||
streamStartPositionUs,
|
streamStartPositionUs,
|
||||||
/* bufferTimestampAdjustmentUs= */ offsetToCompositionTimeUs,
|
/* bufferTimestampAdjustmentUs= */ offsetToCompositionTimeUs,
|
||||||
@ -532,7 +529,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
.setHeight(outputImage.getHeight())
|
.setHeight(outputImage.getHeight())
|
||||||
.setColorInfo(ColorInfo.SRGB_BT709_FULL)
|
.setColorInfo(ColorInfo.SRGB_BT709_FULL)
|
||||||
.setFrameRate(/* frameRate= */ DEFAULT_FRAME_RATE)
|
.setFrameRate(/* frameRate= */ DEFAULT_FRAME_RATE)
|
||||||
.build());
|
.build(),
|
||||||
|
videoEffects);
|
||||||
inputStreamPending = false;
|
inputStreamPending = false;
|
||||||
}
|
}
|
||||||
if (!videoSink.handleInputBitmap(outputImage, checkStateNotNull(timestampIterator))) {
|
if (!videoSink.handleInputBitmap(outputImage, checkStateNotNull(timestampIterator))) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user