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
ba0028ca
authored
Apr 15, 2020
by
olly
Committed by
Ian Baker
Apr 15, 2020
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Parse trick-play role flags from DASH manifests
Issue: #6054 PiperOrigin-RevId: 306641689
parent
50926658
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
158 additions
and
26 deletions
library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/AdaptationSet.java
library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/DashManifest.java
library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParser.java
library/dash/src/test/java/com/google/android/exoplayer2/source/dash/DashMediaPeriodTest.java
library/dash/src/test/java/com/google/android/exoplayer2/source/dash/DashUtilTest.java
library/dash/src/test/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParserTest.java
library/dash/src/test/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestTest.java
testdata/src/test/assets/mpd/sample_mpd_trick_play
library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/AdaptationSet.java
View file @
ba0028ca
...
...
@@ -50,9 +50,10 @@ public class AdaptationSet {
*/
public
final
List
<
Descriptor
>
accessibilityDescriptors
;
/**
* Supplemental properties in the adaptation set.
*/
/** Essential properties in the adaptation set. */
public
final
List
<
Descriptor
>
essentialProperties
;
/** Supplemental properties in the adaptation set. */
public
final
List
<
Descriptor
>
supplementalProperties
;
/**
...
...
@@ -62,21 +63,21 @@ public class AdaptationSet {
* {@code TRACK_TYPE_*} constants.
* @param representations {@link Representation}s in the adaptation set.
* @param accessibilityDescriptors Accessibility descriptors in the adaptation set.
* @param essentialProperties Essential properties in the adaptation set.
* @param supplementalProperties Supplemental properties in the adaptation set.
*/
public
AdaptationSet
(
int
id
,
int
type
,
List
<
Representation
>
representations
,
List
<
Descriptor
>
accessibilityDescriptors
,
List
<
Descriptor
>
supplementalProperties
)
{
public
AdaptationSet
(
int
id
,
int
type
,
List
<
Representation
>
representations
,
List
<
Descriptor
>
accessibilityDescriptors
,
List
<
Descriptor
>
essentialProperties
,
List
<
Descriptor
>
supplementalProperties
)
{
this
.
id
=
id
;
this
.
type
=
type
;
this
.
representations
=
Collections
.
unmodifiableList
(
representations
);
this
.
accessibilityDescriptors
=
accessibilityDescriptors
==
null
?
Collections
.
emptyList
()
:
Collections
.
unmodifiableList
(
accessibilityDescriptors
);
this
.
supplementalProperties
=
supplementalProperties
==
null
?
Collections
.
emptyList
()
:
Collections
.
unmodifiableList
(
supplementalProperties
);
this
.
accessibilityDescriptors
=
Collections
.
unmodifiableList
(
accessibilityDescriptors
);
this
.
essentialProperties
=
Collections
.
unmodifiableList
(
essentialProperties
);
this
.
supplementalProperties
=
Collections
.
unmodifiableList
(
supplementalProperties
);
}
}
library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/DashManifest.java
View file @
ba0028ca
...
...
@@ -224,9 +224,14 @@ public class DashManifest implements FilterableManifest<DashManifest> {
key
=
keys
.
poll
();
}
while
(
key
.
periodIndex
==
periodIndex
&&
key
.
groupIndex
==
adaptationSetIndex
);
copyAdaptationSets
.
add
(
new
AdaptationSet
(
adaptationSet
.
id
,
adaptationSet
.
type
,
copyRepresentations
,
adaptationSet
.
accessibilityDescriptors
,
adaptationSet
.
supplementalProperties
));
copyAdaptationSets
.
add
(
new
AdaptationSet
(
adaptationSet
.
id
,
adaptationSet
.
type
,
copyRepresentations
,
adaptationSet
.
accessibilityDescriptors
,
adaptationSet
.
essentialProperties
,
adaptationSet
.
supplementalProperties
));
}
while
(
key
.
periodIndex
==
periodIndex
);
// Add back the last key which doesn't belong to the period being processed
keys
.
addFirst
(
key
);
...
...
library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParser.java
View file @
ba0028ca
...
...
@@ -289,6 +289,7 @@ public class DashManifestParser extends DefaultHandler
ArrayList
<
Descriptor
>
inbandEventStreams
=
new
ArrayList
<>();
ArrayList
<
Descriptor
>
accessibilityDescriptors
=
new
ArrayList
<>();
ArrayList
<
Descriptor
>
roleDescriptors
=
new
ArrayList
<>();
ArrayList
<
Descriptor
>
essentialProperties
=
new
ArrayList
<>();
ArrayList
<
Descriptor
>
supplementalProperties
=
new
ArrayList
<>();
List
<
RepresentationInfo
>
representationInfos
=
new
ArrayList
<>();
...
...
@@ -317,6 +318,8 @@ public class DashManifestParser extends DefaultHandler
audioChannels
=
parseAudioChannelConfiguration
(
xpp
);
}
else
if
(
XmlPullParserUtil
.
isStartTag
(
xpp
,
"Accessibility"
))
{
accessibilityDescriptors
.
add
(
parseDescriptor
(
xpp
,
"Accessibility"
));
}
else
if
(
XmlPullParserUtil
.
isStartTag
(
xpp
,
"EssentialProperty"
))
{
essentialProperties
.
add
(
parseDescriptor
(
xpp
,
"EssentialProperty"
));
}
else
if
(
XmlPullParserUtil
.
isStartTag
(
xpp
,
"SupplementalProperty"
))
{
supplementalProperties
.
add
(
parseDescriptor
(
xpp
,
"SupplementalProperty"
));
}
else
if
(
XmlPullParserUtil
.
isStartTag
(
xpp
,
"Representation"
))
{
...
...
@@ -334,6 +337,7 @@ public class DashManifestParser extends DefaultHandler
language
,
roleDescriptors
,
accessibilityDescriptors
,
essentialProperties
,
supplementalProperties
,
segmentBase
,
periodDurationMs
);
...
...
@@ -370,14 +374,28 @@ public class DashManifestParser extends DefaultHandler
inbandEventStreams
));
}
return
buildAdaptationSet
(
id
,
contentType
,
representations
,
accessibilityDescriptors
,
return
buildAdaptationSet
(
id
,
contentType
,
representations
,
accessibilityDescriptors
,
essentialProperties
,
supplementalProperties
);
}
protected
AdaptationSet
buildAdaptationSet
(
int
id
,
int
contentType
,
List
<
Representation
>
representations
,
List
<
Descriptor
>
accessibilityDescriptors
,
protected
AdaptationSet
buildAdaptationSet
(
int
id
,
int
contentType
,
List
<
Representation
>
representations
,
List
<
Descriptor
>
accessibilityDescriptors
,
List
<
Descriptor
>
essentialProperties
,
List
<
Descriptor
>
supplementalProperties
)
{
return
new
AdaptationSet
(
id
,
contentType
,
representations
,
accessibilityDescriptors
,
return
new
AdaptationSet
(
id
,
contentType
,
representations
,
accessibilityDescriptors
,
essentialProperties
,
supplementalProperties
);
}
...
...
@@ -492,6 +510,7 @@ public class DashManifestParser extends DefaultHandler
@Nullable
String
adaptationSetLanguage
,
List
<
Descriptor
>
adaptationSetRoleDescriptors
,
List
<
Descriptor
>
adaptationSetAccessibilityDescriptors
,
List
<
Descriptor
>
adaptationSetEssentialProperties
,
List
<
Descriptor
>
adaptationSetSupplementalProperties
,
@Nullable
SegmentBase
segmentBase
,
long
periodDurationMs
)
...
...
@@ -509,7 +528,9 @@ public class DashManifestParser extends DefaultHandler
String
drmSchemeType
=
null
;
ArrayList
<
SchemeData
>
drmSchemeDatas
=
new
ArrayList
<>();
ArrayList
<
Descriptor
>
inbandEventStreams
=
new
ArrayList
<>();
ArrayList
<
Descriptor
>
supplementalProperties
=
new
ArrayList
<>();
ArrayList
<
Descriptor
>
essentialProperties
=
new
ArrayList
<>(
adaptationSetEssentialProperties
);
ArrayList
<
Descriptor
>
supplementalProperties
=
new
ArrayList
<>(
adaptationSetSupplementalProperties
);
boolean
seenFirstBaseUrl
=
false
;
do
{
...
...
@@ -542,6 +563,8 @@ public class DashManifestParser extends DefaultHandler
}
}
else
if
(
XmlPullParserUtil
.
isStartTag
(
xpp
,
"InbandEventStream"
))
{
inbandEventStreams
.
add
(
parseDescriptor
(
xpp
,
"InbandEventStream"
));
}
else
if
(
XmlPullParserUtil
.
isStartTag
(
xpp
,
"EssentialProperty"
))
{
essentialProperties
.
add
(
parseDescriptor
(
xpp
,
"EssentialProperty"
));
}
else
if
(
XmlPullParserUtil
.
isStartTag
(
xpp
,
"SupplementalProperty"
))
{
supplementalProperties
.
add
(
parseDescriptor
(
xpp
,
"SupplementalProperty"
));
}
else
{
...
...
@@ -563,6 +586,7 @@ public class DashManifestParser extends DefaultHandler
adaptationSetRoleDescriptors
,
adaptationSetAccessibilityDescriptors
,
codecs
,
essentialProperties
,
supplementalProperties
);
segmentBase
=
segmentBase
!=
null
?
segmentBase
:
new
SingleSegmentBase
();
...
...
@@ -583,6 +607,7 @@ public class DashManifestParser extends DefaultHandler
List
<
Descriptor
>
roleDescriptors
,
List
<
Descriptor
>
accessibilityDescriptors
,
@Nullable
String
codecs
,
List
<
Descriptor
>
essentialProperties
,
List
<
Descriptor
>
supplementalProperties
)
{
@Nullable
String
sampleMimeType
=
getSampleMimeType
(
containerMimeType
,
codecs
);
if
(
MimeTypes
.
AUDIO_E_AC3
.
equals
(
sampleMimeType
))
{
...
...
@@ -591,6 +616,8 @@ public class DashManifestParser extends DefaultHandler
@C
.
SelectionFlags
int
selectionFlags
=
parseSelectionFlagsFromRoleDescriptors
(
roleDescriptors
);
@C
.
RoleFlags
int
roleFlags
=
parseRoleFlagsFromRoleDescriptors
(
roleDescriptors
);
roleFlags
|=
parseRoleFlagsFromAccessibilityDescriptors
(
accessibilityDescriptors
);
roleFlags
|=
parseRoleFlagsFromProperties
(
essentialProperties
);
roleFlags
|=
parseRoleFlagsFromProperties
(
supplementalProperties
);
Format
.
Builder
formatBuilder
=
new
Format
.
Builder
()
...
...
@@ -1186,6 +1213,18 @@ public class DashManifestParser extends DefaultHandler
}
@C
.
RoleFlags
protected
int
parseRoleFlagsFromProperties
(
List
<
Descriptor
>
accessibilityDescriptors
)
{
@C
.
RoleFlags
int
result
=
0
;
for
(
int
i
=
0
;
i
<
accessibilityDescriptors
.
size
();
i
++)
{
Descriptor
descriptor
=
accessibilityDescriptors
.
get
(
i
);
if
(
"http://dashif.org/guidelines/trickmode"
.
equalsIgnoreCase
(
descriptor
.
schemeIdUri
))
{
result
|=
C
.
ROLE_FLAG_TRICK_PLAY
;
}
}
return
result
;
}
@C
.
RoleFlags
protected
int
parseDashRoleSchemeValue
(
@Nullable
String
value
)
{
if
(
value
==
null
)
{
return
0
;
...
...
library/dash/src/test/java/com/google/android/exoplayer2/source/dash/DashMediaPeriodTest.java
View file @
ba0028ca
...
...
@@ -165,6 +165,7 @@ public final class DashMediaPeriodTest {
trackType
,
Arrays
.
asList
(
representations
),
/* accessibilityDescriptors= */
Collections
.
emptyList
(),
/* essentialProperties= */
Collections
.
emptyList
(),
descriptor
==
null
?
Collections
.
emptyList
()
:
Collections
.
singletonList
(
descriptor
));
}
...
...
library/dash/src/test/java/com/google/android/exoplayer2/source/dash/DashUtilTest.java
View file @
ba0028ca
...
...
@@ -29,6 +29,7 @@ import com.google.android.exoplayer2.source.dash.manifest.SegmentBase.SingleSegm
import
com.google.android.exoplayer2.upstream.DummyDataSource
;
import
com.google.android.exoplayer2.util.MimeTypes
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
...
...
@@ -69,7 +70,13 @@ public final class DashUtilTest {
}
private
static
AdaptationSet
newAdaptationSet
(
Representation
...
representations
)
{
return
new
AdaptationSet
(
0
,
C
.
TRACK_TYPE_VIDEO
,
Arrays
.
asList
(
representations
),
null
,
null
);
return
new
AdaptationSet
(
/* id= */
0
,
C
.
TRACK_TYPE_VIDEO
,
Arrays
.
asList
(
representations
),
/* accessibilityDescriptors= */
Collections
.
emptyList
(),
/* essentialProperties= */
Collections
.
emptyList
(),
/* supplementalProperties= */
Collections
.
emptyList
());
}
private
static
Representation
newRepresentation
(
DrmInitData
drmInitData
)
{
...
...
library/dash/src/test/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParserTest.java
View file @
ba0028ca
...
...
@@ -49,6 +49,7 @@ public class DashManifestParserTest {
private
static
final
String
SAMPLE_MPD_LABELS
=
"mpd/sample_mpd_labels"
;
private
static
final
String
SAMPLE_MPD_ASSET_IDENTIFIER
=
"mpd/sample_mpd_asset_identifier"
;
private
static
final
String
SAMPLE_MPD_TEXT
=
"mpd/sample_mpd_text"
;
private
static
final
String
SAMPLE_MPD_TRICK_PLAY
=
"mpd/sample_mpd_trick_play"
;
private
static
final
String
NEXT_TAG_NAME
=
"Next"
;
private
static
final
String
NEXT_TAG
=
"<"
+
NEXT_TAG_NAME
+
"/>"
;
...
...
@@ -173,7 +174,7 @@ public class DashManifestParserTest {
DashManifestParser
parser
=
new
DashManifestParser
();
DashManifest
manifest
=
parser
.
parse
(
Uri
.
parse
(
"
H
ttps://example.com/test.mpd"
),
Uri
.
parse
(
"
h
ttps://example.com/test.mpd"
),
TestUtil
.
getInputStream
(
ApplicationProvider
.
getApplicationContext
(),
SAMPLE_MPD
));
ProgramInformation
expectedProgramInformation
=
new
ProgramInformation
(
...
...
@@ -201,7 +202,7 @@ public class DashManifestParserTest {
DashManifestParser
parser
=
new
DashManifestParser
();
DashManifest
manifest
=
parser
.
parse
(
Uri
.
parse
(
"
H
ttps://example.com/test.mpd"
),
Uri
.
parse
(
"
h
ttps://example.com/test.mpd"
),
TestUtil
.
getInputStream
(
ApplicationProvider
.
getApplicationContext
(),
SAMPLE_MPD_TEXT
));
List
<
AdaptationSet
>
adaptationSets
=
manifest
.
getPeriod
(
0
).
adaptationSets
;
...
...
@@ -226,6 +227,46 @@ public class DashManifestParserTest {
}
@Test
public
void
parseMediaPresentationDescription_trickPlay
()
throws
IOException
{
DashManifestParser
parser
=
new
DashManifestParser
();
DashManifest
manifest
=
parser
.
parse
(
Uri
.
parse
(
"https://example.com/test.mpd"
),
TestUtil
.
getInputStream
(
ApplicationProvider
.
getApplicationContext
(),
SAMPLE_MPD_TRICK_PLAY
));
List
<
AdaptationSet
>
adaptationSets
=
manifest
.
getPeriod
(
0
).
adaptationSets
;
AdaptationSet
adaptationSet
=
adaptationSets
.
get
(
0
);
assertThat
(
adaptationSet
.
essentialProperties
).
isEmpty
();
assertThat
(
adaptationSet
.
supplementalProperties
).
isEmpty
();
assertThat
(
adaptationSet
.
representations
.
get
(
0
).
format
.
roleFlags
).
isEqualTo
(
0
);
adaptationSet
=
adaptationSets
.
get
(
1
);
assertThat
(
adaptationSet
.
essentialProperties
).
isEmpty
();
assertThat
(
adaptationSet
.
supplementalProperties
).
isEmpty
();
assertThat
(
adaptationSet
.
representations
.
get
(
0
).
format
.
roleFlags
).
isEqualTo
(
0
);
adaptationSet
=
adaptationSets
.
get
(
2
);
assertThat
(
adaptationSet
.
essentialProperties
).
hasSize
(
1
);
assertThat
(
adaptationSet
.
essentialProperties
.
get
(
0
).
schemeIdUri
)
.
isEqualTo
(
"http://dashif.org/guidelines/trickmode"
);
assertThat
(
adaptationSet
.
essentialProperties
.
get
(
0
).
value
).
isEqualTo
(
"0"
);
assertThat
(
adaptationSet
.
supplementalProperties
).
isEmpty
();
assertThat
(
adaptationSet
.
representations
.
get
(
0
).
format
.
roleFlags
)
.
isEqualTo
(
C
.
ROLE_FLAG_TRICK_PLAY
);
adaptationSet
=
adaptationSets
.
get
(
3
);
assertThat
(
adaptationSet
.
essentialProperties
).
isEmpty
();
assertThat
(
adaptationSet
.
supplementalProperties
).
hasSize
(
1
);
assertThat
(
adaptationSet
.
supplementalProperties
.
get
(
0
).
schemeIdUri
)
.
isEqualTo
(
"http://dashif.org/guidelines/trickmode"
);
assertThat
(
adaptationSet
.
supplementalProperties
.
get
(
0
).
value
).
isEqualTo
(
"1"
);
assertThat
(
adaptationSet
.
representations
.
get
(
0
).
format
.
roleFlags
)
.
isEqualTo
(
C
.
ROLE_FLAG_TRICK_PLAY
);
}
@Test
public
void
parseSegmentTimeline_repeatCount
()
throws
Exception
{
DashManifestParser
parser
=
new
DashManifestParser
();
XmlPullParser
xpp
=
XmlPullParserFactory
.
newInstance
().
newPullParser
();
...
...
library/dash/src/test/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestTest.java
View file @
ba0028ca
...
...
@@ -239,6 +239,12 @@ public class DashManifestTest {
}
private
static
AdaptationSet
newAdaptationSet
(
int
seed
,
Representation
...
representations
)
{
return
new
AdaptationSet
(++
seed
,
++
seed
,
Arrays
.
asList
(
representations
),
null
,
null
);
return
new
AdaptationSet
(
++
seed
,
++
seed
,
Arrays
.
asList
(
representations
),
/* accessibilityDescriptors= */
Collections
.
emptyList
(),
/* essentialProperties= */
Collections
.
emptyList
(),
/* supplementalProperties= */
Collections
.
emptyList
());
}
}
testdata/src/test/assets/mpd/sample_mpd_trick_play
0 → 100644
View file @
ba0028ca
<?xml version="1.0" encoding="UTF-8"?>
<MPD
type=
"static"
duration=
"1s"
mediaPresentationDuration=
"PT1S"
>
<Period>
<SegmentTemplate
startNumber=
"0"
timescale=
"1000"
media=
"sq/$Number$"
>
<SegmentTimeline>
<S
d=
"1000"
/>
</SegmentTimeline>
</SegmentTemplate>
<AdaptationSet
id=
"0"
mimeType=
"video/mp4"
subsegmentAlignment=
"true"
>
<Representation
id=
"0"
codecs=
"avc1.42c01f"
bandwidth=
"128000"
>
<BaseURL>
https://test.com/0
</BaseURL>
</Representation>
</AdaptationSet>
<AdaptationSet
id=
"1"
mimeType=
"video/mp4"
subsegmentAlignment=
"true"
>
<Representation
id=
"0"
codecs=
"avc1.42c01f"
bandwidth=
"128000"
>
<BaseURL>
https://test.com/0
</BaseURL>
</Representation>
</AdaptationSet>
<AdaptationSet
id=
"2"
mimeType=
"video/mp4"
subsegmentAlignment=
"true"
>
<EssentialProperty
schemeIdUri=
"http://dashif.org/guidelines/trickmode"
value=
"0"
/>
<Representation
id=
"0"
codecs=
"avc1.42c01f"
bandwidth=
"128000"
>
<BaseURL>
https://test.com/0
</BaseURL>
</Representation>
</AdaptationSet>
<AdaptationSet
id=
"3"
mimeType=
"video/mp4"
subsegmentAlignment=
"true"
>
<SupplementalProperty
schemeIdUri=
"http://dashif.org/guidelines/trickmode"
value=
"1"
/>
<Representation
id=
"0"
codecs=
"avc1.42c01f"
bandwidth=
"128000"
>
<BaseURL>
https://test.com/0
</BaseURL>
</Representation>
</AdaptationSet>
</Period>
</MPD>
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