Android的软糖网络媒体的问题 [英] Android JellyBean network media issue

查看:222
本文介绍了Android的软糖网络媒体的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个播放时可在公共URL MP3文件的应用程序。不幸的是,服务器不支持流媒体,但在Android让用户体验完全可以接受的。

I have an application that is playing MP3 files that are available at a public URL. Unfortunately the server does not support streaming, but the Android makes the user experience quite acceptable.

这一切工作正常,除了软糖所有平台。当请求的MP3,JB要求的范围标头为10倍。只有10次尝试之后,似乎恢复到原来的行为。 看起来这已经报告的问题

It all works fine for all platforms except for JellyBean. When requesting the MP3, JB requests for a Range-Header for 10 times. Only after the 10-th attempt it seems to revert to the old behavior. Looks like this already reported issue.

我发现了另一个<一href="http://stackoverflow.com/questions/11606146/android-media-player-how-to-disable-range-request-broken-audio-streaming-on">SO螺纹,其中推荐的一个解决方案是使用的枢纽换乘编码:分块的头。但是,仅低于有一个评论说,这是行不通的。

I found another SO thread where a solution recommended is to use Tranfer-Encoding: chunked header. But just below there is a comment that this doesn't work.

目前我没有控制任何能够提供上述响应头,但直到我能做到,我认为搜索在客户端的一个选择。 (即便如此,我也只能返回一个内容范围包含指数从0到的Content-Length - 1.前内容范围:字节0-3123456 / 3123457)。

For the moment I have no control whatsoever to deliver above response headers, but until I will be able to do that I thought to search for an alternative at client side. (even so, I can only return a Content-Range that contains indexes from 0 to Content-Length - 1. Ex. Content-Range: bytes 0-3123456/3123457).

我试图做的是实现一个伪流在客户端方式:

What I tried to do is to implement a pseudo-streaming at client side by:

  1. 打开输入流的MP3。
  2. 在德$ C C使用JLayer传入字节$。我发现在此链接。
  3. 发送去codeD字节数组到一个已经playeable stream_mode AudioTrack。

可以是一张code,做解码发现那里,我只修改了它,所以它会得到一个InputStream:

The piece of code that does the decoding can be found there, I have only modified it so it will receive an 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);
        }
    }

我要求的时间块去codeD字节:从(0,5000),所以我将有一个更大的阵列,在第一个上场,那么我请求跨越第二的下一个字节数组: (5000,1000),(6000,1000),(7000,1000)等。

I am requesting the decoded bytes in time chunks: starting with (0, 5000) so I will have a bigger array to play at first, then I am requesting the next byte arrays that span over a second: (5000, 1000), (6000, 1000), (7000, 1000), etc.

解码速度足够快,而在另一个线程,一旦脱codeD字节数组,可我使用的是阻塞队列,将其写入到正在播放的另一个线程的AudioTrack完成。

The decoding is fast enough and is done in another thread and once a decoded byte array is available I am using a blocking queue to write it to the AudioTrack that is playing in another thread.

的问题是,在播放不光滑的块不是在一个连续的轨道(每个块是连续的,但加入在AudioTrack导致马虎播放)。

The problem is that the playback is not smooth as the chunks are not continuous in a track (each chunk is continuous, but added in the AudioTrack results in a sloppy playback).

要包:

  1. 如果您碰到这种软糖问题,你是怎么解决的呢?
  2. 如果你们中的任何尝试过我的方法,我在上面code做错了什么?如果这是您使用的解决方案,我可以发布的code中的其余部分。

谢谢!

推荐答案

您好像正在试图开发自己的流媒体类型。这可以得到块状或中断播放,因为你必须尝试持续的信息管道瓦特/用完的字节进行读取。

It looks like you are trying to develop your own streaming type. This can get blocky or interrupted playback because you have to attempt continuous information piping w/out running out of bytes to read from.

基本上,你将不得不考虑所有正常的流媒体客户端需要照顾的情况。例如,有时某些块可能被丢弃或丢失在传输;有时音频播放可能赶上下载; CPU开始滞后,影响播放;等等等等。

Basically, you will have to account for all the situations that a normal streaming client takes care of. For instance, sometimes some blocks may be dropped or lost in transmission; sometimes the audio playback may catch up to the download; the cpu starts lagging which affects playback; etc. etc.

东西来研究,如果你想继续沿着这条道路将是滑动窗口的实现,它本质上是一个抽象的技术,以尽量保持网络的连通性始终处于活动状态和流体。您应该能够找到通过谷歌几个例子,这里是一个开始的地方: HTTP://en.wikipedia .ORG /维基/ Sliding_window_protocol

Something to research if you want to continue down this path would be Sliding Window implementation, it is essentially an abstract technique to try to keep the network connectivity always active and fluid. You should be able to find several examples through google, here is a place to start: http://en.wikipedia.org/wiki/Sliding_window_protocol

编辑:一种解决方法,可以帮助你,直到这个是固定的将是包括源$ C ​​$下 MediaPlayer.java AudioManager的.java 从SDK&LT; 16到您的项目,看看是否能解决问题。如果你没有源$ C ​​$ C,你可以用SDK管理器进行下载。

One workaround that may help you until this is fixed would be to include the source code for MediaPlayer.java and AudioManager.java from SDK <16 into your project and see if that resolves the problem. If you do not have the source code you can download it with the SDK Manager.

这篇关于Android的软糖网络媒体的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