From 49dec5db8b1b220f7c9a3e805e0087d775239a0b Mon Sep 17 00:00:00 2001 From: ibaker Date: Thu, 17 Oct 2024 07:12:20 -0700 Subject: [PATCH] Ignore renderer errors from text/metadata tracks Before this change: * With legacy subtitle decoding (at render time), load errors (e.g. HTTP 404) would result playback completely failing, while parse errors (e.g. invalid WebVTT data) would be silently ignored, so playback would continue without subtitles. * With new subtitle decoding (at extraction time), both load and parse errors would result in playback completely failing. This change means that now neither load nor parse errors in text or metadata tracks stop playback from continuing. Instead the error'd track is disabled until the end of the current period. With new subtitle decoding, both load and parse errors happen during loading/extraction, and so are emitted to the app via `MediaSourceEventListener.onLoadError` and `AnalyticsListener.onLoadError`. With legacy subtitle decoding, only load errors are emitted via these listeners and parsing errors continue to be silently ignored. Issue: androidx/media#1722 PiperOrigin-RevId: 686902979 --- RELEASENOTES.md | 10 + .../exoplayer/ExoPlayerImplInternal.java | 44 +- .../media3/exoplayer/text/TextRenderer.java | 32 + .../e2etest/SubtitlePlaybackTest.java | 179 +++++ .../dash/e2etest/DashPlaybackTest.java | 189 +++++ .../hls/e2etest/HlsPlaybackTest.java | 176 +++++ .../dash/standalone-webvtt_load-error.dump | 226 ++++++ .../dash/standalone-webvtt_parse-error.dump | 226 ++++++ .../dash/ttml-in-mp4_load-error.dump | 226 ++++++ .../dash/ttml-in-mp4_parse-error.dump | 226 ++++++ .../hls/standalone-webvtt_load-error.dump | 226 ++++++ .../hls/standalone-webvtt_parse-error.dump | 226 ++++++ .../hls/ttml-in-mp4_load-error.dump | 226 ++++++ .../hls/ttml-in-mp4_parse-error.dump | 226 ++++++ .../subtitles/sideloaded-parse-error.mp4.dump | 691 ++++++++++++++++++ .../utils/ThrowingSubtitleParserFactory.java | 73 ++ 16 files changed, 3200 insertions(+), 2 deletions(-) create mode 100644 libraries/exoplayer/src/test/java/androidx/media3/exoplayer/e2etest/SubtitlePlaybackTest.java create mode 100644 libraries/test_data/src/test/assets/playbackdumps/dash/standalone-webvtt_load-error.dump create mode 100644 libraries/test_data/src/test/assets/playbackdumps/dash/standalone-webvtt_parse-error.dump create mode 100644 libraries/test_data/src/test/assets/playbackdumps/dash/ttml-in-mp4_load-error.dump create mode 100644 libraries/test_data/src/test/assets/playbackdumps/dash/ttml-in-mp4_parse-error.dump create mode 100644 libraries/test_data/src/test/assets/playbackdumps/hls/standalone-webvtt_load-error.dump create mode 100644 libraries/test_data/src/test/assets/playbackdumps/hls/standalone-webvtt_parse-error.dump create mode 100644 libraries/test_data/src/test/assets/playbackdumps/hls/ttml-in-mp4_load-error.dump create mode 100644 libraries/test_data/src/test/assets/playbackdumps/hls/ttml-in-mp4_parse-error.dump create mode 100644 libraries/test_data/src/test/assets/playbackdumps/subtitles/sideloaded-parse-error.mp4.dump create mode 100644 libraries/test_utils/src/main/java/androidx/media3/test/utils/ThrowingSubtitleParserFactory.java 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; + } + }; + } +}