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
7b4b5cbf
authored
Mar 22, 2021
by
gyumin
Committed by
Ian Baker
Mar 24, 2021
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Preserve window indices of Timeline when bundling
PiperOrigin-RevId: 364324490
parent
10a8c603
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
282 additions
and
80 deletions
library/common/src/main/java/com/google/android/exoplayer2/Timeline.java
library/common/src/test/java/com/google/android/exoplayer2/TimelineTest.java
library/core/src/test/java/com/google/android/exoplayer2/ExoPlayerTest.java
library/core/src/test/java/com/google/android/exoplayer2/source/LoopingMediaSourceTest.java
testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeTimeline.java
testutils/src/main/java/com/google/android/exoplayer2/testutil/TimelineAsserts.java
library/common/src/main/java/com/google/android/exoplayer2/Timeline.java
View file @
7b4b5cbf
...
...
@@ -15,6 +15,7 @@
*/
package
com
.
google
.
android
.
exoplayer2
;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
Assertions
.
checkArgument
;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
Assertions
.
checkState
;
import
android.net.Uri
;
...
...
@@ -1255,11 +1256,16 @@ public abstract class Timeline implements Bundleable {
@Documented
@Retention
(
RetentionPolicy
.
SOURCE
)
@IntDef
({
FIELD_WINDOWS
,
FIELD_PERIODS
})
@IntDef
({
FIELD_WINDOWS
,
FIELD_PERIODS
,
FIELD_SHUFFLED_WINDOW_INDICES
,
})
private
@interface
FieldNumber
{}
private
static
final
int
FIELD_WINDOWS
=
0
;
private
static
final
int
FIELD_PERIODS
=
1
;
private
static
final
int
FIELD_SHUFFLED_WINDOW_INDICES
=
2
;
/**
* {@inheritDoc}
...
...
@@ -1272,18 +1278,24 @@ public abstract class Timeline implements Bundleable {
public
final
Bundle
toBundle
()
{
List
<
Bundle
>
windowBundles
=
new
ArrayList
<>();
int
windowCount
=
getWindowCount
();
Window
window
=
new
Window
();
for
(
int
i
=
0
;
i
<
windowCount
;
i
++)
{
Window
window
=
new
Window
();
getWindow
(
i
,
window
,
/* defaultPositionProjectionUs= */
0
);
windowBundles
.
add
(
window
.
toBundle
());
windowBundles
.
add
(
getWindow
(
i
,
window
,
/* defaultPositionProjectionUs= */
0
).
toBundle
());
}
List
<
Bundle
>
periodBundles
=
new
ArrayList
<>();
int
periodCount
=
getPeriodCount
();
Period
period
=
new
Period
();
for
(
int
i
=
0
;
i
<
periodCount
;
i
++)
{
Period
period
=
new
Period
();
getPeriod
(
i
,
period
,
/* setIds= */
false
);
periodBundles
.
add
(
period
.
toBundle
());
periodBundles
.
add
(
getPeriod
(
i
,
period
,
/* setIds= */
false
).
toBundle
());
}
int
[]
shuffledWindowIndices
=
new
int
[
windowCount
];
shuffledWindowIndices
[
0
]
=
getFirstWindowIndex
(
/* shuffleModeEnabled= */
true
);
for
(
int
i
=
1
;
i
<
windowCount
;
i
++)
{
shuffledWindowIndices
[
i
]
=
getNextWindowIndex
(
shuffledWindowIndices
[
i
-
1
],
Player
.
REPEAT_MODE_OFF
,
/* shuffleModeEnabled= */
true
);
}
Bundle
bundle
=
new
Bundle
();
...
...
@@ -1291,6 +1303,7 @@ public abstract class Timeline implements Bundleable {
bundle
,
keyForField
(
FIELD_WINDOWS
),
new
BundleListRetriever
(
windowBundles
));
BundleCompat
.
putBinder
(
bundle
,
keyForField
(
FIELD_PERIODS
),
new
BundleListRetriever
(
periodBundles
));
bundle
.
putIntArray
(
keyForField
(
FIELD_SHUFFLED_WINDOW_INDICES
),
shuffledWindowIndices
);
return
bundle
;
}
...
...
@@ -1310,7 +1323,14 @@ public abstract class Timeline implements Bundleable {
ImmutableList
<
Period
>
periods
=
fromBundleListRetriever
(
Period
.
CREATOR
,
BundleCompat
.
getBinder
(
bundle
,
keyForField
(
FIELD_PERIODS
)));
return
new
RemotableTimeline
(
windows
,
periods
);
@Nullable
int
[]
shuffledWindowIndices
=
bundle
.
getIntArray
(
keyForField
(
FIELD_SHUFFLED_WINDOW_INDICES
));
return
new
RemotableTimeline
(
windows
,
periods
,
shuffledWindowIndices
==
null
?
generateUnshuffledIndices
(
windows
.
size
())
:
shuffledWindowIndices
);
}
private
static
<
T
extends
Bundleable
>
ImmutableList
<
T
>
fromBundleListRetriever
(
...
...
@@ -1330,6 +1350,14 @@ public abstract class Timeline implements Bundleable {
return
Integer
.
toString
(
field
,
Character
.
MAX_RADIX
);
}
private
static
int
[]
generateUnshuffledIndices
(
int
n
)
{
int
[]
indices
=
new
int
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++)
{
indices
[
i
]
=
i
;
}
return
indices
;
}
/**
* A concrete class of {@link Timeline} to restore a {@link Timeline} instance from a {@link
* Bundle} sent by another process via {@link IBinder}.
...
...
@@ -1338,10 +1366,19 @@ public abstract class Timeline implements Bundleable {
private
final
ImmutableList
<
Window
>
windows
;
private
final
ImmutableList
<
Period
>
periods
;
private
final
int
[]
shuffledWindowIndices
;
private
final
int
[]
windowIndicesInShuffled
;
public
RemotableTimeline
(
ImmutableList
<
Window
>
windows
,
ImmutableList
<
Period
>
periods
)
{
public
RemotableTimeline
(
ImmutableList
<
Window
>
windows
,
ImmutableList
<
Period
>
periods
,
int
[]
shuffledWindowIndices
)
{
checkArgument
(
windows
.
size
()
==
shuffledWindowIndices
.
length
);
this
.
windows
=
windows
;
this
.
periods
=
periods
;
this
.
shuffledWindowIndices
=
shuffledWindowIndices
;
windowIndicesInShuffled
=
new
int
[
shuffledWindowIndices
.
length
];
for
(
int
i
=
0
;
i
<
shuffledWindowIndices
.
length
;
i
++)
{
windowIndicesInShuffled
[
shuffledWindowIndices
[
i
]]
=
i
;
}
}
@Override
...
...
@@ -1373,6 +1410,56 @@ public abstract class Timeline implements Bundleable {
}
@Override
public
int
getNextWindowIndex
(
int
windowIndex
,
@Player
.
RepeatMode
int
repeatMode
,
boolean
shuffleModeEnabled
)
{
if
(
repeatMode
==
Player
.
REPEAT_MODE_ONE
)
{
return
windowIndex
;
}
if
(
windowIndex
==
getLastWindowIndex
(
shuffleModeEnabled
))
{
return
repeatMode
==
Player
.
REPEAT_MODE_ALL
?
getFirstWindowIndex
(
shuffleModeEnabled
)
:
C
.
INDEX_UNSET
;
}
return
shuffleModeEnabled
?
shuffledWindowIndices
[
windowIndicesInShuffled
[
windowIndex
]
+
1
]
:
windowIndex
+
1
;
}
@Override
public
int
getPreviousWindowIndex
(
int
windowIndex
,
@Player
.
RepeatMode
int
repeatMode
,
boolean
shuffleModeEnabled
)
{
if
(
repeatMode
==
Player
.
REPEAT_MODE_ONE
)
{
return
windowIndex
;
}
if
(
windowIndex
==
getFirstWindowIndex
(
shuffleModeEnabled
))
{
return
repeatMode
==
Player
.
REPEAT_MODE_ALL
?
getLastWindowIndex
(
shuffleModeEnabled
)
:
C
.
INDEX_UNSET
;
}
return
shuffleModeEnabled
?
shuffledWindowIndices
[
windowIndicesInShuffled
[
windowIndex
]
-
1
]
:
windowIndex
-
1
;
}
@Override
public
int
getLastWindowIndex
(
boolean
shuffleModeEnabled
)
{
if
(
isEmpty
())
{
return
C
.
INDEX_UNSET
;
}
return
shuffleModeEnabled
?
shuffledWindowIndices
[
getWindowCount
()
-
1
]
:
getWindowCount
()
-
1
;
}
@Override
public
int
getFirstWindowIndex
(
boolean
shuffleModeEnabled
)
{
if
(
isEmpty
())
{
return
C
.
INDEX_UNSET
;
}
return
shuffleModeEnabled
?
shuffledWindowIndices
[
0
]
:
0
;
}
@Override
public
int
getPeriodCount
()
{
return
periods
.
size
();
}
...
...
library/common/src/test/java/com/google/android/exoplayer2/TimelineTest.java
View file @
7b4b5cbf
...
...
@@ -238,6 +238,47 @@ public class TimelineTest {
}
@Test
public
void
roundtripViaBundle_ofTimeline_preservesWindowIndices
()
{
int
windowCount
=
10
;
FakeTimeline
timeline
=
new
FakeTimeline
(
windowCount
);
Timeline
restoredTimeline
=
Timeline
.
CREATOR
.
fromBundle
(
timeline
.
toBundle
());
assertThat
(
restoredTimeline
.
getLastWindowIndex
(
/* shuffleModeEnabled= */
false
))
.
isEqualTo
(
timeline
.
getLastWindowIndex
(
/* shuffleModeEnabled= */
false
));
assertThat
(
restoredTimeline
.
getLastWindowIndex
(
/* shuffleModeEnabled= */
true
))
.
isEqualTo
(
timeline
.
getLastWindowIndex
(
/* shuffleModeEnabled= */
true
));
assertThat
(
restoredTimeline
.
getFirstWindowIndex
(
/* shuffleModeEnabled= */
false
))
.
isEqualTo
(
timeline
.
getFirstWindowIndex
(
/* shuffleModeEnabled= */
false
));
assertThat
(
restoredTimeline
.
getFirstWindowIndex
(
/* shuffleModeEnabled= */
true
))
.
isEqualTo
(
timeline
.
getFirstWindowIndex
(
/* shuffleModeEnabled= */
true
));
TimelineAsserts
.
assertEqualNextWindowIndices
(
timeline
,
restoredTimeline
,
Player
.
REPEAT_MODE_OFF
,
/* shuffleModeEnabled= */
false
);
TimelineAsserts
.
assertEqualNextWindowIndices
(
timeline
,
restoredTimeline
,
Player
.
REPEAT_MODE_OFF
,
/* shuffleModeEnabled= */
true
);
TimelineAsserts
.
assertEqualNextWindowIndices
(
timeline
,
restoredTimeline
,
Player
.
REPEAT_MODE_ONE
,
/* shuffleModeEnabled= */
false
);
TimelineAsserts
.
assertEqualNextWindowIndices
(
timeline
,
restoredTimeline
,
Player
.
REPEAT_MODE_ONE
,
/* shuffleModeEnabled= */
true
);
TimelineAsserts
.
assertEqualNextWindowIndices
(
timeline
,
restoredTimeline
,
Player
.
REPEAT_MODE_ALL
,
/* shuffleModeEnabled= */
false
);
TimelineAsserts
.
assertEqualNextWindowIndices
(
timeline
,
restoredTimeline
,
Player
.
REPEAT_MODE_ALL
,
/* shuffleModeEnabled= */
true
);
TimelineAsserts
.
assertEqualPreviousWindowIndices
(
timeline
,
restoredTimeline
,
Player
.
REPEAT_MODE_OFF
,
/* shuffleModeEnabled= */
false
);
TimelineAsserts
.
assertEqualPreviousWindowIndices
(
timeline
,
restoredTimeline
,
Player
.
REPEAT_MODE_OFF
,
/* shuffleModeEnabled= */
true
);
TimelineAsserts
.
assertEqualPreviousWindowIndices
(
timeline
,
restoredTimeline
,
Player
.
REPEAT_MODE_ONE
,
/* shuffleModeEnabled= */
false
);
TimelineAsserts
.
assertEqualPreviousWindowIndices
(
timeline
,
restoredTimeline
,
Player
.
REPEAT_MODE_ONE
,
/* shuffleModeEnabled= */
true
);
TimelineAsserts
.
assertEqualPreviousWindowIndices
(
timeline
,
restoredTimeline
,
Player
.
REPEAT_MODE_ALL
,
/* shuffleModeEnabled= */
false
);
TimelineAsserts
.
assertEqualPreviousWindowIndices
(
timeline
,
restoredTimeline
,
Player
.
REPEAT_MODE_ALL
,
/* shuffleModeEnabled= */
true
);
}
@Test
public
void
roundtripViaBundle_ofWindow_yieldsEqualInstanceExceptUidAndManifest
()
{
Timeline
.
Window
window
=
new
Timeline
.
Window
();
window
.
uid
=
new
Object
();
...
...
library/core/src/test/java/com/google/android/exoplayer2/ExoPlayerTest.java
View file @
7b4b5cbf
...
...
@@ -1707,40 +1707,6 @@ public final class ExoPlayerTest {
}
@Test
public
void
testInvalidSeekPositionAfterSourceInfoRefreshWithShuffleModeEnabledUsesCorrectFirstPeriod
()
throws
Exception
{
FakeMediaSource
mediaSource
=
new
FakeMediaSource
(
new
FakeTimeline
(
/* windowCount= */
2
));
AtomicInteger
windowIndexAfterUpdate
=
new
AtomicInteger
();
ActionSchedule
actionSchedule
=
new
ActionSchedule
.
Builder
(
TAG
)
.
setShuffleOrder
(
new
FakeShuffleOrder
(
/* length= */
0
))
.
setShuffleModeEnabled
(
true
)
.
waitForPlaybackState
(
Player
.
STATE_BUFFERING
)
// Seeking to an invalid position will end playback.
.
seek
(
/* windowIndex= */
100
,
/* positionMs= */
0
,
/* catchIllegalSeekException= */
true
)
.
waitForPlaybackState
(
Player
.
STATE_ENDED
)
.
executeRunnable
(
new
PlayerRunnable
()
{
@Override
public
void
run
(
SimpleExoPlayer
player
)
{
windowIndexAfterUpdate
.
set
(
player
.
getCurrentWindowIndex
());
}
})
.
build
();
new
ExoPlayerTestRunner
.
Builder
(
context
)
.
setMediaSources
(
mediaSource
)
.
setActionSchedule
(
actionSchedule
)
.
build
()
.
start
()
.
blockUntilActionScheduleFinished
(
TIMEOUT_MS
)
.
blockUntilEnded
(
TIMEOUT_MS
);
assertThat
(
windowIndexAfterUpdate
.
get
()).
isEqualTo
(
1
);
}
@Test
public
void
restartAfterEmptyTimelineWithShuffleModeEnabledUsesCorrectFirstPeriod
()
throws
Exception
{
ConcatenatingMediaSource
concatenatingMediaSource
=
...
...
library/core/src/test/java/com/google/android/exoplayer2/source/LoopingMediaSourceTest.java
View file @
7b4b5cbf
...
...
@@ -49,18 +49,28 @@ public class LoopingMediaSourceTest {
Timeline
timeline
=
getLoopingTimeline
(
multiWindowTimeline
,
1
);
TimelineAsserts
.
assertWindowTags
(
timeline
,
111
,
222
,
333
);
TimelineAsserts
.
assertPeriodCounts
(
timeline
,
1
,
1
,
1
);
for
(
boolean
shuffled
:
new
boolean
[]
{
false
,
true
})
{
TimelineAsserts
.
assertPreviousWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_OFF
,
shuffled
,
C
.
INDEX_UNSET
,
0
,
1
);
TimelineAsserts
.
assertPreviousWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_ONE
,
shuffled
,
0
,
1
,
2
);
TimelineAsserts
.
assertPreviousWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_ALL
,
shuffled
,
2
,
0
,
1
);
TimelineAsserts
.
assertNextWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_OFF
,
shuffled
,
1
,
2
,
C
.
INDEX_UNSET
);
TimelineAsserts
.
assertNextWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_ONE
,
shuffled
,
0
,
1
,
2
);
TimelineAsserts
.
assertNextWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_ALL
,
shuffled
,
1
,
2
,
0
);
}
boolean
shuffled
=
false
;
TimelineAsserts
.
assertPreviousWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_OFF
,
shuffled
,
C
.
INDEX_UNSET
,
0
,
1
);
TimelineAsserts
.
assertPreviousWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_ONE
,
shuffled
,
0
,
1
,
2
);
TimelineAsserts
.
assertPreviousWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_ALL
,
shuffled
,
2
,
0
,
1
);
TimelineAsserts
.
assertNextWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_OFF
,
shuffled
,
1
,
2
,
C
.
INDEX_UNSET
);
TimelineAsserts
.
assertNextWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_ONE
,
shuffled
,
0
,
1
,
2
);
TimelineAsserts
.
assertNextWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_ALL
,
shuffled
,
1
,
2
,
0
);
shuffled
=
true
;
// FakeTimeline has FakeShuffleOrder which returns a reverse order.
TimelineAsserts
.
assertPreviousWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_OFF
,
shuffled
,
1
,
2
,
C
.
INDEX_UNSET
);
TimelineAsserts
.
assertPreviousWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_ONE
,
shuffled
,
0
,
1
,
2
);
TimelineAsserts
.
assertPreviousWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_ALL
,
shuffled
,
1
,
2
,
0
);
TimelineAsserts
.
assertNextWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_OFF
,
shuffled
,
C
.
INDEX_UNSET
,
0
,
1
);
TimelineAsserts
.
assertNextWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_ONE
,
shuffled
,
0
,
1
,
2
);
TimelineAsserts
.
assertNextWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_ALL
,
shuffled
,
2
,
0
,
1
);
}
@Test
...
...
@@ -68,20 +78,32 @@ public class LoopingMediaSourceTest {
Timeline
timeline
=
getLoopingTimeline
(
multiWindowTimeline
,
3
);
TimelineAsserts
.
assertWindowTags
(
timeline
,
111
,
222
,
333
,
111
,
222
,
333
,
111
,
222
,
333
);
TimelineAsserts
.
assertPeriodCounts
(
timeline
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
);
for
(
boolean
shuffled
:
new
boolean
[]
{
false
,
true
})
{
TimelineAsserts
.
assertPreviousWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_OFF
,
shuffled
,
C
.
INDEX_UNSET
,
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
);
TimelineAsserts
.
assertPreviousWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_ONE
,
shuffled
,
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
);
TimelineAsserts
.
assertPreviousWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_ALL
,
shuffled
,
8
,
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
);
TimelineAsserts
.
assertNextWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_OFF
,
shuffled
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
C
.
INDEX_UNSET
);
TimelineAsserts
.
assertNextWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_ONE
,
shuffled
,
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
);
TimelineAsserts
.
assertNextWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_ALL
,
shuffled
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
0
);
}
boolean
shuffled
=
false
;
TimelineAsserts
.
assertPreviousWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_OFF
,
shuffled
,
C
.
INDEX_UNSET
,
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
);
TimelineAsserts
.
assertPreviousWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_ONE
,
shuffled
,
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
);
TimelineAsserts
.
assertPreviousWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_ALL
,
shuffled
,
8
,
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
);
TimelineAsserts
.
assertNextWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_OFF
,
shuffled
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
C
.
INDEX_UNSET
);
TimelineAsserts
.
assertNextWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_ONE
,
shuffled
,
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
);
TimelineAsserts
.
assertNextWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_ALL
,
shuffled
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
0
);
shuffled
=
true
;
// FakeTimeline has FakeShuffleOrder which returns a reverse order.
TimelineAsserts
.
assertPreviousWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_OFF
,
shuffled
,
1
,
2
,
C
.
INDEX_UNSET
,
4
,
5
,
0
,
7
,
8
,
3
);
TimelineAsserts
.
assertPreviousWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_ONE
,
shuffled
,
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
);
TimelineAsserts
.
assertPreviousWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_ALL
,
shuffled
,
1
,
2
,
6
,
4
,
5
,
0
,
7
,
8
,
3
);
TimelineAsserts
.
assertNextWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_OFF
,
shuffled
,
5
,
0
,
1
,
8
,
3
,
4
,
C
.
INDEX_UNSET
,
6
,
7
);
TimelineAsserts
.
assertNextWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_ONE
,
shuffled
,
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
);
TimelineAsserts
.
assertNextWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_ALL
,
shuffled
,
5
,
0
,
1
,
8
,
3
,
4
,
2
,
6
,
7
);
}
@Test
...
...
@@ -89,17 +111,26 @@ public class LoopingMediaSourceTest {
Timeline
timeline
=
getLoopingTimeline
(
multiWindowTimeline
,
Integer
.
MAX_VALUE
);
TimelineAsserts
.
assertWindowTags
(
timeline
,
111
,
222
,
333
);
TimelineAsserts
.
assertPeriodCounts
(
timeline
,
1
,
1
,
1
);
for
(
boolean
shuffled
:
new
boolean
[]
{
false
,
true
})
{
TimelineAsserts
.
assertPreviousWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_OFF
,
shuffled
,
2
,
0
,
1
);
TimelineAsserts
.
assertPreviousWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_ONE
,
shuffled
,
0
,
1
,
2
);
TimelineAsserts
.
assertPreviousWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_ALL
,
shuffled
,
2
,
0
,
1
);
TimelineAsserts
.
assertNextWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_OFF
,
shuffled
,
1
,
2
,
0
);
TimelineAsserts
.
assertNextWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_ONE
,
shuffled
,
0
,
1
,
2
);
TimelineAsserts
.
assertNextWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_ALL
,
shuffled
,
1
,
2
,
0
);
}
boolean
shuffled
=
false
;
TimelineAsserts
.
assertPreviousWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_OFF
,
shuffled
,
2
,
0
,
1
);
TimelineAsserts
.
assertPreviousWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_ONE
,
shuffled
,
0
,
1
,
2
);
TimelineAsserts
.
assertPreviousWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_ALL
,
shuffled
,
2
,
0
,
1
);
TimelineAsserts
.
assertNextWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_OFF
,
shuffled
,
1
,
2
,
0
);
TimelineAsserts
.
assertNextWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_ONE
,
shuffled
,
0
,
1
,
2
);
TimelineAsserts
.
assertNextWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_ALL
,
shuffled
,
1
,
2
,
0
);
shuffled
=
true
;
// FakeTimeline has FakeShuffleOrder which returns a reverse order.
TimelineAsserts
.
assertPreviousWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_OFF
,
shuffled
,
1
,
2
,
0
);
TimelineAsserts
.
assertPreviousWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_ONE
,
shuffled
,
0
,
1
,
2
);
TimelineAsserts
.
assertPreviousWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_ALL
,
shuffled
,
1
,
2
,
0
);
TimelineAsserts
.
assertNextWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_OFF
,
shuffled
,
2
,
0
,
1
);
TimelineAsserts
.
assertNextWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_ONE
,
shuffled
,
0
,
1
,
2
);
TimelineAsserts
.
assertNextWindowIndices
(
timeline
,
Player
.
REPEAT_MODE_ALL
,
shuffled
,
2
,
0
,
1
);
}
@Test
...
...
testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeTimeline.java
View file @
7b4b5cbf
...
...
@@ -21,6 +21,7 @@ import android.net.Uri;
import
android.util.Pair
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.MediaItem
;
import
com.google.android.exoplayer2.Player
;
import
com.google.android.exoplayer2.Timeline
;
import
com.google.android.exoplayer2.source.ads.AdPlaybackState
;
import
com.google.android.exoplayer2.util.Assertions
;
...
...
@@ -235,6 +236,7 @@ public final class FakeTimeline extends Timeline {
private
final
TimelineWindowDefinition
[]
windowDefinitions
;
private
final
Object
[]
manifests
;
private
final
int
[]
periodOffsets
;
private
final
FakeShuffleOrder
fakeShuffleOrder
;
/**
* Returns an ad playback state with the specified number of ads in each of the specified ad
...
...
@@ -308,6 +310,7 @@ public final class FakeTimeline extends Timeline {
for
(
int
i
=
0
;
i
<
windowDefinitions
.
length
;
i
++)
{
periodOffsets
[
i
+
1
]
=
periodOffsets
[
i
]
+
windowDefinitions
[
i
].
periodCount
;
}
fakeShuffleOrder
=
new
FakeShuffleOrder
(
windowDefinitions
.
length
);
}
@Override
...
...
@@ -316,6 +319,48 @@ public final class FakeTimeline extends Timeline {
}
@Override
public
int
getNextWindowIndex
(
int
windowIndex
,
@Player
.
RepeatMode
int
repeatMode
,
boolean
shuffleModeEnabled
)
{
if
(
repeatMode
==
Player
.
REPEAT_MODE_ONE
)
{
return
windowIndex
;
}
if
(
windowIndex
==
getLastWindowIndex
(
shuffleModeEnabled
))
{
return
repeatMode
==
Player
.
REPEAT_MODE_ALL
?
getFirstWindowIndex
(
shuffleModeEnabled
)
:
C
.
INDEX_UNSET
;
}
return
shuffleModeEnabled
?
fakeShuffleOrder
.
getNextIndex
(
windowIndex
)
:
windowIndex
+
1
;
}
@Override
public
int
getPreviousWindowIndex
(
int
windowIndex
,
@Player
.
RepeatMode
int
repeatMode
,
boolean
shuffleModeEnabled
)
{
if
(
repeatMode
==
Player
.
REPEAT_MODE_ONE
)
{
return
windowIndex
;
}
if
(
windowIndex
==
getFirstWindowIndex
(
shuffleModeEnabled
))
{
return
repeatMode
==
Player
.
REPEAT_MODE_ALL
?
getLastWindowIndex
(
shuffleModeEnabled
)
:
C
.
INDEX_UNSET
;
}
return
shuffleModeEnabled
?
fakeShuffleOrder
.
getPreviousIndex
(
windowIndex
)
:
windowIndex
-
1
;
}
@Override
public
int
getLastWindowIndex
(
boolean
shuffleModeEnabled
)
{
return
shuffleModeEnabled
?
fakeShuffleOrder
.
getLastIndex
()
:
super
.
getLastWindowIndex
(
/* shuffleModeEnabled= */
false
);
}
@Override
public
int
getFirstWindowIndex
(
boolean
shuffleModeEnabled
)
{
return
shuffleModeEnabled
?
fakeShuffleOrder
.
getFirstIndex
()
:
super
.
getFirstWindowIndex
(
/* shuffleModeEnabled= */
false
);
}
@Override
public
Window
getWindow
(
int
windowIndex
,
Window
window
,
long
defaultPositionProjectionUs
)
{
TimelineWindowDefinition
windowDefinition
=
windowDefinitions
[
windowIndex
];
window
.
set
(
...
...
testutils/src/main/java/com/google/android/exoplayer2/testutil/TimelineAsserts.java
View file @
7b4b5cbf
...
...
@@ -105,6 +105,38 @@ public final class TimelineAsserts {
}
/**
* Asserts that previous window indices for each window of the actual timeline are equal to the
* indices of the expected timeline depending on the repeat mode and the shuffle mode.
*/
public
static
void
assertEqualPreviousWindowIndices
(
Timeline
expectedTimeline
,
Timeline
actualTimeline
,
@Player
.
RepeatMode
int
repeatMode
,
boolean
shuffleModeEnabled
)
{
for
(
int
windowIndex
=
0
;
windowIndex
<
actualTimeline
.
getWindowCount
();
windowIndex
++)
{
assertThat
(
actualTimeline
.
getPreviousWindowIndex
(
windowIndex
,
repeatMode
,
shuffleModeEnabled
))
.
isEqualTo
(
expectedTimeline
.
getPreviousWindowIndex
(
windowIndex
,
repeatMode
,
shuffleModeEnabled
));
}
}
/**
* Asserts that next window indices for each window of the actual timeline are equal to the
* indices of the expected timeline depending on the repeat mode and the shuffle mode.
*/
public
static
void
assertEqualNextWindowIndices
(
Timeline
expectedTimeline
,
Timeline
actualTimeline
,
@Player
.
RepeatMode
int
repeatMode
,
boolean
shuffleModeEnabled
)
{
for
(
int
windowIndex
=
0
;
windowIndex
<
actualTimeline
.
getWindowCount
();
windowIndex
++)
{
assertThat
(
actualTimeline
.
getNextWindowIndex
(
windowIndex
,
repeatMode
,
shuffleModeEnabled
))
.
isEqualTo
(
expectedTimeline
.
getNextWindowIndex
(
windowIndex
,
repeatMode
,
shuffleModeEnabled
));
}
}
/**
* Asserts that the durations of the periods in the {@link Timeline} and the durations in the
* given sequence are equal.
*/
...
...
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