I am trying to put together a seamless player using the ExoPlayer and ConcatenatingMediaSource. The general idea is:
I have a set of X short tracks (~15s each), kept in Assets
I load each of them into a ExtractorMediaSource
I put all of them into one ConcatenatingMediaSource
The solution works perfectly, but there is one flaw - ConcatenatingMediaSource seems to be loading media sources dynamically, not all at once.
This created a problem, because iterating Period objects from the Timeline to accumulate the total duration does not work. It will add up to X, but when the playback reaches a certain point, it will jump to X+15.
Any tips on how to get the total duration in this scenario?
i met the same problem before and here comes my solution:
extend a LoadControl
override a shouldContinueLoading returning true to make sure the ExoPlayerImplInternal keeps updating periods,so that the playlist would loaded at once.
i hope it helps
Related
I have an ExoPlayer instance initialized with 4 tracks. 2 of them are MediaCodecVideoTrackRenderer instances, each with its own ExtractorSampleSource.
I'd like to start the playback of one of those track from the middle.
I'm waiting until I get the MSG_PLAYER_STATE_READY message to be able to get the duration of the tracks and then calling seektoUs on the sample-source (also tried calling seekTo on the renderer), but both give unpredictable results.
What's the proper way to seek into a single track while the rest of the tracks play from the beginning?
Managed to solve the issue by overriding my custom TrackRenderer's doSomeWork method and calling super.doSomeWork with a custom positionUs based on the logic I needed.
Imagine score counter made with Text() entity. Simple.
After I start a game, calling setText() causes launching a GC_EXPLICIT that slows down a game causing freezes, and after a few calls - problem disappears. Firstly I thought it's a problem with Strings and concatenation in Java, so I used a StringBuilder. The problem still exists. If I change setText("$" + score + "M") to simple setText("0") no hiccups are noticed!
The problem is in Font. Creation of Texture doesn't actually load characters to this Texture! All you need to do is after creating Font simply call:
pFont.prepareLetters("0123456789".toCharArray());
with all chars you need.
Occasional hiccups that were caused by GC_EXPLICIT were happening because Font in update() was explicitly calling System.gc(). Removing this line we were back on track below the green line, yeah! 60fps.
However, the author of AndEngine might had reasons for this explicit call. Since the stages are short we granted our app call this gc() when the GameScene is paused, quit or stage complete, anywhere where there is no excessive animation.
Preparing characters upfront did not sooth the hiccups, because the texts were dynamic and we could not prepare all possible characters to keep the System.gc() in this method, but honor it later.
Indeed preparing the letters upfront does not trigger GC_EXPLICIT, as it is described in the answer provided by the OP.
EDIT:
After some research, another thing that caused < 60fps, was the SoundPool, we should have playing a sound with volume 0f,0f and looping, in order to prevent the SoundPool reset to idle state and rearm again.
I don't think what is good but it's works.
I want know is it rigth what i do?
I have 2 files tick.wav and tock.wav wich must be played by timer tick or tock. setLooping not good because i need play by timer init.
So i try two methods:
First
I have variable MediaPlayer mp;
When i need play tick i call mp=MediaPlayer.create(context,tickID), when i need play tock i call mp=MediaPlayer.create(contenxt,tockID)
When i call mp.start();
Some time it's work good and i hear tick and tock, but then i start getting errors from mediaplayer. I think this because previous instance of MediaPlayer is still playing file.
Second
So i do next: i create two variables
tickPlayer=MediaPlayer.create(tickID);
and
tockplayer=MediaPlayer.create(tockID);
and then i need tock i call tockPlayer.start() when i need tick i call tickplayer.start()
I't works, but (always exists but) what me do if files will be more than 2, maybe 100?
Create array of mediaplayers like Vector<MediaPlayer> mpPlayers?
And call needed? I think it's eat my memory quickly.
So target is: i need correct playing files with shortime reaction of mediaplayer from RAW soruce, how ca i do what?
May be you don't need Vector to store media files, I think you can use java reflection to get information about "raw" resources as raw is static class from R.java.
And are you stopping media player. tickPlayer.stop().
I would assume that someone would have found an easy solution to this but I haven't found a straight-forward method. I want to build a seeker bar for playing back audio through the MediaPlayer. I haven't been able to find something like an onSeekChanged listener in the MediaPlayer object so I've built an AsyncTask that just keeps refreshing through a while(playing) loop and updates the duration and bar. This doesn't seem to be the best way, however, since this while loop causes the app to run very slowly (the audio doesn't lag, but buttons like pause are delayed). So I want to know what the best implementation is for building a seeker that is efficient. This isn't a difficult question since so many apps use it, I just want to know what the proper way of doing this should be. Thanks!
First of all you need put sleep at least 1 millisecond in your cycle whit:
Thread.sleep(1);
Second you can calculate needed time for next recheck:
Thread.sleep(1000 - currentPos % 1000);
This algorithm is used in standard MediaController.
I want to play one RTSP stream in a surfaceView while I prepare the other in a separate thread. However, the MediaPlayer does give an error when instantiating two SurfaceHolders:
Command PLAYER_PREPARE completed with an error or info PVMFErrResource
Despite this, the video gets buffered, but when I switch to it, only audio is played. In the Android docs it is stated that this is a consequence of not calling setDisplay(SurfaceHolder) but this is what causes the error.
Does anyone have any idea how I can make the video part of the stream show and how to avoid the error when calling setDisplay? Is this a platform limitation?
Thanks.
Maybe you could put two separate SurfaceViews inside (for example) FrameLayout. Use these with two separate MediaPlayers and show/hide (in parallel to stoping/starting video) SurfaceView you desire at given moment (using android:visibility set to GONE for example).