Skip to content

HLS download fails when EXT-X-DEFINE variables from multivariant playlist are used in media playlist segment URLs #3258

@prashant9934

Description

@prashant9934

Version

Media3 main branch

More version details

Media3 1.10.1 (and all prior versions)

Devices that reproduce the issue

All devices

Devices that do not reproduce the issue

No response

Reproducible in the demo app?

Yes

Reproduction steps

  1. Create a multivariant playlist that defines a variable:

master.m3u8:

#EXTM3U
#EXT-X-DEFINE:NAME="cdnPrefix",VALUE="https://cdn.example.com/ (https://cdn.example.com/)"
#EXT-X-STREAM-INF:BANDWIDTH=500000
media.m3u8

media.m3u8:

#EXTM3U
#EXT-X-TARGETDURATION:10
#EXT-X-VERSION:8
#EXTINF:10,
{$cdnPrefix}segment001.ts
#EXTINF:10,
{$cdnPrefix}segment002.ts
#EXT-X-ENDLIST

  1. Host these files on any HTTP server (or use FakeDataSource in a test)
  2. Create a DownloadRequest for master.m3u8 and add it to DownloadManager
  3. Observe that segment requests go to the literal URL {$cdnPrefix}segment001.ts instead of https://cdn.example.com/segment001.ts

Note

Playback works correctly because HlsPlaylistTracker passes the multivariant playlist to the parser. The download path (HlsDownloaderSegmentDownloader) uses a single HlsPlaylistParser() that never
stores the parsed multivariant playlist, so variable definitions are unavailable when media playlists are parsed.

Expected result

Variables defined in the multivariant playlist should resolve in media playlist segment URLs during download, matching the playback behavior.

Actual result

HlsDownloader uses a single HlsPlaylistParser() instance (constructed with HlsMultivariantPlaylist.EMPTY). After parsing the multivariant playlist, the result
is not stored back into the parser. When media playlists are subsequently parsed by the same instance, multivariantPlaylist is still EMPTY, so
variableDefinitions is unavailable and {$variable} references pass through unsubstituted.

This causes:

  • Download failures (HTTP 404/400 on malformed URLs)
  • IndexOutOfBoundsException in HlsMediaPeriod.getStreamKeys() when DownloadHelper.getDownloadRequest() is called

Stack trace:

java.lang.IndexOutOfBoundsException: index (0) must be less than size (0)
at com.google.common.base.Preconditions.checkElementIndex(Preconditions.java:1372)
at com.google.common.collect.RegularImmutableList.get(RegularImmutableList.java:84)
at androidx.media3.exoplayer.hls.HlsMediaPeriod.getStreamKeys(HlsMediaPeriod.java:289)
at androidx.media3.exoplayer.offline.DownloadHelper.getDownloadRequestBuilder(DownloadHelper.java:939)
at androidx.media3.exoplayer.offline.DownloadHelper.getDownloadRequest(DownloadHelper.java:891)

Analysis

  • Playback works because HlsPlaylistTracker creates HlsPlaylistParser(multivariantPlaylist, ...) with the real multivariant playlist.
  • Download fails because HlsDownloader (via SegmentDownloader) uses the same parser instance for both master and media playlists, but the parser never stores
    the parsed multivariant playlist for reuse.

The fix is to make HlsPlaylistParser store the multivariant playlist after parsing it in parse(), so subsequent media playlist parses on the same instance
inherit the variable definitions.

Media

No DRM

Bug Report

Metadata

Metadata

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions