question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Default SingleSampleMediaSource.treatLoadErrorsAsEndOfStream to true

See original GitHub issue
  • ExoPlayer version number : 2.12.2 and 2.12.1
  • Android version : Android 10 (not OS specific)
  • Android device : Not device specific

Steps to reproduce:

  1. Pass the external subtitle url to media item. Can replace this method in source code with the following method.

I have appended _xyz in the vtt url.

private static List<MediaItem.Subtitle> createSubtitlesFromIntent(
      Intent intent, String extrasKeySuffix) {
//    if (!intent.hasExtra(SUBTITLE_URI_EXTRA + extrasKeySuffix)) {
//      return Collections.emptyList();
//    }
    String url = "https://storage.googleapis.com/exoplayer-test-media-1_xyz/webvtt/numeric-lines.vtt";
    MediaItem.Subtitle subtitleMediaItem = new MediaItem.Subtitle(Uri.parse(url), MimeTypes.TEXT_VTT,"en", C.SELECTION_FLAG_DEFAULT, C.ROLE_FLAG_SUBTITLE, "ENGLISH-ZEE");

    return Collections.singletonList(subtitleMediaItem);
  }
  1. Run any content and playback will fail.

Logcat

2021-01-05 19:14:08.615 31453-31570/com.google.android.exoplayer2.demo E/ExoPlayerImplInternal: Playback error
      com.google.android.exoplayer2.ExoPlaybackException: Source error
        at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:554)
        at android.os.Handler.dispatchMessage(Handler.java:98)
        at android.os.Looper.loop(Looper.java:165)
        at android.os.HandlerThread.run(HandlerThread.java:61)
     Caused by: com.google.android.exoplayer2.upstream.HttpDataSource$InvalidResponseCodeException: Response code: 404
        at com.google.android.exoplayer2.ext.cronet.CronetDataSource.open(CronetDataSource.java:486)
        at com.google.android.exoplayer2.upstream.DefaultDataSource.open(DefaultDataSource.java:199)
        at com.google.android.exoplayer2.upstream.cache.CacheDataSource.openNextSource(CacheDataSource.java:764)
        at com.google.android.exoplayer2.upstream.cache.CacheDataSource.open(CacheDataSource.java:579)
        at com.google.android.exoplayer2.upstream.StatsDataSource.open(StatsDataSource.java:84)
        at com.google.android.exoplayer2.source.SingleSampleMediaPeriod$SourceLoadable.load(SingleSampleMediaPeriod.java:428)
        at com.google.android.exoplayer2.upstream.Loader$LoadTask.run(Loader.java:415)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
        at java.lang.Thread.run(Thread.java:760)

Some Background

Prior exoplayer 2.12.1, we were passing DefaultLoadErrorHandlingPolicy and here we were listening to Exception but after 2.12.1 this API does not seem to be working. We tried it but we are not getting any callback.

Following class we have added to listen the callback before 2.12.1 and it was fine. It means if the subtitle does not work, we listen to it and it does not hamper the playback.


public class ExternalTextTrackLoadErrorPolicy extends DefaultLoadErrorHandlingPolicy {

    private static final PKLog log = PKLog.get("ExternalTextTrackLoadError");

    private ExternalTextTrackLoadErrorPolicy.OnTextTrackLoadErrorListener textTrackLoadErrorListener;

    public interface OnTextTrackLoadErrorListener {
        void onTextTrackLoadError(PKError currentError);
    }

    public void setOnTextTrackErrorListener(ExternalTextTrackLoadErrorPolicy.OnTextTrackLoadErrorListener onTextTrackErrorListener) {
        this.textTrackLoadErrorListener = onTextTrackErrorListener;
    }

    //public void onTextTrackLoadError(PKError currentError) {
    //    textTrackLoadErrorListener.onTextTrackLoadError(currentError);
    //} TODO // need to test with vtt errored file

