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
75435b42
authored
Sep 05, 2019
by
Toni
Browse files
Options
_('Browse Files')
Download
Plain Diff
Merge pull request #6286 from sr1990:dev-v2
PiperOrigin-RevId: 267323559
parents
33eb49ca
3198b9ef
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
160 additions
and
25 deletions
library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParser.java
library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/SegmentBase.java
library/dash/src/test/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParserTest.java
library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParser.java
View file @
75435b42
...
...
@@ -243,7 +243,7 @@ public class DashManifestParser extends DefaultHandler
}
else
if
(
XmlPullParserUtil
.
isStartTag
(
xpp
,
"SegmentBase"
))
{
segmentBase
=
parseSegmentBase
(
xpp
,
null
);
}
else
if
(
XmlPullParserUtil
.
isStartTag
(
xpp
,
"SegmentList"
))
{
segmentBase
=
parseSegmentList
(
xpp
,
null
,
durationMs
);
segmentBase
=
parseSegmentList
(
xpp
,
null
,
durationMs
);
}
else
if
(
XmlPullParserUtil
.
isStartTag
(
xpp
,
"SegmentTemplate"
))
{
segmentBase
=
parseSegmentTemplate
(
xpp
,
null
,
Collections
.
emptyList
(),
durationMs
);
}
else
{
...
...
@@ -339,8 +339,8 @@ public class DashManifestParser extends DefaultHandler
segmentBase
=
parseSegmentList
(
xpp
,
(
SegmentList
)
segmentBase
,
periodDurationMs
);
}
else
if
(
XmlPullParserUtil
.
isStartTag
(
xpp
,
"SegmentTemplate"
))
{
segmentBase
=
parseSegmentTemplate
(
xpp
,
(
SegmentTemplate
)
segmentBase
,
supplementalProperties
,
periodDurationMs
);
parseSegmentTemplate
(
xpp
,
(
SegmentTemplate
)
segmentBase
,
supplementalProperties
,
periodDurationMs
);
}
else
if
(
XmlPullParserUtil
.
isStartTag
(
xpp
,
"InbandEventStream"
))
{
inbandEventStreams
.
add
(
parseDescriptor
(
xpp
,
"InbandEventStream"
));
}
else
if
(
XmlPullParserUtil
.
isStartTag
(
xpp
))
{
...
...
@@ -494,7 +494,8 @@ public class DashManifestParser extends DefaultHandler
List
<
Descriptor
>
adaptationSetRoleDescriptors
,
List
<
Descriptor
>
adaptationSetAccessibilityDescriptors
,
List
<
Descriptor
>
adaptationSetSupplementalProperties
,
@Nullable
SegmentBase
segmentBase
,
long
periodDurationMs
)
@Nullable
SegmentBase
segmentBase
,
long
periodDurationMs
)
throws
XmlPullParserException
,
IOException
{
String
id
=
xpp
.
getAttributeValue
(
null
,
"id"
);
int
bandwidth
=
parseInt
(
xpp
,
"bandwidth"
,
Format
.
NO_VALUE
);
...
...
@@ -528,7 +529,9 @@ public class DashManifestParser extends DefaultHandler
}
else
if
(
XmlPullParserUtil
.
isStartTag
(
xpp
,
"SegmentTemplate"
))
{
segmentBase
=
parseSegmentTemplate
(
xpp
,
(
SegmentTemplate
)
segmentBase
,
adaptationSetSupplementalProperties
,
xpp
,
(
SegmentTemplate
)
segmentBase
,
adaptationSetSupplementalProperties
,
periodDurationMs
);
}
else
if
(
XmlPullParserUtil
.
isStartTag
(
xpp
,
"ContentProtection"
))
{
Pair
<
String
,
SchemeData
>
contentProtection
=
parseContentProtection
(
xpp
);
...
...
@@ -720,8 +723,8 @@ public class DashManifestParser extends DefaultHandler
indexLength
);
}
protected
SegmentList
parseSegmentList
(
XmlPullParser
xpp
,
@Nullable
SegmentList
parent
,
long
periodDurationMs
)
protected
SegmentList
parseSegmentList
(
XmlPullParser
xpp
,
@Nullable
SegmentList
parent
,
long
periodDurationMs
)
throws
XmlPullParserException
,
IOException
{
long
timescale
=
parseLong
(
xpp
,
"timescale"
,
parent
!=
null
?
parent
.
timescale
:
1
);
...
...
@@ -739,7 +742,7 @@ public class DashManifestParser extends DefaultHandler
if
(
XmlPullParserUtil
.
isStartTag
(
xpp
,
"Initialization"
))
{
initialization
=
parseInitialization
(
xpp
);
}
else
if
(
XmlPullParserUtil
.
isStartTag
(
xpp
,
"SegmentTimeline"
))
{
timeline
=
parseSegmentTimeline
(
xpp
,
timescale
,
periodDurationMs
);
timeline
=
parseSegmentTimeline
(
xpp
,
timescale
,
periodDurationMs
);
}
else
if
(
XmlPullParserUtil
.
isStartTag
(
xpp
,
"SegmentURL"
))
{
if
(
segments
==
null
)
{
segments
=
new
ArrayList
<>();
...
...
@@ -799,7 +802,7 @@ public class DashManifestParser extends DefaultHandler
if
(
XmlPullParserUtil
.
isStartTag
(
xpp
,
"Initialization"
))
{
initialization
=
parseInitialization
(
xpp
);
}
else
if
(
XmlPullParserUtil
.
isStartTag
(
xpp
,
"SegmentTimeline"
))
{
timeline
=
parseSegmentTimeline
(
xpp
,
timescale
,
periodDurationMs
);
timeline
=
parseSegmentTimeline
(
xpp
,
timescale
,
periodDurationMs
);
}
else
{
maybeSkipTag
(
xpp
);
}
...
...
@@ -994,35 +997,79 @@ public class DashManifestParser extends DefaultHandler
return
new
EventMessage
(
schemeIdUri
,
value
,
durationMs
,
id
,
messageData
);
}
protected
List
<
SegmentTimelineElement
>
parseSegmentTimeline
(
XmlPullParser
xpp
,
long
timescale
,
long
periodDurationMs
)
protected
List
<
SegmentTimelineElement
>
parseSegmentTimeline
(
XmlPullParser
xpp
,
long
timescale
,
long
periodDurationMs
)
throws
XmlPullParserException
,
IOException
{
List
<
SegmentTimelineElement
>
segmentTimeline
=
new
ArrayList
<>();
long
elapsedTime
=
0
;
long
startTime
=
0
;
long
elementDuration
=
C
.
TIME_UNSET
;
int
elementRepeatCount
=
0
;
boolean
havePreviousTimelineElement
=
false
;
do
{
xpp
.
next
();
if
(
XmlPullParserUtil
.
isStartTag
(
xpp
,
"S"
))
{
elapsedTime
=
parseLong
(
xpp
,
"t"
,
elapsedTime
);
long
duration
=
parseLong
(
xpp
,
"d"
,
C
.
TIME_UNSET
);
//if repeat is negative : length of each segment = duration / timescale and
// number of segments = periodDuration / length of each segment
int
repeat
=
parseInt
(
xpp
,
"r"
,
0
);
int
count
=
repeat
>=
0
?
1
+
repeat
:
(
int
)
(((
periodDurationMs
/
1000
)
*
timescale
)
/
duration
);
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
segmentTimeline
.
add
(
buildSegmentTimelineElement
(
elapsedTime
,
duration
));
elapsedTime
+=
duration
;
long
newStartTime
=
parseLong
(
xpp
,
"t"
,
C
.
TIME_UNSET
);
if
(
havePreviousTimelineElement
)
{
startTime
=
addSegmentTimelineElementsToList
(
segmentTimeline
,
startTime
,
elementDuration
,
elementRepeatCount
,
/* endTime= */
newStartTime
);
}
if
(
newStartTime
!=
C
.
TIME_UNSET
)
{
startTime
=
newStartTime
;
}
elementDuration
=
parseLong
(
xpp
,
"d"
,
C
.
TIME_UNSET
);
elementRepeatCount
=
parseInt
(
xpp
,
"r"
,
0
);
havePreviousTimelineElement
=
true
;
}
else
{
maybeSkipTag
(
xpp
);
}
}
while
(!
XmlPullParserUtil
.
isEndTag
(
xpp
,
"SegmentTimeline"
));
if
(
havePreviousTimelineElement
)
{
long
periodDuration
=
Util
.
scaleLargeTimestamp
(
periodDurationMs
,
timescale
,
1000
);
addSegmentTimelineElementsToList
(
segmentTimeline
,
startTime
,
elementDuration
,
elementRepeatCount
,
/* endTime= */
periodDuration
);
}
return
segmentTimeline
;
}
protected
SegmentTimelineElement
buildSegmentTimelineElement
(
long
elapsedTime
,
long
duration
)
{
return
new
SegmentTimelineElement
(
elapsedTime
,
duration
);
/**
* Adds timeline elements for one S tag to the segment timeline.
*
* @param startTime Start time of the first timeline element.
* @param elementDuration Duration of one timeline element.
* @param elementRepeatCount Number of timeline elements minus one. May be negative to indicate
* that the count is determined by the total duration and the element duration.
* @param endTime End time of the last timeline element for this S tag, or {@link C#TIME_UNSET} if
* unknown. Only needed if {@code repeatCount} is negative.
* @return Calculated next start time.
*/
private
long
addSegmentTimelineElementsToList
(
List
<
SegmentTimelineElement
>
segmentTimeline
,
long
startTime
,
long
elementDuration
,
int
elementRepeatCount
,
long
endTime
)
{
int
count
=
elementRepeatCount
>=
0
?
1
+
elementRepeatCount
:
(
int
)
Util
.
ceilDivide
(
endTime
-
startTime
,
elementDuration
);
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
segmentTimeline
.
add
(
buildSegmentTimelineElement
(
startTime
,
elementDuration
));
startTime
+=
elementDuration
;
}
return
startTime
;
}
protected
SegmentTimelineElement
buildSegmentTimelineElement
(
long
startTime
,
long
duration
)
{
return
new
SegmentTimelineElement
(
startTime
,
duration
);
}
@Nullable
...
...
library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/SegmentBase.java
View file @
75435b42
...
...
@@ -397,6 +397,22 @@ public abstract class SegmentBase {
this
.
duration
=
duration
;
}
@Override
public
boolean
equals
(
@Nullable
Object
o
)
{
if
(
this
==
o
)
{
return
true
;
}
if
(
o
==
null
||
getClass
()
!=
o
.
getClass
())
{
return
false
;
}
SegmentTimelineElement
that
=
(
SegmentTimelineElement
)
o
;
return
startTime
==
that
.
startTime
&&
duration
==
that
.
duration
;
}
@Override
public
int
hashCode
()
{
return
31
*
(
int
)
startTime
+
(
int
)
duration
;
}
}
}
library/dash/src/test/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParserTest.java
View file @
75435b42
...
...
@@ -23,14 +23,18 @@ import androidx.test.ext.junit.runners.AndroidJUnit4;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.Format
;
import
com.google.android.exoplayer2.metadata.emsg.EventMessage
;
import
com.google.android.exoplayer2.source.dash.manifest.SegmentBase.SegmentTimelineElement
;
import
com.google.android.exoplayer2.testutil.TestUtil
;
import
com.google.android.exoplayer2.util.Util
;
import
java.io.IOException
;
import
java.io.StringReader
;
import
java.nio.charset.Charset
;
import
java.util.Collections
;
import
java.util.List
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.xmlpull.v1.XmlPullParser
;
import
org.xmlpull.v1.XmlPullParserFactory
;
/** Unit tests for {@link DashManifestParser}. */
@RunWith
(
AndroidJUnit4
.
class
)
...
...
@@ -255,6 +259,74 @@ public class DashManifestParserTest {
.
isEqualTo
(
Format
.
NO_VALUE
);
}
@Test
public
void
parseSegmentTimeline_withRepeatCount
()
throws
Exception
{
DashManifestParser
parser
=
new
DashManifestParser
();
XmlPullParser
xpp
=
XmlPullParserFactory
.
newInstance
().
newPullParser
();
xpp
.
setInput
(
new
StringReader
(
"<SegmentTimeline><S d=\"96000\" r=\"2\"/><S d=\"48000\" r=\"0\"/></SegmentTimeline>"
));
xpp
.
next
();
List
<
SegmentTimelineElement
>
elements
=
parser
.
parseSegmentTimeline
(
xpp
,
/* timescale= */
48000
,
/* periodDurationMs= */
10000
);
assertThat
(
elements
)
.
containsExactly
(
new
SegmentTimelineElement
(
/* startTime= */
0
,
/* duration= */
96000
),
new
SegmentTimelineElement
(
/* startTime= */
96000
,
/* duration= */
96000
),
new
SegmentTimelineElement
(
/* startTime= */
192000
,
/* duration= */
96000
),
new
SegmentTimelineElement
(
/* startTime= */
288000
,
/* duration= */
48000
))
.
inOrder
();
}
@Test
public
void
parseSegmentTimeline_withSingleUndefinedRepeatCount
()
throws
Exception
{
DashManifestParser
parser
=
new
DashManifestParser
();
XmlPullParser
xpp
=
XmlPullParserFactory
.
newInstance
().
newPullParser
();
xpp
.
setInput
(
new
StringReader
(
"<SegmentTimeline><S d=\"96000\" r=\"-1\"/></SegmentTimeline>"
));
xpp
.
next
();
List
<
SegmentTimelineElement
>
elements
=
parser
.
parseSegmentTimeline
(
xpp
,
/* timescale= */
48000
,
/* periodDurationMs= */
10000
);
assertThat
(
elements
)
.
containsExactly
(
new
SegmentTimelineElement
(
/* startTime= */
0
,
/* duration= */
96000
),
new
SegmentTimelineElement
(
/* startTime= */
96000
,
/* duration= */
96000
),
new
SegmentTimelineElement
(
/* startTime= */
192000
,
/* duration= */
96000
),
new
SegmentTimelineElement
(
/* startTime= */
288000
,
/* duration= */
96000
),
new
SegmentTimelineElement
(
/* startTime= */
384000
,
/* duration= */
96000
))
.
inOrder
();
}
@Test
public
void
parseSegmentTimeline_withTimeOffsetsAndUndefinedRepeatCount
()
throws
Exception
{
DashManifestParser
parser
=
new
DashManifestParser
();
XmlPullParser
xpp
=
XmlPullParserFactory
.
newInstance
().
newPullParser
();
xpp
.
setInput
(
new
StringReader
(
"<SegmentTimeline><S t=\"0\" "
+
"d=\"96000\" r=\"-1\"/><S t=\"192000\" d=\"48000\" r=\"-1\"/>"
+
"</SegmentTimeline>"
));
xpp
.
next
();
List
<
SegmentTimelineElement
>
elements
=
parser
.
parseSegmentTimeline
(
xpp
,
/* timescale= */
48000
,
/* periodDurationMs= */
10000
);
assertThat
(
elements
)
.
containsExactly
(
new
SegmentTimelineElement
(
/* startTime= */
0
,
/* duration= */
96000
),
new
SegmentTimelineElement
(
/* startTime= */
96000
,
/* duration= */
96000
),
new
SegmentTimelineElement
(
/* startTime= */
192000
,
/* duration= */
48000
),
new
SegmentTimelineElement
(
/* startTime= */
240000
,
/* duration= */
48000
),
new
SegmentTimelineElement
(
/* startTime= */
288000
,
/* duration= */
48000
),
new
SegmentTimelineElement
(
/* startTime= */
336000
,
/* duration= */
48000
),
new
SegmentTimelineElement
(
/* startTime= */
384000
,
/* duration= */
48000
),
new
SegmentTimelineElement
(
/* startTime= */
432000
,
/* duration= */
48000
))
.
inOrder
();
}
private
static
List
<
Descriptor
>
buildCea608AccessibilityDescriptors
(
String
value
)
{
return
Collections
.
singletonList
(
new
Descriptor
(
"urn:scte:dash:cc:cea-608:2015"
,
value
,
null
));
}
...
...
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