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

Add or remove playlist items (MediaSources) #1706

Closed
dckristiono opened this issue Jul 31, 2016 · 50 comments
Closed

Add or remove playlist items (MediaSources) #1706

dckristiono opened this issue Jul 31, 2016 · 50 comments
Assignees

Comments

@dckristiono
Copy link

dckristiono commented Jul 31, 2016

I use exoplayer dev-v2, I need function to add or remove playlist items (media sources) without release player or initialize player.
Can you make this function?

thanks!

@ojw28 ojw28 changed the title add or remove playlists (MediaSources) + change quality not smooth Add or remove playlist items (MediaSources) Aug 1, 2016
@ojw28
Copy link
Contributor

ojw28 commented Aug 1, 2016

It's pretty easy to implement the first request yourself (create a class a bit like ConcatenatingMediaSource, but with the ability to add/remove). We should be providing a standard component for this. Let's use this issue to track.

Please file a separate enhancement request for the other request; the two aren't related.

@dckristiono
Copy link
Author

do you finish to make this function?

@andrewlewis andrewlewis self-assigned this Aug 8, 2016
@calulelalu
Copy link

Hi, I'm trying to implement a DynamicConcatenatingMediaSource class close to ConcatenatingMediaSource, except for the Lists management instead of arrays for mediasources, timelines and manifests and adding the following addSource method:

public void addSource(MediaSource mediaSource) {
    this.mediaSources.add(mediaSource);
    duplicateFlags = buildDuplicateFlags(this.mediaSources);
}

I receive the following exception when I seek to the last-1 track (before the one I added):
Unexpected exception loading stream
java.lang.NullPointerException at com.google.android.exoplayer2.source.ExtractorMediaSource.onSourceInfoRefreshed(ExtractorMediaSource.java:181)

What am I missing?

Thank you!

@calulelalu
Copy link

I eventually found the problem (yeah!).
The issue, described in this stackoverflow https://stackoverflow.com/questions/39612004/dynamic-playlists-with-exoplayer-2/39725741#39725741
was with the replacement of the arrays to lists.

To add new sources in my DynamicConcatenatingMediaSources:

public void addSource(MediaSource mediaSource) {
    this.mediaSources.add(mediaSource);
    duplicateFlags = buildDuplicateFlags(this.mediaSources);
    if(!mediaSources.isEmpty())
        prepareSource(mediaSources.size() -1);
}

@calulelalu
Copy link

Now I'm stuck on the remove issue... any help?
Performing

public void removeSource(int position){
    MediaSource removedMediaSource = this.mediaSources.remove(position);
}

obviously does not update all the lists and Periods references but I'm losing into the code and not able to figure out what is to be done.

@ascmartins
Copy link

ascmartins commented Nov 18, 2016

I had this working but since I moved to version r2.0.4 it only plays first video and the appended ones causes player to be in idle or end state. The only change I needed to do was refactoring the override method createPeriod from
@Override public MediaPeriod createPeriod(int index, Callback callback, Allocator allocator, long positionUs)
to
@Override public MediaPeriod createPeriod(int index, Allocator allocator, long positionUs)

Since this change all stopped working. Any idea what can cause the issue? Anyone can give me a light what callback does?

@marwanf1
Copy link

marwanf1 commented Jan 4, 2017

Hello, any updates on this issue?

If not, is there any reference on how to implement the remove part?

Thanks

@ascmartins
Copy link

@marwanf1 take a look at issue #2097 and see if the AppendingMediaSource.java class can help you. In addition, to make this work for me I had to make the changes commented on 28 Nov 2016 (referred thread)

@BubuKunz
Copy link

BubuKunz commented Jan 4, 2017

AppendingMediaSource.java is very helpfull, but exist one problem: in method appendSource you use method removeFirstMediaSource() if count of MediaSources bigger then 2. With this method nothing work. I tried to increase the max size of lists (up to 10) and items had been adding (during playing) successfully. But when i added 11-th item, it not played. When i removed method removeFirstMediaSource(), i can adding as much MediaSources as i want, but i care about StackOverFlow or something also. Can you help me with this?
According to my issue i must playing a few short videos in random order endlessly

@ascmartins
Copy link

Hi. Sorry no referring that, but I quit using the removeFirstMediaSource() method. I am using about 8000 videos/day and it works fine. I restart app at 00:00 each day, maybe you can do same thing if you need it run endlessly. I've been watching memory during play, it changes on each movie transaction, up or down according to video resolution. My app has been up and running for a week without stack overflow. Seems like when adding a media source what happens is that Exoplayer adds video to time line to load it as fast as possible when previous video ends.
But in order for this to as I expected I had to add the line renderer.resetPosition(0); in ExoPlayerImplInternal.java on ExoPlayer library, otherwise it won't start next videos.

@BubuKunz
Copy link

BubuKunz commented Jan 4, 2017

Okay, i understand, thank you

@AOrobator
Copy link
Contributor

AOrobator commented May 10, 2017

@ascmartins Did you ever make a MediaSource that can also remove items?

@ojw28 In issue #2097, you suggested exposing a Timeline that creates Periods. To create a Period you'll have to know the corresponding MediaSource, assuming that every Period has exactly one MediaSource. What's the best way to obtain a mapping between Periods and MediaSources? Do you have any other suggestions or best practices for implementing this?

@tonihei tonihei assigned tonihei and unassigned andrewlewis May 10, 2017
@ascmartins
Copy link

Hello @AOrobator !
I didn't implement anything else than posted above. So I don't have it removing MediaSources from list.

@b0g8
Copy link

b0g8 commented May 15, 2017

@calulelalu , @tonihei , did you manage to get a MediaSource where items can be removed/swaped without releasing the player?

@calulelalu
Copy link

Hi, unfortunately not, I had to manage the playlist by myself externally from exoplayer.

@tonihei
Copy link
Collaborator

tonihei commented May 15, 2017

@b0g8, We are going to work on this topic soon to provide a build-in solution for a media source which supports adding/removing. Subscribe to this thread and you'll get informed as soon as we are ready :)

