Skip to content

HLS Playlist with PlaylistType=Event cannot be loaded properly #9067

@dmytropiriatenets

Description

@dmytropiriatenets

Preconditions

To reproduce the issue it's required to have the .m3u8 master playlist with a list of several media playlist (i.e., one of them is for subtitles, all others are to cover different bandwidth).
Further by service I mean the one which prepares the playlist by request, and which ExoPlayer communicates directly with

Description

The issue happens with the HLS playlist which has PlaylistType=Event (EXT-X-PLAYLIST-TYPE:EVENT). The specific of such a playlist in the service implementation is that when it's requested first time from the service, the service returns partial playlist, which doens't have the EndTag (EXT-X-ENDLIST). Depending on the service load, after the second request the service might return either the full stream (which has EXT-X-ENDLIST), or another partial playlist but with more data, and this will continue till the list with EXT-X-ENDLIST tag received. [let's further call such playlists as HLS Event Stream [playlists]].

Since it's HLS Event Stream, the data could be appended to the end of the playlist (according to https://datatracker.ietf.org/doc/html/rfc8216)

Issue

When the playback of such a playlist starts, ExoPlayer cannot receive the full playlist and therefore, cannot get required metadata (like duration etc).
When the playback starts, the ExoPlayer starts loading different media playlist from the master playlist, and even though the loading happens properly (according to Web debugging proxy tool), the received data is not delivered properly inside the ExoPlayer framework.

Investigation

While investigating the ExoPlayer framework (using the ExoPlayer Demo app of the version 2.14.1), the code which causes the described behaviour was found in the DefaultHlsPlaylistTracker.
The following happens: different playlist are downloaded, the method processLoadedPlaylist is called, which calls onPlaylistUpdated (as expected). But inside the onPlaylistUpdated there's a check if (url.equals(primaryMediaPlaylistUrl)) which is false all the time. After some debugging, it turned out that HlsChunkSource calls getPlaylistSnapshot, this one calls maybeSetPrimaryUrl method, which might override the primaryMediaPlaylistUrl value (which basically happens always).
The method maybeSetPrimaryUrl is called many times, but it always called right after onPlaylistUpdated for the same url, which makes the if condition be false almost all the time (because primaryMediaPlaylistUrl remains the same after the previous maybeSetPrimaryUrl call).
(attaching some logs showing this behaviour)
Screenshot 2021-06-16 at 19 45 02
Because of not calling primaryPlaylistListener.onPrimaryPlaylistRefreshed(newSnapshot); (which is inside the if check), the SinglePeriodTimeline couldn't be created inside the HlsMediaSource::onPrimaryPlaylistRefreshed, which is a single place to create the timeline for Hls Playlist.

After creating the own implementation of DefaultHlsPlaylistTracker and removing the if (url.equals(primaryMediaPlaylistUrl)) check, the issue dissappeared, however, it couldn't be considered as a proper fix (unless you could confirm that it is).

Thanks in advance

Additional info

  • ExoPlayer version number: 2.14.1 (could be reproduced on earlier versions, like 2.12.1)
  • Android version: API 28 (could be reproduced on other versions as well)
  • Android device: (Android Emulator API 28, Xiaomi Mi Box, Google Pixel 2 XL)

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions