gpt4 book ai didi

Android JellyBean 网络媒体问题

转载 作者:塔克拉玛干 更新时间:2023-11-01 21:46:47 25 4
gpt4 key购买 nike

我有一个播放 MP3 文件的应用程序,这些文件可以在公共(public) URL 上找到。不幸的是,服务器不支持流媒体,但 Android 使用户体验相当可以接受。

除 JellyBean 外,它适用于所有平台。在请求 MP3 时,JB 请求了 10 次 Range-Header。只有在第 10 次尝试之后,它似乎才恢复到原来的行为。 Looks like this already reported issue

我发现了另一个 SO thread,其中推荐的解决方案是使用 Tranfer-Encoding: chunked header 。但就在下面有一条评论说这不起作用。

目前我无法控制传递上述响应 header ,但在我能够做到这一点之前,我想在客户端搜索替代方案。 (即便如此,我只能返回一个包含从 0 到 Content-Length - 1 的索引的 Content-Range。例如 Content-Range:字节 0-3123456/3123457)。

我尝试做的是通过以下方式在客户端实现伪流:

  1. 打开 MP3 的输入流。
  2. 使用 JLayer 解码传入的字节。我在 this link 找到了解码。
  3. 将解码后的数组字节发送到已可播放的 stream_mode AudioTrack。

可以在那里找到执行解码的代码,我只是修改了它以便接收一个 InputStream:

public byte[] decode(InputStream inputStream, int startMs, int maxMs) throws IOException {
ByteArrayOutputStream outStream = new ByteArrayOutputStream(1024);

float totalMs = 0;
boolean seeking = true;

try {
Bitstream bitstream = new Bitstream(inputStream);
Decoder decoder = new Decoder();

boolean done = false;
while (!done) {
Header frameHeader = bitstream.readFrame();
if (frameHeader == null) {
done = true;
} else {
totalMs += frameHeader.ms_per_frame();

if (totalMs >= startMs) {
seeking = false;
}

if (!seeking) {
// logger.debug("Handling header: " + frameHeader.layer_string());
SampleBuffer output = (SampleBuffer) decoder.decodeFrame(frameHeader, bitstream);

if (output.getSampleFrequency() != 44100 || output.getChannelCount() != 2) {
throw new IllegalArgumentException("mono or non-44100 MP3 not supported");
}

short[] pcm = output.getBuffer();
for (short s : pcm) {
outStream.write(s & 0xff);
outStream.write((s >> 8) & 0xff);
}
}

if (totalMs >= (startMs + maxMs)) {
done = true;
}
}
bitstream.closeFrame();
}

return outStream.toByteArray();
} catch (BitstreamException e) {
throw new IOException("Bitstream error: " + e);
} catch (DecoderException e) {
throw new IOException("Decoder error: " + e);
}
}

我请求时间 block 中的解码字节:从 (0, 5000) 开始,所以我首先要播放一个更大的数组,然后我请求跨越一秒的下一个字节数组:(5000, 1000 ), (6000, 1000), (7000, 1000), 等等

解码速度足够快,并且在另一个线程中完成,一旦解码字节数组可用,我就会使用阻塞队列将其写入在另一个线程中播放的 AudioTrack。

问题是播放不流畅,因为音轨中的 block 不是连续的(每个 block 都是连续的,但添加到 AudioTrack 中会导致播放不流畅)。

总结:

  1. 如果您遇到过这个 JellyBean 问题,您是如何解决的?
  2. 如果你们中有人尝试过我的方法,我在上面的代码中做错了什么?如果这是您使用的解决方案,我可以发布其余代码。

谢谢!

最佳答案

看起来您正在尝试开发自己的流媒体类型。这可能会出现 block 状或中断播放,因为您必须尝试连续的信息管道,而不会用完要读取的字节。

基本上,您必须考虑普通流媒体客户端处理的所有情况。例如,有时某些 block 可能会在传输过程中丢失或丢失;有时音频播放可能会 catch 下载; CPU 开始滞后,影响播放;等等等等

如果您想继续沿着这条路走下去,需要研究的是滑动窗口实现,它本质上是一种抽象技术,试图保持网络连接始终活跃和流畅。你应该能够通过谷歌找到几个例子,这里是一个开始的地方:http://en.wikipedia.org/wiki/Sliding_window_protocol

编辑:在解决此问题之前,一种可能对您有帮助的解决方法是将 SDK <16 中的 MediaPlayer.javaAudioManager.java 的源代码包含到您的项目,看看是否能解决问题。如果您没有源代码,可以使用 SDK 管理器下载它。

关于Android JellyBean 网络媒体问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13191350/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com