Ignore renderer errors from text/metadata tracks

Before this change:

* With legacy subtitle decoding (at render time), load errors (e.g. HTTP
  404) would result playback completely failing, while parse errors
  (e.g. invalid  WebVTT data) would be silently ignored, so playback
  would continue without subtitles.
* With new subtitle decoding (at extraction time), both load and parse
  errors would result in playback completely failing.

This change means that now neither load nor parse errors in text or
metadata tracks stop playback from continuing. Instead the error'd track
is disabled until the end of the current period.

With new subtitle decoding, both load and parse errors happen during
loading/extraction, and so are emitted to the app via
`MediaSourceEventListener.onLoadError` and
`AnalyticsListener.onLoadError`. With legacy subtitle decoding, only
load errors are emitted via these listeners and parsing errors continue
to be silently ignored.

Issue: androidx/media#1722
PiperOrigin-RevId: 686902979
This commit is contained in:
ibaker 2024-10-17 07:12:20 -07:00 committed by Copybara-Service
parent 191bc094a5
commit 49dec5db8b
16 changed files with 3200 additions and 2 deletions

View File

@ -65,6 +65,16 @@
subtitles (those added with subtitles (those added with
`MediaItem.LocalConfiguration.subtitleConfigurations`), which may appear `MediaItem.LocalConfiguration.subtitleConfigurations`), which may appear
as duplicate load events emitted from `AnalyticsListener`. as duplicate load events emitted from `AnalyticsListener`.
* Prevent subtitle & metadata errors from completely stopping playback.
Instead the problematic track is disabled and playback of the remaining
tracks continues
([#1722](https://github.com/google/ExoPlayer/issues/1722)).
* In new subtitle handling (during extraction), associated parse (e.g.
invalid subtitle data) and load errors (e.g. HTTP 404) are emitted
via `onLoadError` callbacks.
* In legacy subtitle handling (during rendering), only associated load
errors are emitted via `onLoadError` callbacks while parse errors
are silently ignored (this is pre-existing behaviour).
* Transformer: * Transformer:
* Make setting the image duration using * Make setting the image duration using
`MediaItem.Builder.setImageDurationMs` mandatory for image export. `MediaItem.Builder.setImageDurationMs` mandatory for image export.

View File

@ -1149,7 +1149,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
maybeTriggerOnRendererReadyChanged(/* rendererIndex= */ i, allowsPlayback); maybeTriggerOnRendererReadyChanged(/* rendererIndex= */ i, allowsPlayback);
renderersAllowPlayback = renderersAllowPlayback && allowsPlayback; renderersAllowPlayback = renderersAllowPlayback && allowsPlayback;
if (!allowsPlayback) { if (!allowsPlayback) {
renderer.maybeThrowStreamError(); maybeThrowRendererStreamError(/* rendererIndex= */ i);
} }
} }
} else { } else {
@ -1200,7 +1200,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
for (int i = 0; i < renderers.length; i++) { for (int i = 0; i < renderers.length; i++) {
if (isRendererEnabled(renderers[i]) if (isRendererEnabled(renderers[i])
&& renderers[i].getStream() == playingPeriodHolder.sampleStreams[i]) { && renderers[i].getStream() == playingPeriodHolder.sampleStreams[i]) {
renderers[i].maybeThrowStreamError(); maybeThrowRendererStreamError(/* rendererIndex= */ i);
} }
} }
if (!playbackInfo.isLoading if (!playbackInfo.isLoading
@ -2940,6 +2940,46 @@ import java.util.concurrent.atomic.AtomicBoolean;
&& playbackInfo.playbackSuppressionReason == Player.PLAYBACK_SUPPRESSION_REASON_NONE; && playbackInfo.playbackSuppressionReason == Player.PLAYBACK_SUPPRESSION_REASON_NONE;
} }
private void maybeThrowRendererStreamError(int rendererIndex)
throws IOException, ExoPlaybackException {
Renderer renderer = renderers[rendererIndex];
try {
renderer.maybeThrowStreamError();
} catch (IOException | RuntimeException e) {
switch (renderer.getTrackType()) {
case C.TRACK_TYPE_TEXT:
case C.TRACK_TYPE_METADATA:
TrackSelectorResult currentTrackSelectorResult =
queue.getPlayingPeriod().getTrackSelectorResult();
Log.e(
TAG,
"Disabling track due to error: "
+ Format.toLogString(
currentTrackSelectorResult.selections[rendererIndex].getSelectedFormat()),
e);
TrackSelectorResult newTrackSelectorResult =
new TrackSelectorResult(
currentTrackSelectorResult.rendererConfigurations.clone(),
currentTrackSelectorResult.selections.clone(),
currentTrackSelectorResult.tracks,
currentTrackSelectorResult.info);
newTrackSelectorResult.rendererConfigurations[rendererIndex] = null;
newTrackSelectorResult.selections[rendererIndex] = null;
disableRenderer(rendererIndex);
queue
.getPlayingPeriod()
.applyTrackSelection(
newTrackSelectorResult,
playbackInfo.positionUs,
/* forceRecreateStreams= */ false);
break;
default:
throw e;
}
}
}
private static PositionUpdateForPlaylistChange resolvePositionForPlaylistChange( private static PositionUpdateForPlaylistChange resolvePositionForPlaylistChange(
Timeline timeline, Timeline timeline,
PlaybackInfo playbackInfo, PlaybackInfo playbackInfo,

View File

@ -42,11 +42,13 @@ import androidx.media3.exoplayer.source.MediaSource;
import androidx.media3.exoplayer.source.SampleStream.ReadDataResult; import androidx.media3.exoplayer.source.SampleStream.ReadDataResult;
import androidx.media3.extractor.text.CueDecoder; import androidx.media3.extractor.text.CueDecoder;
import androidx.media3.extractor.text.CuesWithTiming; import androidx.media3.extractor.text.CuesWithTiming;
import androidx.media3.extractor.text.Subtitle;
import androidx.media3.extractor.text.SubtitleDecoder; import androidx.media3.extractor.text.SubtitleDecoder;
import androidx.media3.extractor.text.SubtitleDecoderException; import androidx.media3.extractor.text.SubtitleDecoderException;
import androidx.media3.extractor.text.SubtitleInputBuffer; import androidx.media3.extractor.text.SubtitleInputBuffer;
import androidx.media3.extractor.text.SubtitleOutputBuffer; import androidx.media3.extractor.text.SubtitleOutputBuffer;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import java.io.IOException;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
@ -122,6 +124,7 @@ public final class TextRenderer extends BaseRenderer implements Callback {
private long lastRendererPositionUs; private long lastRendererPositionUs;
private long finalStreamEndPositionUs; private long finalStreamEndPositionUs;
private boolean legacyDecodingEnabled; private boolean legacyDecodingEnabled;
@Nullable private IOException streamError;
/** /**
* @param output The output. * @param output The output.
@ -472,11 +475,40 @@ public final class TextRenderer extends BaseRenderer implements Callback {
@Override @Override
public boolean isReady() { public boolean isReady() {
if (streamFormat == null) {
return true;
}
if (streamError == null) {
try {
maybeThrowStreamError();
} catch (IOException e) {
streamError = e;
}
}
if (streamError != null) {
if (isCuesWithTiming(checkNotNull(streamFormat))) {
return checkNotNull(cuesResolver).getNextCueChangeTimeUs(lastRendererPositionUs)
!= C.TIME_END_OF_SOURCE;
} else {
if (outputStreamEnded
|| (inputStreamEnded
&& hasNoEventsAfter(subtitle, lastRendererPositionUs)
&& hasNoEventsAfter(nextSubtitle, lastRendererPositionUs)
&& nextSubtitleInputBuffer != null)) {
return false;
}
}
}
// Don't block playback whilst subtitles are loading. // Don't block playback whilst subtitles are loading.
// Note: To change this behavior, it will be necessary to consider [Internal: b/12949941]. // Note: To change this behavior, it will be necessary to consider [Internal: b/12949941].
return true; return true;
} }
private static boolean hasNoEventsAfter(@Nullable Subtitle subtitle, long timeUs) {
return subtitle == null || subtitle.getEventTime(subtitle.getEventTimeCount() - 1) <= timeUs;
}
private void releaseSubtitleBuffers() { private void releaseSubtitleBuffers() {
nextSubtitleInputBuffer = null; nextSubtitleInputBuffer = null;
nextSubtitleEventIndex = C.INDEX_UNSET; nextSubtitleEventIndex = C.INDEX_UNSET;

View File

@ -0,0 +1,179 @@
/*
* Copyright 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.media3.exoplayer.e2etest;
import static androidx.media3.test.utils.robolectric.TestPlayerRunHelper.run;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import android.graphics.SurfaceTexture;
import android.net.Uri;
import android.view.Surface;
import androidx.media3.common.C;
import androidx.media3.common.MediaItem;
import androidx.media3.common.MimeTypes;
import androidx.media3.common.ParserException;
import androidx.media3.common.Player;
import androidx.media3.exoplayer.ExoPlayer;
import androidx.media3.exoplayer.analytics.AnalyticsListener;
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory;
import androidx.media3.exoplayer.source.LoadEventInfo;
import androidx.media3.exoplayer.source.MediaLoadData;
import androidx.media3.test.utils.CapturingRenderersFactory;
import androidx.media3.test.utils.DumpFileAsserts;
import androidx.media3.test.utils.FakeClock;
import androidx.media3.test.utils.ThrowingSubtitleParserFactory;
import androidx.media3.test.utils.robolectric.PlaybackOutput;
import androidx.media3.test.utils.robolectric.ShadowMediaCodecConfig;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
/** End-to-end tests of subtitle playback behaviour. */
@RunWith(AndroidJUnit4.class)
public class SubtitlePlaybackTest {
@Rule
public ShadowMediaCodecConfig mediaCodecConfig =
ShadowMediaCodecConfig.forAllSupportedMimeTypes();
@Test
public void sideloadedSubtitleLoadingError_playbackContinues_errorReportedToAnalyticsListener()
throws Exception {
Context applicationContext = ApplicationProvider.getApplicationContext();
CapturingRenderersFactory capturingRenderersFactory =
new CapturingRenderersFactory(applicationContext);
AtomicReference<LoadEventInfo> loadErrorEventInfo = new AtomicReference<>();
AnalyticsListener analyticsListener =
new AnalyticsListener() {
@Override
public void onLoadError(
EventTime eventTime,
LoadEventInfo loadEventInfo,
MediaLoadData mediaLoadData,
IOException error,
boolean wasCanceled) {
loadErrorEventInfo.set(loadEventInfo);
}
};
ExoPlayer player =
new ExoPlayer.Builder(applicationContext, capturingRenderersFactory)
.setClock(new FakeClock(/* isAutoAdvancing= */ true))
.build();
player.addAnalyticsListener(analyticsListener);
Surface surface = new Surface(new SurfaceTexture(/* texName= */ 1));
player.setVideoSurface(surface);
PlaybackOutput playbackOutput = PlaybackOutput.register(player, capturingRenderersFactory);
Uri notFoundSubtitleUri = Uri.parse("asset:///file/not/found");
MediaItem mediaItem =
new MediaItem.Builder()
.setUri("asset:///media/mp4/sample.mp4")
.setSubtitleConfigurations(
ImmutableList.of(
new MediaItem.SubtitleConfiguration.Builder(notFoundSubtitleUri)
.setMimeType(MimeTypes.TEXT_VTT)
.setLanguage("en")
.setSelectionFlags(C.SELECTION_FLAG_DEFAULT)
.build()))
.build();
player.setMediaItem(mediaItem);
player.prepare();
run(player).ignoringNonFatalErrors().untilState(Player.STATE_READY);
run(player).untilLoadingIs(false);
player.play();
run(player).untilState(Player.STATE_ENDED);
player.release();
surface.release();
assertThat(loadErrorEventInfo.get().uri).isEqualTo(notFoundSubtitleUri);
// Assert the output is the same as playing the video without sideloaded subtitles.
DumpFileAsserts.assertOutput(
applicationContext, playbackOutput, "playbackdumps/mp4/sample.mp4.dump");
}
@Test
public void sideloadedSubtitleParsingError_playbackContinues_errorReportedToAnalyticsListener()
throws Exception {
Context applicationContext = ApplicationProvider.getApplicationContext();
CapturingRenderersFactory capturingRenderersFactory =
new CapturingRenderersFactory(applicationContext);
AtomicReference<LoadEventInfo> loadErrorEventInfo = new AtomicReference<>();
AtomicReference<IOException> loadError = new AtomicReference<>();
AnalyticsListener analyticsListener =
new AnalyticsListener() {
@Override
public void onLoadError(
EventTime eventTime,
LoadEventInfo loadEventInfo,
MediaLoadData mediaLoadData,
IOException error,
boolean wasCanceled) {
loadErrorEventInfo.set(loadEventInfo);
loadError.set(error);
}
};
ExoPlayer player =
new ExoPlayer.Builder(applicationContext, capturingRenderersFactory)
.setClock(new FakeClock(/* isAutoAdvancing= */ true))
.setMediaSourceFactory(
new DefaultMediaSourceFactory(applicationContext)
.setSubtitleParserFactory(
new ThrowingSubtitleParserFactory(
() -> new IllegalStateException("test subtitle parsing error"))))
.build();
player.addAnalyticsListener(analyticsListener);
Surface surface = new Surface(new SurfaceTexture(/* texName= */ 1));
player.setVideoSurface(surface);
PlaybackOutput playbackOutput = PlaybackOutput.register(player, capturingRenderersFactory);
MediaItem mediaItem =
new MediaItem.Builder()
.setUri("asset:///media/mp4/sample.mp4")
.setSubtitleConfigurations(
ImmutableList.of(
new MediaItem.SubtitleConfiguration.Builder(
Uri.parse("asset:///media/webvtt/typical"))
.setMimeType(MimeTypes.TEXT_VTT)
.setLanguage("en")
.setSelectionFlags(C.SELECTION_FLAG_DEFAULT)
.build()))
.build();
player.setMediaItem(mediaItem);
player.prepare();
run(player).ignoringNonFatalErrors().untilState(Player.STATE_READY);
run(player).untilLoadingIs(false);
player.play();
run(player).untilState(Player.STATE_ENDED);
player.release();
surface.release();
assertThat(loadError.get()).isInstanceOf(ParserException.class);
assertThat(loadError.get())
.hasCauseThat()
.hasMessageThat()
.contains("test subtitle parsing error");
DumpFileAsserts.assertOutput(
applicationContext,
playbackOutput,
"playbackdumps/subtitles/sideloaded-parse-error.mp4.dump");
}
}

View File

@ -16,33 +16,44 @@
package androidx.media3.exoplayer.dash.e2etest; package androidx.media3.exoplayer.dash.e2etest;
import static androidx.media3.common.util.Assertions.checkNotNull; import static androidx.media3.common.util.Assertions.checkNotNull;
import static androidx.media3.test.utils.robolectric.TestPlayerRunHelper.run;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import android.content.Context; import android.content.Context;
import android.graphics.SurfaceTexture; import android.graphics.SurfaceTexture;
import android.net.Uri;
import android.view.Surface; import android.view.Surface;
import androidx.annotation.Nullable;
import androidx.media3.common.MediaItem; import androidx.media3.common.MediaItem;
import androidx.media3.common.ParserException;
import androidx.media3.common.Player; import androidx.media3.common.Player;
import androidx.media3.datasource.DataSource; import androidx.media3.datasource.DataSource;
import androidx.media3.datasource.DefaultDataSource; import androidx.media3.datasource.DefaultDataSource;
import androidx.media3.datasource.ResolvingDataSource;
import androidx.media3.exoplayer.DecoderCounters; import androidx.media3.exoplayer.DecoderCounters;
import androidx.media3.exoplayer.ExoPlayer; import androidx.media3.exoplayer.ExoPlayer;
import androidx.media3.exoplayer.Renderer; import androidx.media3.exoplayer.Renderer;
import androidx.media3.exoplayer.RenderersFactory; import androidx.media3.exoplayer.RenderersFactory;
import androidx.media3.exoplayer.analytics.AnalyticsListener;
import androidx.media3.exoplayer.dash.DashMediaSource; import androidx.media3.exoplayer.dash.DashMediaSource;
import androidx.media3.exoplayer.dash.DefaultDashChunkSource; import androidx.media3.exoplayer.dash.DefaultDashChunkSource;
import androidx.media3.exoplayer.metadata.MetadataDecoderFactory; import androidx.media3.exoplayer.metadata.MetadataDecoderFactory;
import androidx.media3.exoplayer.metadata.MetadataRenderer; import androidx.media3.exoplayer.metadata.MetadataRenderer;
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory;
import androidx.media3.exoplayer.source.LoadEventInfo;
import androidx.media3.exoplayer.source.MediaLoadData;
import androidx.media3.exoplayer.source.chunk.BundledChunkExtractor; import androidx.media3.exoplayer.source.chunk.BundledChunkExtractor;
import androidx.media3.exoplayer.trackselection.DefaultTrackSelector; import androidx.media3.exoplayer.trackselection.DefaultTrackSelector;
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;
import androidx.media3.test.utils.ThrowingSubtitleParserFactory;
import androidx.media3.test.utils.robolectric.PlaybackOutput; import androidx.media3.test.utils.robolectric.PlaybackOutput;
import androidx.media3.test.utils.robolectric.ShadowMediaCodecConfig; import androidx.media3.test.utils.robolectric.ShadowMediaCodecConfig;
import androidx.media3.test.utils.robolectric.TestPlayerRunHelper; import androidx.media3.test.utils.robolectric.TestPlayerRunHelper;
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 java.io.IOException;
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;
@ -81,6 +92,88 @@ public final class DashPlaybackTest {
applicationContext, playbackOutput, "playbackdumps/dash/standalone-webvtt.dump"); applicationContext, playbackOutput, "playbackdumps/dash/standalone-webvtt.dump");
} }
@Test
public void webvttStandaloneFile_loadError_playbackContinuesErrorReported() throws Exception {
Context applicationContext = ApplicationProvider.getApplicationContext();
CapturingRenderersFactory capturingRenderersFactory =
new CapturingRenderersFactory(applicationContext);
ResolvingDataSource.Factory webvttNotFoundDataSourceFactory =
new ResolvingDataSource.Factory(
new DefaultDataSource.Factory(applicationContext),
dataSpec ->
dataSpec.uri.getPath().endsWith(".vtt")
? dataSpec.buildUpon().setUri("asset:///file/not/found").build()
: dataSpec);
ExoPlayer player =
new ExoPlayer.Builder(applicationContext, capturingRenderersFactory)
.setClock(new FakeClock(/* isAutoAdvancing= */ true))
.setMediaSourceFactory(new DefaultMediaSourceFactory(webvttNotFoundDataSourceFactory))
.build();
Surface surface = new Surface(new SurfaceTexture(/* texName= */ 1));
player.setVideoSurface(surface);
AnalyticsListenerImpl analyticsListener = new AnalyticsListenerImpl();
player.addAnalyticsListener(analyticsListener);
PlaybackOutput playbackOutput = PlaybackOutput.register(player, capturingRenderersFactory);
// Ensure the subtitle track is selected.
DefaultTrackSelector trackSelector =
checkNotNull((DefaultTrackSelector) player.getTrackSelector());
trackSelector.setParameters(trackSelector.buildUponParameters().setPreferredTextLanguage("en"));
player.setMediaItem(MediaItem.fromUri("asset:///media/dash/standalone-webvtt/sample.mpd"));
player.prepare();
player.play();
run(player).ignoringNonFatalErrors().untilState(Player.STATE_ENDED);
player.release();
surface.release();
assertThat(analyticsListener.loadErrorEventInfo.uri)
.isEqualTo(Uri.parse("asset:///file/not/found"));
DumpFileAsserts.assertOutput(
applicationContext, playbackOutput, "playbackdumps/dash/standalone-webvtt_load-error.dump");
}
@Test
public void webvttStandaloneFile_parseError_playbackContinuesErrorReported() throws Exception {
Context applicationContext = ApplicationProvider.getApplicationContext();
CapturingRenderersFactory capturingRenderersFactory =
new CapturingRenderersFactory(applicationContext);
ExoPlayer player =
new ExoPlayer.Builder(applicationContext, capturingRenderersFactory)
.setClock(new FakeClock(/* isAutoAdvancing= */ true))
.setMediaSourceFactory(
new DefaultMediaSourceFactory(applicationContext)
.setSubtitleParserFactory(
new ThrowingSubtitleParserFactory(
() -> new IllegalStateException("test subtitle parsing error"))))
.build();
Surface surface = new Surface(new SurfaceTexture(/* texName= */ 1));
player.setVideoSurface(surface);
AnalyticsListenerImpl analyticsListener = new AnalyticsListenerImpl();
player.addAnalyticsListener(analyticsListener);
PlaybackOutput playbackOutput = PlaybackOutput.register(player, capturingRenderersFactory);
// Ensure the subtitle track is selected.
DefaultTrackSelector trackSelector =
checkNotNull((DefaultTrackSelector) player.getTrackSelector());
trackSelector.setParameters(trackSelector.buildUponParameters().setPreferredTextLanguage("en"));
player.setMediaItem(MediaItem.fromUri("asset:///media/dash/standalone-webvtt/sample.mpd"));
player.prepare();
player.play();
run(player).ignoringNonFatalErrors().untilState(Player.STATE_ENDED);
player.release();
surface.release();
assertThat(analyticsListener.loadError).isInstanceOf(ParserException.class);
assertThat(analyticsListener.loadError)
.hasCauseThat()
.hasMessageThat()
.isEqualTo("test subtitle parsing error");
DumpFileAsserts.assertOutput(
applicationContext,
playbackOutput,
"playbackdumps/dash/standalone-webvtt_parse-error.dump");
}
@Test @Test
public void ttmlStandaloneXmlFile() throws Exception { public void ttmlStandaloneXmlFile() throws Exception {
Context applicationContext = ApplicationProvider.getApplicationContext(); Context applicationContext = ApplicationProvider.getApplicationContext();
@ -160,6 +253,85 @@ public final class DashPlaybackTest {
applicationContext, playbackOutput, "playbackdumps/dash/ttml-in-mp4.dump"); applicationContext, playbackOutput, "playbackdumps/dash/ttml-in-mp4.dump");
} }
@Test
public void ttmlInMp4_loadError_playbackContinuesErrorReported() throws Exception {
Context applicationContext = ApplicationProvider.getApplicationContext();
CapturingRenderersFactory capturingRenderersFactory =
new CapturingRenderersFactory(applicationContext);
ResolvingDataSource.Factory ttmlNotFoundDataSourceFactory =
new ResolvingDataSource.Factory(
new DefaultDataSource.Factory(applicationContext),
dataSpec ->
dataSpec.uri.getPath().endsWith(".text.mp4")
? dataSpec.buildUpon().setUri("asset:///file/not/found").build()
: dataSpec);
ExoPlayer player =
new ExoPlayer.Builder(applicationContext, capturingRenderersFactory)
.setClock(new FakeClock(/* isAutoAdvancing= */ true))
.setMediaSourceFactory(new DefaultMediaSourceFactory(ttmlNotFoundDataSourceFactory))
.build();
Surface surface = new Surface(new SurfaceTexture(/* texName= */ 1));
player.setVideoSurface(surface);
AnalyticsListenerImpl analyticsListener = new AnalyticsListenerImpl();
player.addAnalyticsListener(analyticsListener);
PlaybackOutput playbackOutput = PlaybackOutput.register(player, capturingRenderersFactory);
// Ensure the subtitle track is selected.
DefaultTrackSelector trackSelector =
checkNotNull((DefaultTrackSelector) player.getTrackSelector());
trackSelector.setParameters(trackSelector.buildUponParameters().setPreferredTextLanguage("en"));
player.setMediaItem(MediaItem.fromUri("asset:///media/dash/ttml-in-mp4/sample.mpd"));
player.prepare();
player.play();
run(player).ignoringNonFatalErrors().untilState(Player.STATE_ENDED);
player.release();
surface.release();
assertThat(analyticsListener.loadErrorEventInfo.uri)
.isEqualTo(Uri.parse("asset:///file/not/found"));
DumpFileAsserts.assertOutput(
applicationContext, playbackOutput, "playbackdumps/dash/ttml-in-mp4_load-error.dump");
}
@Test
public void ttmlInMp4_parseError_playbackContinuesErrorReported() throws Exception {
Context applicationContext = ApplicationProvider.getApplicationContext();
CapturingRenderersFactory capturingRenderersFactory =
new CapturingRenderersFactory(applicationContext);
ExoPlayer player =
new ExoPlayer.Builder(applicationContext, capturingRenderersFactory)
.setClock(new FakeClock(/* isAutoAdvancing= */ true))
.setMediaSourceFactory(
new DefaultMediaSourceFactory(applicationContext)
.setSubtitleParserFactory(
new ThrowingSubtitleParserFactory(
() -> new IllegalStateException("test subtitle parsing error"))))
.build();
Surface surface = new Surface(new SurfaceTexture(/* texName= */ 1));
player.setVideoSurface(surface);
AnalyticsListenerImpl analyticsListener = new AnalyticsListenerImpl();
player.addAnalyticsListener(analyticsListener);
PlaybackOutput playbackOutput = PlaybackOutput.register(player, capturingRenderersFactory);
// Ensure the subtitle track is selected.
DefaultTrackSelector trackSelector =
checkNotNull((DefaultTrackSelector) player.getTrackSelector());
trackSelector.setParameters(trackSelector.buildUponParameters().setPreferredTextLanguage("en"));
player.setMediaItem(MediaItem.fromUri("asset:///media/dash/ttml-in-mp4/sample.mpd"));
player.prepare();
player.play();
run(player).ignoringNonFatalErrors().untilState(Player.STATE_ENDED);
player.release();
surface.release();
assertThat(analyticsListener.loadError)
.hasCauseThat()
.hasMessageThat()
.isEqualTo("test subtitle parsing error");
DumpFileAsserts.assertOutput(
applicationContext, playbackOutput, "playbackdumps/dash/ttml-in-mp4_parse-error.dump");
}
/** /**
* This test and {@link #cea608_parseDuringExtraction()} use the same output dump file, to * This test and {@link #cea608_parseDuringExtraction()} use the same output dump file, to
* demonstrate the flag has no effect on the resulting subtitles. * demonstrate the flag has no effect on the resulting subtitles.
@ -461,4 +633,21 @@ public final class DashPlaybackTest {
DumpFileAsserts.assertOutput( DumpFileAsserts.assertOutput(
applicationContext, playbackOutput, "playbackdumps/dash/multi-period-with-offset.dump"); applicationContext, playbackOutput, "playbackdumps/dash/multi-period-with-offset.dump");
} }
private static class AnalyticsListenerImpl implements AnalyticsListener {
@Nullable private LoadEventInfo loadErrorEventInfo;
@Nullable private IOException loadError;
@Override
public void onLoadError(
EventTime eventTime,
LoadEventInfo loadEventInfo,
MediaLoadData mediaLoadData,
IOException error,
boolean wasCanceled) {
this.loadErrorEventInfo = loadEventInfo;
this.loadError = error;
}
}
} }

View File

@ -16,26 +16,37 @@
package androidx.media3.exoplayer.hls.e2etest; package androidx.media3.exoplayer.hls.e2etest;
import static androidx.media3.test.utils.robolectric.TestPlayerRunHelper.run;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context; import android.content.Context;
import android.graphics.SurfaceTexture; import android.graphics.SurfaceTexture;
import android.net.Uri;
import android.view.Surface; import android.view.Surface;
import androidx.annotation.Nullable;
import androidx.media3.common.MediaItem; import androidx.media3.common.MediaItem;
import androidx.media3.common.Player; import androidx.media3.common.Player;
import androidx.media3.datasource.DefaultDataSource; import androidx.media3.datasource.DefaultDataSource;
import androidx.media3.datasource.ResolvingDataSource;
import androidx.media3.exoplayer.DefaultLoadControl; import androidx.media3.exoplayer.DefaultLoadControl;
import androidx.media3.exoplayer.ExoPlayer; import androidx.media3.exoplayer.ExoPlayer;
import androidx.media3.exoplayer.SeekParameters; import androidx.media3.exoplayer.SeekParameters;
import androidx.media3.exoplayer.analytics.AnalyticsListener;
import androidx.media3.exoplayer.hls.HlsMediaSource; import androidx.media3.exoplayer.hls.HlsMediaSource;
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory; import androidx.media3.exoplayer.source.DefaultMediaSourceFactory;
import androidx.media3.exoplayer.source.LoadEventInfo;
import androidx.media3.exoplayer.source.MediaLoadData;
import androidx.media3.exoplayer.upstream.CmcdConfiguration; import androidx.media3.exoplayer.upstream.CmcdConfiguration;
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;
import androidx.media3.test.utils.ThrowingSubtitleParserFactory;
import androidx.media3.test.utils.robolectric.PlaybackOutput; import androidx.media3.test.utils.robolectric.PlaybackOutput;
import androidx.media3.test.utils.robolectric.ShadowMediaCodecConfig; import androidx.media3.test.utils.robolectric.ShadowMediaCodecConfig;
import androidx.media3.test.utils.robolectric.TestPlayerRunHelper; import androidx.media3.test.utils.robolectric.TestPlayerRunHelper;
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 java.io.IOException;
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;
@ -71,6 +82,81 @@ public final class HlsPlaybackTest {
applicationContext, playbackOutput, "playbackdumps/hls/standalone-webvtt.dump"); applicationContext, playbackOutput, "playbackdumps/hls/standalone-webvtt.dump");
} }
@Test
public void webvttStandaloneSubtitles_loadError_playbackContinuesErrorReported()
throws Exception {
Context applicationContext = ApplicationProvider.getApplicationContext();
CapturingRenderersFactory capturingRenderersFactory =
new CapturingRenderersFactory(applicationContext);
ResolvingDataSource.Factory webvttNotFoundDataSourceFactory =
new ResolvingDataSource.Factory(
new DefaultDataSource.Factory(applicationContext),
dataSpec ->
dataSpec.uri.getPath().endsWith(".vtt")
? dataSpec.buildUpon().setUri("asset:///file/not/found").build()
: dataSpec);
ExoPlayer player =
new ExoPlayer.Builder(applicationContext, capturingRenderersFactory)
.setMediaSourceFactory(new DefaultMediaSourceFactory(webvttNotFoundDataSourceFactory))
.setClock(new FakeClock(/* isAutoAdvancing= */ true))
.build();
Surface surface = new Surface(new SurfaceTexture(/* texName= */ 1));
player.setVideoSurface(surface);
AnalyticsListenerImpl analyticsListener = new AnalyticsListenerImpl();
player.addAnalyticsListener(analyticsListener);
PlaybackOutput playbackOutput = PlaybackOutput.register(player, capturingRenderersFactory);
player.setMediaItem(
MediaItem.fromUri("asset:///media/hls/standalone-webvtt/multivariant_playlist.m3u8"));
player.prepare();
player.play();
run(player).ignoringNonFatalErrors().untilState(Player.STATE_ENDED);
player.release();
surface.release();
assertThat(analyticsListener.loadErrorEventInfo.uri)
.isEqualTo(Uri.parse("asset:///file/not/found"));
DumpFileAsserts.assertOutput(
applicationContext, playbackOutput, "playbackdumps/hls/standalone-webvtt_load-error.dump");
}
@Test
public void webvttStandaloneSubtitles_parseError_playbackContinuesErrorReported()
throws Exception {
Context applicationContext = ApplicationProvider.getApplicationContext();
CapturingRenderersFactory capturingRenderersFactory =
new CapturingRenderersFactory(applicationContext);
ExoPlayer player =
new ExoPlayer.Builder(applicationContext, capturingRenderersFactory)
.setClock(new FakeClock(/* isAutoAdvancing= */ true))
.setMediaSourceFactory(
new DefaultMediaSourceFactory(applicationContext)
.setSubtitleParserFactory(
new ThrowingSubtitleParserFactory(
() -> new IllegalStateException("test subtitle parsing error"))))
.build();
Surface surface = new Surface(new SurfaceTexture(/* texName= */ 1));
player.setVideoSurface(surface);
AnalyticsListenerImpl analyticsListener = new AnalyticsListenerImpl();
player.addAnalyticsListener(analyticsListener);
PlaybackOutput playbackOutput = PlaybackOutput.register(player, capturingRenderersFactory);
player.setMediaItem(
MediaItem.fromUri("asset:///media/hls/standalone-webvtt/multivariant_playlist.m3u8"));
player.prepare();
player.play();
run(player).ignoringNonFatalErrors().untilState(Player.STATE_ENDED);
player.release();
surface.release();
assertThat(analyticsListener.loadError)
.hasCauseThat()
.hasMessageThat()
.isEqualTo("test subtitle parsing error");
DumpFileAsserts.assertOutput(
applicationContext, playbackOutput, "playbackdumps/hls/standalone-webvtt_parse-error.dump");
}
@Test @Test
public void ttmlInMp4() throws Exception { public void ttmlInMp4() throws Exception {
Context applicationContext = ApplicationProvider.getApplicationContext(); Context applicationContext = ApplicationProvider.getApplicationContext();
@ -94,6 +180,79 @@ public final class HlsPlaybackTest {
applicationContext, playbackOutput, "playbackdumps/hls/ttml-in-mp4.dump"); applicationContext, playbackOutput, "playbackdumps/hls/ttml-in-mp4.dump");
} }
@Test
public void ttmlInMp4_loadError_playbackContinuesErrorReported() throws Exception {
Context applicationContext = ApplicationProvider.getApplicationContext();
CapturingRenderersFactory capturingRenderersFactory =
new CapturingRenderersFactory(applicationContext);
ResolvingDataSource.Factory ttmlNotFoundDataSourceFactory =
new ResolvingDataSource.Factory(
new DefaultDataSource.Factory(applicationContext),
dataSpec ->
dataSpec.uri.getPath().endsWith(".text.mp4")
? dataSpec.buildUpon().setUri("asset:///file/not/found").build()
: dataSpec);
ExoPlayer player =
new ExoPlayer.Builder(applicationContext, capturingRenderersFactory)
.setClock(new FakeClock(/* isAutoAdvancing= */ true))
.setMediaSourceFactory(new DefaultMediaSourceFactory(ttmlNotFoundDataSourceFactory))
.build();
Surface surface = new Surface(new SurfaceTexture(/* texName= */ 1));
player.setVideoSurface(surface);
AnalyticsListenerImpl analyticsListener = new AnalyticsListenerImpl();
player.addAnalyticsListener(analyticsListener);
PlaybackOutput playbackOutput = PlaybackOutput.register(player, capturingRenderersFactory);
player.setMediaItem(
MediaItem.fromUri("asset:///media/hls/ttml-in-mp4/multivariant_playlist.m3u8"));
player.prepare();
player.play();
run(player).ignoringNonFatalErrors().untilState(Player.STATE_ENDED);
player.release();
surface.release();
assertThat(analyticsListener.loadErrorEventInfo.uri)
.isEqualTo(Uri.parse("asset:///file/not/found"));
DumpFileAsserts.assertOutput(
applicationContext, playbackOutput, "playbackdumps/hls/ttml-in-mp4_load-error.dump");
}
@Test
public void ttmlInMp4_parseError_playbackContinuesErrorReported() throws Exception {
Context applicationContext = ApplicationProvider.getApplicationContext();
CapturingRenderersFactory capturingRenderersFactory =
new CapturingRenderersFactory(applicationContext);
ExoPlayer player =
new ExoPlayer.Builder(applicationContext, capturingRenderersFactory)
.setClock(new FakeClock(/* isAutoAdvancing= */ true))
.setMediaSourceFactory(
new DefaultMediaSourceFactory(applicationContext)
.setSubtitleParserFactory(
new ThrowingSubtitleParserFactory(
() -> new IllegalStateException("test subtitle parsing error"))))
.build();
Surface surface = new Surface(new SurfaceTexture(/* texName= */ 1));
player.setVideoSurface(surface);
AnalyticsListenerImpl analyticsListener = new AnalyticsListenerImpl();
player.addAnalyticsListener(analyticsListener);
PlaybackOutput playbackOutput = PlaybackOutput.register(player, capturingRenderersFactory);
player.setMediaItem(
MediaItem.fromUri("asset:///media/hls/ttml-in-mp4/multivariant_playlist.m3u8"));
player.prepare();
player.play();
run(player).ignoringNonFatalErrors().untilState(Player.STATE_ENDED);
player.release();
surface.release();
assertThat(analyticsListener.loadError)
.hasCauseThat()
.hasMessageThat()
.isEqualTo("test subtitle parsing error");
DumpFileAsserts.assertOutput(
applicationContext, playbackOutput, "playbackdumps/hls/ttml-in-mp4_parse-error.dump");
}
/** /**
* This test and {@link #cea608_parseDuringExtraction()} use the same output dump file, to * This test and {@link #cea608_parseDuringExtraction()} use the same output dump file, to
* demonstrate the flag has no effect on the resulting subtitles. * demonstrate the flag has no effect on the resulting subtitles.
@ -221,4 +380,21 @@ public final class HlsPlaybackTest {
playbackOutput, playbackOutput,
"playbackdumps/hls/cmcd-enabled-with-init-segment.dump"); "playbackdumps/hls/cmcd-enabled-with-init-segment.dump");
} }
private static class AnalyticsListenerImpl implements AnalyticsListener {
@Nullable private LoadEventInfo loadErrorEventInfo;
@Nullable private IOException loadError;
@Override
public void onLoadError(
EventTime eventTime,
LoadEventInfo loadEventInfo,
MediaLoadData mediaLoadData,
IOException error,
boolean wasCanceled) {
this.loadErrorEventInfo = loadEventInfo;
this.loadError = error;
}
}
} }

View File

@ -0,0 +1,226 @@
MediaCodecAdapter (exotest.video.avc):
inputBuffers:
count = 31
input buffer #0:
timeUs = 1000000000000
contents = length 36692, hash D216076E
input buffer #1:
timeUs = 1000000066733
contents = length 5312, hash D45D3CA0
input buffer #2:
timeUs = 1000000033366
contents = length 599, hash 1BE7812D
input buffer #3:
timeUs = 1000000200200
contents = length 7735, hash 4490F110
input buffer #4:
timeUs = 1000000133466
contents = length 987, hash 560B5036
input buffer #5:
timeUs = 1000000100100
contents = length 673, hash ED7CD8C7
input buffer #6:
timeUs = 1000000166833
contents = length 523, hash 3020DF50
input buffer #7:
timeUs = 1000000333666
contents = length 6061, hash 736C72B2
input buffer #8:
timeUs = 1000000266933
contents = length 992, hash FE132F23
input buffer #9:
timeUs = 1000000233566
contents = length 623, hash 5B2C1816
input buffer #10:
timeUs = 1000000300300
contents = length 421, hash 742E69C1
input buffer #11:
timeUs = 1000000433766
contents = length 4899, hash F72F86A1
input buffer #12:
timeUs = 1000000400400
contents = length 568, hash 519A8E50
input buffer #13:
timeUs = 1000000367033
contents = length 620, hash 3990AA39
input buffer #14:
timeUs = 1000000567233
contents = length 5450, hash F06EC4AA
input buffer #15:
timeUs = 1000000500500
contents = length 1051, hash 92DFA63A
input buffer #16:
timeUs = 1000000467133
contents = length 874, hash 69587FB4
input buffer #17:
timeUs = 1000000533866
contents = length 781, hash 36BE495B
input buffer #18:
timeUs = 1000000700700
contents = length 4725, hash AC0C8CD3
input buffer #19:
timeUs = 1000000633966
contents = length 1022, hash 5D8BFF34
input buffer #20:
timeUs = 1000000600600
contents = length 790, hash 99413A99
input buffer #21:
timeUs = 1000000667333
contents = length 610, hash 5E129290
input buffer #22:
timeUs = 1000000834166
contents = length 2751, hash 769974CB
input buffer #23:
timeUs = 1000000767433
contents = length 745, hash B78A477A
input buffer #24:
timeUs = 1000000734066
contents = length 621, hash CF741E7A
input buffer #25:
timeUs = 1000000800800
contents = length 505, hash 1DB4894E
input buffer #26:
timeUs = 1000000967633
contents = length 1268, hash C15348DC
input buffer #27:
timeUs = 1000000900900
contents = length 880, hash C2DE85D0
input buffer #28:
timeUs = 1000000867533
contents = length 530, hash C98BC6A8
input buffer #29:
timeUs = 1000000934266
contents = length 568, hash 4FE5C8EA
input buffer #30:
timeUs = 0
flags = 4
contents = length 0, hash 1
outputBuffers:
count = 30
output buffer #0:
timeUs = 1000000000000
size = 36692
rendered = true
output buffer #1:
timeUs = 1000000066733
size = 5312
rendered = true
output buffer #2:
timeUs = 1000000033366
size = 599
rendered = true
output buffer #3:
timeUs = 1000000200200
size = 7735
rendered = true
output buffer #4:
timeUs = 1000000133466
size = 987
rendered = true
output buffer #5:
timeUs = 1000000100100
size = 673
rendered = true
output buffer #6:
timeUs = 1000000166833
size = 523
rendered = true
output buffer #7:
timeUs = 1000000333666
size = 6061
rendered = true
output buffer #8:
timeUs = 1000000266933
size = 992
rendered = true
output buffer #9:
timeUs = 1000000233566
size = 623
rendered = true
output buffer #10:
timeUs = 1000000300300
size = 421
rendered = true
output buffer #11:
timeUs = 1000000433766
size = 4899
rendered = true
output buffer #12:
timeUs = 1000000400400
size = 568
rendered = true
output buffer #13:
timeUs = 1000000367033
size = 620
rendered = true
output buffer #14:
timeUs = 1000000567233
size = 5450
rendered = true
output buffer #15:
timeUs = 1000000500500
size = 1051
rendered = true
output buffer #16:
timeUs = 1000000467133
size = 874
rendered = true
output buffer #17:
timeUs = 1000000533866
size = 781
rendered = true
output buffer #18:
timeUs = 1000000700700
size = 4725
rendered = true
output buffer #19:
timeUs = 1000000633966
size = 1022
rendered = true
output buffer #20:
timeUs = 1000000600600
size = 790
rendered = true
output buffer #21:
timeUs = 1000000667333
size = 610
rendered = true
output buffer #22:
timeUs = 1000000834166
size = 2751
rendered = true
output buffer #23:
timeUs = 1000000767433
size = 745
rendered = true
output buffer #24:
timeUs = 1000000734066
size = 621
rendered = true
output buffer #25:
timeUs = 1000000800800
size = 505
rendered = true
output buffer #26:
timeUs = 1000000967633
size = 1268
rendered = true
output buffer #27:
timeUs = 1000000900900
size = 880
rendered = true
output buffer #28:
timeUs = 1000000867533
size = 530
rendered = true
output buffer #29:
timeUs = 1000000934266
size = 568
rendered = true
TextOutput:
Subtitle[0]:
presentationTimeUs = 0
Cues = []
Subtitle[1]:
presentationTimeUs = 0
Cues = []

View File

@ -0,0 +1,226 @@
MediaCodecAdapter (exotest.video.avc):
inputBuffers:
count = 31
input buffer #0:
timeUs = 1000000000000
contents = length 36692, hash D216076E
input buffer #1:
timeUs = 1000000066733
contents = length 5312, hash D45D3CA0
input buffer #2:
timeUs = 1000000033366
contents = length 599, hash 1BE7812D
input buffer #3:
timeUs = 1000000200200
contents = length 7735, hash 4490F110
input buffer #4:
timeUs = 1000000133466
contents = length 987, hash 560B5036
input buffer #5:
timeUs = 1000000100100
contents = length 673, hash ED7CD8C7
input buffer #6:
timeUs = 1000000166833
contents = length 523, hash 3020DF50
input buffer #7:
timeUs = 1000000333666
contents = length 6061, hash 736C72B2
input buffer #8:
timeUs = 1000000266933
contents = length 992, hash FE132F23
input buffer #9:
timeUs = 1000000233566
contents = length 623, hash 5B2C1816
input buffer #10:
timeUs = 1000000300300
contents = length 421, hash 742E69C1
input buffer #11:
timeUs = 1000000433766
contents = length 4899, hash F72F86A1
input buffer #12:
timeUs = 1000000400400
contents = length 568, hash 519A8E50
input buffer #13:
timeUs = 1000000367033
contents = length 620, hash 3990AA39
input buffer #14:
timeUs = 1000000567233
contents = length 5450, hash F06EC4AA
input buffer #15:
timeUs = 1000000500500
contents = length 1051, hash 92DFA63A
input buffer #16:
timeUs = 1000000467133
contents = length 874, hash 69587FB4
input buffer #17:
timeUs = 1000000533866
contents = length 781, hash 36BE495B
input buffer #18:
timeUs = 1000000700700
contents = length 4725, hash AC0C8CD3
input buffer #19:
timeUs = 1000000633966
contents = length 1022, hash 5D8BFF34
input buffer #20:
timeUs = 1000000600600
contents = length 790, hash 99413A99
input buffer #21:
timeUs = 1000000667333
contents = length 610, hash 5E129290
input buffer #22:
timeUs = 1000000834166
contents = length 2751, hash 769974CB
input buffer #23:
timeUs = 1000000767433
contents = length 745, hash B78A477A
input buffer #24:
timeUs = 1000000734066
contents = length 621, hash CF741E7A
input buffer #25:
timeUs = 1000000800800
contents = length 505, hash 1DB4894E
input buffer #26:
timeUs = 1000000967633
contents = length 1268, hash C15348DC
input buffer #27:
timeUs = 1000000900900
contents = length 880, hash C2DE85D0
input buffer #28:
timeUs = 1000000867533
contents = length 530, hash C98BC6A8
input buffer #29:
timeUs = 1000000934266
contents = length 568, hash 4FE5C8EA
input buffer #30:
timeUs = 0
flags = 4
contents = length 0, hash 1
outputBuffers:
count = 30
output buffer #0:
timeUs = 1000000000000
size = 36692
rendered = true
output buffer #1:
timeUs = 1000000066733
size = 5312
rendered = true
output buffer #2:
timeUs = 1000000033366
size = 599
rendered = true
output buffer #3:
timeUs = 1000000200200
size = 7735
rendered = true
output buffer #4:
timeUs = 1000000133466
size = 987
rendered = true
output buffer #5:
timeUs = 1000000100100
size = 673
rendered = true
output buffer #6:
timeUs = 1000000166833
size = 523
rendered = true
output buffer #7:
timeUs = 1000000333666
size = 6061
rendered = true
output buffer #8:
timeUs = 1000000266933
size = 992
rendered = true
output buffer #9:
timeUs = 1000000233566
size = 623
rendered = true
output buffer #10:
timeUs = 1000000300300
size = 421
rendered = true
output buffer #11:
timeUs = 1000000433766
size = 4899
rendered = true
output buffer #12:
timeUs = 1000000400400
size = 568
rendered = true
output buffer #13:
timeUs = 1000000367033
size = 620
rendered = true
output buffer #14:
timeUs = 1000000567233
size = 5450
rendered = true
output buffer #15:
timeUs = 1000000500500
size = 1051
rendered = true
output buffer #16:
timeUs = 1000000467133
size = 874
rendered = true
output buffer #17:
timeUs = 1000000533866
size = 781
rendered = true
output buffer #18:
timeUs = 1000000700700
size = 4725
rendered = true
output buffer #19:
timeUs = 1000000633966
size = 1022
rendered = true
output buffer #20:
timeUs = 1000000600600
size = 790
rendered = true
output buffer #21:
timeUs = 1000000667333
size = 610
rendered = true
output buffer #22:
timeUs = 1000000834166
size = 2751
rendered = true
output buffer #23:
timeUs = 1000000767433
size = 745
rendered = true
output buffer #24:
timeUs = 1000000734066
size = 621
rendered = true
output buffer #25:
timeUs = 1000000800800
size = 505
rendered = true
output buffer #26:
timeUs = 1000000967633
size = 1268
rendered = true
output buffer #27:
timeUs = 1000000900900
size = 880
rendered = true
output buffer #28:
timeUs = 1000000867533
size = 530
rendered = true
output buffer #29:
timeUs = 1000000934266
size = 568
rendered = true
TextOutput:
Subtitle[0]:
presentationTimeUs = 0
Cues = []
Subtitle[1]:
presentationTimeUs = 0
Cues = []

View File

@ -0,0 +1,226 @@
MediaCodecAdapter (exotest.video.avc):
inputBuffers:
count = 31
input buffer #0:
timeUs = 1000000000000
contents = length 36692, hash D216076E
input buffer #1:
timeUs = 1000000066733
contents = length 5312, hash D45D3CA0
input buffer #2:
timeUs = 1000000033366
contents = length 599, hash 1BE7812D
input buffer #3:
timeUs = 1000000200200
contents = length 7735, hash 4490F110
input buffer #4:
timeUs = 1000000133466
contents = length 987, hash 560B5036
input buffer #5:
timeUs = 1000000100100
contents = length 673, hash ED7CD8C7
input buffer #6:
timeUs = 1000000166833
contents = length 523, hash 3020DF50
input buffer #7:
timeUs = 1000000333666
contents = length 6061, hash 736C72B2
input buffer #8:
timeUs = 1000000266933
contents = length 992, hash FE132F23
input buffer #9:
timeUs = 1000000233566
contents = length 623, hash 5B2C1816
input buffer #10:
timeUs = 1000000300300
contents = length 421, hash 742E69C1
input buffer #11:
timeUs = 1000000433766
contents = length 4899, hash F72F86A1
input buffer #12:
timeUs = 1000000400400
contents = length 568, hash 519A8E50
input buffer #13:
timeUs = 1000000367033
contents = length 620, hash 3990AA39
input buffer #14:
timeUs = 1000000567233
contents = length 5450, hash F06EC4AA
input buffer #15:
timeUs = 1000000500500
contents = length 1051, hash 92DFA63A
input buffer #16:
timeUs = 1000000467133
contents = length 874, hash 69587FB4
input buffer #17:
timeUs = 1000000533866
contents = length 781, hash 36BE495B
input buffer #18:
timeUs = 1000000700700
contents = length 4725, hash AC0C8CD3
input buffer #19:
timeUs = 1000000633966
contents = length 1022, hash 5D8BFF34
input buffer #20:
timeUs = 1000000600600
contents = length 790, hash 99413A99
input buffer #21:
timeUs = 1000000667333
contents = length 610, hash 5E129290
input buffer #22:
timeUs = 1000000834166
contents = length 2751, hash 769974CB
input buffer #23:
timeUs = 1000000767433
contents = length 745, hash B78A477A
input buffer #24:
timeUs = 1000000734066
contents = length 621, hash CF741E7A
input buffer #25:
timeUs = 1000000800800
contents = length 505, hash 1DB4894E
input buffer #26:
timeUs = 1000000967633
contents = length 1268, hash C15348DC
input buffer #27:
timeUs = 1000000900900
contents = length 880, hash C2DE85D0
input buffer #28:
timeUs = 1000000867533
contents = length 530, hash C98BC6A8
input buffer #29:
timeUs = 1000000934266
contents = length 568, hash 4FE5C8EA
input buffer #30:
timeUs = 0
flags = 4
contents = length 0, hash 1
outputBuffers:
count = 30
output buffer #0:
timeUs = 1000000000000
size = 36692
rendered = true
output buffer #1:
timeUs = 1000000066733
size = 5312
rendered = true
output buffer #2:
timeUs = 1000000033366
size = 599
rendered = true
output buffer #3:
timeUs = 1000000200200
size = 7735
rendered = true
output buffer #4:
timeUs = 1000000133466
size = 987
rendered = true
output buffer #5:
timeUs = 1000000100100
size = 673
rendered = true
output buffer #6:
timeUs = 1000000166833
size = 523
rendered = true
output buffer #7:
timeUs = 1000000333666
size = 6061
rendered = true
output buffer #8:
timeUs = 1000000266933
size = 992
rendered = true
output buffer #9:
timeUs = 1000000233566
size = 623
rendered = true
output buffer #10:
timeUs = 1000000300300
size = 421
rendered = true
output buffer #11:
timeUs = 1000000433766
size = 4899
rendered = true
output buffer #12:
timeUs = 1000000400400
size = 568
rendered = true
output buffer #13:
timeUs = 1000000367033
size = 620
rendered = true
output buffer #14:
timeUs = 1000000567233
size = 5450
rendered = true
output buffer #15:
timeUs = 1000000500500
size = 1051
rendered = true
output buffer #16:
timeUs = 1000000467133
size = 874
rendered = true
output buffer #17:
timeUs = 1000000533866
size = 781
rendered = true
output buffer #18:
timeUs = 1000000700700
size = 4725
rendered = true
output buffer #19:
timeUs = 1000000633966
size = 1022
rendered = true
output buffer #20:
timeUs = 1000000600600
size = 790
rendered = true
output buffer #21:
timeUs = 1000000667333
size = 610
rendered = true
output buffer #22:
timeUs = 1000000834166
size = 2751
rendered = true
output buffer #23:
timeUs = 1000000767433
size = 745
rendered = true
output buffer #24:
timeUs = 1000000734066
size = 621
rendered = true
output buffer #25:
timeUs = 1000000800800
size = 505
rendered = true
output buffer #26:
timeUs = 1000000967633
size = 1268
rendered = true
output buffer #27:
timeUs = 1000000900900
size = 880
rendered = true
output buffer #28:
timeUs = 1000000867533
size = 530
rendered = true
output buffer #29:
timeUs = 1000000934266
size = 568
rendered = true
TextOutput:
Subtitle[0]:
presentationTimeUs = 0
Cues = []
Subtitle[1]:
presentationTimeUs = 0
Cues = []

View File

@ -0,0 +1,226 @@
MediaCodecAdapter (exotest.video.avc):
inputBuffers:
count = 31
input buffer #0:
timeUs = 1000000000000
contents = length 36692, hash D216076E
input buffer #1:
timeUs = 1000000066733
contents = length 5312, hash D45D3CA0
input buffer #2:
timeUs = 1000000033366
contents = length 599, hash 1BE7812D
input buffer #3:
timeUs = 1000000200200
contents = length 7735, hash 4490F110
input buffer #4:
timeUs = 1000000133466
contents = length 987, hash 560B5036
input buffer #5:
timeUs = 1000000100100
contents = length 673, hash ED7CD8C7
input buffer #6:
timeUs = 1000000166833
contents = length 523, hash 3020DF50
input buffer #7:
timeUs = 1000000333666
contents = length 6061, hash 736C72B2
input buffer #8:
timeUs = 1000000266933
contents = length 992, hash FE132F23
input buffer #9:
timeUs = 1000000233566
contents = length 623, hash 5B2C1816
input buffer #10:
timeUs = 1000000300300
contents = length 421, hash 742E69C1
input buffer #11:
timeUs = 1000000433766
contents = length 4899, hash F72F86A1
input buffer #12:
timeUs = 1000000400400
contents = length 568, hash 519A8E50
input buffer #13:
timeUs = 1000000367033
contents = length 620, hash 3990AA39
input buffer #14:
timeUs = 1000000567233
contents = length 5450, hash F06EC4AA
input buffer #15:
timeUs = 1000000500500
contents = length 1051, hash 92DFA63A
input buffer #16:
timeUs = 1000000467133
contents = length 874, hash 69587FB4
input buffer #17:
timeUs = 1000000533866
contents = length 781, hash 36BE495B
input buffer #18:
timeUs = 1000000700700
contents = length 4725, hash AC0C8CD3
input buffer #19:
timeUs = 1000000633966
contents = length 1022, hash 5D8BFF34
input buffer #20:
timeUs = 1000000600600
contents = length 790, hash 99413A99
input buffer #21:
timeUs = 1000000667333
contents = length 610, hash 5E129290
input buffer #22:
timeUs = 1000000834166
contents = length 2751, hash 769974CB
input buffer #23:
timeUs = 1000000767433
contents = length 745, hash B78A477A
input buffer #24:
timeUs = 1000000734066
contents = length 621, hash CF741E7A
input buffer #25:
timeUs = 1000000800800
contents = length 505, hash 1DB4894E
input buffer #26:
timeUs = 1000000967633
contents = length 1268, hash C15348DC
input buffer #27:
timeUs = 1000000900900
contents = length 880, hash C2DE85D0
input buffer #28:
timeUs = 1000000867533
contents = length 530, hash C98BC6A8
input buffer #29:
timeUs = 1000000934266
contents = length 568, hash 4FE5C8EA
input buffer #30:
timeUs = 0
flags = 4
contents = length 0, hash 1
outputBuffers:
count = 30
output buffer #0:
timeUs = 1000000000000
size = 36692
rendered = true
output buffer #1:
timeUs = 1000000066733
size = 5312
rendered = true
output buffer #2:
timeUs = 1000000033366
size = 599
rendered = true
output buffer #3:
timeUs = 1000000200200
size = 7735
rendered = true
output buffer #4:
timeUs = 1000000133466
size = 987
rendered = true
output buffer #5:
timeUs = 1000000100100
size = 673
rendered = true
output buffer #6:
timeUs = 1000000166833
size = 523
rendered = true
output buffer #7:
timeUs = 1000000333666
size = 6061
rendered = true
output buffer #8:
timeUs = 1000000266933
size = 992
rendered = true
output buffer #9:
timeUs = 1000000233566
size = 623
rendered = true
output buffer #10:
timeUs = 1000000300300
size = 421
rendered = true
output buffer #11:
timeUs = 1000000433766
size = 4899
rendered = true
output buffer #12:
timeUs = 1000000400400
size = 568
rendered = true
output buffer #13:
timeUs = 1000000367033
size = 620
rendered = true
output buffer #14:
timeUs = 1000000567233
size = 5450
rendered = true
output buffer #15:
timeUs = 1000000500500
size = 1051
rendered = true
output buffer #16:
timeUs = 1000000467133
size = 874
rendered = true
output buffer #17:
timeUs = 1000000533866
size = 781
rendered = true
output buffer #18:
timeUs = 1000000700700
size = 4725
rendered = true
output buffer #19:
timeUs = 1000000633966
size = 1022
rendered = true
output buffer #20:
timeUs = 1000000600600
size = 790
rendered = true
output buffer #21:
timeUs = 1000000667333
size = 610
rendered = true
output buffer #22:
timeUs = 1000000834166
size = 2751
rendered = true
output buffer #23:
timeUs = 1000000767433
size = 745
rendered = true
output buffer #24:
timeUs = 1000000734066
size = 621
rendered = true
output buffer #25:
timeUs = 1000000800800
size = 505
rendered = true
output buffer #26:
timeUs = 1000000967633
size = 1268
rendered = true
output buffer #27:
timeUs = 1000000900900
size = 880
rendered = true
output buffer #28:
timeUs = 1000000867533
size = 530
rendered = true
output buffer #29:
timeUs = 1000000934266
size = 568
rendered = true
TextOutput:
Subtitle[0]:
presentationTimeUs = 0
Cues = []
Subtitle[1]:
presentationTimeUs = 0
Cues = []

View File

@ -0,0 +1,226 @@
MediaCodecAdapter (exotest.video.avc):
inputBuffers:
count = 31
input buffer #0:
timeUs = 1000000000000
contents = length 36692, hash D216076E
input buffer #1:
timeUs = 1000000066733
contents = length 5312, hash D45D3CA0
input buffer #2:
timeUs = 1000000033366
contents = length 599, hash 1BE7812D
input buffer #3:
timeUs = 1000000200200
contents = length 7735, hash 4490F110
input buffer #4:
timeUs = 1000000133466
contents = length 987, hash 560B5036
input buffer #5:
timeUs = 1000000100100
contents = length 673, hash ED7CD8C7
input buffer #6:
timeUs = 1000000166833
contents = length 523, hash 3020DF50
input buffer #7:
timeUs = 1000000333666
contents = length 6061, hash 736C72B2
input buffer #8:
timeUs = 1000000266933
contents = length 992, hash FE132F23
input buffer #9:
timeUs = 1000000233566
contents = length 623, hash 5B2C1816
input buffer #10:
timeUs = 1000000300300
contents = length 421, hash 742E69C1
input buffer #11:
timeUs = 1000000433766
contents = length 4899, hash F72F86A1
input buffer #12:
timeUs = 1000000400400
contents = length 568, hash 519A8E50
input buffer #13:
timeUs = 1000000367033
contents = length 620, hash 3990AA39
input buffer #14:
timeUs = 1000000567233
contents = length 5450, hash F06EC4AA
input buffer #15:
timeUs = 1000000500500
contents = length 1051, hash 92DFA63A
input buffer #16:
timeUs = 1000000467133
contents = length 874, hash 69587FB4
input buffer #17:
timeUs = 1000000533866
contents = length 781, hash 36BE495B
input buffer #18:
timeUs = 1000000700700
contents = length 4725, hash AC0C8CD3
input buffer #19:
timeUs = 1000000633966
contents = length 1022, hash 5D8BFF34
input buffer #20:
timeUs = 1000000600600
contents = length 790, hash 99413A99
input buffer #21:
timeUs = 1000000667333
contents = length 610, hash 5E129290
input buffer #22:
timeUs = 1000000834166
contents = length 2751, hash 769974CB
input buffer #23:
timeUs = 1000000767433
contents = length 745, hash B78A477A
input buffer #24:
timeUs = 1000000734066
contents = length 621, hash CF741E7A
input buffer #25:
timeUs = 1000000800800
contents = length 505, hash 1DB4894E
input buffer #26:
timeUs = 1000000967633
contents = length 1268, hash C15348DC
input buffer #27:
timeUs = 1000000900900
contents = length 880, hash C2DE85D0
input buffer #28:
timeUs = 1000000867533
contents = length 530, hash C98BC6A8
input buffer #29:
timeUs = 1000000934266
contents = length 568, hash 4FE5C8EA
input buffer #30:
timeUs = 0
flags = 4
contents = length 0, hash 1
outputBuffers:
count = 30
output buffer #0:
timeUs = 1000000000000
size = 36692
rendered = true
output buffer #1:
timeUs = 1000000066733
size = 5312
rendered = true
output buffer #2:
timeUs = 1000000033366
size = 599
rendered = true
output buffer #3:
timeUs = 1000000200200
size = 7735
rendered = true
output buffer #4:
timeUs = 1000000133466
size = 987
rendered = true
output buffer #5:
timeUs = 1000000100100
size = 673
rendered = true
output buffer #6:
timeUs = 1000000166833
size = 523
rendered = true
output buffer #7:
timeUs = 1000000333666
size = 6061
rendered = true
output buffer #8:
timeUs = 1000000266933
size = 992
rendered = true
output buffer #9:
timeUs = 1000000233566
size = 623
rendered = true
output buffer #10:
timeUs = 1000000300300
size = 421
rendered = true
output buffer #11:
timeUs = 1000000433766
size = 4899
rendered = true
output buffer #12:
timeUs = 1000000400400
size = 568
rendered = true
output buffer #13:
timeUs = 1000000367033
size = 620
rendered = true
output buffer #14:
timeUs = 1000000567233
size = 5450
rendered = true
output buffer #15:
timeUs = 1000000500500
size = 1051
rendered = true
output buffer #16:
timeUs = 1000000467133
size = 874
rendered = true
output buffer #17:
timeUs = 1000000533866
size = 781
rendered = true
output buffer #18:
timeUs = 1000000700700
size = 4725
rendered = true
output buffer #19:
timeUs = 1000000633966
size = 1022
rendered = true
output buffer #20:
timeUs = 1000000600600
size = 790
rendered = true
output buffer #21:
timeUs = 1000000667333
size = 610
rendered = true
output buffer #22:
timeUs = 1000000834166
size = 2751
rendered = true
output buffer #23:
timeUs = 1000000767433
size = 745
rendered = true
output buffer #24:
timeUs = 1000000734066
size = 621
rendered = true
output buffer #25:
timeUs = 1000000800800
size = 505
rendered = true
output buffer #26:
timeUs = 1000000967633
size = 1268
rendered = true
output buffer #27:
timeUs = 1000000900900
size = 880
rendered = true
output buffer #28:
timeUs = 1000000867533
size = 530
rendered = true
output buffer #29:
timeUs = 1000000934266
size = 568
rendered = true
TextOutput:
Subtitle[0]:
presentationTimeUs = 0
Cues = []
Subtitle[1]:
presentationTimeUs = 0
Cues = []

View File

@ -0,0 +1,226 @@
MediaCodecAdapter (exotest.video.avc):
inputBuffers:
count = 31
input buffer #0:
timeUs = 1000000000000
contents = length 36692, hash D216076E
input buffer #1:
timeUs = 1000000066733
contents = length 5312, hash D45D3CA0
input buffer #2:
timeUs = 1000000033366
contents = length 599, hash 1BE7812D
input buffer #3:
timeUs = 1000000200200
contents = length 7735, hash 4490F110
input buffer #4:
timeUs = 1000000133466
contents = length 987, hash 560B5036
input buffer #5:
timeUs = 1000000100100
contents = length 673, hash ED7CD8C7
input buffer #6:
timeUs = 1000000166833
contents = length 523, hash 3020DF50
input buffer #7:
timeUs = 1000000333666
contents = length 6061, hash 736C72B2
input buffer #8:
timeUs = 1000000266933
contents = length 992, hash FE132F23
input buffer #9:
timeUs = 1000000233566
contents = length 623, hash 5B2C1816
input buffer #10:
timeUs = 1000000300300
contents = length 421, hash 742E69C1
input buffer #11:
timeUs = 1000000433766
contents = length 4899, hash F72F86A1
input buffer #12:
timeUs = 1000000400400
contents = length 568, hash 519A8E50
input buffer #13:
timeUs = 1000000367033
contents = length 620, hash 3990AA39
input buffer #14:
timeUs = 1000000567233
contents = length 5450, hash F06EC4AA
input buffer #15:
timeUs = 1000000500500
contents = length 1051, hash 92DFA63A
input buffer #16:
timeUs = 1000000467133
contents = length 874, hash 69587FB4
input buffer #17:
timeUs = 1000000533866
contents = length 781, hash 36BE495B
input buffer #18:
timeUs = 1000000700700
contents = length 4725, hash AC0C8CD3
input buffer #19:
timeUs = 1000000633966
contents = length 1022, hash 5D8BFF34
input buffer #20:
timeUs = 1000000600600
contents = length 790, hash 99413A99
input buffer #21:
timeUs = 1000000667333
contents = length 610, hash 5E129290
input buffer #22:
timeUs = 1000000834166
contents = length 2751, hash 769974CB
input buffer #23:
timeUs = 1000000767433
contents = length 745, hash B78A477A
input buffer #24:
timeUs = 1000000734066
contents = length 621, hash CF741E7A
input buffer #25:
timeUs = 1000000800800
contents = length 505, hash 1DB4894E
input buffer #26:
timeUs = 1000000967633
contents = length 1268, hash C15348DC
input buffer #27:
timeUs = 1000000900900
contents = length 880, hash C2DE85D0
input buffer #28:
timeUs = 1000000867533
contents = length 530, hash C98BC6A8
input buffer #29:
timeUs = 1000000934266
contents = length 568, hash 4FE5C8EA
input buffer #30:
timeUs = 0
flags = 4
contents = length 0, hash 1
outputBuffers:
count = 30
output buffer #0:
timeUs = 1000000000000
size = 36692
rendered = true
output buffer #1:
timeUs = 1000000066733
size = 5312
rendered = true
output buffer #2:
timeUs = 1000000033366
size = 599
rendered = true
output buffer #3:
timeUs = 1000000200200
size = 7735
rendered = true
output buffer #4:
timeUs = 1000000133466
size = 987
rendered = true
output buffer #5:
timeUs = 1000000100100
size = 673
rendered = true
output buffer #6:
timeUs = 1000000166833
size = 523
rendered = true
output buffer #7:
timeUs = 1000000333666
size = 6061
rendered = true
output buffer #8:
timeUs = 1000000266933
size = 992
rendered = true
output buffer #9:
timeUs = 1000000233566
size = 623
rendered = true
output buffer #10:
timeUs = 1000000300300
size = 421
rendered = true
output buffer #11:
timeUs = 1000000433766
size = 4899
rendered = true
output buffer #12:
timeUs = 1000000400400
size = 568
rendered = true
output buffer #13:
timeUs = 1000000367033
size = 620
rendered = true
output buffer #14:
timeUs = 1000000567233
size = 5450
rendered = true
output buffer #15:
timeUs = 1000000500500
size = 1051
rendered = true
output buffer #16:
timeUs = 1000000467133
size = 874
rendered = true
output buffer #17:
timeUs = 1000000533866
size = 781
rendered = true
output buffer #18:
timeUs = 1000000700700
size = 4725
rendered = true
output buffer #19:
timeUs = 1000000633966
size = 1022
rendered = true
output buffer #20:
timeUs = 1000000600600
size = 790
rendered = true
output buffer #21:
timeUs = 1000000667333
size = 610
rendered = true
output buffer #22:
timeUs = 1000000834166
size = 2751
rendered = true
output buffer #23:
timeUs = 1000000767433
size = 745
rendered = true
output buffer #24:
timeUs = 1000000734066
size = 621
rendered = true
output buffer #25:
timeUs = 1000000800800
size = 505
rendered = true
output buffer #26:
timeUs = 1000000967633
size = 1268
rendered = true
output buffer #27:
timeUs = 1000000900900
size = 880
rendered = true
output buffer #28:
timeUs = 1000000867533
size = 530
rendered = true
output buffer #29:
timeUs = 1000000934266
size = 568
rendered = true
TextOutput:
Subtitle[0]:
presentationTimeUs = 0
Cues = []
Subtitle[1]:
presentationTimeUs = 0
Cues = []

View File

@ -0,0 +1,226 @@
MediaCodecAdapter (exotest.video.avc):
inputBuffers:
count = 31
input buffer #0:
timeUs = 1000000000000
contents = length 36692, hash D216076E
input buffer #1:
timeUs = 1000000066733
contents = length 5312, hash D45D3CA0
input buffer #2:
timeUs = 1000000033366
contents = length 599, hash 1BE7812D
input buffer #3:
timeUs = 1000000200200
contents = length 7735, hash 4490F110
input buffer #4:
timeUs = 1000000133466
contents = length 987, hash 560B5036
input buffer #5:
timeUs = 1000000100100
contents = length 673, hash ED7CD8C7
input buffer #6:
timeUs = 1000000166833
contents = length 523, hash 3020DF50
input buffer #7:
timeUs = 1000000333666
contents = length 6061, hash 736C72B2
input buffer #8:
timeUs = 1000000266933
contents = length 992, hash FE132F23
input buffer #9:
timeUs = 1000000233566
contents = length 623, hash 5B2C1816
input buffer #10:
timeUs = 1000000300300
contents = length 421, hash 742E69C1
input buffer #11:
timeUs = 1000000433766
contents = length 4899, hash F72F86A1
input buffer #12:
timeUs = 1000000400400
contents = length 568, hash 519A8E50
input buffer #13:
timeUs = 1000000367033
contents = length 620, hash 3990AA39
input buffer #14:
timeUs = 1000000567233
contents = length 5450, hash F06EC4AA
input buffer #15:
timeUs = 1000000500500
contents = length 1051, hash 92DFA63A
input buffer #16:
timeUs = 1000000467133
contents = length 874, hash 69587FB4
input buffer #17:
timeUs = 1000000533866
contents = length 781, hash 36BE495B
input buffer #18:
timeUs = 1000000700700
contents = length 4725, hash AC0C8CD3
input buffer #19:
timeUs = 1000000633966
contents = length 1022, hash 5D8BFF34
input buffer #20:
timeUs = 1000000600600
contents = length 790, hash 99413A99
input buffer #21:
timeUs = 1000000667333
contents = length 610, hash 5E129290
input buffer #22:
timeUs = 1000000834166
contents = length 2751, hash 769974CB
input buffer #23:
timeUs = 1000000767433
contents = length 745, hash B78A477A
input buffer #24:
timeUs = 1000000734066
contents = length 621, hash CF741E7A
input buffer #25:
timeUs = 1000000800800
contents = length 505, hash 1DB4894E
input buffer #26:
timeUs = 1000000967633
contents = length 1268, hash C15348DC
input buffer #27:
timeUs = 1000000900900
contents = length 880, hash C2DE85D0
input buffer #28:
timeUs = 1000000867533
contents = length 530, hash C98BC6A8
input buffer #29:
timeUs = 1000000934266
contents = length 568, hash 4FE5C8EA
input buffer #30:
timeUs = 0
flags = 4
contents = length 0, hash 1
outputBuffers:
count = 30
output buffer #0:
timeUs = 1000000000000
size = 36692
rendered = true
output buffer #1:
timeUs = 1000000066733
size = 5312
rendered = true
output buffer #2:
timeUs = 1000000033366
size = 599
rendered = true
output buffer #3:
timeUs = 1000000200200
size = 7735
rendered = true
output buffer #4:
timeUs = 1000000133466
size = 987
rendered = true
output buffer #5:
timeUs = 1000000100100
size = 673
rendered = true
output buffer #6:
timeUs = 1000000166833
size = 523
rendered = true
output buffer #7:
timeUs = 1000000333666
size = 6061
rendered = true
output buffer #8:
timeUs = 1000000266933
size = 992
rendered = true
output buffer #9:
timeUs = 1000000233566
size = 623
rendered = true
output buffer #10:
timeUs = 1000000300300
size = 421
rendered = true
output buffer #11:
timeUs = 1000000433766
size = 4899
rendered = true
output buffer #12:
timeUs = 1000000400400
size = 568
rendered = true
output buffer #13:
timeUs = 1000000367033
size = 620
rendered = true
output buffer #14:
timeUs = 1000000567233
size = 5450
rendered = true
output buffer #15:
timeUs = 1000000500500
size = 1051
rendered = true
output buffer #16:
timeUs = 1000000467133
size = 874
rendered = true
output buffer #17:
timeUs = 1000000533866
size = 781
rendered = true
output buffer #18:
timeUs = 1000000700700
size = 4725
rendered = true
output buffer #19:
timeUs = 1000000633966
size = 1022
rendered = true
output buffer #20:
timeUs = 1000000600600
size = 790
rendered = true
output buffer #21:
timeUs = 1000000667333
size = 610
rendered = true
output buffer #22:
timeUs = 1000000834166
size = 2751
rendered = true
output buffer #23:
timeUs = 1000000767433
size = 745
rendered = true
output buffer #24:
timeUs = 1000000734066
size = 621
rendered = true
output buffer #25:
timeUs = 1000000800800
size = 505
rendered = true
output buffer #26:
timeUs = 1000000967633
size = 1268
rendered = true
output buffer #27:
timeUs = 1000000900900
size = 880
rendered = true
output buffer #28:
timeUs = 1000000867533
size = 530
rendered = true
output buffer #29:
timeUs = 1000000934266
size = 568
rendered = true
TextOutput:
Subtitle[0]:
presentationTimeUs = 0
Cues = []
Subtitle[1]:
presentationTimeUs = 0
Cues = []

View File

@ -0,0 +1,226 @@
MediaCodecAdapter (exotest.video.avc):
inputBuffers:
count = 31
input buffer #0:
timeUs = 1000000000000
contents = length 36692, hash D216076E
input buffer #1:
timeUs = 1000000066733
contents = length 5312, hash D45D3CA0
input buffer #2:
timeUs = 1000000033366
contents = length 599, hash 1BE7812D
input buffer #3:
timeUs = 1000000200200
contents = length 7735, hash 4490F110
input buffer #4:
timeUs = 1000000133466
contents = length 987, hash 560B5036
input buffer #5:
timeUs = 1000000100100
contents = length 673, hash ED7CD8C7
input buffer #6:
timeUs = 1000000166833
contents = length 523, hash 3020DF50
input buffer #7:
timeUs = 1000000333666
contents = length 6061, hash 736C72B2
input buffer #8:
timeUs = 1000000266933
contents = length 992, hash FE132F23
input buffer #9:
timeUs = 1000000233566
contents = length 623, hash 5B2C1816
input buffer #10:
timeUs = 1000000300300
contents = length 421, hash 742E69C1
input buffer #11:
timeUs = 1000000433766
contents = length 4899, hash F72F86A1
input buffer #12:
timeUs = 1000000400400
contents = length 568, hash 519A8E50
input buffer #13:
timeUs = 1000000367033
contents = length 620, hash 3990AA39
input buffer #14:
timeUs = 1000000567233
contents = length 5450, hash F06EC4AA
input buffer #15:
timeUs = 1000000500500
contents = length 1051, hash 92DFA63A
input buffer #16:
timeUs = 1000000467133
contents = length 874, hash 69587FB4
input buffer #17:
timeUs = 1000000533866
contents = length 781, hash 36BE495B
input buffer #18:
timeUs = 1000000700700
contents = length 4725, hash AC0C8CD3
input buffer #19:
timeUs = 1000000633966
contents = length 1022, hash 5D8BFF34
input buffer #20:
timeUs = 1000000600600
contents = length 790, hash 99413A99
input buffer #21:
timeUs = 1000000667333
contents = length 610, hash 5E129290
input buffer #22:
timeUs = 1000000834166
contents = length 2751, hash 769974CB
input buffer #23:
timeUs = 1000000767433
contents = length 745, hash B78A477A
input buffer #24:
timeUs = 1000000734066
contents = length 621, hash CF741E7A
input buffer #25:
timeUs = 1000000800800
contents = length 505, hash 1DB4894E
input buffer #26:
timeUs = 1000000967633
contents = length 1268, hash C15348DC
input buffer #27:
timeUs = 1000000900900
contents = length 880, hash C2DE85D0
input buffer #28:
timeUs = 1000000867533
contents = length 530, hash C98BC6A8
input buffer #29:
timeUs = 1000000934266
contents = length 568, hash 4FE5C8EA
input buffer #30:
timeUs = 0
flags = 4
contents = length 0, hash 1
outputBuffers:
count = 30
output buffer #0:
timeUs = 1000000000000
size = 36692
rendered = true
output buffer #1:
timeUs = 1000000066733
size = 5312
rendered = true
output buffer #2:
timeUs = 1000000033366
size = 599
rendered = true
output buffer #3:
timeUs = 1000000200200
size = 7735
rendered = true
output buffer #4:
timeUs = 1000000133466
size = 987
rendered = true
output buffer #5:
timeUs = 1000000100100
size = 673
rendered = true
output buffer #6:
timeUs = 1000000166833
size = 523
rendered = true
output buffer #7:
timeUs = 1000000333666
size = 6061
rendered = true
output buffer #8:
timeUs = 1000000266933
size = 992
rendered = true
output buffer #9:
timeUs = 1000000233566
size = 623
rendered = true
output buffer #10:
timeUs = 1000000300300
size = 421
rendered = true
output buffer #11:
timeUs = 1000000433766
size = 4899
rendered = true
output buffer #12:
timeUs = 1000000400400
size = 568
rendered = true
output buffer #13:
timeUs = 1000000367033
size = 620
rendered = true
output buffer #14:
timeUs = 1000000567233
size = 5450
rendered = true
output buffer #15:
timeUs = 1000000500500
size = 1051
rendered = true
output buffer #16:
timeUs = 1000000467133
size = 874
rendered = true
output buffer #17:
timeUs = 1000000533866
size = 781
rendered = true
output buffer #18:
timeUs = 1000000700700
size = 4725
rendered = true
output buffer #19:
timeUs = 1000000633966
size = 1022
rendered = true
output buffer #20:
timeUs = 1000000600600
size = 790
rendered = true
output buffer #21:
timeUs = 1000000667333
size = 610
rendered = true
output buffer #22:
timeUs = 1000000834166
size = 2751
rendered = true
output buffer #23:
timeUs = 1000000767433
size = 745
rendered = true
output buffer #24:
timeUs = 1000000734066
size = 621
rendered = true
output buffer #25:
timeUs = 1000000800800
size = 505
rendered = true
output buffer #26:
timeUs = 1000000967633
size = 1268
rendered = true
output buffer #27:
timeUs = 1000000900900
size = 880
rendered = true
output buffer #28:
timeUs = 1000000867533
size = 530
rendered = true
output buffer #29:
timeUs = 1000000934266
size = 568
rendered = true
TextOutput:
Subtitle[0]:
presentationTimeUs = 0
Cues = []
Subtitle[1]:
presentationTimeUs = 0
Cues = []

View File

@ -0,0 +1,691 @@
MediaCodecAdapter (exotest.audio.aac):
inputBuffers:
count = 46
input buffer #0:
timeUs = 1000000044000
contents = length 23, hash 47DE9131
input buffer #1:
timeUs = 1000000067219
contents = length 6, hash 31EC5206
input buffer #2:
timeUs = 1000000090439
contents = length 148, hash 894A176B
input buffer #3:
timeUs = 1000000113659
contents = length 189, hash CEF235A1
input buffer #4:
timeUs = 1000000136879
contents = length 205, hash BBF5F7B0
input buffer #5:
timeUs = 1000000160099
contents = length 210, hash F278B193
input buffer #6:
timeUs = 1000000183319
contents = length 210, hash 82DA1589
input buffer #7:
timeUs = 1000000206539
contents = length 207, hash 5BE231DF
input buffer #8:
timeUs = 1000000229759
contents = length 225, hash 18819EE1
input buffer #9:
timeUs = 1000000252979
contents = length 215, hash CA7FA67B
input buffer #10:
timeUs = 1000000276199
contents = length 211, hash 581A1C18
input buffer #11:
timeUs = 1000000299419
contents = length 216, hash ADB88187
input buffer #12:
timeUs = 1000000322639
contents = length 229, hash 2E8BA4DC
input buffer #13:
timeUs = 1000000345859
contents = length 232, hash 22F0C510
input buffer #14:
timeUs = 1000000369079
contents = length 235, hash 867AD0DC
input buffer #15:
timeUs = 1000000392299
contents = length 231, hash 84E823A8
input buffer #16:
timeUs = 1000000415519
contents = length 226, hash 1BEF3A95
input buffer #17:
timeUs = 1000000438739
contents = length 216, hash EAA345AE
input buffer #18:
timeUs = 1000000461959
contents = length 229, hash 6957411F
input buffer #19:
timeUs = 1000000485179
contents = length 219, hash 41275022
input buffer #20:
timeUs = 1000000508399
contents = length 241, hash 6495DF96
input buffer #21:
timeUs = 1000000531619
contents = length 228, hash 63D95906
input buffer #22:
timeUs = 1000000554839
contents = length 238, hash 34F676F9
input buffer #23:
timeUs = 1000000578058
contents = length 234, hash E5CBC045
input buffer #24:
timeUs = 1000000601278
contents = length 231, hash 5FC43661
input buffer #25:
timeUs = 1000000624498
contents = length 217, hash 682708ED
input buffer #26:
timeUs = 1000000647718
contents = length 239, hash D43780FC
input buffer #27:
timeUs = 1000000670938
contents = length 243, hash C5E17980
input buffer #28:
timeUs = 1000000694158
contents = length 231, hash AC5837BA
input buffer #29:
timeUs = 1000000717378
contents = length 230, hash 169EE895
input buffer #30:
timeUs = 1000000740598
contents = length 238, hash C48FF3F1
input buffer #31:
timeUs = 1000000763818
contents = length 225, hash 531E4599
input buffer #32:
timeUs = 1000000787038
contents = length 232, hash CB3C6B8D
input buffer #33:
timeUs = 1000000810258
contents = length 243, hash F8C94C7
input buffer #34:
timeUs = 1000000833478
contents = length 232, hash A646A7D0
input buffer #35:
timeUs = 1000000856698
contents = length 237, hash E8B787A5
input buffer #36:
timeUs = 1000000879918
contents = length 228, hash 3FA7A29F
input buffer #37:
timeUs = 1000000903138
contents = length 235, hash B9B33B0A
input buffer #38:
timeUs = 1000000926358
contents = length 264, hash 71A4869E
input buffer #39:
timeUs = 1000000949578
contents = length 257, hash D049B54C
input buffer #40:
timeUs = 1000000972798
contents = length 227, hash 66757231
input buffer #41:
timeUs = 1000000996018
contents = length 227, hash BD374F1B
input buffer #42:
timeUs = 1000001019238
contents = length 235, hash 999477F6
input buffer #43:
timeUs = 1000001042458
contents = length 229, hash FFF98DF0
input buffer #44:
timeUs = 1000001065678
contents = length 6, hash 31B22286
input buffer #45:
timeUs = 0
flags = 4
contents = length 0, hash 1
outputBuffers:
count = 45
output buffer #0:
timeUs = 1000000044000
size = 0
rendered = false
output buffer #1:
timeUs = 1000000067219
size = 0
rendered = false
output buffer #2:
timeUs = 1000000090439
size = 0
rendered = false
output buffer #3:
timeUs = 1000000113659
size = 0
rendered = false
output buffer #4:
timeUs = 1000000136879
size = 0
rendered = false
output buffer #5:
timeUs = 1000000160099
size = 0
rendered = false
output buffer #6:
timeUs = 1000000183319
size = 0
rendered = false
output buffer #7:
timeUs = 1000000206539
size = 0
rendered = false
output buffer #8:
timeUs = 1000000229759
size = 0
rendered = false
output buffer #9:
timeUs = 1000000252979
size = 0
rendered = false
output buffer #10:
timeUs = 1000000276199
size = 0
rendered = false
output buffer #11:
timeUs = 1000000299419
size = 0
rendered = false
output buffer #12:
timeUs = 1000000322639
size = 0
rendered = false
output buffer #13:
timeUs = 1000000345859
size = 0
rendered = false
output buffer #14:
timeUs = 1000000369079
size = 0
rendered = false
output buffer #15:
timeUs = 1000000392299
size = 0
rendered = false
output buffer #16:
timeUs = 1000000415519
size = 0
rendered = false
output buffer #17:
timeUs = 1000000438739
size = 0
rendered = false
output buffer #18:
timeUs = 1000000461959
size = 0
rendered = false
output buffer #19:
timeUs = 1000000485179
size = 0
rendered = false
output buffer #20:
timeUs = 1000000508399
size = 0
rendered = false
output buffer #21:
timeUs = 1000000531619
size = 0
rendered = false
output buffer #22:
timeUs = 1000000554839
size = 0
rendered = false
output buffer #23:
timeUs = 1000000578058
size = 0
rendered = false
output buffer #24:
timeUs = 1000000601278
size = 0
rendered = false
output buffer #25:
timeUs = 1000000624498
size = 0
rendered = false
output buffer #26:
timeUs = 1000000647718
size = 0
rendered = false
output buffer #27:
timeUs = 1000000670938
size = 0
rendered = false
output buffer #28:
timeUs = 1000000694158
size = 0
rendered = false
output buffer #29:
timeUs = 1000000717378
size = 0
rendered = false
output buffer #30:
timeUs = 1000000740598
size = 0
rendered = false
output buffer #31:
timeUs = 1000000763818
size = 0
rendered = false
output buffer #32:
timeUs = 1000000787038
size = 0
rendered = false
output buffer #33:
timeUs = 1000000810258
size = 0
rendered = false
output buffer #34:
timeUs = 1000000833478
size = 0
rendered = false
output buffer #35:
timeUs = 1000000856698
size = 0
rendered = false
output buffer #36:
timeUs = 1000000879918
size = 0
rendered = false
output buffer #37:
timeUs = 1000000903138
size = 0
rendered = false
output buffer #38:
timeUs = 1000000926358
size = 0
rendered = false
output buffer #39:
timeUs = 1000000949578
size = 0
rendered = false
output buffer #40:
timeUs = 1000000972798
size = 0
rendered = false
output buffer #41:
timeUs = 1000000996018
size = 0
rendered = false
output buffer #42:
timeUs = 1000001019238
size = 0
rendered = false
output buffer #43:
timeUs = 1000001042458
size = 0
rendered = false
output buffer #44:
timeUs = 1000001065678
size = 0
rendered = false
MediaCodecAdapter (exotest.video.avc):
inputBuffers:
count = 31
input buffer #0:
timeUs = 1000000000000
contents = length 36692, hash D216076E
input buffer #1:
timeUs = 1000000066733
contents = length 5312, hash D45D3CA0
input buffer #2:
timeUs = 1000000033366
contents = length 599, hash 1BE7812D
input buffer #3:
timeUs = 1000000200200
contents = length 7735, hash 4490F110
input buffer #4:
timeUs = 1000000133466
contents = length 987, hash 560B5036
input buffer #5:
timeUs = 1000000100100
contents = length 673, hash ED7CD8C7
input buffer #6:
timeUs = 1000000166833
contents = length 523, hash 3020DF50
input buffer #7:
timeUs = 1000000333666
contents = length 6061, hash 736C72B2
input buffer #8:
timeUs = 1000000266933
contents = length 992, hash FE132F23
input buffer #9:
timeUs = 1000000233566
contents = length 623, hash 5B2C1816
input buffer #10:
timeUs = 1000000300300
contents = length 421, hash 742E69C1
input buffer #11:
timeUs = 1000000433766
contents = length 4899, hash F72F86A1
input buffer #12:
timeUs = 1000000400400
contents = length 568, hash 519A8E50
input buffer #13:
timeUs = 1000000367033
contents = length 620, hash 3990AA39
input buffer #14:
timeUs = 1000000567233
contents = length 5450, hash F06EC4AA
input buffer #15:
timeUs = 1000000500500
contents = length 1051, hash 92DFA63A
input buffer #16:
timeUs = 1000000467133
contents = length 874, hash 69587FB4
input buffer #17:
timeUs = 1000000533866
contents = length 781, hash 36BE495B
input buffer #18:
timeUs = 1000000700700
contents = length 4725, hash AC0C8CD3
input buffer #19:
timeUs = 1000000633966
contents = length 1022, hash 5D8BFF34
input buffer #20:
timeUs = 1000000600600
contents = length 790, hash 99413A99
input buffer #21:
timeUs = 1000000667333
contents = length 610, hash 5E129290
input buffer #22:
timeUs = 1000000834166
contents = length 2751, hash 769974CB
input buffer #23:
timeUs = 1000000767433
contents = length 745, hash B78A477A
input buffer #24:
timeUs = 1000000734066
contents = length 621, hash CF741E7A
input buffer #25:
timeUs = 1000000800800
contents = length 505, hash 1DB4894E
input buffer #26:
timeUs = 1000000967633
contents = length 1268, hash C15348DC
input buffer #27:
timeUs = 1000000900900
contents = length 880, hash C2DE85D0
input buffer #28:
timeUs = 1000000867533
contents = length 530, hash C98BC6A8
input buffer #29:
timeUs = 1000000934266
contents = length 568, hash 4FE5C8EA
input buffer #30:
timeUs = 0
flags = 4
contents = length 0, hash 1
outputBuffers:
count = 30
output buffer #0:
timeUs = 1000000000000
size = 36692
rendered = true
output buffer #1:
timeUs = 1000000066733
size = 5312
rendered = true
output buffer #2:
timeUs = 1000000033366
size = 599
rendered = true
output buffer #3:
timeUs = 1000000200200
size = 7735
rendered = true
output buffer #4:
timeUs = 1000000133466
size = 987
rendered = true
output buffer #5:
timeUs = 1000000100100
size = 673
rendered = true
output buffer #6:
timeUs = 1000000166833
size = 523
rendered = true
output buffer #7:
timeUs = 1000000333666
size = 6061
rendered = true
output buffer #8:
timeUs = 1000000266933
size = 992
rendered = true
output buffer #9:
timeUs = 1000000233566
size = 623
rendered = true
output buffer #10:
timeUs = 1000000300300
size = 421
rendered = true
output buffer #11:
timeUs = 1000000433766
size = 4899
rendered = true
output buffer #12:
timeUs = 1000000400400
size = 568
rendered = true
output buffer #13:
timeUs = 1000000367033
size = 620
rendered = true
output buffer #14:
timeUs = 1000000567233
size = 5450
rendered = true
output buffer #15:
timeUs = 1000000500500
size = 1051
rendered = true
output buffer #16:
timeUs = 1000000467133
size = 874
rendered = true
output buffer #17:
timeUs = 1000000533866
size = 781
rendered = true
output buffer #18:
timeUs = 1000000700700
size = 4725
rendered = true
output buffer #19:
timeUs = 1000000633966
size = 1022
rendered = true
output buffer #20:
timeUs = 1000000600600
size = 790
rendered = true
output buffer #21:
timeUs = 1000000667333
size = 610
rendered = true
output buffer #22:
timeUs = 1000000834166
size = 2751
rendered = true
output buffer #23:
timeUs = 1000000767433
size = 745
rendered = true
output buffer #24:
timeUs = 1000000734066
size = 621
rendered = true
output buffer #25:
timeUs = 1000000800800
size = 505
rendered = true
output buffer #26:
timeUs = 1000000967633
size = 1268
rendered = true
output buffer #27:
timeUs = 1000000900900
size = 880
rendered = true
output buffer #28:
timeUs = 1000000867533
size = 530
rendered = true
output buffer #29:
timeUs = 1000000934266
size = 568
rendered = true
AudioSink:
buffer count = 45
config:
pcmEncoding = 2
channelCount = 1
sampleRate = 44100
buffer #0:
time = 1000000044000
data = 1
buffer #1:
time = 1000000067219
data = 1
buffer #2:
time = 1000000090439
data = 1
buffer #3:
time = 1000000113659
data = 1
buffer #4:
time = 1000000136879
data = 1
buffer #5:
time = 1000000160099
data = 1
buffer #6:
time = 1000000183319
data = 1
buffer #7:
time = 1000000206539
data = 1
buffer #8:
time = 1000000229759
data = 1
buffer #9:
time = 1000000252979
data = 1
buffer #10:
time = 1000000276199
data = 1
buffer #11:
time = 1000000299419
data = 1
buffer #12:
time = 1000000322639
data = 1
buffer #13:
time = 1000000345859
data = 1
buffer #14:
time = 1000000369079
data = 1
buffer #15:
time = 1000000392299
data = 1
buffer #16:
time = 1000000415519
data = 1
buffer #17:
time = 1000000438739
data = 1
buffer #18:
time = 1000000461959
data = 1
buffer #19:
time = 1000000485179
data = 1
buffer #20:
time = 1000000508399
data = 1
buffer #21:
time = 1000000531619
data = 1
buffer #22:
time = 1000000554839
data = 1
buffer #23:
time = 1000000578058
data = 1
buffer #24:
time = 1000000601278
data = 1
buffer #25:
time = 1000000624498
data = 1
buffer #26:
time = 1000000647718
data = 1
buffer #27:
time = 1000000670938
data = 1
buffer #28:
time = 1000000694158
data = 1
buffer #29:
time = 1000000717378
data = 1
buffer #30:
time = 1000000740598
data = 1
buffer #31:
time = 1000000763818
data = 1
buffer #32:
time = 1000000787038
data = 1
buffer #33:
time = 1000000810258
data = 1
buffer #34:
time = 1000000833478
data = 1
buffer #35:
time = 1000000856698
data = 1
buffer #36:
time = 1000000879918
data = 1
buffer #37:
time = 1000000903138
data = 1
buffer #38:
time = 1000000926358
data = 1
buffer #39:
time = 1000000949578
data = 1
buffer #40:
time = 1000000972798
data = 1
buffer #41:
time = 1000000996018
data = 1
buffer #42:
time = 1000001019238
data = 1
buffer #43:
time = 1000001042458
data = 1
buffer #44:
time = 1000001065678
data = 1
TextOutput:
Subtitle[0]:
presentationTimeUs = 0
Cues = []
Subtitle[1]:
presentationTimeUs = 0
Cues = []

View File

@ -0,0 +1,73 @@
/*
* Copyright 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.media3.test.utils;
import androidx.media3.common.Format;
import androidx.media3.common.MimeTypes;
import androidx.media3.common.util.Consumer;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.extractor.text.CuesWithTiming;
import androidx.media3.extractor.text.SubtitleParser;
import com.google.common.base.Supplier;
/**
* A {@link SubtitleParser.Factory} for {@link SubtitleParser} instances that throw an exception on
* every call to {@link SubtitleParser#parse}.
*
* <p>It claims support for all subtitle formats (returns the result of {@link MimeTypes#isText}
* from {@link SubtitleParser.Factory#supportsFormat}).
*/
@UnstableApi
public class ThrowingSubtitleParserFactory implements SubtitleParser.Factory {
public static final @Format.CueReplacementBehavior int REPLACEMENT_BEHAVIOR =
Format.CUE_REPLACEMENT_BEHAVIOR_REPLACE;
private final Supplier<RuntimeException> exceptionSupplier;
public ThrowingSubtitleParserFactory(Supplier<RuntimeException> exceptionSupplier) {
this.exceptionSupplier = exceptionSupplier;
}
@Override
public boolean supportsFormat(Format format) {
return MimeTypes.isText(format.sampleMimeType);
}
@Override
public @Format.CueReplacementBehavior int getCueReplacementBehavior(Format format) {
return REPLACEMENT_BEHAVIOR;
}
@Override
public SubtitleParser create(Format format) {
return new SubtitleParser() {
@Override
public void parse(
byte[] data,
int offset,
int length,
OutputOptions outputOptions,
Consumer<CuesWithTiming> output) {
throw exceptionSupplier.get();
}
@Override
public @Format.CueReplacementBehavior int getCueReplacementBehavior() {
return REPLACEMENT_BEHAVIOR;
}
};
}
}