Problem z mediami sieciowymi Android JellyBean

Mam aplikację, która odtwarza pliki MP3 dostępne pod publicznym adresem URL. Niestety serwer nie obsługuje przesyłania strumieniowego, ale Android sprawia, że ​​korzystanie z niego jest całkiem akceptowalne.

Wszystko działa dobrze dla wszystkich platform z wyjątkiem JellyBean. Podczas żądania MP3 JB żąda 10-krotnego zasięgu. Dopiero po dziesiątej próbie wydaje się, że powraca do starego zachowania.Wygląda na to, że ten już zgłoszony problem.

Znalazłem innySO wątek gdzie zalecanym rozwiązaniem jest użycieTranfer-Encoding: chunked nagłówek. Ale tuż poniżej jest komentarz, że to nie działa.

Na razie nie mam żadnej kontroli nad dostarczaniem nagłówków odpowiedzi, ale dopóki nie będę w stanie tego zrobić, pomyślałem, że będę szukał alternatywy po stronie klienta. (mimo to mogę zwrócić tylko zakres zawartości, który zawiera indeksy od 0 do długości treści - 1. Przykładowy zakres zawartości: bajty 0-3123456 / 3123457).

To, co próbowałem zrobić, to zaimplementować pseudo-streaming po stronie klienta:

Otwórz strumień wejściowy do MP3.Dekoduj przychodzące bajty za pomocą JLayer. Znalazłem dekodowanie naten link.Wyślij zdekodowane bajty tablicowe do już odtwarzalnego stream_mode AudioTrack.

Fragment kodu, który zawiera dekodowanie, został zmodyfikowany, więc otrzyma strumień wejściowy:

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

Żądam zdekodowanych bajtów w kawałkach czasu: począwszy od (0, 5000), więc najpierw będę miał większą tablicę do gry, a następnie żądam następnych tablic bajtów, które rozciągają się na sekundę: (5000, 1000), ( 6000, 1000), (7000, 1000) itd.

Dekodowanie jest wystarczająco szybkie i odbywa się w innym wątku, a gdy dostępna jest dekodowana tablica bajtów, używam kolejki blokującej, aby zapisać ją w AudioTrack, który gra w innym wątku.

Problem polega na tym, że odtwarzanie nie jest płynne, ponieważ kawałki nie są ciągłe na ścieżce (każdy fragment jest ciągły, ale dodany w ścieżce AudioTrack powoduje niechlujne odtwarzanie).

Zapakować:

Jeśli natknąłeś się na ten problem JellyBean, jak go rozwiązałeś?Jeśli któryś z was próbował mojego podejścia, co robię źle w powyższym kodzie? Jeśli jest to rozwiązanie, którego użyłeś, mogę opublikować resztę kodu.

Dzięki!

questionAnswers(2)

yourAnswerToTheQuestion