Android – Размер буфера MediaPlayer в ICS 4.0

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

Код 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 прослушивателя.

Пример количества данных, записанных в Socket OutputStream до onPrepared ():

В SGS2 с 2.3.4 – onPrepared () после ~ 133920 байт

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

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

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

РЕДАКТИРОВАТЬ

Вот как прокси пишет в сокет. В этом примере это из 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 не дает возможности изменить поведение.

ИЗМЕНИТЬ 3:

Создана ошибка Android. Также добавьте комментарии и звездочку http://code.google.com/p/android/issues/detail?id=29870.

EDIT 4:

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

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

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

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

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

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

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

 player.setAudioStreamType(AudioManager.STREAM_MUSIC); 

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

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

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

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

Для меня было решение использовать MediaCodec с AudioTrack, я нашел все, что мне нужно знать здесь:

Это может быть решением: http://www.piterwilson.com/blog/2014/03/15/mediacodec-mediaextractor-and-audiotrack-to-the-rescue/

Intereting Posts
Как реализовать ContentObserver для журналов вызовов О request.setTesting (true) строка кода Каков наилучший способ неоднократно повторять задачу в android? (Например: – Обновление баллов, Обновление Ui) Как протестировать собственное приложение для Android с помощью Protractor Расширяемый вид списка Индикатор не устанавливается с правой стороны Android popupmenu position Android NTLM, получающий HTTP / 1.1 401 Несанкционированный Отбросить мяч назад андроид Как заставить панель поиска Search Search заполнить всю панель действий? Динамический вид с прокруткой по горизонтали и вертикали Не удалось запустить работу: UnsupportedOperationException: addView (View, LayoutParams) не поддерживается в AdapterView Android и вычисление размера однострочной строки в заданном шрифте и размере шрифта? Android: увеличьте размер стека вызовов Как предотвратить остановку службы, когда onTaskRemoved – это вызовы? AndEngine-Drawing sprite's child за родителем