Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unexpected runtime error (When Chunks have different playlist urls) #8937

Closed
KostyaLyapochkin opened this issue May 13, 2021 · 5 comments
Closed
Assignees
Labels

Comments

@KostyaLyapochkin
Copy link

KostyaLyapochkin commented May 13, 2021

Hi, I have caught an unexpected runtime error when I use HLS and codecNeedsSetOutputSurfaceWorkaround = true. For example, A xiaomi device like MiBox4 returns true, because it was established in the parent class - MediaCodecVideoRenderer.

When I change the configuration of a mobile phone or hide an app - ExoPlayer passes a nullable Surface to clear/release codec inside MediaCodecVideoRenderer. The error happens when chunks have differents playlists, for instance, I dived to the source code and found out that ExoPlayer has this kind of a code’s snippet like:

HlsMediaChunk.java 139 line - Where ExoPlayer checks playlist between the last and current chunk:

playlistUrl.equals(previousChunk.playlistUrl) // so, They are not equal.

then, 144 line:

boolean canContinueWithoutSplice =
   isFollowingChunk || (isIndependent && segmentStartTimeInPeriodUs >= previousChunk.endTimeUs);

shouldSpliceIn = !canContinueWithoutSplice;

as, isFollowingChunk is false and the right block too, I have shouldSpliceIn true

and the end of all, when ExoPlayer checkes state with Assertions.class in 319 line it converts true expression to false and checks state. For example:

public int getFirstSampleIndex(int sampleQueueIndex) {
 Assertions.checkState(!shouldSpliceIn); // convert true to false


public static void checkState(boolean expression) {
 if (ExoPlayerLibraryInfo.ASSERTIONS_ENABLED && !expression) {
   throw new IllegalStateException();
 }
}

How to replay the issue:

  1. You have to return true inside codecNeedsSetOutputSurfaceWorkaround method (It does not matter that you have emulators or real devices)
  2. Start playing with HLS (adaptive streaming)
  3. a little wait when player changes playlists between chunks (I use Charles to intercept these one’s)
  4. hide or rotate an app

In conclusion, the error happens, when the method codecNeedsSetOutputSurfaceWorkaround returns true and the render has chunks with different playlist urls inside. I consider that it's normal behaviour to have different urls in a queue. Full error stack:

Caused by: java.lang.IllegalStateException
        at com.google.android.exoplayer2.util.Assertions.checkState(Assertions.java:86)
        at com.google.android.exoplayer2.source.hls.HlsMediaChunk.getFirstSampleIndex(HlsMediaChunk.java:319)
        at com.google.android.exoplayer2.source.hls.HlsSampleStreamWrapper.skipData(HlsSampleStreamWrapper.java:638)
        at com.google.android.exoplayer2.source.hls.HlsSampleStream.skipData(HlsSampleStream.java:86)
        at com.google.android.exoplayer2.BaseRenderer.skipSource(BaseRenderer.java:427)
        at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.render(MediaCodecRenderer.java:829)
        at com.google.android.exoplayer2.ExoPlayerImplInternal.doSomeWork(ExoPlayerImplInternal.java:948)
        at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:478)
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        at android.os.Looper.loop(Looper.java:193) 
        at android.os.HandlerThread.run(HandlerThread.java:65) 
@KostyaLyapochkin KostyaLyapochkin changed the title Unexpected runtime error Unexpected runtime error (When Chunks have different playlist urls) May 13, 2021
@ojw28
Copy link
Contributor

ojw28 commented May 14, 2021

Note: Looks like a duplicate of #8890.

@christosts christosts assigned tonihei and unassigned christosts May 14, 2021
@christosts
Copy link
Contributor

@tonihei can you take a look?

@tonihei
Copy link
Collaborator

tonihei commented May 20, 2021

Yes, this is a bug introduced by 8349d78 (in 2.13.0). The method getFirstSampleIndex is not allowed to be called for spliced-in chunks (as we don't know the first sample index in this case) and we need to avoid calling this method for all chunks.

We'll provide a fix soon.

@KostyaLyapochkin
Copy link
Author

@tonihei Thanks for the feedback!

ojw28 pushed a commit that referenced this issue May 20, 2021
Preload chunks may still need to be discarded. However, we don't
currently support discarding spliced-in chunks. Thus, we need to
avoid loadng a preload chunk that needs to be spliced-in.

Issue: #8937

#minor-release

PiperOrigin-RevId: 374851661
ojw28 pushed a commit that referenced this issue May 21, 2021
We need to avoid reading and skipping into preload chunks as they
may need to be discarded. The current code iterates over all chunks,
but this can be simplified by just checking the last chunk knowing
that the preload chunk must always be the last one.

As a result, we avoid calling getFirstSampleIndex on all chunks. This
is a bug since the method is not allowed to be called for chunks
that have been spliced in. This still leaves the smaller issue of
potentially calling this method for spliced-in preload chunks, which
will be solved separately.

Issue: #8937

#minor-release

PiperOrigin-RevId: 375053638
@tonihei
Copy link
Collaborator

tonihei commented May 21, 2021

Issue should be fixed by the two commits above.

@tonihei tonihei closed this as completed May 21, 2021
ojw28 pushed a commit that referenced this issue Jun 10, 2021
Preload chunks may still need to be discarded. However, we don't
currently support discarding spliced-in chunks. Thus, we need to
avoid loadng a preload chunk that needs to be spliced-in.

Issue: #8937

#minor-release

PiperOrigin-RevId: 374851661
ojw28 pushed a commit that referenced this issue Jun 10, 2021
We need to avoid reading and skipping into preload chunks as they
may need to be discarded. The current code iterates over all chunks,
but this can be simplified by just checking the last chunk knowing
that the preload chunk must always be the last one.

As a result, we avoid calling getFirstSampleIndex on all chunks. This
is a bug since the method is not allowed to be called for chunks
that have been spliced in. This still leaves the smaller issue of
potentially calling this method for spliced-in preload chunks, which
will be solved separately.

Issue: #8937

PiperOrigin-RevId: 375053638
@google google locked and limited conversation to collaborators Jul 21, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

4 participants