2012-04-08 17 views
42

Estoy usando un socket como proxy para MediaPlayer para poder descargar y descifrar audio en mp3 antes de escribirlo en el socket. Esto es similar al ejemplo que se muestra en la aplicación de noticias NPR, sin embargo, estoy usando esto para todas las versiones de Android 2.1 - 4 atm.Android - Tamaño del búfer de MediaPlayer en ICS 4.0

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

Mi problema es que la reproducción es rápido el 2,1 - 2,3, pero en Android 4.0 ICS los buffers MediaPlayer demasiados datos antes de disparar el oyente onPrepared.

Una cantidad ejemplo de los datos escritos en el conector OutputStream antes onPrepared():

En SGS2 con 2.3.4 - onPrepared() después de ~ 133920 bytes

en Nexus S con 4.0.4 - onPrepared() después de ~ 961930 bytes

Esto también ocurre en el Galaxy Nexus.

Extrañamente, el emulador 4.0 no almacena tantos datos como los 4.0 dispositivos. ¿Alguien tiene un problema similar con MediaPlayer en ICS?

EDITAR

Así es como el proxy está escribiendo en el zócalo. En este ejemplo, proviene de un CipherInputStream cargado desde un archivo, pero lo mismo ocurre cuando se carga desde 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(); 

las cabeceras HTTP que se escriben en el MediaPlayer antes de que el 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(); 
} 

He mirado alrededor de implementaciones alternativas, pero como he cifrado de audio y el MediaPlayer no admite como InputStreams una fuente de datos, mi única opción (creo ...) es usar un proxy como este.

Una vez más, esto está funcionando bastante bien Android 2.1 - 2.3 pero en ICS el MediaPlayer está almacenando una gran cantidad de estos datos antes de jugar.

EDIT 2:

Además la prueba muestra que esto también es un problema en el SGS2 una vez actualizado a Android 4.0.3. Parece que la implementación del buffering de MediaPlayer ha cambiado significativamente en 4.0. Esto es frustrante ya que la API no proporciona ninguna forma de alterar el comportamiento.

EDIT 3:

Error de Android creado. Por favor, añadir comentarios y la estrella allí también http://code.google.com/p/android/issues/detail?id=29870

EDITAR 4:

Mi código de la reproducción es bastante estándar .. Tengo la llamada de inicio() en el MediaPlayer en mi método onPrepared().

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

lo han intentado usar Sólo tiene que preparar() y también es ajacian81 forma recomendada, pero en vano.

Debo añadir que recientemente, un empleado de Google volvió a consultarme sobre mi pregunta y confirmó que el tamaño del búfer se aumentó intencionadamente en ICS (para contenido HD). Se ha solicitado a los desarrolladores de API que agreguen la capacidad de establecer un tamaño de búfer en MediaPlayer.

Aunque creo que esta solicitud de cambio de API había existido antes de que yo llegara, así que no aconsejaría a nadie que contuviera la respiración.

+1

Wow! ¡el mismo problema! Nexus S. Demasiado buffer con MediaPlayer – Alexis

+0

Puede valer la pena registrar esto como un error con los desarrolladores de Android. –

+3

Marque la falla de Android que envié para ayudarlo a obtener un poco de visibilidad: https://code.google.com/p/android/issues/detail?id=29870 – denizmveli

Respuesta

2

¿Sería posible ver el código donde está comenzando() el MediaPlayer?

¿Está utilizando el tipo de secuencia de audio STREAM_MUSIC?

player.setAudioStreamType(AudioManager.STREAM_MUSIC); 

¿Has probado también entre player.prepareAsync(); y player.prepare() ;?

había un problema similar el año pasado que recuerdo, en donde la solución era: iniciar, pausar y luego onPrepared a start():

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

Es improbable que sea el punto de referencia en este caso, pero mientras Girar las ruedas esto podría valer la pena.

+0

Gracias por su respuesta. Lamentablemente no solucionó mi problema. Por cierto, ¿cuál era el problema que tenía que requería esta implementación? – denizmveli

+0

@TheModernInk Largas lagunas en el almacenamiento en búfer, incluso con una conexión WIFI muy rápida. – ajacian81

Cuestiones relacionadas