2012-04-08 6 views
42

Я использую сокет в качестве прокси-сервера для MediaPlayer, поэтому я могу загружать и расшифровывать mp3-аудио, прежде чем записывать его в сокет. Это похоже на пример, показанный в новостном приложении NPR, но я использую его для всех Android версии 2.1 - 4 атм.Android - Размер буфера MediaPlayer в ICS 4.0

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

Моя проблема заключается в том, что воспроизведение быстро для 2.1 - 2.3, но в Android 4.0 ICS буферы MediaPlayer слишком много данных перед обжигом onPrepared слушателя.

В качестве примера объем данных, записываемых в сокет OutputStream, прежде чем onPrepared():

На SGS2 с 2.3.4 - onPrepared() после того, как ~ 133920 байт

На Nexus S с 4.0.4 - onPrepared() после ~ 961930 байт

Это также происходит на Galaxy Nexus.

Странно, что эмулятор 4.0 не хранит столько данных, сколько 4.0 устройств. Кто-нибудь сталкивается с аналогичной проблемой с MediaPlayer в ICS?

EDIT

Вот как прокси-сервер записи в сокет. В этом примере это из CipherInputStream, загруженного из файла, но то же самое происходит, когда он загружается из 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-заголовки, которые написаны на MediaPlayer до аудио ..

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

Я посмотрел вокруг альтернативных реализаций, но, как я зашифрованы аудио и MediaPlayer не поддерживает InputStreams, как источник данных мой единственный вариант (я думаю ..) заключается в использовании прокси-сервера, такого как это.

Опять же, это работает довольно хорошо Android 2.1 - 2.3, но в ICS MediaPlayer буферизует огромное количество этих данных перед игрой.

EDIT 2:

Дальнейшее тестирование показывает, что это также вопрос о sgs2 раз повышен до Android 4.0.3. Таким образом, похоже, что буферизация MediaPlayer значительно изменилась в 4.0. Это расстраивает, поскольку API не дает возможности изменить поведение.

EDIT 3:

Ошибка Android создана. Пожалуйста, добавьте комментарии и звезды там также http://code.google.com/p/android/issues/detail?id=29870

EDIT 4:

Мой код воспроизведения довольно стандартный .. У меня есть вызов старт() на MediaPlayer в моем методе onPrepared().

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

Пробовал, используя только готовый(), а также рекомендованный способ ajacian81, но безрезультатно.

Я должен добавить, что недавно сотрудник Google вернулся ко мне о моем вопросе и подтвердил, что размер буфера был намеренно увеличен в ICS (для контента HD). Разработчикам API было предложено добавить возможность устанавливать размер буфера на MediaPlayer.

Хотя я думаю, что этот запрос на изменение API был вокруг, прежде чем я пришел, чтобы я не советовал никому задерживать дыхание.

+1

Wow! та же проблема! Nexus S. Слишком много буфера с MediaPlayer – Alexis

+0

Возможно, стоит записать это как ошибку с разработчиками Android. –

+3

Пожалуйста, отметьте ошибку Android, которую я отправил, чтобы помочь вам получить видимость - https://code.google.com/p/android/issues/detail?id=29870 – denizmveli

ответ

2

Можно ли увидеть код, с которого вы начинаете() в MediaPlayer?

Вы используете аудиопоток STREAM_MUSIC?

player.setAudioStreamType(AudioManager.STREAM_MUSIC); 

Вы также экспериментировали между player.prepareAsync(); и player.prepare() ;?

Был аналогичный вопрос в прошлом году, я помню, где решение было: начать, пауза, а затем onPrepared начать():

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

Вряд ли будет исправить в этом случае, но пока вы «Вращая ваши колеса, это может стоить того.

+0

Благодарим вас за ответ. К сожалению, это не исправило мою проблему. Кстати, какой у вас был вопрос, требующий этой реализации? – denizmveli

+0

@ TheModernInk Длинные промежутки в буферизации, даже при очень быстром подключении WIFI. – ajacian81

Смежные вопросы