mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Fix bug in CompositingVideoSinkProvider.isInitialized()
Fix a bug where CompositingVideoSinkProvider.isInitialized() returns true even after releasing the CompositingVideoSinkProvider. PiperOrigin-RevId: 588481744
This commit is contained in:
parent
073ee8a1d0
commit
faeff17a4c
2 changed files with 35 additions and 5 deletions
|
|
@ -18,6 +18,7 @@ package androidx.media3.exoplayer.video;
|
||||||
import static androidx.media3.common.util.Assertions.checkNotNull;
|
import static androidx.media3.common.util.Assertions.checkNotNull;
|
||||||
import static androidx.media3.common.util.Assertions.checkState;
|
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 static java.lang.annotation.ElementType.TYPE_USE;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
|
|
@ -25,6 +26,7 @@ import android.os.Looper;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
import androidx.annotation.FloatRange;
|
import androidx.annotation.FloatRange;
|
||||||
|
import androidx.annotation.IntDef;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
import androidx.media3.common.ColorInfo;
|
import androidx.media3.common.ColorInfo;
|
||||||
|
|
@ -50,6 +52,10 @@ import androidx.media3.exoplayer.video.VideoFrameReleaseControl.FrameTimingEvalu
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
import com.google.common.base.Suppliers;
|
import com.google.common.base.Suppliers;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
@ -199,6 +205,16 @@ public final class CompositingVideoSinkProvider
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Documented
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
@Target(TYPE_USE)
|
||||||
|
@IntDef({STATE_CREATED, STATE_INITIALIZED, STATE_RELEASED})
|
||||||
|
private @interface State {}
|
||||||
|
|
||||||
|
private static final int STATE_CREATED = 0;
|
||||||
|
private static final int STATE_INITIALIZED = 1;
|
||||||
|
private static final int STATE_RELEASED = 2;
|
||||||
|
|
||||||
private static final Executor NO_OP_EXECUTOR = runnable -> {};
|
private static final Executor NO_OP_EXECUTOR = runnable -> {};
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
|
|
@ -217,7 +233,7 @@ public final class CompositingVideoSinkProvider
|
||||||
private VideoSink.Listener listener;
|
private VideoSink.Listener listener;
|
||||||
private Executor listenerExecutor;
|
private Executor listenerExecutor;
|
||||||
private int pendingFlushCount;
|
private int pendingFlushCount;
|
||||||
private boolean released;
|
private @State int state;
|
||||||
|
|
||||||
private CompositingVideoSinkProvider(Builder builder) {
|
private CompositingVideoSinkProvider(Builder builder) {
|
||||||
this.context = builder.context;
|
this.context = builder.context;
|
||||||
|
|
@ -230,13 +246,14 @@ public final class CompositingVideoSinkProvider
|
||||||
clock = Clock.DEFAULT;
|
clock = Clock.DEFAULT;
|
||||||
listener = VideoSink.Listener.NO_OP;
|
listener = VideoSink.Listener.NO_OP;
|
||||||
listenerExecutor = NO_OP_EXECUTOR;
|
listenerExecutor = NO_OP_EXECUTOR;
|
||||||
|
state = STATE_CREATED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// VideoSinkProvider methods
|
// VideoSinkProvider methods
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize(Format sourceFormat) throws VideoSink.VideoSinkException {
|
public void initialize(Format sourceFormat) throws VideoSink.VideoSinkException {
|
||||||
checkState(!released && videoSinkImpl == null);
|
checkState(state == STATE_CREATED);
|
||||||
checkStateNotNull(videoEffects);
|
checkStateNotNull(videoEffects);
|
||||||
|
|
||||||
// Lazily initialize the handler here so it's initialized on the playback looper.
|
// Lazily initialize the handler here so it's initialized on the playback looper.
|
||||||
|
|
@ -272,18 +289,20 @@ public final class CompositingVideoSinkProvider
|
||||||
throw new VideoSink.VideoSinkException(e, sourceFormat);
|
throw new VideoSink.VideoSinkException(e, sourceFormat);
|
||||||
}
|
}
|
||||||
videoSinkImpl.setVideoEffects(checkNotNull(videoEffects));
|
videoSinkImpl.setVideoEffects(checkNotNull(videoEffects));
|
||||||
|
state = STATE_INITIALIZED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isInitialized() {
|
public boolean isInitialized() {
|
||||||
return videoSinkImpl != null;
|
return state == STATE_INITIALIZED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void release() {
|
public void release() {
|
||||||
if (released) {
|
if (state == STATE_RELEASED) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handler != null) {
|
if (handler != null) {
|
||||||
handler.removeCallbacksAndMessages(/* token= */ null);
|
handler.removeCallbacksAndMessages(/* token= */ null);
|
||||||
}
|
}
|
||||||
|
|
@ -292,7 +311,7 @@ public final class CompositingVideoSinkProvider
|
||||||
videoGraph.release();
|
videoGraph.release();
|
||||||
}
|
}
|
||||||
currentSurfaceAndSize = null;
|
currentSurfaceAndSize = null;
|
||||||
released = true;
|
state = STATE_RELEASED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,17 @@ public final class CompositingVideoSinkProviderTest {
|
||||||
IllegalStateException.class, () -> provider.initialize(new Format.Builder().build()));
|
IllegalStateException.class, () -> provider.initialize(new Format.Builder().build()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isInitialized_afterRelease_returnsFalse() throws VideoSink.VideoSinkException {
|
||||||
|
CompositingVideoSinkProvider provider = createCompositingVideoSinkProvider();
|
||||||
|
provider.setVideoEffects(ImmutableList.of());
|
||||||
|
provider.initialize(new Format.Builder().build());
|
||||||
|
|
||||||
|
provider.release();
|
||||||
|
|
||||||
|
assertThat(provider.isInitialized()).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void initialize_afterRelease_throws() throws VideoSink.VideoSinkException {
|
public void initialize_afterRelease_throws() throws VideoSink.VideoSinkException {
|
||||||
CompositingVideoSinkProvider provider = createCompositingVideoSinkProvider();
|
CompositingVideoSinkProvider provider = createCompositingVideoSinkProvider();
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue