Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DynamicConcatenatingMediaSource with no auto play #3773

Closed
skyler-b opened this issue Jan 30, 2018 · 7 comments
Closed

DynamicConcatenatingMediaSource with no auto play #3773

skyler-b opened this issue Jan 30, 2018 · 7 comments
Assignees
Labels

Comments

@skyler-b
Copy link

Issue description

I am wondering if there's a way to have a DynamicConcatenatingMediaSource which does not automatically start the next track.

I've followed the conversation on #2810. In which the suggestion was to simply not use a ConcatenatingMediaSource. However, in my use case, the user can toggle whether they want to "auto play", and I always want to be able to show the "next track" button. This happens to be the same behavior as Youtube.

The only other way I think it could be accomplished, is if I could smoothly (without affecting playback) swap my DynamicConcatenatingMediaSource for a singular MediaSource, and still be able to show the "next track" button as enabled. Is that possible?

Version of ExoPlayer being used

2.6.1

@skyler-b
Copy link
Author

@ojw28 you've fielded this question before, I was hoping you might have some advice, thanks in advance!

@tonihei
Copy link
Collaborator

tonihei commented Jan 31, 2018

You could listen to Player.EventListener.onPositionDiscontinuity and check if the reason for the discontinuity is DISCONTINUITY_REASON_PERIOD_TRANSITION. This indicates that the source has transitioned to a new period (I assume your individual tracks contain one period only). In this case, call player.setPlayWhenReady(false) to pause playback.

Be aware that this solution means that the player already switched to the next track but does not continue playing.

@skyler-b
Copy link
Author

Thanks @tonihei, ya I do know that trick, but unfortunately I need it to stop on the current one. For now I will just be using a single media source, and supplying my own "next" button, and my own auto-play, instead of using the built in ones.

@tonihei
Copy link
Collaborator

tonihei commented Feb 1, 2018

There is actually another option which allows you to pause playback at the end of the current item.

We recently added the option to send messages at specified playback positions. This feature is currently on the dev-branch but will be part of the next release. With that, you can send a message at the end of each playlist item and pause the player in this message. By default, messages are sent on the playback thread which helps to ensure that the pause command reaches the playback loop in time before the transition to the next playlist item. Sending the message should look like this:

player
    .createMessage((int messageType, Object payload) -> player.setPlayWhenReady(false))
    .setPosition(itemIndex, durationMs)
    .setDeleteAfterDelivery(false)
    .send();

Setting deleteAfterDelivery to false ensures that the message is kept around and the player always pauses at the end of this item when it is played again. The best place to send this message is probably within eventListener.onTimelineChanged where you can check whether the duration of each window is available (!= C.TIME_UNSET).

However, there are two caveats to this approach:

  1. Pausing the player is now done on a different thread. To prevent any parallel execution issue, you should synchronize access to the player (or live with the risk of getting a user-initiated pause or play command at exactly the same moment).
  2. The eventListener.onPlayerStateChanged(/* playWhenready* / false, ...) callback is now also delivered on another thread. This is more of a bug really because our documentation says otherwise. Until we fix this, you'll need to check in each event listener where this is relevant if it is called on the correct thread. For example, the ExoPlayer UI components try to update their buttons based on this change and they throw an exception if this is not done on the main application thread. So for this to work, I needed to adapt these listeners too.

@tonihei tonihei reopened this Feb 1, 2018
@tonihei tonihei added the bug label Feb 1, 2018
@tonihei
Copy link
Collaborator

tonihei commented Feb 1, 2018

Marked as bug because of the possibility of getting listener callbacks which are not on the thread which created the player.

@tonihei
Copy link
Collaborator

tonihei commented Feb 1, 2018

We decided that we actually can't support access to the player from multiple threads because there is no way to fully synchronize this access from outside. This essentially means that the solution I proposed above is not valid.

Nevertheless, you can try to set a Handler to the message which ensures it's executed on your application thread:

player
    .createMessage((int messageType, Object payload) -> player.setPlayWhenReady(false))
    .setHandler(new Handler())
    .setPosition(itemIndex, durationMs - SHORT_OFFSET)
    .setDeleteAfterDelivery(false)
    .send();

This prevents any synchronization issues and problems caused by getting listener callbacks on the wrong thread. However, it now depends on the system how fast it can deliver this message back to the player. In the majority of cases, this will work (even without the offset I added above), but it's not 100% guaranteed.

@tonihei tonihei removed the bug label Feb 1, 2018
@skyler-b
Copy link
Author

skyler-b commented Feb 1, 2018

Thanks for the update - that messaging system sounds very interesting - I can already think of one other thing I would use it for. I'll take a look at that in the next release - thanks again!

@skyler-b skyler-b closed this as completed Feb 1, 2018
ojw28 pushed a commit that referenced this issue Feb 1, 2018
…ad of allowing it.

Even if a developer synchronizes every method, thread safety is still not guaranteed
because the internal callback methods can't be synced from outside.

Issue:#3773

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=184122072
@google google locked and limited conversation to collaborators Jun 29, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

3 participants