How to reduce Buffer time on streaming app? - android

I'm Building an android app that is supposed to stream an online radio station from a URL.
I am currently working on a demo and I have gotten a lot of help from online tutorials but I have a problem.
When I click on the NEXT button it's supposed to get it's audio from another URL, which gives it the effect of changing the station, but it takes too much time and most times it doesn't seem to work.
Is there any way I could reduce the time by 95% cause I want it to start almost immediately you click on the next button
CODE FOR THE NEXT BUTTON
b_next.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mediaPlayer.stop();
mediaPlayer.reset();
try {
mediaPlayer.setDataSource("http://stream.radioreklama.bg/veronika.opus");
mediaPlayer.prepare();
} catch (IOException e) {
e.printStackTrace();
}
mediaPlayer.start();
}
});

The problem may not be buffering- there might be some slow startup time on the server side for example.
Either way, if you want to monitor the buffering there is a call back provided with MediaPlayer which will do this - 'OnBufferingUpdateListener.onBufferingUpdate()'.
From the MediaPlayer documentation (https://developer.android.com/reference/android/media/MediaPlayer.html#setOnPreparedListener(android.media.MediaPlayer.OnPreparedListener)):
While in the Started state, the internal player engine calls a user supplied OnBufferingUpdateListener.onBufferingUpdate() callback method if a OnBufferingUpdateListener has been registered beforehand via setOnBufferingUpdateListener(OnBufferingUpdateListener). This callback allows applications to keep track of the buffering status while streaming audio/video.
One common technique to speed up switching between streams, across platforms, is to have the next stream prepared in advance.
For your case you would need a second media player which you would initialise and move to the prepared state, and possibly even seek to a point, and then play it as soon as you stop the other one.
For live streams this will be a little more difficult as you can't see to a point in the same way. You could experiment with having the second player playing but with the volume turned down, although this is obviously not very efficient, unless you have some reliable way to predict when the user is about to switch.

Related

Time taken in connecting while audio streaming in android?

I am using simple audio streaming in android app like this:
try {
MediaPlayer media = new MediaPlayer();
media.setAudioStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE);
media.setDataSource("http://indiespectrum.com:9000");
media.prepare();
media.start();
}
catch(Exception e)
{
//Getting Exception
}
Where I am using four different URL .When I start the radio streaming it takes a while to start playing.Sometimes it takes 5-6 sec and sometimes around 40-45 sec to start playing the radio. I just want to know if I can speed up these time taken .As all of these uses Shoutcast is there anyway I could speed up the connection or it depends on some kind of bitrate or something.Please help?
One way to speed up things a lot is leveraging the UIMain thread and doing the audiostreaming using AsyncTask, wich enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.

Gapless Playback with android MediaPlayer

I'm trying to repeatedly play a audio continuously, without any gap. I've tried,
mediaplayer.setLooping(true);
But it gives a gap between repeat time. And tried this,
mediaplayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp)
{
mediaplayer.start();
}
});
It gives a gap also. I've tried with different audio format. But neither way worked for me. Is there any other way in android?
When a playback finishes, the player engine would check if all tracks are completed and once done, it will check for the looping flag. Based on the looping flag, a seek to 0 seconds. As part of the seek, the player engine will read the data from the specific position and start the playback.
The delay may be due to the seek implementation along with the delay introduced by the storage medium like sdcard apart from re-initializing all tracks and restarting them. Hence, there is definite delay by the time the player reverts back to the starting position.
The underlying looping implementation can be found in this function AwesomePlayer::onStreamDone as shown here: http://androidxref.com/4.2.2_r1/xref/frameworks/av/media/libstagefright/AwesomePlayer.cpp#834
EDIT 1:
To implement a true gapless playback, you could also consider the setNextMediaPlayer() feature.
Probably MediaPlayer is re-prefetching the data from server (or even from the device itself), this may take some seconds. Only if the buffering is done, it starts playing again.
If you want to bypass this, you can AFAIK only use a second MediaPlayer which starts buffering the media file shortly before the first one stops playing. Then you can start the second one on OnCompletionListener.

Android Media Player hanging or returning null

