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
8861ab48
authored
Aug 27, 2021
by
bachinger
Committed by
kim-vde
Sep 02, 2021
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Implement setPlaybackParameters for CastPlayer
Issue: #6784 PiperOrigin-RevId: 393374139
parent
9b2cd6a4
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
155 additions
and
7 deletions
RELEASENOTES.md
extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastPlayer.java
extensions/cast/src/test/java/com/google/android/exoplayer2/ext/cast/CastPlayerTest.java
RELEASENOTES.md
View file @
8861ab48
...
...
@@ -48,6 +48,10 @@
`DefaultHttpDataSource.Factory`
instead.
*
Remove
`GvrAudioProcessor`
and the GVR extension, which has been
deprecated since 2.11.0.
*
Cast extension:
*
Implement
`CastPlayer.setPlaybackParameters(PlaybackParameters)`
to
support setting the playback speed
(
[
#6784
](
https://github.com/google/ExoPlayer/issues/6784
)
).
### 2.15.0 (2021-08-10)
...
...
extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastPlayer.java
View file @
8861ab48
...
...
@@ -97,6 +97,7 @@ public final class CastPlayer extends BasePlayer {
COMMAND_SEEK_TO_DEFAULT_POSITION
,
COMMAND_SEEK_TO_WINDOW
,
COMMAND_SET_REPEAT_MODE
,
COMMAND_SET_SPEED_AND_PITCH
,
COMMAND_GET_CURRENT_MEDIA_ITEM
,
COMMAND_GET_TIMELINE
,
COMMAND_GET_MEDIA_ITEMS_METADATA
,
...
...
@@ -104,6 +105,9 @@ public final class CastPlayer extends BasePlayer {
COMMAND_CHANGE_MEDIA_ITEMS
)
.
build
();
public
static
final
float
MIN_SPEED_SUPPORTED
=
0.5f
;
public
static
final
float
MAX_SPEED_SUPPORTED
=
2.0f
;
private
static
final
String
TAG
=
"CastPlayer"
;
private
static
final
int
RENDERER_COUNT
=
3
;
...
...
@@ -134,6 +138,7 @@ public final class CastPlayer extends BasePlayer {
// Internal state.
private
final
StateHolder
<
Boolean
>
playWhenReady
;
private
final
StateHolder
<
Integer
>
repeatMode
;
private
final
StateHolder
<
PlaybackParameters
>
playbackParameters
;
@Nullable
private
RemoteMediaClient
remoteMediaClient
;
private
CastTimeline
currentTimeline
;
private
TrackGroupArray
currentTrackGroups
;
...
...
@@ -210,6 +215,7 @@ public final class CastPlayer extends BasePlayer {
(
listener
,
flags
)
->
listener
.
onEvents
(
/* player= */
this
,
new
Events
(
flags
)));
playWhenReady
=
new
StateHolder
<>(
false
);
repeatMode
=
new
StateHolder
<>(
REPEAT_MODE_OFF
);
playbackParameters
=
new
StateHolder
<>(
PlaybackParameters
.
DEFAULT
);
playbackState
=
STATE_IDLE
;
currentTimeline
=
CastTimeline
.
EMPTY_CAST_TIMELINE
;
currentTrackGroups
=
TrackGroupArray
.
EMPTY
;
...
...
@@ -466,13 +472,8 @@ public final class CastPlayer extends BasePlayer {
}
@Override
public
void
setPlaybackParameters
(
PlaybackParameters
playbackParameters
)
{
// Unsupported by the RemoteMediaClient API. Do nothing.
}
@Override
public
PlaybackParameters
getPlaybackParameters
()
{
return
PlaybackParameters
.
DEFAULT
;
return
playbackParameters
.
value
;
}
@Override
...
...
@@ -492,6 +493,32 @@ public final class CastPlayer extends BasePlayer {
}
@Override
public
void
setPlaybackParameters
(
PlaybackParameters
playbackParameters
)
{
if
(
remoteMediaClient
==
null
)
{
return
;
}
PlaybackParameters
actualPlaybackParameters
=
new
PlaybackParameters
(
Util
.
constrainValue
(
playbackParameters
.
speed
,
MIN_SPEED_SUPPORTED
,
MAX_SPEED_SUPPORTED
));
setPlaybackParametersAndNotifyIfChanged
(
actualPlaybackParameters
);
listeners
.
flushEvents
();
PendingResult
<
MediaChannelResult
>
pendingResult
=
remoteMediaClient
.
setPlaybackRate
(
actualPlaybackParameters
.
speed
,
/* customData= */
null
);
this
.
playbackParameters
.
pendingResultCallback
=
new
ResultCallback
<
MediaChannelResult
>()
{
@Override
public
void
onResult
(
MediaChannelResult
mediaChannelResult
)
{
if
(
remoteMediaClient
!=
null
)
{
updatePlaybackRateAndNotifyIfChanged
(
this
);
listeners
.
flushEvents
();
}
}
};
pendingResult
.
setResultCallback
(
this
.
playbackParameters
.
pendingResultCallback
);
}
@Override
public
void
setRepeatMode
(
@RepeatMode
int
repeatMode
)
{
if
(
remoteMediaClient
==
null
)
{
return
;
...
...
@@ -771,6 +798,7 @@ public final class CastPlayer extends BasePlayer {
Player
.
EVENT_IS_PLAYING_CHANGED
,
listener
->
listener
.
onIsPlayingChanged
(
isPlaying
));
}
updateRepeatModeAndNotifyIfChanged
(
/* resultCallback= */
null
);
updatePlaybackRateAndNotifyIfChanged
(
/* resultCallback= */
null
);
boolean
playingPeriodChangedByTimelineChange
=
updateTimelineAndNotifyIfChanged
();
Timeline
currentTimeline
=
getCurrentTimeline
();
currentWindowIndex
=
fetchCurrentWindowIndex
(
remoteMediaClient
,
currentTimeline
);
...
...
@@ -857,6 +885,22 @@ public final class CastPlayer extends BasePlayer {
}
@RequiresNonNull
(
"remoteMediaClient"
)
private
void
updatePlaybackRateAndNotifyIfChanged
(
@Nullable
ResultCallback
<?>
resultCallback
)
{
if
(
playbackParameters
.
acceptsUpdate
(
resultCallback
))
{
@Nullable
MediaStatus
mediaStatus
=
remoteMediaClient
.
getMediaStatus
();
float
speed
=
mediaStatus
!=
null
?
(
float
)
mediaStatus
.
getPlaybackRate
()
:
PlaybackParameters
.
DEFAULT
.
speed
;
if
(
speed
>
0.0f
)
{
// Set the speed if not paused.
setPlaybackParametersAndNotifyIfChanged
(
new
PlaybackParameters
(
speed
));
}
playbackParameters
.
clearPendingResultCallback
();
}
}
@RequiresNonNull
(
"remoteMediaClient"
)
private
void
updateRepeatModeAndNotifyIfChanged
(
@Nullable
ResultCallback
<?>
resultCallback
)
{
if
(
repeatMode
.
acceptsUpdate
(
resultCallback
))
{
setRepeatModeAndNotifyIfChanged
(
fetchRepeatMode
(
remoteMediaClient
));
...
...
@@ -1115,6 +1159,17 @@ public final class CastPlayer extends BasePlayer {
}
}
private
void
setPlaybackParametersAndNotifyIfChanged
(
PlaybackParameters
playbackParameters
)
{
if
(
this
.
playbackParameters
.
value
.
equals
(
playbackParameters
))
{
return
;
}
this
.
playbackParameters
.
value
=
playbackParameters
;
listeners
.
queueEvent
(
Player
.
EVENT_PLAYBACK_PARAMETERS_CHANGED
,
listener
->
listener
.
onPlaybackParametersChanged
(
playbackParameters
));
updateAvailableCommandsAndNotifyIfChanged
();
}
@SuppressWarnings
(
"deprecation"
)
private
void
setPlayerStateAndNotifyIfChanged
(
boolean
playWhenReady
,
...
...
extensions/cast/src/test/java/com/google/android/exoplayer2/ext/cast/CastPlayerTest.java
View file @
8861ab48
...
...
@@ -61,6 +61,7 @@ import android.net.Uri;
import
androidx.test.ext.junit.runners.AndroidJUnit4
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.MediaItem
;
import
com.google.android.exoplayer2.PlaybackParameters
;
import
com.google.android.exoplayer2.Player
;
import
com.google.android.exoplayer2.Timeline
;
import
com.google.android.exoplayer2.util.Assertions
;
...
...
@@ -126,6 +127,7 @@ public class CastPlayerTest {
// Make the remote media client present the same default values as ExoPlayer:
when
(
mockRemoteMediaClient
.
isPaused
()).
thenReturn
(
true
);
when
(
mockMediaStatus
.
getQueueRepeatMode
()).
thenReturn
(
MediaStatus
.
REPEAT_MODE_REPEAT_OFF
);
when
(
mockMediaStatus
.
getPlaybackRate
()).
thenReturn
(
1.0d
);
castPlayer
=
new
CastPlayer
(
mockCastContext
);
castPlayer
.
addListener
(
mockListener
);
verify
(
mockRemoteMediaClient
).
registerCallback
(
callbackArgumentCaptor
.
capture
());
...
...
@@ -209,6 +211,93 @@ public class CastPlayerTest {
}
@Test
public
void
playbackParameters_defaultPlaybackSpeed_isUnitSpeed
()
{
assertThat
(
castPlayer
.
getPlaybackParameters
()).
isEqualTo
(
PlaybackParameters
.
DEFAULT
);
}
@Test
public
void
playbackParameters_onStatusUpdated_setsRemotePlaybackSpeed
()
{
PlaybackParameters
expectedPlaybackParameters
=
new
PlaybackParameters
(
/* speed= */
1.234f
);
when
(
mockMediaStatus
.
getPlaybackRate
()).
thenReturn
(
1.234d
);
remoteMediaClientCallback
.
onStatusUpdated
();
assertThat
(
castPlayer
.
getPlaybackParameters
()).
isEqualTo
(
expectedPlaybackParameters
);
verify
(
mockListener
).
onPlaybackParametersChanged
(
expectedPlaybackParameters
);
}
@Test
public
void
playbackParameters_onStatusUpdated_ignoreInPausedState
()
{
when
(
mockMediaStatus
.
getPlaybackRate
()).
thenReturn
(
0.0d
);
remoteMediaClientCallback
.
onStatusUpdated
();
assertThat
(
castPlayer
.
getPlaybackParameters
()).
isEqualTo
(
PlaybackParameters
.
DEFAULT
);
verifyNoMoreInteractions
(
mockListener
);
}
@Test
public
void
setPlaybackParameters_speedOutOfRange_valueIsConstraintToMinAndMax
()
{
when
(
mockRemoteMediaClient
.
setPlaybackRate
(
eq
(
2
d
),
any
())).
thenReturn
(
mockPendingResult
);
when
(
mockRemoteMediaClient
.
setPlaybackRate
(
eq
(
0.5d
),
any
())).
thenReturn
(
mockPendingResult
);
PlaybackParameters
expectedMaxValuePlaybackParameters
=
new
PlaybackParameters
(
/* speed= */
2
f
);
PlaybackParameters
expectedMinValuePlaybackParameters
=
new
PlaybackParameters
(
/* speed= */
0.5f
);
castPlayer
.
setPlaybackParameters
(
new
PlaybackParameters
(
/* speed= */
2.001f
));
verify
(
mockListener
).
onPlaybackParametersChanged
(
expectedMaxValuePlaybackParameters
);
castPlayer
.
setPlaybackParameters
(
new
PlaybackParameters
(
/* speed= */
0.499f
));
verify
(
mockListener
).
onPlaybackParametersChanged
(
expectedMinValuePlaybackParameters
);
}
@Test
public
void
setPlaybackParameters_masksPendingState
()
{
PlaybackParameters
playbackParameters
=
new
PlaybackParameters
(
/* speed= */
1.234f
);
when
(
mockRemoteMediaClient
.
setPlaybackRate
(
eq
((
double
)
1.234f
),
any
()))
.
thenReturn
(
mockPendingResult
);
castPlayer
.
setPlaybackParameters
(
playbackParameters
);
verify
(
mockPendingResult
).
setResultCallback
(
setResultCallbackArgumentCaptor
.
capture
());
assertThat
(
castPlayer
.
getPlaybackParameters
().
speed
).
isEqualTo
(
1.234f
);
verify
(
mockListener
).
onPlaybackParametersChanged
(
playbackParameters
);
// Simulate a status update while the update is pending that must not override the masked speed.
when
(
mockMediaStatus
.
getPlaybackRate
()).
thenReturn
(
99.0d
);
remoteMediaClientCallback
.
onStatusUpdated
();
assertThat
(
castPlayer
.
getPlaybackParameters
().
speed
).
isEqualTo
(
1.234f
);
// Call the captured result callback when the device responds. The listener must not be called.
when
(
mockMediaStatus
.
getPlaybackRate
()).
thenReturn
(
1.234d
);
setResultCallbackArgumentCaptor
.
getValue
()
.
onResult
(
mock
(
RemoteMediaClient
.
MediaChannelResult
.
class
));
assertThat
(
castPlayer
.
getPlaybackParameters
().
speed
).
isEqualTo
(
1.234f
);
verifyNoMoreInteractions
(
mockListener
);
}
@Test
public
void
setPlaybackParameters_speedChangeNotSupported_resetOnResultCallback
()
{
when
(
mockRemoteMediaClient
.
setPlaybackRate
(
eq
((
double
)
1.234f
),
any
()))
.
thenReturn
(
mockPendingResult
);
PlaybackParameters
playbackParameters
=
new
PlaybackParameters
(
/* speed= */
1.234f
);
// Change the playback speed and and capture the result callback.
castPlayer
.
setPlaybackParameters
(
playbackParameters
);
verify
(
mockPendingResult
).
setResultCallback
(
setResultCallbackArgumentCaptor
.
capture
());
verify
(
mockListener
).
onPlaybackParametersChanged
(
new
PlaybackParameters
(
/* speed= */
1.234f
));
// The device does not support speed changes and returns unit speed to the result callback.
when
(
mockMediaStatus
.
getPlaybackRate
()).
thenReturn
(
1.0d
);
setResultCallbackArgumentCaptor
.
getValue
()
.
onResult
(
mock
(
RemoteMediaClient
.
MediaChannelResult
.
class
));
assertThat
(
castPlayer
.
getPlaybackParameters
()).
isEqualTo
(
PlaybackParameters
.
DEFAULT
);
verify
(
mockListener
).
onPlaybackParametersChanged
(
PlaybackParameters
.
DEFAULT
);
verifyNoMoreInteractions
(
mockListener
);
}
@Test
public
void
setRepeatMode_masksRemoteState
()
{
when
(
mockRemoteMediaClient
.
queueSetRepeatMode
(
anyInt
(),
any
())).
thenReturn
(
mockPendingResult
);
assertThat
(
castPlayer
.
getRepeatMode
()).
isEqualTo
(
Player
.
REPEAT_MODE_OFF
);
...
...
@@ -1236,7 +1325,7 @@ public class CastPlayerTest {
assertThat
(
castPlayer
.
isCommandAvailable
(
COMMAND_SEEK_TO_WINDOW
)).
isTrue
();
assertThat
(
castPlayer
.
isCommandAvailable
(
COMMAND_SEEK_BACK
)).
isTrue
();
assertThat
(
castPlayer
.
isCommandAvailable
(
COMMAND_SEEK_FORWARD
)).
isTrue
();
assertThat
(
castPlayer
.
isCommandAvailable
(
COMMAND_SET_SPEED_AND_PITCH
)).
is
Fals
e
();
assertThat
(
castPlayer
.
isCommandAvailable
(
COMMAND_SET_SPEED_AND_PITCH
)).
is
Tru
e
();
assertThat
(
castPlayer
.
isCommandAvailable
(
COMMAND_SET_SHUFFLE_MODE
)).
isFalse
();
assertThat
(
castPlayer
.
isCommandAvailable
(
COMMAND_SET_REPEAT_MODE
)).
isTrue
();
assertThat
(
castPlayer
.
isCommandAvailable
(
COMMAND_GET_CURRENT_MEDIA_ITEM
)).
isTrue
();
...
...
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