Android - MediaPlayer buffer size in ICS 4.0

I use the socket as a proxy for MediaPlayer, so I can download and decrypt mp3 audio before writing it to the socket. This is similar to the example shown in the NPR news app, but I use it for all Android versions 2.1 - 4 atm.

NPR StreamProxy Code - http://code.google.com/p/npr-android-app/source/browse/Npr/src/org/npr/android/news/StreamProxy.java

My problem is that playback is fast for 2.1 - 2.3, but in Android 4.0 ICS MediaPlayer buffers too much data before running the onPrepared listener.

An example of the amount of data written to Socket OutputStream before onPrepared ():

In SGS2 with 2.3.4 - onPrepared () after ~ 133920 bytes

On Nexus S with 4.0.4 - onPrepared () after ~ 961930 bytes

This also happens in the Nexus Galaxy.

The 4.0 emulator is unlikely to buffer as much data as 4.0. Does anyone encounter a similar issue with MediaPlayer on ICS?

EDIT

Here's how a proxy writes to a socket. In this example, this is from a CipherInputStream loaded from a file, but the same thing happens when it is loaded from HttpResponse.

final Socket client = (setup above) // encrypted file input stream final CipherInputStream inputStream = getInputStream(file); // setup the socket output stream final OutputStream output = client.getOutputStream(); // Writing the header final String httpHeader = buildHttpHeader(file.length()); final byte[] buffer = httpHeader.getBytes("UTF-8"); output.write(buffer, 0, buffer.length); int writtenBytes = 0; int readBytes; final byte[] buff = new byte[1024 * 12]; // 12 KB while (mIsRunning && (readBytes = inputStream.read(buff)) != -1) { output.write(buff, 0, readBytes); writtenBytes += readBytes; } output.flush(); output.close(); 

HTTP headers that are written to MediaPlayer before the sound.

 private String buildHttpHeader(final int contentLength) { final StringBuilder sb = new StringBuilder(); sb.append("HTTP/1.1 200 OK\r\n"); sb.append("Content-Length: ").append(contentLength).append("\r\n"); sb.append("Accept-Ranges: bytes\r\n" ); sb.append("Content-Type: audio/mpeg\r\n"); sb.append("Connection: close\r\n" ); sb.append("\r\n"); return sb.toString(); } 

I was looking for alternative implementations, but since I have encrypted sound and MediaPlayer does not support InputStreams as a data source, my only option (I think ..) is to use a proxy server like this.

Again, this works pretty well Android 2.1 - 2.3, but in ICS MediaPlayer buffers a huge amount of this data before the game.

EDIT 2:

Further testing shows that this is also a problem on SGS2 after upgrading to Android 4.0.3. So it looks like the implementation of MediaPlayer buffering has changed significantly in 4.0. This is disappointing, because the API does not allow you to change the behavior.

EDIT 3:

Android error generated. Please add comments and stars there as well as http://code.google.com/p/android/issues/detail?id=29870

EDIT 4:

My replay code is pretty standard. I have a start () call on MediaPlayer in my onPrepared () method.

 mCurrentPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); mCurrentPlayer.setDataSource(url); mCurrentPlayer.prepareAsync(); 

We tried this using only the prepare () method, as well as recommended by ajacian81, but to no avail.

I must add that a Google employee recently came back to me about my question and confirmed that the buffer size was intentionally increased in ICS (for HD content). API developers were asked to add the ability to set the buffer size on MediaPlayer.

Although I think this request for an API change was around before I came, so I would not advise anyone to hold their breath.

+42
android audio streaming music-player
Apr 08 2018-12-12T00:
source share
2 answers

Can I see the code where you run () in MediaPlayer?

Are you using the audio stream type STREAM_MUSIC ?

 player.setAudioStreamType(AudioManager.STREAM_MUSIC); 

You also experimented between player.prepareAsync (); and player.prepare () ;?

Last year there was a similar problem, which I remember where the decision was made: start, pause, and then go to the beginning ():

 player.setAudioStreamType(AudioManager.STREAM_MUSIC); player.setDataSource(src); player.prepare(); player.start(); player.pause(); player.setOnPreparedListener(new OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { player.start(); } }); 

In this case, it’s unlikely to be fixed, but as long as you spin your wheels, it may be worth it.

+2
May 17 '12 at 17:31
source share

For me there was a decision to use MediaCodec with AudioTrack, I found everything I need to know here:

It could be a solution: http://www.piterwilson.com/blog/2014/03/15/mediacodec-mediaextractor-and-audiotrack-to-the-rescue/

0
Oct 01 '14 at 16:01
source share



All Articles