web-dev-qa-db-fra.com

Android - Taille tampon Mediaplayer In ICS 4.0

J'utilise une prise en tant que proxy sur le MediaPlayer afin que je puisse télécharger et décrypter MP3 audio avant de l'écrire sur la prise. Ceci est similaire à celui indiqué dans l'application NPR News, mais j'utilise cela pour tout Android Version 2.1 - 4 ATM.

NPR StreamProxy Code - http://code.google.com/p/npr-android-app/source/browse/npr/src/org/npr/andrrid/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 tamponne trop de données avant de tirer l'auditeur surpared.

Un exemple de données écrit sur la sortie de la prise avant la préparation ():

Sur SGS2 avec 2.3.4 - Onpepared () après ~ 133920 octets

Sur Nexus S avec 4.0.4 - Onpreparé () après ~ 961930 octets

Cela se produit également sur le Galaxy Nexus.

Beirdly L'émulateur 4.0 ne tamponne pas autant de données que 4,0 périphériques. Quelqu'un a-t-il un problème similaire avec le MediaPlayer sur ICS?

ÉDITER

Voici comment la proxy écrit sur la prise. Dans cet exemple, il s'agit d'une cipreunputtream chargé à partir d'un fichier, mais la même chose se produit lorsqu'elle est chargée à partir de l'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();

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

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

J'ai regardé autour de vous pour des implémentations alternatives, mais comme j'ai crypté audio et que le MediaPlayer ne prend pas en charge les intrigions en tant que 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 IN ICS Le MediaPlayer tamponne une quantité énorme de ces données avant de jouer.

Edit 2:

Des tests supplémentaires montrent que ceci est également un problème sur le SGS2 une fois mis à niveau sur Android 4.0.3. Il semble donc que la mise en œuvre tampon du MediaPlayer ait changé de manière significative dans 4.0. Ceci est frustrant comme l'API ne fournit aucun moyen de modifier le comportement.

Edit 3:

Bug android créé. S'il vous plaît ajouter des commentaires et star là aussi http://code.google.com/p/android/issues/detail?id=2987

Edit 4:

Mon code de lecture est assez standard. J'ai le démarrage () appeler () sur le MediaPlayer de ma méthode OnPrepa ().

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

Je l'ai essayé en utilisant simplement la préparation () et aussi la solution recommandée par Ajacian81, mais sans être en vain.

Je devrais ajouter que récemment, un employé de Google m'a repris sur ma question et a confirmé que la taille de la mémoire tampon était intentionnellement augmentée dans ICS (pour la teneur en HD). Il a été demandé aux développeurs de l'API à Ajoutez la possibilité de définir une taille de mémoire tampon sur MediaPlayer.

Bien que je pense que cette demande de changement d'API avait été portée avant que je ne sois ce que je ne conseillerais personne de garder son souffle.

42
denizmveli

Serait-il possible de voir le code où vous êtes démarrer () ING The MediaPlayer?

Utilisez-vous le STREAM_MUSIC Type de flux audio?

player.setAudioStreamType(AudioManager.STREAM_MUSIC);

Avez-vous également expérimenté entre joueur.PrepaEeSync (); et joueur.prepare ();?

Il y avait un problème similaire l'année dernière, je me souviens, où la solution devait: commencer, faire une pause puis préparé pour commencer ():

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

Peu susceptible d'être la solution dans ce cas, mais pendant que vous tournez vos roues, cela vaut peut-être un coup.

2
ajacian81