I've got an interesting situation with the android MediaPlayer. I've got about 30 sounds that I need to play in an activity. I'm getting strange results that I'm not sure are coming from memory issues or not...
The reason why I need to use media player is that I've got a timed flow to the sounds where one sound needs to play after the other in a certain order. I also use the callbacks to see which sound is played next. Thus, soundpool is out...
I've tried loading each sound in to it's own media player using MediaPlayer.create(). Now, this works fine on my device, a Samsung Galaxy S Vibrant. My client with a Samsung Ace, however is getting null pointer exceptions when I try to set the onCompletionListener, meaning .create() returned null on his device but not mine.
So, I switched from loading them all at once to loading them on the fly in the onCompletionListener of the previous sound using this method
This kind of works, the fist 3-4 sounds play and then it hangs on my client's device (still works fine on my device). Which I'm assuming it's hanging on the .prepare()
This is incredibly hard to sort out since my client has no real knowledge of logcat and no SDK to debug, and it works fine on my device. It even hangs on his second device which is the same model as mine.
Anyone have any idea what might be causing this or how to debug it?
I'm thinking my next step will be to simply just use the one MediaPlayer and use the mp parameter of OnCompletionListener to load up the next sound on the same media player. I'll post my findings.
Providing you are releasing the media player correctly, it shouldn't be a memory problem. You can properly ensure this by doing:
if(mediaplayer!=null){
if(mediaplayer.isPlaying()){
mediaplayer.stop();
}
mediaplayer.release();
mediaplayer = null;
}
I believe there is a 10MB limit (minimum, some phones are higher) to apk memory allocation, so you should be able to check this fits within your limits. Market will allow up to 50MB however.
For debugging, I suggest you ensure that all the assests are there (sounds silly, but it rules it out) since if you're missing the sound files it will of course fail to create. Creating Toast notifications if an exception is thrown e.g. IllegalStateException will ensure that you management of media player states is not a problem.
It's also worth mentioning that you should not ever mix prepare and create. If you are using create, it will already call prepare and subsequent calls to prepare may cause odd behaviour; not sure if it will nullify the player though!
In general, you don't want to really be doing it the way you propose (creating a new mediaplayer and changing the sound in onComplete). The reason for this is simple, when you call create or prepare, it will load the sound into memory - this will take a variable amount of time dependant on phone (it may be a really long time for some phones!). It's far better to load them all up at once.
So, it must have been some kind of memory issue. I had 20+ media players loaded up initially.
Now I combined them all in to one media player and am loading the sounds dynamically. The sounds are small so I'm not worried about the loading time.
Here is some helper code in case anyone wants it.
private MediaPlayer getMediaPlayer(MediaPlayer mp, int resID, OnCompletionListener listener){
mp.release();
mp = null;
mp = new MediaPlayer();
AssetFileDescriptor afd = getResources().openRawResourceFd(resID);
try {
mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getDeclaredLength());
mp.prepare();
mp.setOnCompletionListener(listener);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return mp;
}
I use this to load a new sound. Its got a fair bit of overhead but it works and that's what's important.
Here is how I use it.
mSoundPlayer = getMediaPlayer(mSoundPlayer, R.raw.a123switch, endSwitch123Listener);
mSoundPlayer.start();

How to use Async task for audio streaming in android

Can we stream an audio file via async task in android. give me an example if u have done.
Alright I've struggled with this myself for quite a while, since everyone always told me "just use prepareAsync() and it will work.
However, you will still need to wait until enough has been buffered before trying to start() otherwise you'll get errors and nothing will happen.
First of, let your music-streamer class implement OnPreparedListener. This will be used to check if enough has been buffered before starting to play.
Next, use this piece of code to start the buffering and set the listener:
mediaPlayer.setDataSource(URL here);
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(this);
You have now set your listener to check whether or not enough has been buffered. Only one more step to go
public void onPrepared(MediaPlayer mediaplayer) {
// We now have buffered enough to be able to play
mediaPlayer.start();
}
The song will now be able to start playing without giving errors and all that.
Good luck!
As for the fact you want to play the music and be able to stop it at any time, you will need to use a Service if you plan on being able to stop your music from all activities. There are a few tutorials about that to be found on the internet.
You can use mediaPlayer object.
mediaPlayer.setDataSource("Your datasource");
mediaPlayer.prepareAsync();
The method prepareAsyc: Prepares the player for playback, asynchronously.
For more information see: http://developer.android.com/reference/android/media/MediaPlayer.html
Hope this helps...

AudioHardware pcm playback is going to standby error for playing from SD-card

After reading several similar questions I found that all developers that experience this error see this behaviour when streaming media files from the internet.
I use audio files (MP3) from the SD card and I play them in a Service. I do play them one after each other and at some point MediaPlayer dies with the message shown in the title. It does not throw any error thru the registered OnErrorListener. It's simply dead after the last tune of one of the files. It's always the same file if I use the same file order.
Tracing the app did not show any growth in memory consumption. I even tried to make MediaPlayer static to avoid GC. The last approach was to close MediaPlayer intirely, NULL its static variable and create and restart everything new. This didn't help. If the hardware is gone - it's gone.
I do experience this with a Google Nexus One and I need help. I read a tip to fade out three seconds before end of the files. Is this really a solution and how should I do this?
Many thanks in advance.
well, I think u implemented "onCompletion" event of MediaPlayer,
I think the bug is that android fires onCompletion event while (mediaPlayer.isPlaying) still true
so my idea is to stop media player before playing next mp3
something like this ...
public void onCompletion(MediaPlayer mp) {
if(mp != null && mp.isPlaying()){
Log.d("onCompletion", "mp is playing !!! stop it!!!");
mp.stop();
}
/*
play next item here or prepare or ...
*/
}

Categories

Resources