安卓 - ICS 4.0中MediaPlayer的缓冲大小

42
我正在使用socket作为MediaPlayer的代理,以便在将mp3音频下载并解密后写入socket之前进行处理。这类似于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版本中,播放速度很快,但在Android 4.0 ICS中,MediaPlayer在触发onPrepared监听器之前缓冲了太多的数据。
Socket OutputStream在onPrepared()之前写入的数据示例:
在带有2.3.4的SGS2上 - onPrepared()之后约133920字节
在带有4.0.4的Nexus S上 - onPrepared()之后约961930字节
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();

在音频播放器之前写入的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不支持InputStream作为数据源,所以我的唯一选择(我认为是)是使用这样的代理。
同样,在Android 2.1-2.3中运行得相当顺利,但在ICS中,MediaPlayer在播放之前缓冲了大量数据。
编辑2:
进一步测试表明,一旦将SGS2升级到Android 4.0.3,这也是一个问题。因此,似乎MediaPlayer的缓冲实现在4.0中发生了显着变化。这很令人沮丧,因为API没有提供改变行为的方法。
编辑3:
创建了Android bug。请在那里添加评论和星号 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中故意增加(用于高清内容)。已要求API开发人员添加在MediaPlayer上设置缓冲区大小的功能。 虽然我认为这个API变更请求早在我出现之前就存在了,所以我不建议任何人抱有期望。

1
哇!同样的问题!Nexus S。使用MediaPlayer时缓冲太多。 - Alexis
可能值得向Android开发人员记录此问题作为一个bug。 - Rob Kielty
3
请给我提交的Android bug点个赞,以帮助它获得更多关注 - https://code.google.com/p/android/issues/detail?id=29870 - denizmveli
你能解决这个问题吗? - StackOverflowed
@StackOverflowed 不好意思,不是的。 - denizmveli
@denizmveli,你找到解决方案了吗?还是采用了AudioTrack + MP3解码器的方式? - burakk
2个回答

2

你能否提供启动MediaPlayer的代码?

你是否在使用STREAM_MUSIC音频流类型?

player.setAudioStreamType(AudioManager.STREAM_MUSIC);

你是否也尝试过player.prepareAsync(); 和 player.prepare();之间的区别?

我记得去年有类似的问题,解决方法是:先开始播放,然后暂停,最后在onPrepared中调用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();                
                }
          });

在这种情况下,这可能不是解决方案,但是当您正在白费劲时,这也许值得一试。


谢谢你的回答。不幸的是,它没有解决我的问题。顺便问一下,你之前遇到了什么问题需要这个实现呢? - denizmveli
@TheModernInk 即使在非常快的WIFI连接下,缓冲中出现了长时间的间隔。 - ajacian81

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接