Android - Rozmiar bufora MediaPlayer w ICS 4.0
Używam gniazda jako proxy do MediaPlayera, więc mogę pobrać i odszyfrować dźwięk mp3 przed zapisaniem go w gnieździe. Jest to podobne do przykładu pokazanego w aplikacji wiadomości NPR, ale używam tego dla wszystkich wersji Androida 2.1 - 4 atm.
Kod NPR StreamProxy -http://code.google.com/p/npr-android-app/source/browse/Npr/src/org/npr/android/news/StreamProxy.java
Moim problemem jest to, że odtwarzanie jest szybkie dla 2.1 - 2.3, ale w Android 4.0 ICS MediaPlayer buforuje zbyt wiele danych przed uruchomieniem słuchacza onPrepared.
Przykładowa ilość danych zapisanych w Socket OutputStream przed onPrepared ():
Na SGS2 z 2.3.4 - onPrepared () po ~ 133920 bajtach
Na Nexusie S z 4.0.4 - onPrepared () po ~ 961930 bajtach
Dzieje się tak również w Galaxy Nexus.
Dziwnie jest, że emulator 4.0 nie buforuje tak dużo danych jak urządzenia 4.0. Czy ktoś ma podobny problem z MediaPlayerem na ICS?
EDYTOWAĆ
Oto jak proxy zapisuje w gnieździe. W tym przykładzie jest to ładowany z pliku CipherInputStream, ale to samo dzieje się, gdy jest ładowany z HttpResponse.
<code>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(); </code>
Nagłówki HTTP, które są zapisywane w MediaPlayer przed dźwiękiem.
<code>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(); } </code>
Szukałem alternatywnych implementacji, ale ponieważ mam zaszyfrowane audio i MediaPlayer nie obsługuje InputStreams jako źródła danych, moją jedyną opcją (myślę ..) jest użycie proxy takiego jak to.
Ponownie działa to całkiem dobrze Android 2.1 - 2.3, ale w ICS MediaPlayer buforuje ogromną ilość tych danych przed rozpoczęciem odtwarzania.
EDYCJA 2:
Dalsze testy pokazują, że jest to również problem na SGS2 po aktualizacji do Androida 4.0.3. Wygląda więc na to, że implementacja buforowania MediaPlayera znacznie się zmieniła w wersji 4.0. Jest to frustrujące, ponieważ API nie daje możliwości zmiany zachowania.
EDYCJA 3:
Utworzono błąd Androida. Dodaj tam również komentarze i gwiazdkęhttp://code.google.com/p/android/issues/detail?id=29870
EDYTUJ 4:
Mój kod odtwarzania jest dość standardowy .. Mam wywołanie start () w MediaPlayer w mojej metodzie onPrepared ().
<code>mCurrentPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); mCurrentPlayer.setDataSource(url); mCurrentPlayer.prepareAsync(); </code>
Wypróbowałem go za pomocą polecenia just prepare () i zalecanego sposobu ajacian81, ale bezskutecznie.
Powinienem dodać, że niedawno pracownik Google zwrócił się do mnie o moim pytaniu i potwierdził, że rozmiar bufora został celowo zwiększony w ICS (dla treści HD). Programiści API poprosili o dodanie możliwości ustawiania rozmiaru bufora na MediaPlayer.
Chociaż myślę, że prośba o zmianę API pojawiła się przed przyjściem, więc nie radzę nikomu wstrzymywać oddechu.