Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
SDK
/
exoplayer
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
88de7745
authored
Apr 17, 2020
by
bachinger
Browse files
Options
_('Browse Files')
Download
Plain Diff
Merge pull request #6270 from TiVo:p-iframe-only-playlist
PiperOrigin-RevId: 306677468
parents
ed977d14
8c4d31a9
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
106 additions
and
10 deletions
library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistParser.java
library/hls/src/test/java/com/google/android/exoplayer2/source/hls/playlist/HlsMasterPlaylistParserTest.java
library/hls/src/test/java/com/google/android/exoplayer2/source/hls/playlist/HlsMediaPlaylistParserTest.java
library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistParser.java
View file @
88de7745
...
@@ -69,6 +69,8 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
...
@@ -69,6 +69,8 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
private
static
final
String
TAG_PLAYLIST_TYPE
=
"#EXT-X-PLAYLIST-TYPE"
;
private
static
final
String
TAG_PLAYLIST_TYPE
=
"#EXT-X-PLAYLIST-TYPE"
;
private
static
final
String
TAG_DEFINE
=
"#EXT-X-DEFINE"
;
private
static
final
String
TAG_DEFINE
=
"#EXT-X-DEFINE"
;
private
static
final
String
TAG_STREAM_INF
=
"#EXT-X-STREAM-INF"
;
private
static
final
String
TAG_STREAM_INF
=
"#EXT-X-STREAM-INF"
;
private
static
final
String
TAG_I_FRAME_STREAM_INF
=
"#EXT-X-I-FRAME-STREAM-INF"
;
private
static
final
String
TAG_IFRAME
=
"#EXT-X-I-FRAMES-ONLY"
;
private
static
final
String
TAG_MEDIA
=
"#EXT-X-MEDIA"
;
private
static
final
String
TAG_MEDIA
=
"#EXT-X-MEDIA"
;
private
static
final
String
TAG_TARGET_DURATION
=
"#EXT-X-TARGETDURATION"
;
private
static
final
String
TAG_TARGET_DURATION
=
"#EXT-X-TARGETDURATION"
;
private
static
final
String
TAG_DISCONTINUITY
=
"#EXT-X-DISCONTINUITY"
;
private
static
final
String
TAG_DISCONTINUITY
=
"#EXT-X-DISCONTINUITY"
;
...
@@ -281,6 +283,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
...
@@ -281,6 +283,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
// We expose all tags through the playlist.
// We expose all tags through the playlist.
tags
.
add
(
line
);
tags
.
add
(
line
);
}
}
boolean
isIFrameOnlyVariant
=
line
.
startsWith
(
TAG_I_FRAME_STREAM_INF
);
if
(
line
.
startsWith
(
TAG_DEFINE
))
{
if
(
line
.
startsWith
(
TAG_DEFINE
))
{
variableDefinitions
.
put
(
variableDefinitions
.
put
(
...
@@ -301,8 +304,9 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
...
@@ -301,8 +304,9 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
String
scheme
=
parseEncryptionScheme
(
method
);
String
scheme
=
parseEncryptionScheme
(
method
);
sessionKeyDrmInitData
.
add
(
new
DrmInitData
(
scheme
,
schemeData
));
sessionKeyDrmInitData
.
add
(
new
DrmInitData
(
scheme
,
schemeData
));
}
}
}
else
if
(
line
.
startsWith
(
TAG_STREAM_INF
))
{
}
else
if
(
line
.
startsWith
(
TAG_STREAM_INF
)
||
isIFrameOnlyVariant
)
{
noClosedCaptions
|=
line
.
contains
(
ATTR_CLOSED_CAPTIONS_NONE
);
noClosedCaptions
|=
line
.
contains
(
ATTR_CLOSED_CAPTIONS_NONE
);
int
roleFlags
=
isIFrameOnlyVariant
?
C
.
ROLE_FLAG_TRICK_PLAY
:
0
;
int
peakBitrate
=
parseIntAttr
(
line
,
REGEX_BANDWIDTH
);
int
peakBitrate
=
parseIntAttr
(
line
,
REGEX_BANDWIDTH
);
int
averageBitrate
=
parseOptionalIntAttr
(
line
,
REGEX_AVERAGE_BANDWIDTH
,
-
1
);
int
averageBitrate
=
parseOptionalIntAttr
(
line
,
REGEX_AVERAGE_BANDWIDTH
,
-
1
);
String
codecs
=
parseOptionalStringAttr
(
line
,
REGEX_CODECS
,
variableDefinitions
);
String
codecs
=
parseOptionalStringAttr
(
line
,
REGEX_CODECS
,
variableDefinitions
);
...
@@ -335,13 +339,18 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
...
@@ -335,13 +339,18 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
parseOptionalStringAttr
(
line
,
REGEX_SUBTITLES
,
variableDefinitions
);
parseOptionalStringAttr
(
line
,
REGEX_SUBTITLES
,
variableDefinitions
);
String
closedCaptionsGroupId
=
String
closedCaptionsGroupId
=
parseOptionalStringAttr
(
line
,
REGEX_CLOSED_CAPTIONS
,
variableDefinitions
);
parseOptionalStringAttr
(
line
,
REGEX_CLOSED_CAPTIONS
,
variableDefinitions
);
if
(!
iterator
.
hasNext
())
{
Uri
uri
;
throw
new
ParserException
(
"#EXT-X-STREAM-INF tag must be followed by another line"
);
if
(
isIFrameOnlyVariant
)
{
uri
=
UriUtil
.
resolveToUri
(
baseUri
,
parseStringAttr
(
line
,
REGEX_URI
,
variableDefinitions
));
}
else
if
(!
iterator
.
hasNext
())
{
throw
new
ParserException
(
"#EXT-X-STREAM-INF must be followed by another line"
);
}
else
{
// The following line contains #EXT-X-STREAM-INF's URI.
line
=
replaceVariableReferences
(
iterator
.
next
(),
variableDefinitions
);
uri
=
UriUtil
.
resolveToUri
(
baseUri
,
line
);
}
}
line
=
replaceVariableReferences
(
iterator
.
next
(),
variableDefinitions
);
// #EXT-X-STREAM-INF's URI.
Uri
uri
=
UriUtil
.
resolveToUri
(
baseUri
,
line
);
Format
format
=
Format
format
=
new
Format
.
Builder
()
new
Format
.
Builder
()
.
setId
(
variants
.
size
())
.
setId
(
variants
.
size
())
...
@@ -352,6 +361,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
...
@@ -352,6 +361,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
.
setWidth
(
width
)
.
setWidth
(
width
)
.
setHeight
(
height
)
.
setHeight
(
height
)
.
setFrameRate
(
frameRate
)
.
setFrameRate
(
frameRate
)
.
setRoleFlags
(
roleFlags
)
.
build
();
.
build
();
Variant
variant
=
Variant
variant
=
new
Variant
(
new
Variant
(
...
@@ -558,8 +568,9 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
...
@@ -558,8 +568,9 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
long
targetDurationUs
=
C
.
TIME_UNSET
;
long
targetDurationUs
=
C
.
TIME_UNSET
;
boolean
hasIndependentSegmentsTag
=
masterPlaylist
.
hasIndependentSegments
;
boolean
hasIndependentSegmentsTag
=
masterPlaylist
.
hasIndependentSegments
;
boolean
hasEndTag
=
false
;
boolean
hasEndTag
=
false
;
Segment
initializationSegment
=
null
;
@Nullable
Segment
initializationSegment
=
null
;
HashMap
<
String
,
String
>
variableDefinitions
=
new
HashMap
<>();
HashMap
<
String
,
String
>
variableDefinitions
=
new
HashMap
<>();
HashMap
<
String
,
Segment
>
urlToInferredInitSegment
=
new
HashMap
<>();
List
<
Segment
>
segments
=
new
ArrayList
<>();
List
<
Segment
>
segments
=
new
ArrayList
<>();
List
<
String
>
tags
=
new
ArrayList
<>();
List
<
String
>
tags
=
new
ArrayList
<>();
...
@@ -572,6 +583,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
...
@@ -572,6 +583,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
long
segmentStartTimeUs
=
0
;
long
segmentStartTimeUs
=
0
;
long
segmentByteRangeOffset
=
0
;
long
segmentByteRangeOffset
=
0
;
long
segmentByteRangeLength
=
C
.
LENGTH_UNSET
;
long
segmentByteRangeLength
=
C
.
LENGTH_UNSET
;
boolean
isIFrameOnly
=
false
;
long
segmentMediaSequence
=
0
;
long
segmentMediaSequence
=
0
;
boolean
hasGapTag
=
false
;
boolean
hasGapTag
=
false
;
...
@@ -598,6 +610,8 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
...
@@ -598,6 +610,8 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
}
else
if
(
"EVENT"
.
equals
(
playlistTypeString
))
{
}
else
if
(
"EVENT"
.
equals
(
playlistTypeString
))
{
playlistType
=
HlsMediaPlaylist
.
PLAYLIST_TYPE_EVENT
;
playlistType
=
HlsMediaPlaylist
.
PLAYLIST_TYPE_EVENT
;
}
}
}
else
if
(
line
.
equals
(
TAG_IFRAME
))
{
isIFrameOnly
=
true
;
}
else
if
(
line
.
startsWith
(
TAG_START
))
{
}
else
if
(
line
.
startsWith
(
TAG_START
))
{
startOffsetUs
=
(
long
)
(
parseDoubleAttr
(
line
,
REGEX_TIME_OFFSET
)
*
C
.
MICROS_PER_SECOND
);
startOffsetUs
=
(
long
)
(
parseDoubleAttr
(
line
,
REGEX_TIME_OFFSET
)
*
C
.
MICROS_PER_SECOND
);
}
else
if
(
line
.
startsWith
(
TAG_INIT_SEGMENT
))
{
}
else
if
(
line
.
startsWith
(
TAG_INIT_SEGMENT
))
{
...
@@ -715,8 +729,25 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
...
@@ -715,8 +729,25 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
}
}
segmentMediaSequence
++;
segmentMediaSequence
++;
String
segmentUri
=
replaceVariableReferences
(
line
,
variableDefinitions
);
@Nullable
Segment
inferredInitSegment
=
urlToInferredInitSegment
.
get
(
segmentUri
);
if
(
segmentByteRangeLength
==
C
.
LENGTH_UNSET
)
{
if
(
segmentByteRangeLength
==
C
.
LENGTH_UNSET
)
{
// The segment is not byte range defined.
segmentByteRangeOffset
=
0
;
segmentByteRangeOffset
=
0
;
}
else
if
(
isIFrameOnly
&&
initializationSegment
==
null
&&
inferredInitSegment
==
null
)
{
// The segment is a resource byte range without an initialization segment.
// As per RFC 8216, Section 4.3.3.6, we assume the initialization section exists in the
// bytes preceding the first segment in this segment's URL.
// We assume the implicit initialization segment is unencrypted, since there's no way for
// the playlist to provide an initialization vector for it.
inferredInitSegment
=
new
Segment
(
segmentUri
,
/* byteRangeOffset= */
0
,
segmentByteRangeOffset
,
/* fullSegmentEncryptionKeyUri= */
null
,
/* encryptionIV= */
null
);
urlToInferredInitSegment
.
put
(
segmentUri
,
inferredInitSegment
);
}
}
if
(
cachedDrmInitData
==
null
&&
!
currentSchemeDatas
.
isEmpty
())
{
if
(
cachedDrmInitData
==
null
&&
!
currentSchemeDatas
.
isEmpty
())
{
...
@@ -733,8 +764,8 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
...
@@ -733,8 +764,8 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
segments
.
add
(
segments
.
add
(
new
Segment
(
new
Segment
(
replaceVariableReferences
(
line
,
variableDefinitions
)
,
segmentUri
,
initializationSegment
,
initializationSegment
!=
null
?
initializationSegment
:
inferredInitSegment
,
segmentTitle
,
segmentTitle
,
segmentDurationUs
,
segmentDurationUs
,
relativeDiscontinuitySequence
,
relativeDiscontinuitySequence
,
...
...
library/hls/src/test/java/com/google/android/exoplayer2/source/hls/playlist/HlsMasterPlaylistParserTest.java
View file @
88de7745
...
@@ -25,6 +25,7 @@ import com.google.android.exoplayer2.Format;
...
@@ -25,6 +25,7 @@ import com.google.android.exoplayer2.Format;
import
com.google.android.exoplayer2.ParserException
;
import
com.google.android.exoplayer2.ParserException
;
import
com.google.android.exoplayer2.metadata.Metadata
;
import
com.google.android.exoplayer2.metadata.Metadata
;
import
com.google.android.exoplayer2.source.hls.HlsTrackMetadataEntry
;
import
com.google.android.exoplayer2.source.hls.HlsTrackMetadataEntry
;
import
com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist.Variant
;
import
com.google.android.exoplayer2.util.MimeTypes
;
import
com.google.android.exoplayer2.util.MimeTypes
;
import
java.io.ByteArrayInputStream
;
import
java.io.ByteArrayInputStream
;
import
java.io.IOException
;
import
java.io.IOException
;
...
@@ -207,6 +208,22 @@ public class HlsMasterPlaylistParserTest {
...
@@ -207,6 +208,22 @@ public class HlsMasterPlaylistParserTest {
+
"#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID=\"aud1\",NAME=\"English\",URI=\"a1/index.m3u8\"\n"
+
"#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID=\"aud1\",NAME=\"English\",URI=\"a1/index.m3u8\"\n"
+
"#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID=\"sub1\",NAME=\"English\",AUTOSELECT=YES,DEFAULT=YES,URI=\"s1/en/prog_index.m3u8\"\n"
;
+
"#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID=\"sub1\",NAME=\"English\",AUTOSELECT=YES,DEFAULT=YES,URI=\"s1/en/prog_index.m3u8\"\n"
;
private
static
final
String
PLAYLIST_WITH_IFRAME_VARIANTS
=
"#EXTM3U\n"
+
"#EXT-X-VERSION:5\n"
+
"#EXT-X-MEDIA:URI=\"AUDIO_English/index.m3u8\",TYPE=AUDIO,GROUP-ID=\"audio-aac\",LANGUAGE=\"en\",NAME=\"English\",AUTOSELECT=YES\n"
+
"#EXT-X-MEDIA:URI=\"AUDIO_Spanish/index.m3u8\",TYPE=AUDIO,GROUP-ID=\"audio-aac\",LANGUAGE=\"es\",NAME=\"Spanish\",AUTOSELECT=YES\n"
+
"#EXT-X-MEDIA:TYPE=CLOSED-CAPTIONS,GROUP-ID=\"cc1\",LANGUAGE=\"en\",NAME=\"English\",AUTOSELECT=YES,DEFAULT=YES,INSTREAM-ID=\"CC1\"\n"
+
"#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=400000,RESOLUTION=480x320,CODECS=\"mp4a.40.2,avc1.640015\",AUDIO=\"audio-aac\",CLOSED-CAPTIONS=\"cc1\"\n"
+
"400000/index.m3u8\n"
+
"#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1000000,RESOLUTION=848x480,CODECS=\"mp4a.40.2,avc1.64001f\",AUDIO=\"audio-aac\",CLOSED-CAPTIONS=\"cc1\"\n"
+
"1000000/index.m3u8\n"
+
"#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=3220000,RESOLUTION=1280x720,CODECS=\"mp4a.40.2,avc1.64001f\",AUDIO=\"audio-aac\",CLOSED-CAPTIONS=\"cc1\"\n"
+
"3220000/index.m3u8\n"
+
"#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=8940000,RESOLUTION=1920x1080,CODECS=\"mp4a.40.2,avc1.640028\",AUDIO=\"audio-aac\",CLOSED-CAPTIONS=\"cc1\"\n"
+
"8940000/index.m3u8\n"
+
"#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=1313400,RESOLUTION=1920x1080,CODECS=\"avc1.640028\",URI=\"iframe_1313400/index.m3u8\"\n"
;
@Test
@Test
public
void
parseMasterPlaylist_withSimple_success
()
throws
IOException
{
public
void
parseMasterPlaylist_withSimple_success
()
throws
IOException
{
HlsMasterPlaylist
masterPlaylist
=
parseMasterPlaylist
(
PLAYLIST_URI
,
PLAYLIST_SIMPLE
);
HlsMasterPlaylist
masterPlaylist
=
parseMasterPlaylist
(
PLAYLIST_URI
,
PLAYLIST_SIMPLE
);
...
@@ -407,6 +424,19 @@ public class HlsMasterPlaylistParserTest {
...
@@ -407,6 +424,19 @@ public class HlsMasterPlaylistParserTest {
.
isEqualTo
(
createExtXMediaMetadata
(
/* groupId= */
"aud3"
,
/* name= */
"English"
));
.
isEqualTo
(
createExtXMediaMetadata
(
/* groupId= */
"aud3"
,
/* name= */
"English"
));
}
}
@Test
public
void
testIFrameVariant
()
throws
IOException
{
HlsMasterPlaylist
playlist
=
parseMasterPlaylist
(
PLAYLIST_URI
,
PLAYLIST_WITH_IFRAME_VARIANTS
);
assertThat
(
playlist
.
variants
).
hasSize
(
5
);
for
(
int
i
=
0
;
i
<
4
;
i
++)
{
assertThat
(
playlist
.
variants
.
get
(
i
).
format
.
roleFlags
).
isEqualTo
(
0
);
}
Variant
iFramesOnlyVariant
=
playlist
.
variants
.
get
(
4
);
assertThat
(
iFramesOnlyVariant
.
format
.
bitrate
).
isEqualTo
(
1313400
);
assertThat
(
iFramesOnlyVariant
.
format
.
roleFlags
&
C
.
ROLE_FLAG_TRICK_PLAY
)
.
isEqualTo
(
C
.
ROLE_FLAG_TRICK_PLAY
);
}
private
static
Metadata
createExtXStreamInfMetadata
(
HlsTrackMetadataEntry
.
VariantInfo
...
infos
)
{
private
static
Metadata
createExtXStreamInfMetadata
(
HlsTrackMetadataEntry
.
VariantInfo
...
infos
)
{
return
new
Metadata
(
return
new
Metadata
(
new
HlsTrackMetadataEntry
(
/* groupId= */
null
,
/* name= */
null
,
Arrays
.
asList
(
infos
)));
new
HlsTrackMetadataEntry
(
/* groupId= */
null
,
/* name= */
null
,
Arrays
.
asList
(
infos
)));
...
...
library/hls/src/test/java/com/google/android/exoplayer2/source/hls/playlist/HlsMediaPlaylistParserTest.java
View file @
88de7745
...
@@ -19,6 +19,7 @@ import static com.google.common.truth.Truth.assertThat;
...
@@ -19,6 +19,7 @@ import static com.google.common.truth.Truth.assertThat;
import
static
org
.
junit
.
Assert
.
fail
;
import
static
org
.
junit
.
Assert
.
fail
;
import
android.net.Uri
;
import
android.net.Uri
;
import
androidx.annotation.Nullable
;
import
androidx.test.ext.junit.runners.AndroidJUnit4
;
import
androidx.test.ext.junit.runners.AndroidJUnit4
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.ParserException
;
import
com.google.android.exoplayer2.ParserException
;
...
@@ -368,6 +369,40 @@ public class HlsMediaPlaylistParserTest {
...
@@ -368,6 +369,40 @@ public class HlsMediaPlaylistParserTest {
}
}
@Test
@Test
public
void
noExplicitInitSegmentInIFrameOnly_infersInitSegment
()
throws
IOException
{
Uri
playlistUri
=
Uri
.
parse
(
"https://example.com/test3.m3u8"
);
String
playlistString
=
"#EXTM3U\n"
+
"#EXT-X-TARGETDURATION:5\n"
+
"#EXT-X-I-FRAMES-ONLY\n"
+
"#EXTINF:5.005,\n"
+
"#EXT-X-BYTERANGE:100@300\n"
+
"segment1.ts\n"
+
"#EXTINF:5.005,\n"
+
"#EXT-X-BYTERANGE:100@400\n"
+
"segment2.ts\n"
+
"#EXTINF:5.005,\n"
+
"#EXT-X-BYTERANGE:100@400\n"
+
"segment1.ts\n"
;
InputStream
inputStream
=
new
ByteArrayInputStream
(
Util
.
getUtf8Bytes
(
playlistString
));
HlsMediaPlaylist
playlist
=
(
HlsMediaPlaylist
)
new
HlsPlaylistParser
().
parse
(
playlistUri
,
inputStream
);
List
<
Segment
>
segments
=
playlist
.
segments
;
@Nullable
Segment
initializationSegment
=
segments
.
get
(
0
).
initializationSegment
;
assertThat
(
initializationSegment
.
url
).
isEqualTo
(
"segment1.ts"
);
assertThat
(
initializationSegment
.
byteRangeOffset
).
isEqualTo
(
0
);
assertThat
(
initializationSegment
.
byteRangeLength
).
isEqualTo
(
300
);
initializationSegment
=
segments
.
get
(
1
).
initializationSegment
;
assertThat
(
initializationSegment
.
url
).
isEqualTo
(
"segment2.ts"
);
assertThat
(
initializationSegment
.
byteRangeOffset
).
isEqualTo
(
0
);
assertThat
(
initializationSegment
.
byteRangeLength
).
isEqualTo
(
400
);
initializationSegment
=
segments
.
get
(
2
).
initializationSegment
;
assertThat
(
initializationSegment
.
url
).
isEqualTo
(
"segment1.ts"
);
assertThat
(
initializationSegment
.
byteRangeOffset
).
isEqualTo
(
0
);
assertThat
(
initializationSegment
.
byteRangeLength
).
isEqualTo
(
300
);
}
@Test
public
void
encryptedMapTag
()
throws
IOException
{
public
void
encryptedMapTag
()
throws
IOException
{
Uri
playlistUri
=
Uri
.
parse
(
"https://example.com/test3.m3u8"
);
Uri
playlistUri
=
Uri
.
parse
(
"https://example.com/test3.m3u8"
);
String
playlistString
=
String
playlistString
=
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment