diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 30ce2b58bf..06c52f78c3 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -65,6 +65,16 @@ subtitles (those added with `MediaItem.LocalConfiguration.subtitleConfigurations`), which may appear 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: * Make setting the image duration using `MediaItem.Builder.setImageDurationMs` mandatory for image export. diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImplInternal.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImplInternal.java index 6f0accaa4e..27d5cc0ddc 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImplInternal.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImplInternal.java @@ -1149,7 +1149,7 @@ import java.util.concurrent.atomic.AtomicBoolean; maybeTriggerOnRendererReadyChanged(/* rendererIndex= */ i, allowsPlayback); renderersAllowPlayback = renderersAllowPlayback && allowsPlayback; if (!allowsPlayback) { - renderer.maybeThrowStreamError(); + maybeThrowRendererStreamError(/* rendererIndex= */ i); } } } else { @@ -1200,7 +1200,7 @@ import java.util.concurrent.atomic.AtomicBoolean; for (int i = 0; i < renderers.length; i++) { if (isRendererEnabled(renderers[i]) && renderers[i].getStream() == playingPeriodHolder.sampleStreams[i]) { - renderers[i].maybeThrowStreamError(); + maybeThrowRendererStreamError(/* rendererIndex= */ i); } } if (!playbackInfo.isLoading @@ -2940,6 +2940,46 @@ import java.util.concurrent.atomic.AtomicBoolean; && 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( Timeline timeline, PlaybackInfo playbackInfo, diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/text/TextRenderer.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/text/TextRenderer.java index cc25bee7f7..89943c0b7f 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/text/TextRenderer.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/text/TextRenderer.java @@ -42,11 +42,13 @@ import androidx.media3.exoplayer.source.MediaSource; import androidx.media3.exoplayer.source.SampleStream.ReadDataResult; import androidx.media3.extractor.text.CueDecoder; import androidx.media3.extractor.text.CuesWithTiming; +import androidx.media3.extractor.text.Subtitle; import androidx.media3.extractor.text.SubtitleDecoder; import androidx.media3.extractor.text.SubtitleDecoderException; import androidx.media3.extractor.text.SubtitleInputBuffer; import androidx.media3.extractor.text.SubtitleOutputBuffer; import com.google.common.collect.ImmutableList; +import java.io.IOException; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -122,6 +124,7 @@ public final class TextRenderer extends BaseRenderer implements Callback { private long lastRendererPositionUs; private long finalStreamEndPositionUs; private boolean legacyDecodingEnabled; + @Nullable private IOException streamError; /** * @param output The output. @@ -472,11 +475,40 @@ public final class TextRenderer extends BaseRenderer implements Callback { @Override 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. // Note: To change this behavior, it will be necessary to consider [Internal: b/12949941]. return true; } + private static boolean hasNoEventsAfter(@Nullable Subtitle subtitle, long timeUs) { + return subtitle == null || subtitle.getEventTime(subtitle.getEventTimeCount() - 1) <= timeUs; + } + private void releaseSubtitleBuffers() { nextSubtitleInputBuffer = null; nextSubtitleEventIndex = C.INDEX_UNSET; diff --git a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/e2etest/SubtitlePlaybackTest.java b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/e2etest/SubtitlePlaybackTest.java new file mode 100644 index 0000000000..cff92a3fcb --- /dev/null +++ b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/e2etest/SubtitlePlaybackTest.java @@ -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 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 loadErrorEventInfo = new AtomicReference<>(); + AtomicReference 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"); + } +} diff --git a/libraries/exoplayer_dash/src/test/java/androidx/media3/exoplayer/dash/e2etest/DashPlaybackTest.java b/libraries/exoplayer_dash/src/test/java/androidx/media3/exoplayer/dash/e2etest/DashPlaybackTest.java index 57b2b3d1ac..5aa768c4c5 100644 --- a/libraries/exoplayer_dash/src/test/java/androidx/media3/exoplayer/dash/e2etest/DashPlaybackTest.java +++ b/libraries/exoplayer_dash/src/test/java/androidx/media3/exoplayer/dash/e2etest/DashPlaybackTest.java @@ -16,33 +16,44 @@ package androidx.media3.exoplayer.dash.e2etest; 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 android.content.Context; import android.graphics.SurfaceTexture; +import android.net.Uri; import android.view.Surface; +import androidx.annotation.Nullable; import androidx.media3.common.MediaItem; +import androidx.media3.common.ParserException; import androidx.media3.common.Player; import androidx.media3.datasource.DataSource; import androidx.media3.datasource.DefaultDataSource; +import androidx.media3.datasource.ResolvingDataSource; import androidx.media3.exoplayer.DecoderCounters; import androidx.media3.exoplayer.ExoPlayer; import androidx.media3.exoplayer.Renderer; import androidx.media3.exoplayer.RenderersFactory; +import androidx.media3.exoplayer.analytics.AnalyticsListener; import androidx.media3.exoplayer.dash.DashMediaSource; import androidx.media3.exoplayer.dash.DefaultDashChunkSource; import androidx.media3.exoplayer.metadata.MetadataDecoderFactory; 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.trackselection.DefaultTrackSelector; 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.media3.test.utils.robolectric.TestPlayerRunHelper; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; +import java.io.IOException; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -81,6 +92,88 @@ public final class DashPlaybackTest { 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 public void ttmlStandaloneXmlFile() throws Exception { Context applicationContext = ApplicationProvider.getApplicationContext(); @@ -160,6 +253,85 @@ public final class DashPlaybackTest { 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 * demonstrate the flag has no effect on the resulting subtitles. @@ -461,4 +633,21 @@ public final class DashPlaybackTest { DumpFileAsserts.assertOutput( 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; + } + } } diff --git a/libraries/exoplayer_hls/src/test/java/androidx/media3/exoplayer/hls/e2etest/HlsPlaybackTest.java b/libraries/exoplayer_hls/src/test/java/androidx/media3/exoplayer/hls/e2etest/HlsPlaybackTest.java index 16e460b294..f142f5a538 100644 --- a/libraries/exoplayer_hls/src/test/java/androidx/media3/exoplayer/hls/e2etest/HlsPlaybackTest.java +++ b/libraries/exoplayer_hls/src/test/java/androidx/media3/exoplayer/hls/e2etest/HlsPlaybackTest.java @@ -16,26 +16,37 @@ 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.graphics.SurfaceTexture; +import android.net.Uri; import android.view.Surface; +import androidx.annotation.Nullable; import androidx.media3.common.MediaItem; import androidx.media3.common.Player; import androidx.media3.datasource.DefaultDataSource; +import androidx.media3.datasource.ResolvingDataSource; import androidx.media3.exoplayer.DefaultLoadControl; import androidx.media3.exoplayer.ExoPlayer; import androidx.media3.exoplayer.SeekParameters; +import androidx.media3.exoplayer.analytics.AnalyticsListener; import androidx.media3.exoplayer.hls.HlsMediaSource; 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.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.media3.test.utils.robolectric.TestPlayerRunHelper; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; +import java.io.IOException; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -71,6 +82,81 @@ public final class HlsPlaybackTest { 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 public void ttmlInMp4() throws Exception { Context applicationContext = ApplicationProvider.getApplicationContext(); @@ -94,6 +180,79 @@ public final class HlsPlaybackTest { 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 * demonstrate the flag has no effect on the resulting subtitles. @@ -221,4 +380,21 @@ public final class HlsPlaybackTest { playbackOutput, "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; + } + } } diff --git a/libraries/test_data/src/test/assets/playbackdumps/dash/standalone-webvtt_load-error.dump b/libraries/test_data/src/test/assets/playbackdumps/dash/standalone-webvtt_load-error.dump new file mode 100644 index 0000000000..489a107bc7 --- /dev/null +++ b/libraries/test_data/src/test/assets/playbackdumps/dash/standalone-webvtt_load-error.dump @@ -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 = [] diff --git a/libraries/test_data/src/test/assets/playbackdumps/dash/standalone-webvtt_parse-error.dump b/libraries/test_data/src/test/assets/playbackdumps/dash/standalone-webvtt_parse-error.dump new file mode 100644 index 0000000000..489a107bc7 --- /dev/null +++ b/libraries/test_data/src/test/assets/playbackdumps/dash/standalone-webvtt_parse-error.dump @@ -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 = [] diff --git a/libraries/test_data/src/test/assets/playbackdumps/dash/ttml-in-mp4_load-error.dump b/libraries/test_data/src/test/assets/playbackdumps/dash/ttml-in-mp4_load-error.dump new file mode 100644 index 0000000000..489a107bc7 --- /dev/null +++ b/libraries/test_data/src/test/assets/playbackdumps/dash/ttml-in-mp4_load-error.dump @@ -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 = [] diff --git a/libraries/test_data/src/test/assets/playbackdumps/dash/ttml-in-mp4_parse-error.dump b/libraries/test_data/src/test/assets/playbackdumps/dash/ttml-in-mp4_parse-error.dump new file mode 100644 index 0000000000..489a107bc7 --- /dev/null +++ b/libraries/test_data/src/test/assets/playbackdumps/dash/ttml-in-mp4_parse-error.dump @@ -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 = [] diff --git a/libraries/test_data/src/test/assets/playbackdumps/hls/standalone-webvtt_load-error.dump b/libraries/test_data/src/test/assets/playbackdumps/hls/standalone-webvtt_load-error.dump new file mode 100644 index 0000000000..489a107bc7 --- /dev/null +++ b/libraries/test_data/src/test/assets/playbackdumps/hls/standalone-webvtt_load-error.dump @@ -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 = [] diff --git a/libraries/test_data/src/test/assets/playbackdumps/hls/standalone-webvtt_parse-error.dump b/libraries/test_data/src/test/assets/playbackdumps/hls/standalone-webvtt_parse-error.dump new file mode 100644 index 0000000000..489a107bc7 --- /dev/null +++ b/libraries/test_data/src/test/assets/playbackdumps/hls/standalone-webvtt_parse-error.dump @@ -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 = [] diff --git a/libraries/test_data/src/test/assets/playbackdumps/hls/ttml-in-mp4_load-error.dump b/libraries/test_data/src/test/assets/playbackdumps/hls/ttml-in-mp4_load-error.dump new file mode 100644 index 0000000000..489a107bc7 --- /dev/null +++ b/libraries/test_data/src/test/assets/playbackdumps/hls/ttml-in-mp4_load-error.dump @@ -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 = [] diff --git a/libraries/test_data/src/test/assets/playbackdumps/hls/ttml-in-mp4_parse-error.dump b/libraries/test_data/src/test/assets/playbackdumps/hls/ttml-in-mp4_parse-error.dump new file mode 100644 index 0000000000..489a107bc7 --- /dev/null +++ b/libraries/test_data/src/test/assets/playbackdumps/hls/ttml-in-mp4_parse-error.dump @@ -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 = [] diff --git a/libraries/test_data/src/test/assets/playbackdumps/subtitles/sideloaded-parse-error.mp4.dump b/libraries/test_data/src/test/assets/playbackdumps/subtitles/sideloaded-parse-error.mp4.dump new file mode 100644 index 0000000000..553d61a65f --- /dev/null +++ b/libraries/test_data/src/test/assets/playbackdumps/subtitles/sideloaded-parse-error.mp4.dump @@ -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 = [] diff --git a/libraries/test_utils/src/main/java/androidx/media3/test/utils/ThrowingSubtitleParserFactory.java b/libraries/test_utils/src/main/java/androidx/media3/test/utils/ThrowingSubtitleParserFactory.java new file mode 100644 index 0000000000..1593b8f75d --- /dev/null +++ b/libraries/test_utils/src/main/java/androidx/media3/test/utils/ThrowingSubtitleParserFactory.java @@ -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}. + * + *

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 exceptionSupplier; + + public ThrowingSubtitleParserFactory(Supplier 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 output) { + throw exceptionSupplier.get(); + } + + @Override + public @Format.CueReplacementBehavior int getCueReplacementBehavior() { + return REPLACEMENT_BEHAVIOR; + } + }; + } +}