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
fea43767
authored
Apr 19, 2020
by
olly
Committed by
Oliver Woodman
Apr 20, 2020
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Merge trick play tracks into main track groups
Issue: #6054 PiperOrigin-RevId: 307285068
parent
8ea33e23
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
291 additions
and
75 deletions
RELEASENOTES.md
library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaPeriod.java
library/dash/src/test/java/com/google/android/exoplayer2/source/dash/DashMediaPeriodTest.java
testutils/src/main/java/com/google/android/exoplayer2/testutil/MediaPeriodAsserts.java
RELEASENOTES.md
View file @
fea43767
...
...
@@ -97,6 +97,11 @@
*
Remove generics from DRM components.
*
Downloads: Merge downloads in
`SegmentDownloader`
to improve overall
download speed (
[
#5978
](
https://github.com/google/ExoPlayer/issues/5978
)
).
*
DASH:
*
Merge trick play adaptation sets (i.e., adaptation sets marked with
`http://dashif.org/guidelines/trickmode`
) into the same
`TrackGroup`
as
the main adaptation sets to which they refer. Trick play tracks are
marked with the
`C.ROLE_FLAG_TRICK_PLAY`
flag.
*
MP3: Add
`IndexSeeker`
for accurate seeks in VBR streams
(
[
#6787
](
https://github.com/google/ExoPlayer/issues/6787
)
). This seeker is
enabled by passing
`FLAG_ENABLE_INDEX_SEEKING`
to the
`Mp3Extractor`
. It may
...
...
library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaPeriod.java
View file @
fea43767
...
...
@@ -16,6 +16,7 @@
package
com
.
google
.
android
.
exoplayer2
.
source
.
dash
;
import
android.util.Pair
;
import
android.util.SparseArray
;
import
android.util.SparseIntArray
;
import
androidx.annotation.IntDef
;
import
androidx.annotation.Nullable
;
...
...
@@ -516,51 +517,94 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
return
Pair
.
create
(
new
TrackGroupArray
(
trackGroups
),
trackGroupInfos
);
}
/**
* Groups adaptation sets. Two adaptations sets belong to the same group if either:
*
* <ul>
* <li>One is a trick-play adaptation set and uses a {@code
* http://dashif.org/guidelines/trickmode} essential or supplemental property to indicate
* that the other is the main adaptation set to which it corresponds.
* <li>The two adaptation sets are marked as safe for switching using {@code
* urn:mpeg:dash:adaptation-set-switching:2016} supplemental properties.
* </ul>
*
* @param adaptationSets The adaptation sets to merge.
* @return An array of groups, where each group is an array of adaptation set indices.
*/
private
static
int
[][]
getGroupedAdaptationSetIndices
(
List
<
AdaptationSet
>
adaptationSets
)
{
int
adaptationSetCount
=
adaptationSets
.
size
();
SparseIntArray
idToIndexMap
=
new
SparseIntArray
(
adaptationSetCount
);
SparseIntArray
adaptationSetIdToIndex
=
new
SparseIntArray
(
adaptationSetCount
);
List
<
List
<
Integer
>>
adaptationSetGroupedIndices
=
new
ArrayList
<>(
adaptationSetCount
);
SparseArray
<
List
<
Integer
>>
adaptationSetIndexToGroupedIndices
=
new
SparseArray
<>(
adaptationSetCount
);
// Initially make each adaptation set belong to its own group. Also build the
// adaptationSetIdToIndex map.
for
(
int
i
=
0
;
i
<
adaptationSetCount
;
i
++)
{
idToIndexMap
.
put
(
adaptationSets
.
get
(
i
).
id
,
i
);
adaptationSetIdToIndex
.
put
(
adaptationSets
.
get
(
i
).
id
,
i
);
List
<
Integer
>
initialGroup
=
new
ArrayList
<>();
initialGroup
.
add
(
i
);
adaptationSetGroupedIndices
.
add
(
initialGroup
);
adaptationSetIndexToGroupedIndices
.
put
(
i
,
initialGroup
);
}
int
[][]
groupedAdaptationSetIndices
=
new
int
[
adaptationSetCount
][];
boolean
[]
adaptationSetUsedFlags
=
new
boolean
[
adaptationSetCount
];
int
groupCount
=
0
;
// Merge adaptation set groups.
for
(
int
i
=
0
;
i
<
adaptationSetCount
;
i
++)
{
if
(
adaptationSetUsedFlags
[
i
])
{
// This adaptation set has already been included in a group.
continue
;
}
adaptationSetUsedFlags
[
i
]
=
true
;
int
mergedGroupIndex
=
i
;
AdaptationSet
adaptationSet
=
adaptationSets
.
get
(
i
);
// Trick-play adaptation sets are merged with their corresponding main adaptation sets.
@Nullable
Descriptor
adaptationSetSwitchingProperty
=
findAdaptationSetSwitchingProperty
(
adaptationSets
.
get
(
i
).
supplementalProperties
);
if
(
adaptationSetSwitchingProperty
==
null
)
{
groupedAdaptationSetIndices
[
groupCount
++]
=
new
int
[]
{
i
};
}
else
{
String
[]
extraAdaptationSetIds
=
Util
.
split
(
adaptationSetSwitchingProperty
.
value
,
","
);
int
[]
adaptationSetIndices
=
new
int
[
1
+
extraAdaptationSetIds
.
length
];
adaptationSetIndices
[
0
]
=
i
;
int
outputIndex
=
1
;
for
(
String
adaptationSetId
:
extraAdaptationSetIds
)
{
int
extraIndex
=
idToIndexMap
.
get
(
Integer
.
parseInt
(
adaptationSetId
),
/* valueIfKeyNotFound= */
-
1
);
if
(
extraIndex
!=
-
1
)
{
adaptationSetUsedFlags
[
extraIndex
]
=
true
;
adaptationSetIndices
[
outputIndex
]
=
extraIndex
;
outputIndex
++;
}
Descriptor
trickPlayProperty
=
findTrickPlayProperty
(
adaptationSet
.
essentialProperties
);
if
(
trickPlayProperty
==
null
)
{
// Trick-play can also be specified using a supplemental property.
trickPlayProperty
=
findTrickPlayProperty
(
adaptationSet
.
supplementalProperties
);
}
if
(
trickPlayProperty
!=
null
)
{
int
mainAdaptationSetId
=
Integer
.
parseInt
(
trickPlayProperty
.
value
);
int
mainAdaptationSetIndex
=
adaptationSetIdToIndex
.
get
(
mainAdaptationSetId
,
/* valueIfKeyNotFound= */
-
1
);
if
(
mainAdaptationSetIndex
!=
-
1
)
{
mergedGroupIndex
=
mainAdaptationSetIndex
;
}
if
(
outputIndex
<
adaptationSetIndices
.
length
)
{
adaptationSetIndices
=
Arrays
.
copyOf
(
adaptationSetIndices
,
outputIndex
);
}
// Adaptation sets that are safe for switching are merged, using the smallest index for the
// merged group.
if
(
mergedGroupIndex
==
i
)
{
@Nullable
Descriptor
adaptationSetSwitchingProperty
=
findAdaptationSetSwitchingProperty
(
adaptationSet
.
supplementalProperties
);
if
(
adaptationSetSwitchingProperty
!=
null
)
{
String
[]
otherAdaptationSetIds
=
Util
.
split
(
adaptationSetSwitchingProperty
.
value
,
","
);
for
(
String
adaptationSetId
:
otherAdaptationSetIds
)
{
int
otherAdaptationSetId
=
adaptationSetIdToIndex
.
get
(
Integer
.
parseInt
(
adaptationSetId
),
/* valueIfKeyNotFound= */
-
1
);
if
(
otherAdaptationSetId
!=
-
1
)
{
mergedGroupIndex
=
Math
.
min
(
mergedGroupIndex
,
otherAdaptationSetId
);
}
}
}
groupedAdaptationSetIndices
[
groupCount
++]
=
adaptationSetIndices
;
}
// Merge the groups if necessary.
if
(
mergedGroupIndex
!=
i
)
{
List
<
Integer
>
thisGroup
=
adaptationSetIndexToGroupedIndices
.
get
(
i
);
List
<
Integer
>
mergedGroup
=
adaptationSetIndexToGroupedIndices
.
get
(
mergedGroupIndex
);
mergedGroup
.
addAll
(
thisGroup
);
adaptationSetIndexToGroupedIndices
.
put
(
i
,
mergedGroup
);
adaptationSetGroupedIndices
.
remove
(
thisGroup
);
}
}
return
groupCount
<
adaptationSetCount
?
Arrays
.
copyOf
(
groupedAdaptationSetIndices
,
groupCount
)
:
groupedAdaptationSetIndices
;
int
[][]
groupedAdaptationSetIndices
=
new
int
[
adaptationSetGroupedIndices
.
size
()][];
for
(
int
i
=
0
;
i
<
groupedAdaptationSetIndices
.
length
;
i
++)
{
groupedAdaptationSetIndices
[
i
]
=
Util
.
toArray
(
adaptationSetGroupedIndices
.
get
(
i
));
// Restore the original adaptation set order within each group.
Arrays
.
sort
(
groupedAdaptationSetIndices
[
i
]);
}
return
groupedAdaptationSetIndices
;
}
/**
...
...
@@ -747,9 +791,19 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
@Nullable
private
static
Descriptor
findAdaptationSetSwitchingProperty
(
List
<
Descriptor
>
descriptors
)
{
return
findDescriptor
(
descriptors
,
"urn:mpeg:dash:adaptation-set-switching:2016"
);
}
@Nullable
private
static
Descriptor
findTrickPlayProperty
(
List
<
Descriptor
>
descriptors
)
{
return
findDescriptor
(
descriptors
,
"http://dashif.org/guidelines/trickmode"
);
}
@Nullable
private
static
Descriptor
findDescriptor
(
List
<
Descriptor
>
descriptors
,
String
schemeIdUri
)
{
for
(
int
i
=
0
;
i
<
descriptors
.
size
();
i
++)
{
Descriptor
descriptor
=
descriptors
.
get
(
i
);
if
(
"urn:mpeg:dash:adaptation-set-switching:2016"
.
equals
(
descriptor
.
schemeIdUri
))
{
if
(
schemeIdUri
.
equals
(
descriptor
.
schemeIdUri
))
{
return
descriptor
;
}
}
...
...
library/dash/src/test/java/com/google/android/exoplayer2/source/dash/DashMediaPeriodTest.java
View file @
fea43767
...
...
@@ -26,6 +26,8 @@ import com.google.android.exoplayer2.drm.DrmSessionManager;
import
com.google.android.exoplayer2.source.CompositeSequenceableLoaderFactory
;
import
com.google.android.exoplayer2.source.MediaSource.MediaPeriodId
;
import
com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher
;
import
com.google.android.exoplayer2.source.TrackGroup
;
import
com.google.android.exoplayer2.source.TrackGroupArray
;
import
com.google.android.exoplayer2.source.dash.PlayerEmsgHandler.PlayerEmsgCallback
;
import
com.google.android.exoplayer2.source.dash.manifest.AdaptationSet
;
import
com.google.android.exoplayer2.source.dash.manifest.DashManifest
;
...
...
@@ -35,7 +37,6 @@ import com.google.android.exoplayer2.source.dash.manifest.Representation;
import
com.google.android.exoplayer2.source.dash.manifest.SegmentBase.SingleSegmentBase
;
import
com.google.android.exoplayer2.source.dash.manifest.UtcTimingElement
;
import
com.google.android.exoplayer2.testutil.MediaPeriodAsserts
;
import
com.google.android.exoplayer2.testutil.MediaPeriodAsserts.FilterableManifestMediaPeriodFactory
;
import
com.google.android.exoplayer2.upstream.Allocator
;
import
com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy
;
import
com.google.android.exoplayer2.upstream.LoaderErrorThrower
;
...
...
@@ -43,6 +44,7 @@ import com.google.android.exoplayer2.upstream.TransferListener;
import
com.google.android.exoplayer2.util.MimeTypes
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.List
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.robolectric.annotation.LooperMode
;
...
...
@@ -53,7 +55,7 @@ import org.robolectric.annotation.LooperMode;
public
final
class
DashMediaPeriodTest
{
@Test
public
void
getSteamKeys_isCompatibleWithDashManifestFilter
()
{
public
void
getSt
r
eamKeys_isCompatibleWithDashManifestFilter
()
{
// Test manifest which covers various edge cases:
// - Multiple periods.
// - Single and multiple representations per adaptation set.
...
...
@@ -61,83 +63,220 @@ public final class DashMediaPeriodTest {
// - Embedded track groups.
// All cases are deliberately combined in one test to catch potential indexing problems which
// only occur in combination.
DashManifest
testM
anifest
=
DashManifest
m
anifest
=
createDashManifest
(
createPeriod
(
createAdaptationSet
(
/* id= */
0
,
/* trackType= */
C
.
TRACK_TYPE_VIDEO
,
C
.
TRACK_TYPE_VIDEO
,
/* descriptor= */
null
,
createVideoRepresentation
(
/* bitrate= */
1000000
))),
createPeriod
(
createAdaptationSet
(
/* id= */
100
,
/* trackType= */
C
.
TRACK_TYPE_VIDEO
,
/* descriptor= */
createSwitchDescriptor
(
/* ids...= */
103
,
104
),
C
.
TRACK_TYPE_VIDEO
,
createSwitchDescriptor
(
/* ids...= */
103
,
104
),
createVideoRepresentationWithInbandEventStream
(
/* bitrate= */
200000
),
createVideoRepresentationWithInbandEventStream
(
/* bitrate= */
400000
),
createVideoRepresentationWithInbandEventStream
(
/* bitrate= */
600000
)),
createAdaptationSet
(
/* id= */
101
,
/* trackType= */
C
.
TRACK_TYPE_AUDIO
,
/* descriptor= */
createSwitchDescriptor
(
/* ids...= */
102
),
C
.
TRACK_TYPE_AUDIO
,
createSwitchDescriptor
(
/* ids...= */
102
),
createAudioRepresentation
(
/* bitrate= */
48000
),
createAudioRepresentation
(
/* bitrate= */
96000
)),
createAdaptationSet
(
/* id= */
102
,
/* trackType= */
C
.
TRACK_TYPE_AUDIO
,
/* descriptor= */
createSwitchDescriptor
(
/* ids...= */
101
),
C
.
TRACK_TYPE_AUDIO
,
createSwitchDescriptor
(
/* ids...= */
101
),
createAudioRepresentation
(
/* bitrate= */
256000
)),
createAdaptationSet
(
/* id= */
103
,
/* trackType= */
C
.
TRACK_TYPE_VIDEO
,
/* descriptor= */
createSwitchDescriptor
(
/* ids...= */
100
,
104
),
C
.
TRACK_TYPE_VIDEO
,
createSwitchDescriptor
(
/* ids...= */
100
,
104
),
createVideoRepresentationWithInbandEventStream
(
/* bitrate= */
800000
),
createVideoRepresentationWithInbandEventStream
(
/* bitrate= */
1000000
)),
createAdaptationSet
(
/* id= */
104
,
/* trackType= */
C
.
TRACK_TYPE_VIDEO
,
/* descriptor= */
createSwitchDescriptor
(
/* ids...= */
100
,
103
),
C
.
TRACK_TYPE_VIDEO
,
createSwitchDescriptor
(
/* ids...= */
100
,
103
),
createVideoRepresentationWithInbandEventStream
(
/* bitrate= */
2000000
)),
createAdaptationSet
(
/* id= */
105
,
/* trackType= */
C
.
TRACK_TYPE_TEXT
,
C
.
TRACK_TYPE_TEXT
,
/* descriptor= */
null
,
createTextRepresentation
(
/* language= */
"eng"
)),
createAdaptationSet
(
/* id= */
105
,
/* trackType= */
C
.
TRACK_TYPE_TEXT
,
C
.
TRACK_TYPE_TEXT
,
/* descriptor= */
null
,
createTextRepresentation
(
/* language= */
"ger"
))));
FilterableManifestMediaPeriodFactory
<
DashManifest
>
mediaPeriodFactory
=
(
manifest
,
periodIndex
)
->
new
DashMediaPeriod
(
/* id= */
periodIndex
,
manifest
,
periodIndex
,
mock
(
DashChunkSource
.
Factory
.
class
),
mock
(
TransferListener
.
class
),
DrmSessionManager
.
getDummyDrmSessionManager
(),
mock
(
LoadErrorHandlingPolicy
.
class
),
new
EventDispatcher
()
.
withParameters
(
/* windowIndex= */
0
,
/* mediaPeriodId= */
new
MediaPeriodId
(
/* periodUid= */
new
Object
()),
/* mediaTimeOffsetMs= */
0
),
/* elapsedRealtimeOffsetMs= */
0
,
mock
(
LoaderErrorThrower
.
class
),
mock
(
Allocator
.
class
),
mock
(
CompositeSequenceableLoaderFactory
.
class
),
mock
(
PlayerEmsgCallback
.
class
));
// Ignore embedded metadata as we don't want to select primary group just to get embedded track.
MediaPeriodAsserts
.
assertGetStreamKeysAndManifestFilterIntegration
(
mediaPeriodFactory
,
testM
anifest
,
DashMediaPeriodTest:
:
createDashMediaPeriod
,
m
anifest
,
/* periodIndex= */
1
,
/* ignoredMimeType= */
"application/x-emsg"
);
}
@Test
public
void
adaptationSetSwitchingProperty_mergesTrackGroups
()
{
DashManifest
manifest
=
createDashManifest
(
createPeriod
(
createAdaptationSet
(
/* id= */
0
,
C
.
TRACK_TYPE_VIDEO
,
createSwitchDescriptor
(
/* ids...= */
1
,
2
),
createVideoRepresentation
(
/* bitrate= */
0
),
createVideoRepresentation
(
/* bitrate= */
1
)),
createAdaptationSet
(
/* id= */
3
,
C
.
TRACK_TYPE_VIDEO
,
/* descriptor= */
null
,
createVideoRepresentation
(
/* bitrate= */
300
)),
createAdaptationSet
(
/* id= */
2
,
C
.
TRACK_TYPE_VIDEO
,
createSwitchDescriptor
(
/* ids...= */
0
,
1
),
createVideoRepresentation
(
/* bitrate= */
200
),
createVideoRepresentation
(
/* bitrate= */
201
)),
createAdaptationSet
(
/* id= */
1
,
C
.
TRACK_TYPE_VIDEO
,
createSwitchDescriptor
(
/* ids...= */
0
,
2
),
createVideoRepresentation
(
/* bitrate= */
100
))));
DashMediaPeriod
dashMediaPeriod
=
createDashMediaPeriod
(
manifest
,
0
);
List
<
AdaptationSet
>
adaptationSets
=
manifest
.
getPeriod
(
0
).
adaptationSets
;
// We expect the three adaptation sets with the switch descriptor to be merged, retaining the
// representations in their original order.
TrackGroupArray
expectedTrackGroups
=
new
TrackGroupArray
(
new
TrackGroup
(
adaptationSets
.
get
(
0
).
representations
.
get
(
0
).
format
,
adaptationSets
.
get
(
0
).
representations
.
get
(
1
).
format
,
adaptationSets
.
get
(
2
).
representations
.
get
(
0
).
format
,
adaptationSets
.
get
(
2
).
representations
.
get
(
1
).
format
,
adaptationSets
.
get
(
3
).
representations
.
get
(
0
).
format
),
new
TrackGroup
(
adaptationSets
.
get
(
1
).
representations
.
get
(
0
).
format
));
MediaPeriodAsserts
.
assertTrackGroups
(
dashMediaPeriod
,
expectedTrackGroups
);
}
@Test
public
void
trickPlayProperty_mergesTrackGroups
()
{
DashManifest
manifest
=
createDashManifest
(
createPeriod
(
createAdaptationSet
(
/* id= */
0
,
C
.
TRACK_TYPE_VIDEO
,
createTrickPlayDescriptor
(
/* mainAdaptationSetId= */
1
),
createVideoRepresentation
(
/* bitrate= */
0
),
createVideoRepresentation
(
/* bitrate= */
1
)),
createAdaptationSet
(
/* id= */
1
,
C
.
TRACK_TYPE_VIDEO
,
/* descriptor= */
null
,
createVideoRepresentation
(
/* bitrate= */
100
)),
createAdaptationSet
(
/* id= */
2
,
C
.
TRACK_TYPE_VIDEO
,
/* descriptor= */
null
,
createVideoRepresentation
(
/* bitrate= */
200
),
createVideoRepresentation
(
/* bitrate= */
201
)),
createAdaptationSet
(
/* id= */
3
,
C
.
TRACK_TYPE_VIDEO
,
createTrickPlayDescriptor
(
/* mainAdaptationSetId= */
2
),
createVideoRepresentation
(
/* bitrate= */
300
))));
DashMediaPeriod
dashMediaPeriod
=
createDashMediaPeriod
(
manifest
,
0
);
List
<
AdaptationSet
>
adaptationSets
=
manifest
.
getPeriod
(
0
).
adaptationSets
;
// We expect the trick play adaptation sets to be merged with the ones to which they refer,
// retaining representations in their original order.
TrackGroupArray
expectedTrackGroups
=
new
TrackGroupArray
(
new
TrackGroup
(
adaptationSets
.
get
(
0
).
representations
.
get
(
0
).
format
,
adaptationSets
.
get
(
0
).
representations
.
get
(
1
).
format
,
adaptationSets
.
get
(
1
).
representations
.
get
(
0
).
format
),
new
TrackGroup
(
adaptationSets
.
get
(
2
).
representations
.
get
(
0
).
format
,
adaptationSets
.
get
(
2
).
representations
.
get
(
1
).
format
,
adaptationSets
.
get
(
3
).
representations
.
get
(
0
).
format
));
MediaPeriodAsserts
.
assertTrackGroups
(
dashMediaPeriod
,
expectedTrackGroups
);
}
@Test
public
void
adaptationSetSwitchingProperty_andTrickPlayProperty_mergesTrackGroups
()
{
DashManifest
manifest
=
createDashManifest
(
createPeriod
(
createAdaptationSet
(
/* id= */
0
,
C
.
TRACK_TYPE_VIDEO
,
createTrickPlayDescriptor
(
/* mainAdaptationSetId= */
1
),
createVideoRepresentation
(
/* bitrate= */
0
),
createVideoRepresentation
(
/* bitrate= */
1
)),
createAdaptationSet
(
/* id= */
1
,
C
.
TRACK_TYPE_VIDEO
,
createSwitchDescriptor
(
/* ids...= */
2
),
createVideoRepresentation
(
/* bitrate= */
100
)),
createAdaptationSet
(
/* id= */
2
,
C
.
TRACK_TYPE_VIDEO
,
createSwitchDescriptor
(
/* ids...= */
1
),
createVideoRepresentation
(
/* bitrate= */
200
),
createVideoRepresentation
(
/* bitrate= */
201
)),
createAdaptationSet
(
/* id= */
3
,
C
.
TRACK_TYPE_VIDEO
,
createTrickPlayDescriptor
(
/* mainAdaptationSetId= */
2
),
createVideoRepresentation
(
/* bitrate= */
300
))));
DashMediaPeriod
dashMediaPeriod
=
createDashMediaPeriod
(
manifest
,
0
);
List
<
AdaptationSet
>
adaptationSets
=
manifest
.
getPeriod
(
0
).
adaptationSets
;
// We expect all adaptation sets to be merged into one group, retaining representations in their
// original order.
TrackGroupArray
expectedTrackGroups
=
new
TrackGroupArray
(
new
TrackGroup
(
adaptationSets
.
get
(
0
).
representations
.
get
(
0
).
format
,
adaptationSets
.
get
(
0
).
representations
.
get
(
1
).
format
,
adaptationSets
.
get
(
1
).
representations
.
get
(
0
).
format
,
adaptationSets
.
get
(
2
).
representations
.
get
(
0
).
format
,
adaptationSets
.
get
(
2
).
representations
.
get
(
1
).
format
,
adaptationSets
.
get
(
3
).
representations
.
get
(
0
).
format
));
MediaPeriodAsserts
.
assertTrackGroups
(
dashMediaPeriod
,
expectedTrackGroups
);
}
private
static
DashMediaPeriod
createDashMediaPeriod
(
DashManifest
manifest
,
int
periodIndex
)
{
return
new
DashMediaPeriod
(
/* id= */
periodIndex
,
manifest
,
periodIndex
,
mock
(
DashChunkSource
.
Factory
.
class
),
mock
(
TransferListener
.
class
),
DrmSessionManager
.
getDummyDrmSessionManager
(),
mock
(
LoadErrorHandlingPolicy
.
class
),
new
EventDispatcher
()
.
withParameters
(
/* windowIndex= */
0
,
/* mediaPeriodId= */
new
MediaPeriodId
(
/* periodUid= */
new
Object
()),
/* mediaTimeOffsetMs= */
0
),
/* elapsedRealtimeOffsetMs= */
0
,
mock
(
LoaderErrorThrower
.
class
),
mock
(
Allocator
.
class
),
mock
(
CompositeSequenceableLoaderFactory
.
class
),
mock
(
PlayerEmsgCallback
.
class
));
}
private
static
DashManifest
createDashManifest
(
Period
...
periods
)
{
return
new
DashManifest
(
/* availabilityStartTimeMs= */
0
,
...
...
@@ -228,6 +367,13 @@ public final class DashMediaPeriodTest {
/* id= */
null
);
}
private
static
Descriptor
createTrickPlayDescriptor
(
int
mainAdaptationSetId
)
{
return
new
Descriptor
(
/* schemeIdUri= */
"http://dashif.org/guidelines/trickmode"
,
/* value= */
Integer
.
toString
(
mainAdaptationSetId
),
/* id= */
null
);
}
private
static
Descriptor
getInbandEventDescriptor
()
{
return
new
Descriptor
(
/* schemeIdUri= */
"inBandSchemeIdUri"
,
/* value= */
"inBandValue"
,
/* id= */
"inBandId"
);
...
...
testutils/src/main/java/com/google/android/exoplayer2/testutil/MediaPeriodAsserts.java
View file @
fea43767
...
...
@@ -55,6 +55,17 @@ public final class MediaPeriodAsserts {
private
MediaPeriodAsserts
()
{}
/**
* Prepares the {@link MediaPeriod} and asserts that it provides the specified track groups.
*
* @param mediaPeriod The {@link MediaPeriod} to test.
* @param expectedGroups The expected track groups.
*/
public
static
void
assertTrackGroups
(
MediaPeriod
mediaPeriod
,
TrackGroupArray
expectedGroups
)
{
TrackGroupArray
actualGroups
=
prepareAndGetTrackGroups
(
mediaPeriod
);
assertThat
(
actualGroups
).
isEqualTo
(
expectedGroups
);
}
/**
* Asserts that the values returns by {@link MediaPeriod#getStreamKeys(List)} are compatible with
* a {@link FilterableManifest} using these stream keys.
*
...
...
@@ -85,7 +96,7 @@ public final class MediaPeriodAsserts {
int
periodIndex
,
@Nullable
String
ignoredMimeType
)
{
MediaPeriod
mediaPeriod
=
mediaPeriodFactory
.
createMediaPeriod
(
manifest
,
periodIndex
);
TrackGroupArray
trackGroupArray
=
g
etTrackGroups
(
mediaPeriod
);
TrackGroupArray
trackGroupArray
=
prepareAndG
etTrackGroups
(
mediaPeriod
);
// Create test vector of query test selections:
// - One selection with one track per group, two tracks or all tracks.
...
...
@@ -146,7 +157,7 @@ public final class MediaPeriodAsserts {
// The filtered manifest should only have one period left.
MediaPeriod
filteredMediaPeriod
=
mediaPeriodFactory
.
createMediaPeriod
(
filteredManifest
,
/* periodIndex= */
0
);
TrackGroupArray
filteredTrackGroupArray
=
g
etTrackGroups
(
filteredMediaPeriod
);
TrackGroupArray
filteredTrackGroupArray
=
prepareAndG
etTrackGroups
(
filteredMediaPeriod
);
for
(
TrackSelection
trackSelection
:
testSelection
)
{
if
(
ignoredMimeType
!=
null
&&
ignoredMimeType
.
equals
(
trackSelection
.
getFormat
(
0
).
sampleMimeType
))
{
...
...
@@ -186,7 +197,7 @@ public final class MediaPeriodAsserts {
return
true
;
}
private
static
TrackGroupArray
g
etTrackGroups
(
MediaPeriod
mediaPeriod
)
{
private
static
TrackGroupArray
prepareAndG
etTrackGroups
(
MediaPeriod
mediaPeriod
)
{
AtomicReference
<
TrackGroupArray
>
trackGroupArray
=
new
AtomicReference
<>();
DummyMainThread
dummyMainThread
=
new
DummyMainThread
();
ConditionVariable
preparedCondition
=
new
ConditionVariable
();
...
...
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