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
a60ed20f
authored
Mar 09, 2021
by
gyumin
Committed by
Ian Baker
Mar 12, 2021
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Implement Bundleable for Timeline.Window
PiperOrigin-RevId: 361741354
parent
ae7c1091
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
229 additions
and
49 deletions
library/common/src/main/java/com/google/android/exoplayer2/MediaItem.java
library/common/src/main/java/com/google/android/exoplayer2/Timeline.java
library/common/src/test/java/com/google/android/exoplayer2/TimelineTest.java
library/common/src/main/java/com/google/android/exoplayer2/MediaItem.java
View file @
a60ed20f
...
...
@@ -1272,6 +1272,12 @@ public final class MediaItem implements Bundleable {
private
static
final
int
FIELD_MEDIA_METADATA
=
2
;
private
static
final
int
FIELD_CLIPPING_PROPERTIES
=
3
;
/**
* {@inheritDoc}
*
* <p>It omits the {@link #playbackProperties} field. The {@link #playbackProperties} of an
* instance restored by {@link #CREATOR} will always be {@code null}.
*/
@Override
public
Bundle
toBundle
()
{
Bundle
bundle
=
new
Bundle
();
...
...
@@ -1282,46 +1288,51 @@ public final class MediaItem implements Bundleable {
return
bundle
;
}
/** Object that can restore {@link MediaItem} from a {@link Bundle}. */
public
static
final
Creator
<
MediaItem
>
CREATOR
=
bundle
->
{
String
mediaId
=
checkNotNull
(
bundle
.
getString
(
keyForField
(
FIELD_MEDIA_ID
)));
@Nullable
Bundle
liveConfigurationBundle
=
bundle
.
getBundle
(
keyForField
(
FIELD_LIVE_CONFIGURATION
));
LiveConfiguration
liveConfiguration
;
if
(
liveConfigurationBundle
==
null
)
{
liveConfiguration
=
LiveConfiguration
.
UNSET
;
}
else
{
liveConfiguration
=
LiveConfiguration
.
CREATOR
.
fromBundle
(
liveConfigurationBundle
);
}
@Nullable
Bundle
mediaMetadataBundle
=
bundle
.
getBundle
(
keyForField
(
FIELD_MEDIA_METADATA
));
MediaMetadata
mediaMetadata
;
if
(
mediaMetadataBundle
==
null
)
{
mediaMetadata
=
new
MediaMetadata
.
Builder
().
build
();
}
else
{
mediaMetadata
=
MediaMetadata
.
CREATOR
.
fromBundle
(
mediaMetadataBundle
);
}
@Nullable
Bundle
clippingPropertiesBundle
=
bundle
.
getBundle
(
keyForField
(
FIELD_CLIPPING_PROPERTIES
));
ClippingProperties
clippingProperties
;
if
(
clippingPropertiesBundle
==
null
)
{
clippingProperties
=
new
ClippingProperties
(
/* startPositionMs= */
0
,
/* endPositionMs= */
C
.
TIME_END_OF_SOURCE
,
/* relativeToLiveWindow= */
false
,
/* relativeToDefaultPosition= */
false
,
/* startsAtKeyFrame= */
false
);
}
else
{
clippingProperties
=
ClippingProperties
.
CREATOR
.
fromBundle
(
clippingPropertiesBundle
);
}
return
new
MediaItem
(
mediaId
,
clippingProperties
,
/* playbackProperties= */
null
,
liveConfiguration
,
mediaMetadata
);
};
/**
* Object that can restore {@link MediaItem} from a {@link Bundle}.
*
* <p>The {@link #playbackProperties} of a restored instance will always be {@code null}.
*/
public
static
final
Creator
<
MediaItem
>
CREATOR
=
MediaItem:
:
fromBundle
;
private
static
MediaItem
fromBundle
(
Bundle
bundle
)
{
String
mediaId
=
checkNotNull
(
bundle
.
getString
(
keyForField
(
FIELD_MEDIA_ID
)));
@Nullable
Bundle
liveConfigurationBundle
=
bundle
.
getBundle
(
keyForField
(
FIELD_LIVE_CONFIGURATION
));
LiveConfiguration
liveConfiguration
;
if
(
liveConfigurationBundle
==
null
)
{
liveConfiguration
=
LiveConfiguration
.
UNSET
;
}
else
{
liveConfiguration
=
LiveConfiguration
.
CREATOR
.
fromBundle
(
liveConfigurationBundle
);
}
@Nullable
Bundle
mediaMetadataBundle
=
bundle
.
getBundle
(
keyForField
(
FIELD_MEDIA_METADATA
));
MediaMetadata
mediaMetadata
;
if
(
mediaMetadataBundle
==
null
)
{
mediaMetadata
=
new
MediaMetadata
.
Builder
().
build
();
}
else
{
mediaMetadata
=
MediaMetadata
.
CREATOR
.
fromBundle
(
mediaMetadataBundle
);
}
@Nullable
Bundle
clippingPropertiesBundle
=
bundle
.
getBundle
(
keyForField
(
FIELD_CLIPPING_PROPERTIES
));
ClippingProperties
clippingProperties
;
if
(
clippingPropertiesBundle
==
null
)
{
clippingProperties
=
new
ClippingProperties
(
/* startPositionMs= */
0
,
/* endPositionMs= */
C
.
TIME_END_OF_SOURCE
,
/* relativeToLiveWindow= */
false
,
/* relativeToDefaultPosition= */
false
,
/* startsAtKeyFrame= */
false
);
}
else
{
clippingProperties
=
ClippingProperties
.
CREATOR
.
fromBundle
(
clippingPropertiesBundle
);
}
return
new
MediaItem
(
mediaId
,
clippingProperties
,
/* playbackProperties= */
null
,
liveConfiguration
,
mediaMetadata
);
}
private
static
String
keyForField
(
@FieldNumber
int
field
)
{
return
Integer
.
toString
(
field
,
Character
.
MAX_RADIX
);
...
...
library/common/src/main/java/com/google/android/exoplayer2/Timeline.java
View file @
a60ed20f
...
...
@@ -136,13 +136,15 @@ public abstract class Timeline {
* <p style="align:center"><img src="doc-files/timeline-window.svg" alt="Information defined by a
* timeline window">
*/
public
static
final
class
Window
{
public
static
final
class
Window
implements
Bundleable
{
/**
* A {@link #uid} for a window that must be used for single-window {@link Timeline Timelines}.
*/
public
static
final
Object
SINGLE_WINDOW_UID
=
new
Object
();
private
static
final
Object
FAKE_WINDOW_UID
=
new
Object
();
private
static
final
MediaItem
EMPTY_MEDIA_ITEM
=
new
MediaItem
.
Builder
()
.
setMediaId
(
"com.google.android.exoplayer2.Timeline"
)
...
...
@@ -213,14 +215,6 @@ public abstract class Timeline {
*/
public
boolean
isPlaceholder
;
/** The index of the first period that belongs to this window. */
public
int
firstPeriodIndex
;
/**
* The index of the last period that belongs to this window.
*/
public
int
lastPeriodIndex
;
/**
* The default position relative to the start of the window at which to begin playback, in
* microseconds. May be {@link C#TIME_UNSET} if and only if the window was populated with a
...
...
@@ -234,6 +228,12 @@ public abstract class Timeline {
*/
public
long
durationUs
;
/** The index of the first period that belongs to this window. */
public
int
firstPeriodIndex
;
/** The index of the last period that belongs to this window. */
public
int
lastPeriodIndex
;
/**
* The position of the start of this window relative to the start of the first period belonging
* to it, in microseconds.
...
...
@@ -404,6 +404,142 @@ public abstract class Timeline {
result
=
31
*
result
+
(
int
)
(
positionInFirstPeriodUs
^
(
positionInFirstPeriodUs
>>>
32
));
return
result
;
}
// Bundleable implementation.
@Documented
@Retention
(
RetentionPolicy
.
SOURCE
)
@IntDef
({
FIELD_MEDIA_ITEM
,
FIELD_PRESENTATION_START_TIME_MS
,
FIELD_WINDOW_START_TIME_MS
,
FIELD_ELAPSED_REALTIME_EPOCH_OFFSET_MS
,
FIELD_IS_SEEKABLE
,
FIELD_IS_DYNAMIC
,
FIELD_LIVE_CONFIGURATION
,
FIELD_IS_PLACEHOLDER
,
FIELD_DEFAULT_POSITION_US
,
FIELD_DURATION_US
,
FIELD_FIRST_PERIOD_INDEX
,
FIELD_LAST_PERIOD_INDEX
,
FIELD_POSITION_IN_FIRST_PERIOD_US
,
})
private
@interface
FieldNumber
{}
private
static
final
int
FIELD_MEDIA_ITEM
=
1
;
private
static
final
int
FIELD_PRESENTATION_START_TIME_MS
=
2
;
private
static
final
int
FIELD_WINDOW_START_TIME_MS
=
3
;
private
static
final
int
FIELD_ELAPSED_REALTIME_EPOCH_OFFSET_MS
=
4
;
private
static
final
int
FIELD_IS_SEEKABLE
=
5
;
private
static
final
int
FIELD_IS_DYNAMIC
=
6
;
private
static
final
int
FIELD_LIVE_CONFIGURATION
=
7
;
private
static
final
int
FIELD_IS_PLACEHOLDER
=
8
;
private
static
final
int
FIELD_DEFAULT_POSITION_US
=
9
;
private
static
final
int
FIELD_DURATION_US
=
10
;
private
static
final
int
FIELD_FIRST_PERIOD_INDEX
=
11
;
private
static
final
int
FIELD_LAST_PERIOD_INDEX
=
12
;
private
static
final
int
FIELD_POSITION_IN_FIRST_PERIOD_US
=
13
;
/**
* {@inheritDoc}
*
* <p>It omits the {@link #uid} and {@link #manifest} fields. The {@link #uid} of an instance
* restored by {@link #CREATOR} will be a fake {@link Object} and the {@link #manifest} of the
* instance will be {@code null}.
*/
// TODO(b/166765820): See if missing fields would be okay and add them to the Bundle otherwise.
@Override
public
Bundle
toBundle
()
{
Bundle
bundle
=
new
Bundle
();
bundle
.
putBundle
(
keyForField
(
FIELD_MEDIA_ITEM
),
mediaItem
.
toBundle
());
bundle
.
putLong
(
keyForField
(
FIELD_PRESENTATION_START_TIME_MS
),
presentationStartTimeMs
);
bundle
.
putLong
(
keyForField
(
FIELD_WINDOW_START_TIME_MS
),
windowStartTimeMs
);
bundle
.
putLong
(
keyForField
(
FIELD_ELAPSED_REALTIME_EPOCH_OFFSET_MS
),
elapsedRealtimeEpochOffsetMs
);
bundle
.
putBoolean
(
keyForField
(
FIELD_IS_SEEKABLE
),
isSeekable
);
bundle
.
putBoolean
(
keyForField
(
FIELD_IS_DYNAMIC
),
isDynamic
);
@Nullable
MediaItem
.
LiveConfiguration
liveConfiguration
=
this
.
liveConfiguration
;
if
(
liveConfiguration
!=
null
)
{
bundle
.
putBundle
(
keyForField
(
FIELD_LIVE_CONFIGURATION
),
liveConfiguration
.
toBundle
());
}
bundle
.
putBoolean
(
keyForField
(
FIELD_IS_PLACEHOLDER
),
isPlaceholder
);
bundle
.
putLong
(
keyForField
(
FIELD_DEFAULT_POSITION_US
),
defaultPositionUs
);
bundle
.
putLong
(
keyForField
(
FIELD_DURATION_US
),
durationUs
);
bundle
.
putInt
(
keyForField
(
FIELD_FIRST_PERIOD_INDEX
),
firstPeriodIndex
);
bundle
.
putInt
(
keyForField
(
FIELD_LAST_PERIOD_INDEX
),
lastPeriodIndex
);
bundle
.
putLong
(
keyForField
(
FIELD_POSITION_IN_FIRST_PERIOD_US
),
positionInFirstPeriodUs
);
return
bundle
;
}
/**
* Object that can restore {@link Period} from a {@link Bundle}.
*
* <p>The {@link #uid} of a restored instance will be a fake {@link Object} and the {@link
* #manifest} of the instance will be {@code null}.
*/
public
static
final
Creator
<
Window
>
CREATOR
=
Window:
:
fromBundle
;
private
static
Window
fromBundle
(
Bundle
bundle
)
{
@Nullable
Bundle
mediaItemBundle
=
bundle
.
getBundle
(
keyForField
(
FIELD_MEDIA_ITEM
));
@Nullable
MediaItem
mediaItem
=
mediaItemBundle
!=
null
?
MediaItem
.
CREATOR
.
fromBundle
(
mediaItemBundle
)
:
null
;
long
presentationStartTimeMs
=
bundle
.
getLong
(
keyForField
(
FIELD_PRESENTATION_START_TIME_MS
),
/* defaultValue= */
C
.
TIME_UNSET
);
long
windowStartTimeMs
=
bundle
.
getLong
(
keyForField
(
FIELD_WINDOW_START_TIME_MS
),
/* defaultValue= */
C
.
TIME_UNSET
);
long
elapsedRealtimeEpochOffsetMs
=
bundle
.
getLong
(
keyForField
(
FIELD_ELAPSED_REALTIME_EPOCH_OFFSET_MS
),
/* defaultValue= */
C
.
TIME_UNSET
);
boolean
isSeekable
=
bundle
.
getBoolean
(
keyForField
(
FIELD_IS_SEEKABLE
),
/* defaultValue= */
false
);
boolean
isDynamic
=
bundle
.
getBoolean
(
keyForField
(
FIELD_IS_DYNAMIC
),
/* defaultValue= */
false
);
@Nullable
Bundle
liveConfigurationBundle
=
bundle
.
getBundle
(
keyForField
(
FIELD_LIVE_CONFIGURATION
));
@Nullable
MediaItem
.
LiveConfiguration
liveConfiguration
=
liveConfigurationBundle
!=
null
?
MediaItem
.
LiveConfiguration
.
CREATOR
.
fromBundle
(
liveConfigurationBundle
)
:
null
;
boolean
isPlaceHolder
=
bundle
.
getBoolean
(
keyForField
(
FIELD_IS_PLACEHOLDER
),
/* defaultValue= */
false
);
long
defaultPositionUs
=
bundle
.
getLong
(
keyForField
(
FIELD_DEFAULT_POSITION_US
),
/* defaultValue= */
0
);
long
durationUs
=
bundle
.
getLong
(
keyForField
(
FIELD_DURATION_US
),
/* defaultValue= */
C
.
TIME_UNSET
);
int
firstPeriodIndex
=
bundle
.
getInt
(
keyForField
(
FIELD_FIRST_PERIOD_INDEX
),
/* defaultValue= */
0
);
int
lastPeriodIndex
=
bundle
.
getInt
(
keyForField
(
FIELD_LAST_PERIOD_INDEX
),
/* defaultValue= */
0
);
long
positionInFirstPeriodUs
=
bundle
.
getLong
(
keyForField
(
FIELD_POSITION_IN_FIRST_PERIOD_US
),
/* defaultValue= */
0
);
Window
window
=
new
Window
();
window
.
set
(
FAKE_WINDOW_UID
,
mediaItem
,
/* manifest= */
null
,
presentationStartTimeMs
,
windowStartTimeMs
,
elapsedRealtimeEpochOffsetMs
,
isSeekable
,
isDynamic
,
liveConfiguration
,
defaultPositionUs
,
durationUs
,
firstPeriodIndex
,
lastPeriodIndex
,
positionInFirstPeriodUs
);
window
.
isPlaceholder
=
isPlaceHolder
;
return
window
;
}
private
static
String
keyForField
(
@Window
.
FieldNumber
int
field
)
{
return
Integer
.
toString
(
field
,
Character
.
MAX_RADIX
);
}
}
/**
...
...
library/common/src/test/java/com/google/android/exoplayer2/TimelineTest.java
View file @
a60ed20f
...
...
@@ -202,6 +202,39 @@ public class TimelineTest {
}
@Test
public
void
roundtripViaBundle_ofWindow_yieldsEqualInstanceExceptUidAndManifest
()
{
Timeline
.
Window
window
=
new
Timeline
.
Window
();
window
.
uid
=
new
Object
();
window
.
mediaItem
=
new
MediaItem
.
Builder
().
setMediaId
(
"mediaId"
).
build
();
window
.
manifest
=
new
Object
();
window
.
presentationStartTimeMs
=
111
;
window
.
windowStartTimeMs
=
222
;
window
.
elapsedRealtimeEpochOffsetMs
=
333
;
window
.
isSeekable
=
true
;
window
.
isDynamic
=
true
;
window
.
liveConfiguration
=
new
LiveConfiguration
(
/* targetOffsetMs= */
1
,
/* minOffsetMs= */
2
,
/* maxOffsetMs= */
3
,
/* minPlaybackSpeed= */
0.5f
,
/* maxPlaybackSpeed= */
1.5f
);
window
.
isPlaceholder
=
true
;
window
.
defaultPositionUs
=
444
;
window
.
durationUs
=
555
;
window
.
firstPeriodIndex
=
6
;
window
.
lastPeriodIndex
=
7
;
window
.
positionInFirstPeriodUs
=
888
;
Timeline
.
Window
restoredWindow
=
Timeline
.
Window
.
CREATOR
.
fromBundle
(
window
.
toBundle
());
assertThat
(
restoredWindow
.
manifest
).
isNull
();
window
.
uid
=
restoredWindow
.
uid
;
window
.
manifest
=
null
;
assertThat
(
restoredWindow
).
isEqualTo
(
window
);
}
@Test
public
void
roundtripViaBundle_ofPeriod_yieldsEqualInstanceExceptIds
()
{
Timeline
.
Period
period
=
new
Timeline
.
Period
();
period
.
id
=
new
Object
();
...
...
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