Почему для MediaPlayer для Android требуется много времени для подготовки некоторых живых потоков для воспроизведения?


Answers

Переключение MediaPlayer помощью FFmpegMediaPlayer работает намного лучше, чем MediaPlayer если вы хотите протестировать свои потоки, вы можете сделать это через demo которое у них есть.

Question

Я нахожу большие различия во времени, которое требуется для Android MediaPlayer для подготовки к воспроизведению в прямом эфире с различными потоками.

Жесткие данные

Я добавил регистрацию между prepareAsync () и обратным вызовом onPrepared (MediaPlayer mp) и протестировал несколько потоков несколько раз каждый. Время для каждого потока было очень последовательным (+/- одна секунда), и вот результаты:

  1. Поток новостей MPR: 27 секунд (http://newsstream1.publicradio.org:80/)
  2. MPR классический музыкальный поток: 15 секунд (http://classicalstream1.publicradio.org:80/)
  3. MPR Текущий поток: 7 секунд (http://currentstream1.publicradio.org:80/)
  4. PRI поток: 52 секунды (http://pri-ice.streamguys.biz/pri1)

Тесты были выполнены на Nexus S с Android 2.3.4 на 3G-соединении (~ 1100 Кбит / с).

Воспроизведение безпоточных аудиофайлов MP3 не является проблемой.

Вот фрагменты того, как я играю в потоки:

Подготовьте MediaPlayer:

...
mediaPlayer.setDataSource(playUrl);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.prepareAsync();
...

Затем в onPrepared (MediaPlayer mp):

mediaPlayer.start();

Почему так долго нужно готовить потоки, но не другие? Вышеприведенные данные, по-видимому, предполагают, что это может быть основано на количестве данных, которые были буферизованы, а не на продолжительности буферизованного аудиоконтента. Неужели это действительно так?

Обновление. Я тестировал прямую трансляцию на физических устройствах с Android 1.6, 2.2 и 2.3.4 и эмуляторы с 1.6, 2.1, 2.2, 2.3.1 и 2.3.3. Я вижу только длительную задержку на 2.3.3 и 2.3.4. Старшие версии начинают воспроизведение в течение 5 секунд.




Если вы переходите из Icecast, посмотрите на параметр burst-size :

Размер пакета - это объем данных (в байтах) для взлома клиенту во время соединения. Подобно пакетному подключению, это быстрое заполнение предварительного буфера, используемого медиаплеерами. По умолчанию используется 64 кбайта, что является типичным размером, используемым большинством клиентов, поэтому его изменение обычно не требуется. Этот параметр применяется ко всем точкам монтирования, если они не переопределены в настройках монтирования. Убедитесь, что это значение меньше размера очереди, при необходимости увеличьте размер очереди, который будет больше, чем требуемый размер пакета. Несоблюдение этого требования может привести к попыткам прерывания подключения клиента-слушателя из-за первоначального пакета, ведущего к соединению, уже превышающему ограничение размера очереди.

Я увеличил burst-size до 131072 на моем сервере, и теперь мое приложение для Android на основе MediaPlayer воспроизводит потоки без особых задержек.




Когда у меня возникла эта проблема, я решил проверить, доступен ли поток, прежде чем открывать плеер. Если вы заставите пользователя долго ждать, и музыка начнет его нормально (это не так, но, допустим, все в порядке). Худший сценарий - заставить его долго ждать, и музыка никогда не начнется! Итак, у нас есть две ситуации:

  • Сценарий в прямом эфире, как и радиостанция.
  • Записанный mp3-файл, который доступен онлайн.

В сценарии радиосвязи мы можем проверить, принимает ли порт соединения (состояние «открыть / закрыть»). Если он открыт, подготовьте плеер к музыке, иначе не подготовьте его вообще.

public static boolean isLiveStreamingAvailable() {
        SocketAddress sockaddr = new InetSocketAddress(STREAMING_HOST, STREAMING_PORT);
        // Create your socket
        Socket socket = new Socket();
        boolean online = true;
        // Connect with 10 s timeout
        try {
            socket.connect(sockaddr, 10000);
        } catch (SocketTimeoutException stex) {
            // treating timeout errors separately from other io exceptions
            // may make sense
            return false;
        } catch (IOException iOException) {
            return false;
        } finally {
            // As the close() operation can also throw an IOException
            // it must caught here
            try {
                socket.close();
            } catch (IOException ex) {
                // feel free to do something moderately useful here, eg log the event
            }

        }
        return true;
    }

В сценарии mp3-файлов все немного отличается. Вы должны проверить код ответа, который следует после HTTP-запроса.

public static boolean isRecordedStreamingAvailable() {
        try {
            HttpURLConnection.setFollowRedirects(false);
            // note : you may also need
            //        HttpURLConnection.setInstanceFollowRedirects(false)
            HttpURLConnection con =
                    (HttpURLConnection) new URL(RECORDED_URL).openConnection();
            con.setRequestMethod("HEAD");
            return (con.getResponseCode() == HttpURLConnection.HTTP_OK);
        }
        catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }



Links