42

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

NPRStreamProxyコード-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()の前にSocketOutputStreamに書き込まれるデータ量の例:

2.3.4のSGS2の場合-〜133920バイト後のonPrepared()

4.0.4のNexusSの場合-〜961930バイト後のonPrepared()

これはGalaxyNexusでも発生します。

奇妙なことに、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:

さらなるテストでは、これがAndroid4.0.3にアップグレードされたSGS2の問題でもあることが示されています。したがって、MediaPlayerのバッファリングの実装は4.0で大幅に変更されたようです。APIは動作を変更する方法を提供しないため、これはイライラします。

編集3:

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

編集4:

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

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

prepare()とajacian81の推奨方法を使用して試してみましたが、役に立ちませんでした。

最近、Googleの従業員が私の質問について私に連絡し、ICS(HDコンテンツ用)でバッファーサイズが意図的に増加していることを確認したことを付け加えておきます。MediaPlayerでバッファサイズを設定する機能を追加することがAPI開発者に要求されました。

このAPI変更リクエストは私が来る前からあったと思うので、誰にも息を止めてはいけません。

4

2 に答える 2

2

MediaPlayer を start() しているコードを確認できますか?

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

player.setAudioStreamType(AudioManager.STREAM_MUSIC);

player.prepareAsync(); の間でも実験しましたか? と player.prepare();?

去年も同様の問題がありましたが、解決策は次のとおりでした: start、pause、そして 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();                
                }
          });

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

于 2012-05-17T17:31:21.950 に答える
0

私にとっての解決策は、AudioTrack で MediaCodec を使用することでした。ここで知る必要があるすべてを見つけました。

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

于 2014-10-01T16:01:50.373 に答える