web-dev-qa-db-ja.com

Android-MediaPlayerのバッファサイズICS 4.0

MediaPlayerのプロキシとしてソケットを使用しているため、ソケットに書き込む前にmp3オーディオをダウンロードして復号化できます。これはNPRニュースアプリに表示される例に似ていますが、Androidバージョン2.1-4 atmのすべてに使用しています。

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リスナーを起動する前に、あまりにも多くのデータをバッファリングします。

OnPrepared()の前にSocket OutputStreamに書き込まれるデータ量の例:

2.3.4がインストールされたSGS2の場合-133920バイト以降のonPrepared()

4.0.4を搭載したNexus Sの場合-961930バイト以降のonPrepared()

これはGalaxy Nexusでも発生します。

奇妙なことに、4.0エミュレータは4.0デバイスほどのデータをバッファリングしません。だれでもICSのMediaPlayerで同様の問題が発生しますか?

編集

プロキシがソケットに書き込む方法は次のとおりです。この例では、ファイルから読み込まれた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();

オーディオの前にMediaPlayerに書き込まれるHTTPヘッダー。

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が再生する前にこのデータを大量にバッファリングしています。

編集2:

さらにテストを行ったところ、これはSGS2でもAndroid 4.0.3にアップグレードされた場合の問題です。したがって、MediaPlayerのバッファリング実装が4.0で大幅に変更されたようです。これはAPIとしてイライラします。動作を変更する方法はありません。

編集3:

Androidのバグが作成されました。コメントを追加して、そこにもスターを付けてください http://code.google.com/p/Android/issues/detail?id=2987

編集4:

私の再生コードはかなり標準的なものです。MediaPlayerのonPrepared()メソッドでstart()を呼び出しています。

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

Prepare()とajacian81の推奨される方法を使用して試したが、役に立たなかった。

最近Googleの従業員が私の質問について返答し、ICS(HDコンテンツの場合)でバッファサイズが意図的に増加したことを確認しました。API開発者にリクエストされました。 MediaPlayerでバッファサイズを設定する機能を追加します。

このAPI変更リクエストは私が来る前に存在していたと思いますが、息を止めるようにアドバイスするつもりはありません。

42
denizmveli

MediaPlayerを開始()しているコードを確認することはできますか?

STREAM_MUSICオーディオストリームタイプを使用していますか?

player.setAudioStreamType(AudioManager.STREAM_MUSIC);

Player.prepareAsync();の間でも実験をしましたか。そしてplayer.prepare();?

昨年覚えていた同様の問題がありました。解決策は、開始、一時停止、そしてonPrepared to 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();                
                }
          });

この場合は修正される可能性は低いですが、ホイールを回転させている間、これは一撃の価値があるかもしれません。

2
ajacian81

私にとっての解決策は、AudioTrackでMediaCodecを使用することでした。

これは解決策になる可能性があります: http://www.piterwilson.com/blog/2014/03/15/mediacodec-mediaextractor-and-audiotrack-to-the-rescue/

0
OriolJ