mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Reduce flakiness for ServerSideAdInsertion±MediaSourceTest past SDK 30
PiperOrigin-RevId: 737631774
This commit is contained in:
parent
ff0a359e93
commit
4932300b9a
@ -57,6 +57,9 @@ import androidx.media3.exoplayer.FormatHolder;
|
|||||||
import androidx.media3.exoplayer.LoadingInfo;
|
import androidx.media3.exoplayer.LoadingInfo;
|
||||||
import androidx.media3.exoplayer.analytics.AnalyticsListener;
|
import androidx.media3.exoplayer.analytics.AnalyticsListener;
|
||||||
import androidx.media3.exoplayer.analytics.PlayerId;
|
import androidx.media3.exoplayer.analytics.PlayerId;
|
||||||
|
import androidx.media3.exoplayer.audio.AudioSink;
|
||||||
|
import androidx.media3.exoplayer.audio.DefaultAudioSink;
|
||||||
|
import androidx.media3.exoplayer.audio.TeeAudioProcessor;
|
||||||
import androidx.media3.exoplayer.drm.DrmSessionEventListener;
|
import androidx.media3.exoplayer.drm.DrmSessionEventListener;
|
||||||
import androidx.media3.exoplayer.drm.DrmSessionManager;
|
import androidx.media3.exoplayer.drm.DrmSessionManager;
|
||||||
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory;
|
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory;
|
||||||
@ -71,6 +74,7 @@ import androidx.media3.exoplayer.trackselection.ExoTrackSelection;
|
|||||||
import androidx.media3.exoplayer.trackselection.FixedTrackSelection;
|
import androidx.media3.exoplayer.trackselection.FixedTrackSelection;
|
||||||
import androidx.media3.exoplayer.upstream.Allocator;
|
import androidx.media3.exoplayer.upstream.Allocator;
|
||||||
import androidx.media3.exoplayer.upstream.DefaultAllocator;
|
import androidx.media3.exoplayer.upstream.DefaultAllocator;
|
||||||
|
import androidx.media3.test.utils.CapturingAudioSink;
|
||||||
import androidx.media3.test.utils.CapturingRenderersFactory;
|
import androidx.media3.test.utils.CapturingRenderersFactory;
|
||||||
import androidx.media3.test.utils.DumpFileAsserts;
|
import androidx.media3.test.utils.DumpFileAsserts;
|
||||||
import androidx.media3.test.utils.FakeClock;
|
import androidx.media3.test.utils.FakeClock;
|
||||||
@ -93,10 +97,8 @@ import org.junit.Assert;
|
|||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.robolectric.annotation.Config;
|
|
||||||
|
|
||||||
/** Unit test for {@link ServerSideAdInsertionMediaSource}. */
|
/** Unit test for {@link ServerSideAdInsertionMediaSource}. */
|
||||||
@Config(sdk = 30) // TODO: b/382017156 - Remove this when the tests pass on API 31+.
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
public final class ServerSideAdInsertionMediaSourceTest {
|
public final class ServerSideAdInsertionMediaSourceTest {
|
||||||
|
|
||||||
@ -472,7 +474,8 @@ public final class ServerSideAdInsertionMediaSourceTest {
|
|||||||
public void playbackWithNewlyInsertedAds_playsSuccessfulWithoutRendererResets() throws Exception {
|
public void playbackWithNewlyInsertedAds_playsSuccessfulWithoutRendererResets() throws Exception {
|
||||||
Context context = ApplicationProvider.getApplicationContext();
|
Context context = ApplicationProvider.getApplicationContext();
|
||||||
AtomicReference<Object> periodUid = new AtomicReference<>();
|
AtomicReference<Object> periodUid = new AtomicReference<>();
|
||||||
CapturingRenderersFactory renderersFactory = new CapturingRenderersFactory(context);
|
CapturingRenderersFactory renderersFactory =
|
||||||
|
new CapturingRenderersFactory(context, DiscontinuitySkippingCapturingAudioSink.create());
|
||||||
ExoPlayer player =
|
ExoPlayer player =
|
||||||
new ExoPlayer.Builder(context, renderersFactory)
|
new ExoPlayer.Builder(context, renderersFactory)
|
||||||
.setClock(new FakeClock(/* isAutoAdvancing= */ true))
|
.setClock(new FakeClock(/* isAutoAdvancing= */ true))
|
||||||
@ -552,7 +555,8 @@ public final class ServerSideAdInsertionMediaSourceTest {
|
|||||||
throws Exception {
|
throws Exception {
|
||||||
Context context = ApplicationProvider.getApplicationContext();
|
Context context = ApplicationProvider.getApplicationContext();
|
||||||
AtomicReference<Object> periodUid = new AtomicReference<>();
|
AtomicReference<Object> periodUid = new AtomicReference<>();
|
||||||
CapturingRenderersFactory renderersFactory = new CapturingRenderersFactory(context);
|
CapturingRenderersFactory renderersFactory =
|
||||||
|
new CapturingRenderersFactory(context, DiscontinuitySkippingCapturingAudioSink.create());
|
||||||
ExoPlayer player =
|
ExoPlayer player =
|
||||||
new ExoPlayer.Builder(context, renderersFactory)
|
new ExoPlayer.Builder(context, renderersFactory)
|
||||||
.setClock(new FakeClock(/* isAutoAdvancing= */ true))
|
.setClock(new FakeClock(/* isAutoAdvancing= */ true))
|
||||||
@ -832,4 +836,29 @@ public final class ServerSideAdInsertionMediaSourceTest {
|
|||||||
|
|
||||||
assertThat(readSamples).containsExactly(0L, 200L, 400L, 600L, 800L).inOrder();
|
assertThat(readSamples).containsExactly(0L, 200L, 400L, 600L, 800L).inOrder();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final class DiscontinuitySkippingCapturingAudioSink extends CapturingAudioSink {
|
||||||
|
/** Creates the capturing audio sink that skips dumping discontinuity events. */
|
||||||
|
public static DiscontinuitySkippingCapturingAudioSink create() {
|
||||||
|
InterceptingBufferSink interceptingBufferSink = new InterceptingBufferSink();
|
||||||
|
DiscontinuitySkippingCapturingAudioSink capturingAudioSink =
|
||||||
|
new DiscontinuitySkippingCapturingAudioSink(
|
||||||
|
new DefaultAudioSink.Builder(ApplicationProvider.getApplicationContext())
|
||||||
|
.setAudioProcessorChain(
|
||||||
|
new DefaultAudioSink.DefaultAudioProcessorChain(
|
||||||
|
new TeeAudioProcessor(interceptingBufferSink)))
|
||||||
|
.build());
|
||||||
|
interceptingBufferSink.setCapturingAudioSink(capturingAudioSink);
|
||||||
|
return capturingAudioSink;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DiscontinuitySkippingCapturingAudioSink(AudioSink sink) {
|
||||||
|
super(sink);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleDiscontinuity() {
|
||||||
|
getDelegateAudioSink().handleDiscontinuity();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -593,9 +593,6 @@ AudioSink:
|
|||||||
buffer #19:
|
buffer #19:
|
||||||
time = 1000000485179
|
time = 1000000485179
|
||||||
data = empty
|
data = empty
|
||||||
discontinuity:
|
|
||||||
discontinuity:
|
|
||||||
discontinuity:
|
|
||||||
buffer #20:
|
buffer #20:
|
||||||
time = 1000000508399
|
time = 1000000508399
|
||||||
data = empty
|
data = empty
|
||||||
|
@ -620,9 +620,6 @@ AudioSink:
|
|||||||
buffer #28:
|
buffer #28:
|
||||||
time = 1000000694158
|
time = 1000000694158
|
||||||
data = empty
|
data = empty
|
||||||
discontinuity:
|
|
||||||
discontinuity:
|
|
||||||
discontinuity:
|
|
||||||
buffer #29:
|
buffer #29:
|
||||||
time = 1000000717378
|
time = 1000000717378
|
||||||
data = empty
|
data = empty
|
||||||
@ -635,7 +632,6 @@ AudioSink:
|
|||||||
buffer #32:
|
buffer #32:
|
||||||
time = 1000000787038
|
time = 1000000787038
|
||||||
data = empty
|
data = empty
|
||||||
discontinuity:
|
|
||||||
buffer #33:
|
buffer #33:
|
||||||
time = 1000000810258
|
time = 1000000810258
|
||||||
data = empty
|
data = empty
|
||||||
|
@ -41,9 +41,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
* discontinuity and buffer events.
|
* discontinuity and buffer events.
|
||||||
*/
|
*/
|
||||||
@UnstableApi
|
@UnstableApi
|
||||||
public final class CapturingAudioSink extends ForwardingAudioSink implements Dumper.Dumpable {
|
public class CapturingAudioSink extends ForwardingAudioSink implements Dumper.Dumpable {
|
||||||
|
|
||||||
private final List<Dumper.Dumpable> interceptedData;
|
private final List<Dumper.Dumpable> interceptedData;
|
||||||
|
private final AudioSink audioSink;
|
||||||
|
|
||||||
private int bufferCount;
|
private int bufferCount;
|
||||||
private long lastPresentationTimeUs;
|
private long lastPresentationTimeUs;
|
||||||
@ -53,19 +54,26 @@ public final class CapturingAudioSink extends ForwardingAudioSink implements Dum
|
|||||||
/** Creates the capturing audio sink. */
|
/** Creates the capturing audio sink. */
|
||||||
public static CapturingAudioSink create() {
|
public static CapturingAudioSink create() {
|
||||||
InterceptingBufferSink interceptingBufferSink = new InterceptingBufferSink();
|
InterceptingBufferSink interceptingBufferSink = new InterceptingBufferSink();
|
||||||
return new CapturingAudioSink(
|
CapturingAudioSink capturingAudioSink =
|
||||||
|
new CapturingAudioSink(
|
||||||
new DefaultAudioSink.Builder(ApplicationProvider.getApplicationContext())
|
new DefaultAudioSink.Builder(ApplicationProvider.getApplicationContext())
|
||||||
.setAudioProcessorChain(
|
.setAudioProcessorChain(
|
||||||
new DefaultAudioSink.DefaultAudioProcessorChain(
|
new DefaultAudioSink.DefaultAudioProcessorChain(
|
||||||
new TeeAudioProcessor(interceptingBufferSink)))
|
new TeeAudioProcessor(interceptingBufferSink)))
|
||||||
.build(),
|
.build());
|
||||||
interceptingBufferSink);
|
interceptingBufferSink.setCapturingAudioSink(capturingAudioSink);
|
||||||
|
return capturingAudioSink;
|
||||||
}
|
}
|
||||||
|
|
||||||
private CapturingAudioSink(AudioSink sink, InterceptingBufferSink interceptingBufferSink) {
|
protected CapturingAudioSink(AudioSink sink) {
|
||||||
super(sink);
|
super(sink);
|
||||||
|
audioSink = sink;
|
||||||
interceptedData = new ArrayList<>();
|
interceptedData = new ArrayList<>();
|
||||||
interceptingBufferSink.setCapturingAudioSink(this);
|
}
|
||||||
|
|
||||||
|
/** Returns the wrapped {@link AudioSink}. */
|
||||||
|
protected final AudioSink getDelegateAudioSink() {
|
||||||
|
return audioSink;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -121,7 +129,7 @@ public final class CapturingAudioSink extends ForwardingAudioSink implements Dum
|
|||||||
dumper.endBlock();
|
dumper.endBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class InterceptingBufferSink implements TeeAudioProcessor.AudioBufferSink {
|
public static final class InterceptingBufferSink implements TeeAudioProcessor.AudioBufferSink {
|
||||||
|
|
||||||
private @MonotonicNonNull CapturingAudioSink capturingAudioSink;
|
private @MonotonicNonNull CapturingAudioSink capturingAudioSink;
|
||||||
private @MonotonicNonNull Format format;
|
private @MonotonicNonNull Format format;
|
||||||
|
@ -86,9 +86,19 @@ public class CapturingRenderersFactory implements RenderersFactory, Dumper.Dumpa
|
|||||||
* @param context The {@link Context}.
|
* @param context The {@link Context}.
|
||||||
*/
|
*/
|
||||||
public CapturingRenderersFactory(Context context) {
|
public CapturingRenderersFactory(Context context) {
|
||||||
|
this(context, CapturingAudioSink.create());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instance.
|
||||||
|
*
|
||||||
|
* @param context The {@link Context}.
|
||||||
|
* @param capturingAudioSink The audio sink to use for capturing audio output.
|
||||||
|
*/
|
||||||
|
public CapturingRenderersFactory(Context context, CapturingAudioSink capturingAudioSink) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.mediaCodecAdapterFactory = new CapturingMediaCodecAdapter.Factory(context);
|
this.mediaCodecAdapterFactory = new CapturingMediaCodecAdapter.Factory(context);
|
||||||
this.audioSink = CapturingAudioSink.create();
|
this.audioSink = capturingAudioSink;
|
||||||
this.imageOutput = new CapturingImageOutput();
|
this.imageOutput = new CapturingImageOutput();
|
||||||
this.imageDecoderFactory = ImageDecoder.Factory.DEFAULT;
|
this.imageDecoderFactory = ImageDecoder.Factory.DEFAULT;
|
||||||
this.textRendererFactory = TextRenderer::new;
|
this.textRendererFactory = TextRenderer::new;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user