androidx / media

Jetpack Media3 support libraries for media use cases, including ExoPlayer, an extensible media player for Android
https://developer.android.com/media/media3
Apache License 2.0
1.65k stars 390 forks source link

Duplicate child manifest and segment is loaded at the beginning of HLS playback #1356

Open mayurk2 opened 5 months ago

mayurk2 commented 5 months ago

Version

ExoPlayer 2.16.1, 2.18.2

More version details

We are using Exoplayer 2.16.1 demo player in our application. We are observing that in case of HLS playback, the Exoplayer downloads a duplicate child manifest and segment at start up.

I am able to reproduce the issue with the demo app and sample stream under HLS section.

      {
        "name": "Apple 4x3 basic stream (TS)",
        "uri": "https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_4x3/bipbop_4x3_variant.m3u8"
      },

Here is the screenshot from the Charles log:

Screenshot 2024-05-09 at 1 36 44 PM

I see that it with this file it always downloads gear1/prog_index.m3u8 and gear1/fileSequence0.ts but again gear3/prog_index.m3u8 and gear3/fileSequence0.ts. Please note that this issue is seen with all HLS contents and with good/bad network cases.

This is impacting overall start up time of the player and consuming extra data.

I am able to reproduce similar issue on Exoplayer 2.18.2 as well. But the only difference is in that version it downloads only the duplicate child manifest and not the segment.

Is this a known issue? Can we resolve this with any steps?

Devices that reproduce the issue

Tested on multiple android phones (Redmi Note 9 Pro, Oneplus Nord CE2 5G). Reproducible on all phones.

Devices that do not reproduce the issue

No response

Reproducible in the demo app?

Yes

Reproduction steps

  1. Install the demo app.
  2. Play some HLS content -
      {
        "name": "Apple 4x3 basic stream (TS)",
        "uri": "https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_4x3/bipbop_4x3_variant.m3u8"
      },

Expected result

It should download single child manifest and segment at the beginning (at least in good network case). During playback it may download different child manifest and segments.

Actual result

It is always downloading 2 child manifest and 2 segments at the beginning of the playback (For timestamp 0).

Media

Can be reproducible with demo app.

HLS > Apple 4x3 basic stream (TS)

      {
        "name": "Apple 4x3 basic stream (TS)",
        "uri": "https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_4x3/bipbop_4x3_variant.m3u8"
      },

Bug Report

icbaker commented 5 months ago

I suspect the difference you're seeing between 2.16.1 and 2.18.2 is due to HLS chunkless preparation being enabled by default in 2.17.0. You can enable it manually in 2.16.1 to see if that changes the behaviour you observe. More details here: https://medium.com/google-exoplayer/faster-hls-preparation-f6611aa15ea6


Using the latest version of the media3 demo app, I also observe two media playlists being loaded before segments from the second one are loaded:

uri=https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_4x3/bipbop_4x3_variant.m3u8
uri=https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_4x3/gear1/prog_index.m3u8
uri=https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_4x3/gear4/prog_index.m3u8
uri=https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_4x3/gear4/fileSequence0.ts
uri=https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_4x3/gear4/fileSequence1.ts

Over to @tianyif to comment on this part.

mayurk2 commented 5 months ago

@tianyif did you get a chance to check this ^^

tianyif commented 5 months ago

Hi @mayurk2,

Thanks for the question!

The playlist gear1/prog_index.m3u8 and segment gear1/fileSequence0.ts are downloaded when the HlsMediaSource and HlsMediaPeriod are being prepared. Here are some facts:

1) In the default HLS implementation, after the multivariant playlist has been fetched, it uses the first variant url as the primary media playlist url, gets that media playlist and establish the timeline. At this point, the track selection hasn't done yet.

2) Once the timeline is available, the ExoPlayer will create a HlsMediaPeriod and prepare it. Like @icbaker already said, in 2.16.1, the chunkless preparation hasn't been enabled by default, then HlsMediaPeriod is prepared in a "chunkfull" way, which means that it needs to download a chunk of media, in order to build the tracks. And this behaviour was improved by the chunkless preparation, where it can build the tracks based on the multivariant playlist, if the multivariant playlist contains the sufficient track information.

3) After the period is prepared, ExoPlayer will have the track selector to select the tracks, and applies the selected tracks to the period, and that's also when the ABR algorithm is in effect. As the period loads the chunks, it will loads the selected playlist and the corresponding segments. So here comes the gear3/prog_index.m3u8 and gear3/fileSequence0.ts.

The chunkless preparation feature in 2) was enabled as default in 2.17.0, so in 2.18.2 you can see the gear1/fileSequence0.ts is no longer downloaded. However, the inefficiency in 1) remains, and we are now using https://github.com/google/ExoPlayer/issues/8826 to track this enhancement.

Hope the above information helps!