Android – Taille du tampon MediaPlayer dans ICS 4.0

J’utilise un socket comme proxy pour le MediaPlayer afin que je puisse télécharger et déchiffrer l’audio mp3 avant de l’écrire sur le socket. Ceci est similaire à l’exemple montré dans l’application de nouvelles NPR mais je l’utilise pour toutes les versions Android 2.1 – 4 atm.

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

Mon problème est que la lecture est rapide pour 2.1 – 2.3, mais dans Android 4.0 ICS, le MediaPlayer stocke trop de données avant de déclencher le programme d’écoute.

Un exemple de quantité de données écrites dans le Socket OutputStream avant onPrepared ():

Sur SGS2 avec 2.3.4 – onPrepared () après ~ 133920 octets

Sur Nexus S avec 4.0.4 – onPrepared () après ~ 961930 octets

Cela se produit également sur le Galaxy Nexus.

Bizarrement, l’émulateur 4.0 ne stocke pas autant de données que les périphériques 4.0. Quelqu’un a-t-il rencontré un problème similaire avec le MediaPlayer sur ICS?

MODIFIER

Voici comment le proxy écrit sur le socket. Dans cet exemple, il provient d’un fichier CipherInputStream chargé à partir d’un fichier, mais il en va de même lorsqu’il est chargé depuis 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 Ssortingng 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(); 

Les en-têtes HTTP écrits sur le MediaPlayer avant l’audio.

 private Ssortingng buildHttpHeader(final int contentLength) { final SsortingngBuilder sb = new SsortingngBuilder(); 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.toSsortingng(); } 

J’ai cherché des implémentations alternatives, mais comme j’ai crypté l’audio et que MediaPlayer ne supporte pas InputStreams comme source de données, ma seule option (je pense ..) est d’utiliser un proxy tel que celui-ci.

Encore une fois, cela fonctionne assez bien Android 2.1 – 2.3 mais dans ICS, le MediaPlayer met en mémoire tampon une grande quantité de ces données avant de les jouer.

EDIT 2:

Des tests supplémentaires montrent que ceci est également un problème sur le SGS2 une fois mis à niveau vers Android 4.0.3. Il semble donc que l’implémentation de la mise en mémoire tampon de MediaPlayer a changé de manière significative en 4.0. Cela est frustrant car l’API ne fournit aucun moyen de modifier le comportement.

MODIFIER 3:

Bug Android créé. S’il vous plaît append des commentaires et écanvass là aussi http://code.google.com/p/android/issues/detail?id=29870

EDIT 4:

Mon code de lecture est assez standard. J’ai l’appel start () sur le MediaPlayer dans ma méthode onPrepared ().

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

Je l’ai essayé en utilisant simplement prepare () et aussi la manière recommandée d’ajacian81 mais en vain.

Je dois append que récemment, un employé de Google est revenu sur ma question et a confirmé que la taille de la mémoire tampon avait été intentionnellement augmentée dans ICS (pour le contenu HD). Il a été demandé aux développeurs de l’API d’append la possibilité de définir une taille de mémoire tampon sur MediaPlayer.

Bien que je pense que cette demande de changement d’API ait été faite avant mon arrivée, je ne conseillerais à personne de retenir leur souffle.

Serait-il possible de voir le code où vous commencez () le MediaPlayer?

Utilisez-vous le type de stream audio STREAM_MUSIC ?

 player.setAudioStreamType(AudioManager.STREAM_MUSIC); 

Avez-vous également expérimenté entre player.prepareAsync (); et player.prepare () ;?

Il y a eu un problème similaire l’année dernière, je me souviens, où la solution était de: démarrer, mettre en pause et ensuite onPrepared pour démarrer ():

 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(); } }); 

Il est peu probable que ce soit le cas, mais pendant que vous roulez, cela vaut peut-être le coup.

Pour moi, la solution était d’utiliser MediaCodec avec AudioTrack, j’ai trouvé tout ce que j’ai besoin de savoir ici:

Cela pourrait être une solution: http://www.piterwilson.com/blog/2014/03/15/mediacodec-mediaextractor-and-audiotrack-to-the-rescue/