mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
VideoFrameReleaseControl: merge onEnabled and onProcessedStreamChange
This is a step towards removing the assumption that there is only one sequence and therefore one renderer feeding data to DefaultVideoSink and VideoFrameReleaseControl. This is a no-op refactoring. PiperOrigin-RevId: 734044100
This commit is contained in:
parent
f996a5e3e4
commit
7e6089d3aa
@ -17,6 +17,8 @@ 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.exoplayer.video.VideoFrameReleaseControl.RELEASE_FIRST_FRAME_IMMEDIATELY;
|
||||
import static androidx.media3.exoplayer.video.VideoFrameReleaseControl.RELEASE_FIRST_FRAME_WHEN_STARTED;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.view.Surface;
|
||||
@ -83,7 +85,9 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
|
||||
@Override
|
||||
public void onRendererEnabled(boolean mayRenderStartOfStream) {
|
||||
videoFrameReleaseControl.onEnabled(mayRenderStartOfStream);
|
||||
int firstFrameReleaseInstruction =
|
||||
mayRenderStartOfStream ? RELEASE_FIRST_FRAME_IMMEDIATELY : RELEASE_FIRST_FRAME_WHEN_STARTED;
|
||||
videoFrameReleaseControl.onStreamChanged(firstFrameReleaseInstruction);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -22,6 +22,9 @@ import static androidx.media3.common.util.Assertions.checkStateNotNull;
|
||||
import static androidx.media3.exoplayer.DecoderReuseEvaluation.DISCARD_REASON_MAX_INPUT_SIZE_EXCEEDED;
|
||||
import static androidx.media3.exoplayer.DecoderReuseEvaluation.DISCARD_REASON_VIDEO_MAX_RESOLUTION_EXCEEDED;
|
||||
import static androidx.media3.exoplayer.DecoderReuseEvaluation.REUSE_RESULT_NO;
|
||||
import static androidx.media3.exoplayer.video.VideoFrameReleaseControl.RELEASE_FIRST_FRAME_IMMEDIATELY;
|
||||
import static androidx.media3.exoplayer.video.VideoFrameReleaseControl.RELEASE_FIRST_FRAME_WHEN_PREVIOUS_STREAM_PROCESSED;
|
||||
import static androidx.media3.exoplayer.video.VideoFrameReleaseControl.RELEASE_FIRST_FRAME_WHEN_STARTED;
|
||||
import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
|
||||
import static java.lang.Math.max;
|
||||
import static java.lang.Math.min;
|
||||
@ -911,7 +914,11 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer
|
||||
}
|
||||
} else {
|
||||
videoFrameReleaseControl.setClock(getClock());
|
||||
videoFrameReleaseControl.onEnabled(mayRenderStartOfStream);
|
||||
int firstFrameReleaseInstruction =
|
||||
mayRenderStartOfStream
|
||||
? RELEASE_FIRST_FRAME_IMMEDIATELY
|
||||
: RELEASE_FIRST_FRAME_WHEN_STARTED;
|
||||
videoFrameReleaseControl.onStreamChanged(firstFrameReleaseInstruction);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1837,7 +1844,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer
|
||||
videoSink.setStreamTimestampInfo(
|
||||
getOutputStreamStartPositionUs(), getBufferTimestampAdjustmentUs());
|
||||
} else {
|
||||
videoFrameReleaseControl.onProcessedStreamChange();
|
||||
videoFrameReleaseControl.onStreamChanged(RELEASE_FIRST_FRAME_WHEN_PREVIOUS_STREAM_PROCESSED);
|
||||
}
|
||||
pendingVideoSinkInputStreamChange = true;
|
||||
maybeSetupTunnelingForFirstFrame();
|
||||
|
@ -41,6 +41,35 @@ import java.lang.annotation.Target;
|
||||
@UnstableApi
|
||||
public final class VideoFrameReleaseControl {
|
||||
|
||||
/**
|
||||
* The instruction provided to {@link #onStreamChanged(int)} for releasing the first frame.
|
||||
*
|
||||
* <p>One of {@link #RELEASE_FIRST_FRAME_IMMEDIATELY}, {@link #RELEASE_FIRST_FRAME_WHEN_STARTED}
|
||||
* or {@link #RELEASE_FIRST_FRAME_WHEN_PREVIOUS_STREAM_PROCESSED}.
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@Target(TYPE_USE)
|
||||
@UnstableApi
|
||||
@IntDef({
|
||||
RELEASE_FIRST_FRAME_IMMEDIATELY,
|
||||
RELEASE_FIRST_FRAME_WHEN_STARTED,
|
||||
RELEASE_FIRST_FRAME_WHEN_PREVIOUS_STREAM_PROCESSED
|
||||
})
|
||||
public @interface FirstFrameReleaseInstruction {}
|
||||
|
||||
/** Instructs to release the first frame as soon as possible. */
|
||||
public static final int RELEASE_FIRST_FRAME_IMMEDIATELY = 0;
|
||||
|
||||
/** Instructs to release the first frame when rendering starts. */
|
||||
public static final int RELEASE_FIRST_FRAME_WHEN_STARTED = 1;
|
||||
|
||||
/**
|
||||
* Instructs to release the first frame when the playback position reaches the stream start
|
||||
* position.
|
||||
*/
|
||||
public static final int RELEASE_FIRST_FRAME_WHEN_PREVIOUS_STREAM_PROCESSED = 2;
|
||||
|
||||
/**
|
||||
* The frame release action returned by {@link #getFrameReleaseAction(long, long, long, long,
|
||||
* boolean, FrameReleaseInfo)}.
|
||||
@ -206,12 +235,25 @@ public final class VideoFrameReleaseControl {
|
||||
clock = Clock.DEFAULT;
|
||||
}
|
||||
|
||||
/** Called when the renderer is enabled. */
|
||||
public void onEnabled(boolean releaseFirstFrameBeforeStarted) {
|
||||
firstFrameState =
|
||||
releaseFirstFrameBeforeStarted
|
||||
? C.FIRST_FRAME_NOT_RENDERED
|
||||
: C.FIRST_FRAME_NOT_RENDERED_ONLY_ALLOWED_IF_STARTED;
|
||||
/**
|
||||
* Called when the stream changes.
|
||||
*
|
||||
* <p>Must also be called for the first stream.
|
||||
*/
|
||||
public void onStreamChanged(@FirstFrameReleaseInstruction int firstFrameReleaseInstruction) {
|
||||
switch (firstFrameReleaseInstruction) {
|
||||
case RELEASE_FIRST_FRAME_IMMEDIATELY:
|
||||
firstFrameState = C.FIRST_FRAME_NOT_RENDERED;
|
||||
break;
|
||||
case RELEASE_FIRST_FRAME_WHEN_STARTED:
|
||||
firstFrameState = C.FIRST_FRAME_NOT_RENDERED_ONLY_ALLOWED_IF_STARTED;
|
||||
break;
|
||||
case RELEASE_FIRST_FRAME_WHEN_PREVIOUS_STREAM_PROCESSED:
|
||||
lowerFirstFrameState(C.FIRST_FRAME_NOT_RENDERED_AFTER_STREAM_CHANGE);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
/** Called when the renderer is started. */
|
||||
@ -228,11 +270,6 @@ public final class VideoFrameReleaseControl {
|
||||
frameReleaseHelper.onStopped();
|
||||
}
|
||||
|
||||
/** Called when the renderer processed a stream change. */
|
||||
public void onProcessedStreamChange() {
|
||||
lowerFirstFrameState(C.FIRST_FRAME_NOT_RENDERED_AFTER_STREAM_CHANGE);
|
||||
}
|
||||
|
||||
/** Called when the display surface changed. */
|
||||
public void setOutputSurface(@Nullable Surface outputSurface) {
|
||||
frameReleaseHelper.onSurfaceChanged(outputSurface);
|
||||
|
@ -17,6 +17,7 @@ package androidx.media3.exoplayer.video;
|
||||
|
||||
import static androidx.media3.common.util.Assertions.checkArgument;
|
||||
import static androidx.media3.common.util.Assertions.checkNotNull;
|
||||
import static androidx.media3.exoplayer.video.VideoFrameReleaseControl.RELEASE_FIRST_FRAME_WHEN_PREVIOUS_STREAM_PROCESSED;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.media3.common.C;
|
||||
@ -138,7 +139,8 @@ import androidx.media3.exoplayer.ExoPlaybackException;
|
||||
long presentationTimeUs = presentationTimestampsUs.element();
|
||||
// Check whether this buffer comes with a new stream start position.
|
||||
if (maybeUpdateOutputStreamStartPosition(presentationTimeUs)) {
|
||||
videoFrameReleaseControl.onProcessedStreamChange();
|
||||
videoFrameReleaseControl.onStreamChanged(
|
||||
RELEASE_FIRST_FRAME_WHEN_PREVIOUS_STREAM_PROCESSED);
|
||||
}
|
||||
@VideoFrameReleaseControl.FrameReleaseAction
|
||||
int frameReleaseAction =
|
||||
|
@ -15,6 +15,8 @@
|
||||
*/
|
||||
package androidx.media3.exoplayer.video;
|
||||
|
||||
import static androidx.media3.exoplayer.video.VideoFrameReleaseControl.RELEASE_FIRST_FRAME_IMMEDIATELY;
|
||||
import static androidx.media3.exoplayer.video.VideoFrameReleaseControl.RELEASE_FIRST_FRAME_WHEN_STARTED;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import androidx.media3.exoplayer.ExoPlaybackException;
|
||||
@ -98,21 +100,12 @@ public class VideoFrameReleaseControlTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onFrameReleasedIsFirstFrame_resetsAfterOnEnabled() {
|
||||
public void onFrameReleasedIsFirstFrame_resetsAfterOnStreamChanged() {
|
||||
VideoFrameReleaseControl videoFrameReleaseControl = createVideoFrameReleaseControl();
|
||||
|
||||
assertThat(videoFrameReleaseControl.onFrameReleasedIsFirstFrame()).isTrue();
|
||||
videoFrameReleaseControl.onEnabled(/* releaseFirstFrameBeforeStarted= */ true);
|
||||
|
||||
assertThat(videoFrameReleaseControl.onFrameReleasedIsFirstFrame()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onFrameReleasedIsFirstFrame_resetsAfterOnProcessedStreamChange() {
|
||||
VideoFrameReleaseControl videoFrameReleaseControl = createVideoFrameReleaseControl();
|
||||
|
||||
assertThat(videoFrameReleaseControl.onFrameReleasedIsFirstFrame()).isTrue();
|
||||
videoFrameReleaseControl.onProcessedStreamChange();
|
||||
videoFrameReleaseControl.onFrameReleasedIsFirstFrame();
|
||||
assertThat(videoFrameReleaseControl.onFrameReleasedIsFirstFrame()).isFalse();
|
||||
videoFrameReleaseControl.onStreamChanged(RELEASE_FIRST_FRAME_IMMEDIATELY);
|
||||
|
||||
assertThat(videoFrameReleaseControl.onFrameReleasedIsFirstFrame()).isTrue();
|
||||
}
|
||||
@ -144,7 +137,7 @@ public class VideoFrameReleaseControlTest {
|
||||
VideoFrameReleaseControl.FrameReleaseInfo frameReleaseInfo =
|
||||
new VideoFrameReleaseControl.FrameReleaseInfo();
|
||||
VideoFrameReleaseControl videoFrameReleaseControl = createVideoFrameReleaseControl();
|
||||
videoFrameReleaseControl.onEnabled(/* releaseFirstFrameBeforeStarted= */ true);
|
||||
videoFrameReleaseControl.onStreamChanged(RELEASE_FIRST_FRAME_IMMEDIATELY);
|
||||
|
||||
assertThat(
|
||||
videoFrameReleaseControl.getFrameReleaseAction(
|
||||
@ -163,7 +156,7 @@ public class VideoFrameReleaseControlTest {
|
||||
VideoFrameReleaseControl.FrameReleaseInfo frameReleaseInfo =
|
||||
new VideoFrameReleaseControl.FrameReleaseInfo();
|
||||
VideoFrameReleaseControl videoFrameReleaseControl = createVideoFrameReleaseControl();
|
||||
videoFrameReleaseControl.onEnabled(/* releaseFirstFrameBeforeStarted= */ false);
|
||||
videoFrameReleaseControl.onStreamChanged(RELEASE_FIRST_FRAME_WHEN_STARTED);
|
||||
|
||||
assertThat(
|
||||
videoFrameReleaseControl.getFrameReleaseAction(
|
||||
@ -185,7 +178,7 @@ public class VideoFrameReleaseControlTest {
|
||||
FakeClock clock = new FakeClock(/* isAutoAdvancing= */ false);
|
||||
VideoFrameReleaseControl videoFrameReleaseControl = createVideoFrameReleaseControl();
|
||||
videoFrameReleaseControl.setClock(clock);
|
||||
videoFrameReleaseControl.onEnabled(/* releaseFirstFrameBeforeStarted= */ false);
|
||||
videoFrameReleaseControl.onStreamChanged(RELEASE_FIRST_FRAME_WHEN_STARTED);
|
||||
|
||||
videoFrameReleaseControl.onStarted();
|
||||
|
||||
@ -208,7 +201,7 @@ public class VideoFrameReleaseControlTest {
|
||||
FakeClock clock = new FakeClock(/* isAutoAdvancing= */ false);
|
||||
VideoFrameReleaseControl videoFrameReleaseControl = createVideoFrameReleaseControl();
|
||||
videoFrameReleaseControl.setClock(clock);
|
||||
videoFrameReleaseControl.onEnabled(/* releaseFirstFrameBeforeStarted= */ true);
|
||||
videoFrameReleaseControl.onStreamChanged(RELEASE_FIRST_FRAME_IMMEDIATELY);
|
||||
|
||||
// First frame released.
|
||||
assertThat(
|
||||
@ -242,7 +235,7 @@ public class VideoFrameReleaseControlTest {
|
||||
FakeClock clock = new FakeClock(/* isAutoAdvancing= */ false);
|
||||
VideoFrameReleaseControl videoFrameReleaseControl = createVideoFrameReleaseControl();
|
||||
videoFrameReleaseControl.setClock(clock);
|
||||
videoFrameReleaseControl.onEnabled(/* releaseFirstFrameBeforeStarted= */ true);
|
||||
videoFrameReleaseControl.onStreamChanged(RELEASE_FIRST_FRAME_IMMEDIATELY);
|
||||
videoFrameReleaseControl.onStarted();
|
||||
|
||||
// First frame released.
|
||||
@ -277,7 +270,7 @@ public class VideoFrameReleaseControlTest {
|
||||
FakeClock clock = new FakeClock(/* isAutoAdvancing= */ false);
|
||||
VideoFrameReleaseControl videoFrameReleaseControl = createVideoFrameReleaseControl();
|
||||
videoFrameReleaseControl.setClock(clock);
|
||||
videoFrameReleaseControl.onEnabled(/* releaseFirstFrameBeforeStarted= */ true);
|
||||
videoFrameReleaseControl.onStreamChanged(RELEASE_FIRST_FRAME_IMMEDIATELY);
|
||||
|
||||
videoFrameReleaseControl.onStarted();
|
||||
|
||||
@ -320,7 +313,7 @@ public class VideoFrameReleaseControlTest {
|
||||
/* shouldIgnoreFrame= */ false),
|
||||
/* allowedJoiningTimeMs= */ 0);
|
||||
videoFrameReleaseControl.setClock(clock);
|
||||
videoFrameReleaseControl.onEnabled(/* releaseFirstFrameBeforeStarted= */ true);
|
||||
videoFrameReleaseControl.onStreamChanged(RELEASE_FIRST_FRAME_IMMEDIATELY);
|
||||
|
||||
videoFrameReleaseControl.onStarted();
|
||||
|
||||
@ -365,7 +358,7 @@ public class VideoFrameReleaseControlTest {
|
||||
/* shouldIgnoreFrame= */ false),
|
||||
/* allowedJoiningTimeMs= */ 1234);
|
||||
videoFrameReleaseControl.setClock(clock);
|
||||
videoFrameReleaseControl.onEnabled(/* releaseFirstFrameBeforeStarted= */ true);
|
||||
videoFrameReleaseControl.onStreamChanged(RELEASE_FIRST_FRAME_IMMEDIATELY);
|
||||
videoFrameReleaseControl.onStarted();
|
||||
|
||||
// Start joining.
|
||||
@ -409,7 +402,7 @@ public class VideoFrameReleaseControlTest {
|
||||
/* shouldIgnoreFrame= */ false),
|
||||
/* allowedJoiningTimeMs= */ 1234);
|
||||
videoFrameReleaseControl.setClock(clock);
|
||||
videoFrameReleaseControl.onEnabled(/* releaseFirstFrameBeforeStarted= */ true);
|
||||
videoFrameReleaseControl.onStreamChanged(RELEASE_FIRST_FRAME_IMMEDIATELY);
|
||||
videoFrameReleaseControl.onStarted();
|
||||
|
||||
// Start joining.
|
||||
@ -452,7 +445,7 @@ public class VideoFrameReleaseControlTest {
|
||||
/* shouldIgnoreFrame= */ true),
|
||||
/* allowedJoiningTimeMs= */ 0);
|
||||
videoFrameReleaseControl.setClock(clock);
|
||||
videoFrameReleaseControl.onEnabled(/* releaseFirstFrameBeforeStarted= */ true);
|
||||
videoFrameReleaseControl.onStreamChanged(RELEASE_FIRST_FRAME_IMMEDIATELY);
|
||||
|
||||
videoFrameReleaseControl.onStarted();
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package androidx.media3.exoplayer.video;
|
||||
|
||||
import static androidx.media3.exoplayer.video.VideoFrameReleaseControl.RELEASE_FIRST_FRAME_IMMEDIATELY;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
@ -44,7 +45,7 @@ public class VideoFrameRenderControlTest {
|
||||
VideoFrameRenderControl videoFrameRenderControl =
|
||||
new VideoFrameRenderControl(frameRenderer, videoFrameReleaseControl);
|
||||
|
||||
videoFrameReleaseControl.onEnabled(/* releaseFirstFrameBeforeStarted= */ true);
|
||||
videoFrameReleaseControl.onStreamChanged(RELEASE_FIRST_FRAME_IMMEDIATELY);
|
||||
videoFrameRenderControl.onVideoSizeChanged(
|
||||
/* width= */ VIDEO_WIDTH, /* height= */ VIDEO_HEIGHT);
|
||||
videoFrameRenderControl.onFrameAvailableForRendering(/* presentationTimeUs= */ 0);
|
||||
@ -72,7 +73,7 @@ public class VideoFrameRenderControlTest {
|
||||
VideoFrameRenderControl videoFrameRenderControl =
|
||||
new VideoFrameRenderControl(frameRenderer, videoFrameReleaseControl);
|
||||
|
||||
videoFrameReleaseControl.onEnabled(/* releaseFirstFrameBeforeStarted= */ true);
|
||||
videoFrameReleaseControl.onStreamChanged(RELEASE_FIRST_FRAME_IMMEDIATELY);
|
||||
videoFrameReleaseControl.onStarted();
|
||||
videoFrameRenderControl.onVideoSizeChanged(
|
||||
/* width= */ VIDEO_WIDTH, /* height= */ VIDEO_HEIGHT);
|
||||
@ -117,7 +118,7 @@ public class VideoFrameRenderControlTest {
|
||||
VideoFrameRenderControl videoFrameRenderControl =
|
||||
new VideoFrameRenderControl(frameRenderer, videoFrameReleaseControl);
|
||||
|
||||
videoFrameReleaseControl.onEnabled(/* releaseFirstFrameBeforeStarted= */ true);
|
||||
videoFrameReleaseControl.onStreamChanged(RELEASE_FIRST_FRAME_IMMEDIATELY);
|
||||
videoFrameReleaseControl.onStarted();
|
||||
videoFrameRenderControl.onVideoSizeChanged(
|
||||
/* width= */ VIDEO_WIDTH, /* height= */ VIDEO_HEIGHT);
|
||||
@ -164,7 +165,7 @@ public class VideoFrameRenderControlTest {
|
||||
VideoFrameRenderControl videoFrameRenderControl =
|
||||
new VideoFrameRenderControl(frameRenderer, videoFrameReleaseControl);
|
||||
|
||||
videoFrameReleaseControl.onEnabled(/* releaseFirstFrameBeforeStarted= */ true);
|
||||
videoFrameReleaseControl.onStreamChanged(RELEASE_FIRST_FRAME_IMMEDIATELY);
|
||||
videoFrameReleaseControl.onStarted();
|
||||
videoFrameRenderControl.onVideoSizeChanged(
|
||||
/* width= */ VIDEO_WIDTH, /* height= */ VIDEO_HEIGHT);
|
||||
@ -202,7 +203,7 @@ public class VideoFrameRenderControlTest {
|
||||
VideoFrameRenderControl videoFrameRenderControl =
|
||||
new VideoFrameRenderControl(frameRenderer, videoFrameReleaseControl);
|
||||
|
||||
videoFrameReleaseControl.onEnabled(/* releaseFirstFrameBeforeStarted= */ true);
|
||||
videoFrameReleaseControl.onStreamChanged(RELEASE_FIRST_FRAME_IMMEDIATELY);
|
||||
videoFrameReleaseControl.onStarted();
|
||||
videoFrameRenderControl.onVideoSizeChanged(
|
||||
/* width= */ VIDEO_WIDTH, /* height= */ VIDEO_HEIGHT);
|
||||
@ -247,7 +248,7 @@ public class VideoFrameRenderControlTest {
|
||||
VideoFrameRenderControl videoFrameRenderControl =
|
||||
new VideoFrameRenderControl(frameRenderer, videoFrameReleaseControl);
|
||||
|
||||
videoFrameReleaseControl.onEnabled(/* releaseFirstFrameBeforeStarted= */ true);
|
||||
videoFrameReleaseControl.onStreamChanged(RELEASE_FIRST_FRAME_IMMEDIATELY);
|
||||
videoFrameRenderControl.onVideoSizeChanged(
|
||||
/* width= */ VIDEO_WIDTH, /* height= */ VIDEO_HEIGHT);
|
||||
videoFrameRenderControl.onFrameAvailableForRendering(/* presentationTimeUs= */ 0);
|
||||
@ -265,7 +266,7 @@ public class VideoFrameRenderControlTest {
|
||||
VideoFrameRenderControl videoFrameRenderControl =
|
||||
new VideoFrameRenderControl(frameRenderer, videoFrameReleaseControl);
|
||||
|
||||
videoFrameReleaseControl.onEnabled(/* releaseFirstFrameBeforeStarted= */ true);
|
||||
videoFrameReleaseControl.onStreamChanged(RELEASE_FIRST_FRAME_IMMEDIATELY);
|
||||
videoFrameRenderControl.onVideoSizeChanged(
|
||||
/* width= */ VIDEO_WIDTH, /* height= */ VIDEO_HEIGHT);
|
||||
videoFrameRenderControl.onFrameAvailableForRendering(/* presentationTimeUs= */ 0);
|
||||
|
Loading…
x
Reference in New Issue
Block a user