ojw28 pushed a commit that referenced this issue Jun 13, 2017
(Preparation for GitHub issue #1706)

AbstractConcatenatedTimeline repeatly calls methods of its implementation to
query a specific child timeline. This may be inefficient if the implementation
repeatly executes the same code to find the timeline.

Changed the class such that it now queries all information at once using a meta
data class. As all methods need at least two of four variables anyway, this
doesn't generate unnecessary overhead.

Also generified the UID for the child indices to allow new implementations to
use some other UID besides the index.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=158711979
@b0g8
Copy link

b0g8 commented Jun 16, 2017

@tonihei, is this on hold?

@tonihei
Copy link
Collaborator

tonihei commented Jun 16, 2017

No, still working on it. It is currently undergoing internal reviews.

@oikmar
Copy link

oikmar commented Jun 20, 2017

@tonihei any approximate ETA on this. not a specific date, but in terms of time frame: day(s), week(s), month(s)?

@tonihei
Copy link
Collaborator

tonihei commented Jun 20, 2017

@oikmar Days, most likely.

@AOrobator
Copy link
Contributor

@tonihei When this is implemented, will gapless playback be supported?

@tonihei
Copy link
Collaborator

tonihei commented Jun 26, 2017

@AOrobator Gapless playback is already supported when you use ConcatenatingMediaSource.

@AOrobator
Copy link
Contributor

@tonihei I understand that ConcatenatingMediaSource supports gapless playback. I would assume that when this PlaylistMediaSource gets implemented it would also support gapless playback by extension, but I just wanted to clarify instead of assuming.

@tonihei
Copy link
Collaborator

tonihei commented Jul 4, 2017

We finished working on the DynamicConcatenatingMediaSource by now. You'll find it in the dev branch. It works exactly the same as the ConcatenatingMediaSource but also offers methods to add, remove, and access media sources during playback.

@tonihei tonihei closed this as completed Jul 4, 2017
@magillus
Copy link

magillus commented Jul 4, 2017 via email

@ursusursus
Copy link

Hi, do you provide some snapshot builds of dev branch or do I have to checkout sources / wait for stable release?

@tonihei
Copy link
Collaborator

tonihei commented Jul 7, 2017

Yes, you're right. Until we merge this change into our release branch, you would either need to check out the sources or wait for the release.

@AOrobator
Copy link
Contributor

@ursusursus I've built an aar off the develop branch that I've been playing around with that has DynamicConcatenatingMediaSource merged in. You can include it in your project by putting the aar file in your libs folder then adding the following line to your app level build.gradle file

compile(name: "library-core-release", ext: "aar")

library-core-release.aar.zip

ojw28 pushed a commit that referenced this issue Jul 12, 2017
This option allows to move the currently playing media source to another position
and also to move other media source without creating a new MediaSource object.

Issue:#1706

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=161402022
@mirandole
Copy link

Hello @tonihei,

Do you know when the DynamicConcatenatingMediaSource class will be merged on master ? And when will it be available on Gradle ?

Thank you very much for your work !

@ojw28
Copy link
Contributor

ojw28 commented Jul 20, 2017

Probably a couple of weeks. It'll be available in the 2.5 release. Thanks.

@mirandole
Copy link

mirandole commented Jul 20, 2017

Hello @AOrobator !

Thank you for your .aar file.
I've added your aar to my app. Gradle sync well. But I can't find any DynamicConcatenatingMediaSource class in my app.

Do you know how I could get it ?

@AOrobator
Copy link
Contributor

@mirandole try a clean build? Make sure you're spelling it correctly? It's in the aar and I'm using it in a project of mine, so I know it works

@mirandole
Copy link

mirandole commented Jul 21, 2017

@AOrobator I've extrat .aar and add the classes .jar file to my build.gradle app with this line :

compile files('libs/exoplayer-dev-v2-snapshot')

Now everything works well.

Thank you

@mirandole
Copy link

mirandole commented Jul 21, 2017

Hello @tonihei @ojw28 @AOrobator !

My app crash when I prepare Exoplayer with a DynamicConcatenatingMediaSource.
But everything works fine using ConcatenatingMediaSource.

Source Code :

private void testSimple(Metadatas metadatas) {
        if(this.dynamicConcatenatingMediaSource != null) {
            this.dynamicConcatenatingMediaSource.releaseSource();
        }
        this.dynamicConcatenatingMediaSource = new DynamicConcatenatingMediaSource();
        MediaSource ms1 = new ExtractorMediaSource(Uri.parse(metadatas.getResolvedStreamUrl()), dataSourceFactory, extractorsFactory, null, null);
        MediaSource ms2 = new ExtractorMediaSource(Uri.parse(metadatas.getResolvedStreamUrl()), dataSourceFactory, extractorsFactory, null, null);
        dynamicConcatenatingMediaSource.addMediaSource(ms1);
        dynamicConcatenatingMediaSource.addMediaSource(ms2);

        exoPlayer.prepare(this.dynamicConcatenatingMediaSource);

        //this.concatenatingMediaSource = new ConcatenatingMediaSource(ms1, ms2);
        //exoPlayer.prepare(this.concatenatingMediaSource);
    }

Log

FATAL EXCEPTION: ExoPlayerImplInternal:Handler
                                                   Process: PID: 21073
                                                   java.lang.AbstractMethodError: abstract method "com.google.android.exoplayer2.source.MediaPeriod com.google.android.exoplayer2.source.MediaSource.createPeriod(int, com.google.android.exoplayer2.upstream.Allocator, long)"
                                                       at com.google.android.exoplayer2.ExoPlayerImplInternal$MediaPeriodHolder.<init>(ExoPlayerImplInternal.java:1472)
                                                       at com.google.android.exoplayer2.ExoPlayerImplInternal.maybeUpdateLoadingPeriod(ExoPlayerImplInternal.java:1289)
                                                       at com.google.android.exoplayer2.ExoPlayerImplInternal.updatePeriods(ExoPlayerImplInternal.java:1138)
                                                       at com.google.android.exoplayer2.ExoPlayerImplInternal.doSomeWork(ExoPlayerImplInternal.java:460)
                                                       at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:308)
                                                       at android.os.Handler.dispatchMessage(Handler.java:98)
                                                       at android.os.Looper.loop(Looper.java:154)
                                                       at android.os.HandlerThread.run(HandlerThread.java:61)`


Everything works fine with `ConcatenatingMediaSource