    @Override
    public long getRetryDelayMsFor(LoadErrorInfo loadErrorInfo) {
        if (loadErrorInfo == null) {
            return Consts.TIME_UNSET;
        }

        IOException exception = loadErrorInfo.exception;
        Uri pathSegment = getPathSegmentUri(exception);
        if (pathSegment == null || !(exception instanceof HttpDataSource.HttpDataSourceException)) {
            return super.getRetryDelayMsFor(loadErrorInfo);
        }


        String lastPathSegment = pathSegment.getLastPathSegment();
        if (lastPathSegment != null && (lastPathSegment.endsWith(PKSubtitleFormat.vtt.pathExt) || lastPathSegment.endsWith(PKSubtitleFormat.srt.pathExt))) {
            PKError currentError = new PKError(PKPlayerErrorType.SOURCE_ERROR, PKError.Severity.Recoverable, "TextTrack is invalid url=" + pathSegment, exception);
            if (textTrackLoadErrorListener != null) {
                log.e("Error-Event sent, type = " + PKPlayerErrorType.SOURCE_ERROR);
                textTrackLoadErrorListener.onTextTrackLoadError(currentError);
            }
            return Consts.TIME_UNSET;
        } else {
            return super.getRetryDelayMsFor(loadErrorInfo);
        }
    }

    private Uri getPathSegmentUri(IOException ioException) {
        DataSpec dataSpec = null;
        if (ioException instanceof HttpDataSource.InvalidResponseCodeException) {
            dataSpec = ((HttpDataSource.InvalidResponseCodeException) ioException).dataSpec;
        } else if (ioException instanceof HttpDataSource.HttpDataSourceException) {
            dataSpec = ((HttpDataSource.HttpDataSourceException) ioException).dataSpec;
        }

        if (dataSpec != null) {
            return dataSpec.uri;
        }
        return null;
    }
}


Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:9 (5 by maintainers)

github_iconTop GitHub Comments

2reactions
icbakercommented, Jan 13, 2021

We plan to handle treatLoadErrorsAsEndOfStream in some way (possibly by adding it to MediaItem.Subtitle, possibly by defaulting to it to true, or possibly by other means).

We haven’t made this change yet (hence this issue is still open), so yes it’s not included in 2.12.3 released today.

2reactions
icbakercommented, Jan 8, 2021

Thanks for the branch - using that I’m able to reproduce what you’re seeing, and using the debugger I pinned down the problem - you’re right that basically your policy is being accidentally dropped internally. Specifically here, it needs to be propagated down to the SingleSampleMediaSource.Factory: https://github.com/google/ExoPlayer/blob/107fed9b2afc1e1edce95eee4a1fbc952377efd2/library/core/src/main/java/com/google/android/exoplayer2/source/DefaultMediaSourceFactory.java#L253-L254

I’ve sent a fix for this - it should be included in 2.12.3 which will be released before the end of the month.

Note that even with this fix, your content doesn’t play in your LoadErrorHandlingPolicy branch - but I think that’s due to the implementation of your policy - the execution does now reach the getRetryDelayMsFor method.

Read more comments on GitHub >

github_iconTop Results From Across the Web

SingleSampleMediaSource.Factory (ExoPlayer library)
The default value is true. Parameters: treatLoadErrorsAsEndOfStream - If true, load errors will not be propagated by sample streams, treating them as ended ......
Read more >
SingleSampleMediaSource.Factory - Android Developers
The default value is true. Parameters. treatLoadErrorsAsEndOfStream: Boolean. If true, load errors will not be propagated by sample streams, ...
Read more >
SingleSampleMediaSource.Factory - androidx.* javadoc
treatLoadErrorsAsEndOfStream: If true, load errors will not be propagated by sample streams, treating them as ended instead.
Read more >
com.google.android.exoplayer2.upstream ...
@Deprecated public SingleSampleMediaSource( Uri uri, DataSource. ... @param treatLoadErrorsAsEndOfStream If true, load errors will not be propagated by ...
Read more >
RELEASENOTES.md - google/ExoPlayer - Sourcegraph
Default SingleSampleMediaSource.treatLoadErrorsAsEndOfStream to true so that errors loading external subtitle files do not cause playback to fail (#8430).
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found