Exoplayer: Why we have always the value of castPlayer.getCurrentTimeline().getWindowCount() <= 3 ?

Created on 16 Oct 2018  路  9Comments  路  Source: google/ExoPlayer

Hi,

I've tried to use the MediaSession extension and the Cast Extension together with the CastMediaControlIntent.DEFAULT_MEDIA_RECEIVER_APPLICATION_ID from the package com.google.android.gms.cast as the receiver application id. I notice strange behaviour with the method castPlayer.getCurrentTimeline().getWindowCount() which returns always a value less or equal than 3, even if I have a long playlist.
The problem is in the TimelineQueueNavigator.onSkipToQueueItem. If the param id of this method is great than 3, so player.seekTo is not called.

@Override
  public void onSkipToQueueItem(Player player, long id) { //<- id = 4 
    Timeline timeline = player.getCurrentTimeline();
    if (timeline.isEmpty()) {
      return;
    }
    int windowIndex = (int) id;
    if (0 <= windowIndex && windowIndex < timeline.getWindowCount()) {
      player.seekTo(windowIndex, C.TIME_UNSET); //<- Not called because timeline.getWindowCount() <= 3
    }
  }
bug

Most helpful comment

Hi, I apologize for not looking into the reported issues in time. Right now our efforts are focused on writing our own receiver app which will solve most of the current CastPlayer shortcomings.

Thanks for your patience!

All 9 comments

I hit this same issue. It looks like the timeline under the CastPlayer only maps to the handful of queue items that are returned in the latest MediaStatus report from the cast device (i.e. the CastPlayerTimeline doesn't know about the entire MediaQueue of items that were loaded). This makes CastPlayer think with incorrect windowIndex values across the board.

I came up with (sad but serviceable) workarounds for my two use cases for windowIndex values:

  • monitoring what is currently playing (getCurrentWindowIndex())
  • skipping to specific items (seekTo())

Here are my workarounds:

When the client is available, you can get the MediaQueue and current MediaQueueItem from the session:

// NOTE: in real code you'll need to check for nulls along this chain of methods
sessionManager.getCurrentCastSession().getRemoteMediaClient().getMediaQueue()
sessionManager.getCurrentCastSession().getRemoteMediaClient().getCurrentItem()

For getCurrentWindowIndex I use the MediaQueue when available with a fallback to my best guess (based on what I recently tried to load).

int getCurrentWindowIndex() {
  MediaQueue queue = getMediaQueue();
  MediaQueueItem current = getCurrentMediaQueueItem();
  if (queue == null || current == null) {
    index = /** ... my best guess... **/;
  }
  int itemId = current.getItemId();
  int index = queue.indexOfItemWithId(itemId);
  if (index == -1) {
    index = /** ... my best guess... **/;
  }
  return index;
}

For seekTo I took the sad approach of just reloading the entire queue at that index:

void seekTo(int windowIndex, long offsetMs) {
  MediaQueueItem[] items = /** ... the full queue of items ... **/;
  player.loadItems(items, windowIndex, offsetMs, Player.REPEAT_MODE_OFF);
}

Hi, I apologize for not looking into the reported issues in time. Right now our efforts are focused on writing our own receiver app which will solve most of the current CastPlayer shortcomings.

Thanks for your patience!

I had the same problem with that and some method like getDuration() doesn't work for window number greater that 1 because out of array boundary. I have figured out that Timeline contains info about current Window, previous and the next - so 3 Windows like in the issue title. It can be 2 when it is first or last Window.
I store total Window count in variable created by me. The other problem that I described with getting current Window I fixed with modifying getWindow in CastTimeline:
```java @Override
public Window getWindow(
int windowIndex, Window window, boolean setTag, long defaultPositionProjectionUs) {

    if (windowIndex > 0)
        windowIndex = durationsUs.length - 1;

    if (durationsUs.length == 3)
        windowIndex = 1;
    //rest of the method

```

I found this in the documentation of the Javascript SDK: https://developers.google.com/cast/docs/reference/caf_receiver/cast.framework.QueueManager#setQueueStatusLimit

When you have a custom receiver app you can remove the limit from the queue. This fixed seeking for me.

Recently @ojw28 found this in the cast release notes:

Previously, the media queue comes with the media status, which can be accessed through MediaStatus#getQueueItems(). This will be deprecated in the future and MediaStatus#getQueueItems() will return a maximum of 3 items.

Sorry for not providing better support around this. We are actively working on it.

I will migrate CastPlayer to depend on MediaQueue instead of MediaStatus#getQueueItems. Since this change was announced in April 2018, i think the behavior changed after the Cast extension release.

Internal ref: b/74587087

Can this be marked as fixed in dev-v2?

Hi all, please try the fix referenced above and post here if you can still reproduce the issue. I'll be closing as fixed for now.

Was this page helpful?
0 / 5 - 0 ratings