Commit 5fd6ce5e by tonihei Committed by christosts

Fix threading of onFallbackApplied callback

The callback is currently triggered on the ExoPlayer playback thread
instead of the app thread that added the listener.

PiperOrigin-RevId: 492474405
(cherry picked from commit f3fc4fb9)
parent fec7b1b5
...@@ -20,6 +20,7 @@ import static com.google.android.exoplayer2.util.Assertions.checkState; ...@@ -20,6 +20,7 @@ import static com.google.android.exoplayer2.util.Assertions.checkState;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.util.HandlerWrapper;
import com.google.android.exoplayer2.util.ListenerSet; import com.google.android.exoplayer2.util.ListenerSet;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
...@@ -32,6 +33,7 @@ import com.google.android.exoplayer2.util.Util; ...@@ -32,6 +33,7 @@ import com.google.android.exoplayer2.util.Util;
private final MediaItem mediaItem; private final MediaItem mediaItem;
private final TransformationRequest originalTransformationRequest; private final TransformationRequest originalTransformationRequest;
private final ListenerSet<Transformer.Listener> transformerListeners; private final ListenerSet<Transformer.Listener> transformerListeners;
private final HandlerWrapper transformerListenerHandler;
private TransformationRequest fallbackTransformationRequest; private TransformationRequest fallbackTransformationRequest;
private int trackCount; private int trackCount;
...@@ -40,16 +42,20 @@ import com.google.android.exoplayer2.util.Util; ...@@ -40,16 +42,20 @@ import com.google.android.exoplayer2.util.Util;
* Creates a new instance. * Creates a new instance.
* *
* @param mediaItem The {@link MediaItem} to transform. * @param mediaItem The {@link MediaItem} to transform.
* @param transformerListeners The {@linkplain Transformer.Listener listeners} to forward events * @param transformerListeners The {@linkplain Transformer.Listener listeners} to call {@link
* to. * Transformer.Listener#onFallbackApplied} on.
* @param transformerListenerHandler The {@link HandlerWrapper} to call {@link
* Transformer.Listener#onFallbackApplied} events on.
* @param originalTransformationRequest The original {@link TransformationRequest}. * @param originalTransformationRequest The original {@link TransformationRequest}.
*/ */
public FallbackListener( public FallbackListener(
MediaItem mediaItem, MediaItem mediaItem,
ListenerSet<Transformer.Listener> transformerListeners, ListenerSet<Transformer.Listener> transformerListeners,
HandlerWrapper transformerListenerHandler,
TransformationRequest originalTransformationRequest) { TransformationRequest originalTransformationRequest) {
this.mediaItem = mediaItem; this.mediaItem = mediaItem;
this.transformerListeners = transformerListeners; this.transformerListeners = transformerListeners;
this.transformerListenerHandler = transformerListenerHandler;
this.originalTransformationRequest = originalTransformationRequest; this.originalTransformationRequest = originalTransformationRequest;
this.fallbackTransformationRequest = originalTransformationRequest; this.fallbackTransformationRequest = originalTransformationRequest;
} }
...@@ -104,15 +110,19 @@ import com.google.android.exoplayer2.util.Util; ...@@ -104,15 +110,19 @@ import com.google.android.exoplayer2.util.Util;
fallbackRequestBuilder.setEnableRequestSdrToneMapping( fallbackRequestBuilder.setEnableRequestSdrToneMapping(
transformationRequest.enableRequestSdrToneMapping); transformationRequest.enableRequestSdrToneMapping);
} }
fallbackTransformationRequest = fallbackRequestBuilder.build(); TransformationRequest newFallbackTransformationRequest = fallbackRequestBuilder.build();
fallbackTransformationRequest = newFallbackTransformationRequest;
if (trackCount == 0 && !originalTransformationRequest.equals(fallbackTransformationRequest)) { if (trackCount == 0 && !originalTransformationRequest.equals(fallbackTransformationRequest)) {
transformerListeners.queueEvent( transformerListenerHandler.post(
/* eventFlag= */ C.INDEX_UNSET, () ->
listener -> transformerListeners.sendEvent(
listener.onFallbackApplied( /* eventFlag= */ C.INDEX_UNSET,
mediaItem, originalTransformationRequest, fallbackTransformationRequest)); listener ->
transformerListeners.flushEvents(); listener.onFallbackApplied(
mediaItem,
originalTransformationRequest,
newFallbackTransformationRequest)));
} }
} }
} }
...@@ -727,7 +727,11 @@ public final class Transformer { ...@@ -727,7 +727,11 @@ public final class Transformer {
/* asyncErrorListener= */ componentListener); /* asyncErrorListener= */ componentListener);
this.muxerWrapper = muxerWrapper; this.muxerWrapper = muxerWrapper;
FallbackListener fallbackListener = FallbackListener fallbackListener =
new FallbackListener(mediaItem, listeners, transformationRequest); new FallbackListener(
mediaItem,
listeners,
clock.createHandler(looper, /* callback= */ null),
transformationRequest);
exoPlayerAssetLoader.start( exoPlayerAssetLoader.start(
mediaItem, mediaItem,
muxerWrapper, muxerWrapper,
......
...@@ -26,10 +26,12 @@ import android.os.Looper; ...@@ -26,10 +26,12 @@ import android.os.Looper;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.util.Clock; import com.google.android.exoplayer2.util.Clock;
import com.google.android.exoplayer2.util.HandlerWrapper;
import com.google.android.exoplayer2.util.ListenerSet; import com.google.android.exoplayer2.util.ListenerSet;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.robolectric.shadows.ShadowLooper;
/** Unit tests for {@link FallbackListener}. */ /** Unit tests for {@link FallbackListener}. */
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
...@@ -41,7 +43,8 @@ public class FallbackListenerTest { ...@@ -41,7 +43,8 @@ public class FallbackListenerTest {
public void onTransformationRequestFinalized_withoutTrackRegistration_throwsException() { public void onTransformationRequestFinalized_withoutTrackRegistration_throwsException() {
TransformationRequest transformationRequest = new TransformationRequest.Builder().build(); TransformationRequest transformationRequest = new TransformationRequest.Builder().build();
FallbackListener fallbackListener = FallbackListener fallbackListener =
new FallbackListener(PLACEHOLDER_MEDIA_ITEM, createListenerSet(), transformationRequest); new FallbackListener(
PLACEHOLDER_MEDIA_ITEM, createListenerSet(), createHandler(), transformationRequest);
assertThrows( assertThrows(
IllegalStateException.class, IllegalStateException.class,
...@@ -52,10 +55,12 @@ public class FallbackListenerTest { ...@@ -52,10 +55,12 @@ public class FallbackListenerTest {
public void onTransformationRequestFinalized_afterTrackRegistration_completesSuccessfully() { public void onTransformationRequestFinalized_afterTrackRegistration_completesSuccessfully() {
TransformationRequest transformationRequest = new TransformationRequest.Builder().build(); TransformationRequest transformationRequest = new TransformationRequest.Builder().build();
FallbackListener fallbackListener = FallbackListener fallbackListener =
new FallbackListener(PLACEHOLDER_MEDIA_ITEM, createListenerSet(), transformationRequest); new FallbackListener(
PLACEHOLDER_MEDIA_ITEM, createListenerSet(), createHandler(), transformationRequest);
fallbackListener.registerTrack(); fallbackListener.registerTrack();
fallbackListener.onTransformationRequestFinalized(transformationRequest); fallbackListener.onTransformationRequestFinalized(transformationRequest);
ShadowLooper.idleMainLooper();
} }
@Test @Test
...@@ -66,10 +71,14 @@ public class FallbackListenerTest { ...@@ -66,10 +71,14 @@ public class FallbackListenerTest {
Transformer.Listener mockListener = mock(Transformer.Listener.class); Transformer.Listener mockListener = mock(Transformer.Listener.class);
FallbackListener fallbackListener = FallbackListener fallbackListener =
new FallbackListener( new FallbackListener(
PLACEHOLDER_MEDIA_ITEM, createListenerSet(mockListener), originalRequest); PLACEHOLDER_MEDIA_ITEM,
createListenerSet(mockListener),
createHandler(),
originalRequest);
fallbackListener.registerTrack(); fallbackListener.registerTrack();
fallbackListener.onTransformationRequestFinalized(unchangedRequest); fallbackListener.onTransformationRequestFinalized(unchangedRequest);
ShadowLooper.idleMainLooper();
verify(mockListener, never()).onFallbackApplied(any(), any(), any()); verify(mockListener, never()).onFallbackApplied(any(), any(), any());
} }
...@@ -83,10 +92,14 @@ public class FallbackListenerTest { ...@@ -83,10 +92,14 @@ public class FallbackListenerTest {
Transformer.Listener mockListener = mock(Transformer.Listener.class); Transformer.Listener mockListener = mock(Transformer.Listener.class);
FallbackListener fallbackListener = FallbackListener fallbackListener =
new FallbackListener( new FallbackListener(
PLACEHOLDER_MEDIA_ITEM, createListenerSet(mockListener), originalRequest); PLACEHOLDER_MEDIA_ITEM,
createListenerSet(mockListener),
createHandler(),
originalRequest);
fallbackListener.registerTrack(); fallbackListener.registerTrack();
fallbackListener.onTransformationRequestFinalized(audioFallbackRequest); fallbackListener.onTransformationRequestFinalized(audioFallbackRequest);
ShadowLooper.idleMainLooper();
verify(mockListener) verify(mockListener)
.onFallbackApplied(PLACEHOLDER_MEDIA_ITEM, originalRequest, audioFallbackRequest); .onFallbackApplied(PLACEHOLDER_MEDIA_ITEM, originalRequest, audioFallbackRequest);
...@@ -109,12 +122,16 @@ public class FallbackListenerTest { ...@@ -109,12 +122,16 @@ public class FallbackListenerTest {
Transformer.Listener mockListener = mock(Transformer.Listener.class); Transformer.Listener mockListener = mock(Transformer.Listener.class);
FallbackListener fallbackListener = FallbackListener fallbackListener =
new FallbackListener( new FallbackListener(
PLACEHOLDER_MEDIA_ITEM, createListenerSet(mockListener), originalRequest); PLACEHOLDER_MEDIA_ITEM,
createListenerSet(mockListener),
createHandler(),
originalRequest);
fallbackListener.registerTrack(); fallbackListener.registerTrack();
fallbackListener.registerTrack(); fallbackListener.registerTrack();
fallbackListener.onTransformationRequestFinalized(audioFallbackRequest); fallbackListener.onTransformationRequestFinalized(audioFallbackRequest);
fallbackListener.onTransformationRequestFinalized(videoFallbackRequest); fallbackListener.onTransformationRequestFinalized(videoFallbackRequest);
ShadowLooper.idleMainLooper();
verify(mockListener) verify(mockListener)
.onFallbackApplied(PLACEHOLDER_MEDIA_ITEM, originalRequest, mergedFallbackRequest); .onFallbackApplied(PLACEHOLDER_MEDIA_ITEM, originalRequest, mergedFallbackRequest);
...@@ -130,4 +147,8 @@ public class FallbackListenerTest { ...@@ -130,4 +147,8 @@ public class FallbackListenerTest {
private static ListenerSet<Transformer.Listener> createListenerSet() { private static ListenerSet<Transformer.Listener> createListenerSet() {
return new ListenerSet<>(Looper.myLooper(), Clock.DEFAULT, (listener, flags) -> {}); return new ListenerSet<>(Looper.myLooper(), Clock.DEFAULT, (listener, flags) -> {});
} }
private static HandlerWrapper createHandler() {
return Clock.DEFAULT.createHandler(Looper.myLooper(), /* callback= */ null);
}
} }
...@@ -45,6 +45,7 @@ public final class VideoEncoderWrapperTest { ...@@ -45,6 +45,7 @@ public final class VideoEncoderWrapperTest {
new FallbackListener( new FallbackListener(
MediaItem.fromUri(Uri.EMPTY), MediaItem.fromUri(Uri.EMPTY),
new ListenerSet<>(Looper.myLooper(), Clock.DEFAULT, (listener, flags) -> {}), new ListenerSet<>(Looper.myLooper(), Clock.DEFAULT, (listener, flags) -> {}),
Clock.DEFAULT.createHandler(Looper.myLooper(), /* callback= */ null),
emptyTransformationRequest); emptyTransformationRequest);
private final VideoTranscodingSamplePipeline.EncoderWrapper encoderWrapper = private final VideoTranscodingSamplePipeline.EncoderWrapper encoderWrapper =
new VideoTranscodingSamplePipeline.EncoderWrapper( new VideoTranscodingSamplePipeline.EncoderWrapper(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment