ExoPlayer nextTrack listener

Created on 11 May 2017  路  20Comments  路  Source: google/ExoPlayer

Hello,
I am using ExoPlayer v2.2.0 with MediaSourcees.
onTracksChanged is called when the track _is_ changed.
How to know if the next track _will_ be played?
And how to disable automatically playing the nextTrack?

need more info

All 20 comments

I'm not sure I understand the question. What's the difference between the tracks changing and the tracks playing? If the only difference is whether the player is playing or paused then you should be able to check that state and work out what you want in application code.

@ojw28 onTracksChanged is called much before setting plackbackinfo in ExoPlayerImplInternal:updatePeriods, because of which if we needto get windowindex or preiodindex to fetch metainfo of the track being played it will return old index.
I think setPlayingPeriodHolder(playingPeriodHolder.next) should be called after setting new playback info.

If you're looking for points where the window and/or period indices change, you should use ExoPlayer.EventListener.onPositionDiscontinuity. This callback is invoked at the point in time when the indices change.

@ojw28 onPositionDiscontinuity will be called for seek changes as well. What I am saying in there is no specific call back to indicate there is a change in window index so that display meta information can be checked. onTracksChanged works most of the cases but in cases of gapless playback it will be holding previous index.

Right, but you can check whether the index has changed in onPositionDiscontinuity. For example, store the index for which you're displaying metadata somewhere, then check whether the index is different in onPositionDiscontinuity. If it is then update the metadata.

I have a player with
player?.prepare(concatenatingMediaSources, false, false)

so, I have multiple tracks in the player.
now, when the current track ends, ExoPlayer automatically plays the next track.
so, how to stop the player from starting the next track automatically?

@bluemix
when onTracksChanged is called call player.setPlayWhenReady(false)

@prakash-altair ah ok, thanks, but
how to know if the _current_ track is ended?
ExoPlayer.STATE_ENDED didn't get called...

@bluemix
onTracksChanged will be called once new track started playing. So you will get kow previous track ended

@prakash-altair if I set player.setPlayWhenReady(false), how onTracksChanged will get called?

I think you need to provide more detail about your use case for us to assist further, because it's not really very clear exactly what you're trying to do. Specifically:

  • What MediaSource are you passing in to the player (presumably some kind of concatenating source), and what's the use case for wanting to disable automatic playback across its entries?
  • At the point where you'd want playback to halt, would you expect the last frame of the previous video or the first frame of the next video to be displayed? Would you expect the next video to be buffered ready for playback, or not?
  • I want to know if the current track will be ended to start playing another _specific_ track
  • I don't want the first frame of the next track video to be loaded; no, I don't want the next video to be buffered.

I have a player with four tracks in it, and I want to know if the current track ends to set another four tracks for the player.

another question: when ExoPlayer.STATE_ENDED get called?
cause I have a track that ends, but it didn't get called.

You should just not use ConcatenatingMediaSource for this use case. The whole point of that class is to allow you to seamlessly play through multiple pieces of media in order, but this is not what you actually want to do.

For your use case, you can prepare the player with a regular (i.e. non-concatenated) MediaSource representing whatever individual piece of media you want to play. You'll receive STATE_ENDED when the piece of media has finished playing. You can then prepare the player with a regular MediaSource representing whatever you want to play next, and so on.

To answer your final question: STATE_ENDED occurs when the entire MediaSource has finished playing. For a ConcatenatingMediaSource it occurs when the entire concatenation has finished playing (i.e. you've played up to the end of the final item in the concatenation).

ah, 馃憤
I really appreciate your help dear
thanks a lot @ojw28

@bluemix
What I did to solve your case, I created 'MyConcatenatingMediaSource' extending 'ConcatenatingMediaSource' that overrides the 'releasePeriod' and 'createPeriod' methods. I noticed they are called on each transition.

That's really not a good solution to this problem. You should use ExoPlayer.EventListener.onPositionDiscontinuity to figure out when transitions occur . onPositionDiscontinuity is invoked for some other cases too, but you can call ExoPlayer.getCurrentWindowIndex and compare it to what window you think you're in to determine whether a transition has occurred.

i see that @magillus's solution is more practical than having to handle state variables for ExoPlayer.EventListener.onPositionDiscontinuity and ExoPlayer.getCurrentWindowIndex

Sorry, but it's just not a correct thing to do. ExoPlayer.EventListener.onPositionDiscontinuity and ExoPlayer.getCurrentWindowIndex are APIs intended for this purpose.

Conversely, createPeriod and releasePeriod are internal methods that are not intended for this purpose at all. They're intended for internal use by the player when it needs to instantiate and release MediaPeriod objects. We do not make any guarantees about when the player implementation will do this. We may choose to make changes in the future that do things like cache MediaPeriod instances, avoiding the need to create and release them as often, for example, which will break your usage of these methods.

Olly, you are right that call happens on end of file playback, which works for my case.

The exoPlayer.getCurrentWindowIndex() call on that onPositionDiscontinuity returns the next INDEX value in ConcatenatingMediaSource, however that needs to be tracked as separate state in cases when this callback is called with seek also happens.
@bluemix However the createPeriod/releasePeriod also are called when seek so complete media and begin media callbacks can't be hooked with that.

I'm still struggling to see why this isn't an easy thing to do. The typical use case I'm imagining is that there's a ConcatenatingMediaSource and the goal is to update some UI when transitioning from one source to the next. If the UI is showing state for the current source then your app is already tracking lots of state about the current source, one way or another. It's hard to imagine that tracking an extra integer makes any practical difference. It's just a matter of doing this:

public void onPositionDiscontinuity() {
  int newIndex = player.getCurrentWindowIndex();
  if (newIndex != currentIndex) {
    // The index has changed; update the UI to show info for source at newIndex
    currentIndex = newIndex;
  }
}

Why is this difficult?

Was this page helpful?
0 / 5 - 0 ratings