2012-04-08 25 views
42

我使用套接字作为MediaPlayer的代理,因此我可以在将它写入套接字之前下载和解密mp3音频。这与NPR新闻应用程序中显示的示例类似,但是我将其用于所有Android版本2.1 - 4 atm。Android - MediaSlayer缓冲区大小在ICS 4.0中

NPR StreamProxy码 - http://code.google.com/p/npr-android-app/source/browse/Npr/src/org/npr/android/news/StreamProxy.java

我的问题是,播放快2.1 - 2.3,但烧制onPrepared听众之前的Android 4.0 ICS的MediaPlayer的缓冲数据太多。

onPrepared(前写入到插座的OutputStream)的数据的示例量:

在SGS2与2.3.4 - onPrepared()之后〜133920个字节

在Nexus S采用4.0.4 - 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(); 

,音频之前被写入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:

进一步测试显示,这也是一次升级至Android 4.0.3的SGS2的问题。所以看起来MediaPlayer的缓冲实现在4.0中发生了显着变化。这令人沮丧,因为API没有办法改变行为。

编辑3:

已创建Android错误。请添加注释和明星有作为 http://code.google.com/p/android/issues/detail?id=29870

编辑4:

我的播放代码是相当标准。我有我的onPrepared()方法的MediaPlayer的开始()调用。

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

已经试过它只使用prepare()和ajacian81的推荐方式,但无济于事。

我应该补充一点,Google员工最近回复了我的问题,并确认缓冲区大小在ICS(针对HD内容)中有意增加。已向API开发人员要求添加在MediaPlayer上设置缓冲区大小的功能。

虽然我认为这个API变更请求在我出现之前已经存在,所以我不会建议任何人屏住呼吸。

+1

哇!同样的问题! Nexus S. MediaPlayer的缓冲区太大 – Alexis 2012-04-12 07:45:18

+0

这可能是值得记录的,这是Android开发人员的一个错误。 – 2012-04-27 22:17:48

+3

请明星我提交的Android错误以帮助获得一些可见性 - https://code.google.com/p/android/issues/detail?id=29870 – denizmveli 2012-05-01 14:17:17

回答

2

是否可以看到开始()MediaPlayer的代码?

您使用的是STREAM_MUSIC音频流类型吗?

player.setAudioStreamType(AudioManager.STREAM_MUSIC); 

您是否还在player.prepareAsync();和player.prepare();?

也有类似的问题,去年我记得,这里的解决方案是:开始,暂停,然后onPrepared开始():

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

,不可能在这种情况下,修复,但是当你'转动你的轮子这可能值得一试。

+0

谢谢你的回答。不幸的是,它并没有解决我的问题。顺便说一句,你有哪些需要实现的问题? – denizmveli 2012-05-17 23:32:48

+0

@TheModernInk即使在非常快速的WIFI连接时,缓冲区中的长间隙也是如此。 – ajacian81 2012-05-18 03:30:23