@ojw28
Copy link
Contributor

ojw28 commented Jul 21, 2017

That looks like an issue with the way you're building and including the code. If you want to depend on the dev-v2 branch you should really do so properly by following the instructions under "Locally" in the README.

@mirandole
Copy link

Thank you that solved my problem.

@mirandole
Copy link

Hello @ojw28

DynamicConcatenatingMediaSource works well to play several tracks with gapless.
But I need to refresh metadatas of the current track playing on Exoplayer. To do that I need to know when exoplayer has completed the current playing track and started the next one.

It seems that I can't use playbackstate listener because STATE_ENDED with DynamicConcatenatingMediaSource until i've played all the playlist tracks.

How can I know if the current track is completed and the next one started to always get current track playing metadatas on my front activity screen ?

Thank you very much.

@ursusursus
Copy link

@mirandole onPositionDiscontinuity (from memory) is the callback you want

@mirandole
Copy link

mirandole commented Jul 24, 2017

Thanks @ursusursus but it could be a seekTo discontinuity, right ? Could discontinuity come from other things that a track change ? Because I can only verify if discontinuity comes from a seek, I can't verify for other event that produce onPositionDiscontinuity. I don't know them.

@andrewlewis
Copy link
Collaborator

To detect advancing from window (playlist item) to the next, handle onPositionDiscontinuity and check for the current window index returned by player.getCurrentWindowIndex() having changed since the last call.

Several things can cause a discontinuity: (1) advancing from one window (playlist item) to the next, (2) advancing from one period to the next (which is different from (1) for multi-period windows), (3) seeking and (4) source-initiated discontinuities (for example, when the source retries loading due to an error, but has to move the playback position).

@AOrobator
Copy link
Contributor

AOrobator commented Jul 24, 2017

@mirandole I've been using onTracksChanged() with success as it's a bit more specific to our use case. You just have to keep track of how many tracks have played because the first time it's called, it's with the first track.

@andrewlewis @ojw28 curious to get your thoughts on my approach

@tonihei
Copy link
Collaborator

tonihei commented Jul 25, 2017

onTracksChanged is only triggered when the available or selected tracks change. For example, this could be a switch between different video resolutions in an adaptive media source, activating or deactivating audio or video, or similar things. When playback advances to the next playlist item this method might or might not be called depending on the available tracks in the both items.

We recommend to use onPositionDiscontinuity to get notified of any changes to the currently playing window (playlist item) as @andrewlewis already pointed out.

@mirandole
Copy link

mirandole commented Jul 28, 2017

Thank you @AOrobator @tonihei .
It works well with onPositionDiscontinuity

Unfortunately, it seems that DynamicConcatenatingMediaSource mp3 track transition isn't truly gapless.
I still hear a very small gap between tracks of albums. Superpoze artist Opening album is a good one to gapless test. I probably did something wrong.

Did someone succeed in playing mp3 or FLAC tracks album gapless?

@AOrobator
Copy link
Contributor

AOrobator commented Jul 28, 2017

I'm also confirming that I hear a small gap between tracks when using DynamicConcatenatingMediaSource. I guess it's probably best to create another issue, then link it here. @mirandole

@tonihei
Copy link
Collaborator

tonihei commented Jul 28, 2017

Yes, please create a new issue with steps to reproduce your problem. Thanks!

@keyboardr
Copy link

It looks like ExoPlayer.getDuration() doesn't work with DynamicConcatenatingMediaSource, even after calling prepare(). Is there a way to get a queued MediaSource's duration (and seek to a position) before setPlayWhenReady(true) is called?

@tonihei
Copy link
Collaborator

tonihei commented Aug 24, 2017

Please create a new issue using the issue template if you think something is wrong. Thank you!

@keyboardr
Copy link

I don't necessarily think there is anything wrong. It might just be my own lack of understanding how DeferredTimeline is expected to work. I'll file a bug just in case.

@google google locked and limited conversation to collaborators Nov 2, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests