Наши партнеры

UnixForum





Библиотека сайта rus-linux.net

Фреймворк GStreamer. Руководство разработчика приложений. Буферизация

Оригинал: GStreamer Application Development Manual
Авторы: Wim Taymans, Steve Baker, Andy Wingo, Ronald S. Bultje, Stefan Kost
Дата публикации: 21 мая 2014 г.
Перевод: А.Панин
Дата перевода: 20 июня 2014 г.

Глава 15. Буферизация

Целью процесса буферизации является накопление в конвейере достаточного количества данных для того, чтобы проигрывание осуществлялось плавно без прерываний. Обычно эта операция осуществляется при получении данных из (медленного) источника данных, не являющегося источником реального времени, но она также может выполняться при работе с источниками данных реального времени.

Фреймворк GStreamer поддерживает следующие варианты буферизации:
  • Буферизация определенного объема данных в памяти перед началом проигрывания потока для минимизации негативного воздействия флуктуаций скорости сетевого соединения. Обратитесь к разделу "Буферизация потока" для ознакомления с подробностями.
  • Закачка файла посредством сетевого соединения на локальный диск для осуществления быстрого перехода к заданным позициям в загруженных данных потока. Этот подход аналогичен подходу, используемому в мультимедийных проигрывателях quicktime/youtube. Обратитесь к разделу "Буферизация посредством загрузки файла" для ознакомления с подробностями.
  • Кэширование потоков из источника данных, по некоторым параметрам являющегося источником реального времени, с использованием расположенного на диске локального кольцевого буфера для получения возможности перехода к заданной позиции в кэшированном потоке. Этот подход аналогичен реализации механизма сдвига по времени, используемой в продуктах компании tivo. Обратитесь к разделу "Буферизация для сдвига по времени" для ознакомления с подробностями.

Фреймворк GStreamer может передавать приложению отчеты с данными о текущем состоянии буфера, а также позволяет приложению самостоятельно принимать решения о том, как осуществлять буферизацию потока данных и когда процесс буферизации должен прерываться.

В самом простом случае приложение должно отслеживать сообщения BUFFERING, передаваемое с помощью шины сообщений. В том случае, если индикатор степени завершения процесса буферизации в процентах из сообщении BUFFERING имеет значения, меньшие 100, конвейер осуществляет буферизацию потока. В момент, когда принимается сообщение, содержащее значение 100 процентов, процесс буферизации завершается. В ходе процесса буферизации приложение должно поддерживать конвейер в состоянии "пауза" (PAUSED). После завершения процесса буферизации оно может перевести конвейер (назад) в состояние "проигрывается" (PLAYNIG).

Ниже приведен пример реализации обработчика для сообщений BUFFERING. Мы познакомимся с более сложными методами обработки данных сообщений в разделе под названием "Стратегии буферизации".

15.1. Буферизация потока

      +---------+     +---------+     +-------+
      | httpsrc |     | buffer  |     | demux |
      |       вых. - вход.    вых. - вход.     ....
      +---------+     +---------+     +-------+

В данном случае мы принимаем данные из медленного сетевого источника и помещаем их в элемент буфера (такой, как queue2).

Элемент буфера имеет нижнее и верхнее ограничения объема данных, заданные в байтах. Буфер использует ограничения следующим образом:
  • Элемент буфера будет отправлять сообщения BUFFERING до того момента, когда будет достигнуто верхнее ограничение объема данных. Эти сообщения уведомляют приложение о необходимости удержания конвейера в состоянии "пауза" (PAUSED), в котором в конце концов произойдет блокировка операций передачи данных посредством входных точек соединения с одновременной остановкой обработки данных элементами для вывода данных.
  • В момент, когда верхнее ограничение объема данных будет достигнуто, будет отправлено сообщение BUFFERING с значением 100%, которое уведомит приложение о том, что можно продолжать воспроизведение.
  • В момент, когда в процессе воспроизведения достигается нижнее ограничение объема данных, элемент буфера снова начнет отправлять сообщения BUFFERING, все также принуждая приложение к переводу конвейера в состояние "пауза" (PAUSED) до того момента, когда снова будет достигнуто верхнее ограничение объема данных. Этот этап называется повторным заполнением буфера.
  • В процессе проигрывания уровень заполнения буфера будет изменяться от верхнего до нижнего ограничения объема данных для компенсации изменений пропускной способности сетевого соединения.

Данный метод буферизации может использоваться тогда, когда демультиплексор работает в режиме заполнения. При этом перемещение в мультимедийном потоке требует осуществления операции перемещения на уровне сетевого источника данных. Использование этого метода крайне желательно в тех случаях, когда общая продолжительность мультимедийного потока неизвестна, например, при передаче потока в реальном времени или тогда, когда быстрое перемещение в потоке невозможно или не требуется.

Проблемой в данном случае является установка оптимальных значений верхнего и нижнего ограничения объема данных. Ниже приведено несколько соображений:
  • Существует возможность измерения пропускной способности сети, а также настройки нижнего и верхнего ограничения объема данных на основе этого измерения для того, чтобы буферизация занимала фиксированный промежуток времени.
    Элемент queue2 из набора основных элементов фреймворка GStreamer имеет параметр max-size-time, который совместно с параметром use-rate-estimate позволяет решить именно эту задачу. Также параметр buffer-duration элемента playbin использует оценку пропускной способности сети для установки объема данных для буферизации.
  • На основе значения скорости мультимедийного потока, полученного от кодека, также можно установить ограничения таким образом, что фиксированный объем данных будет помещаться в буфер до начала проигрывания потока. В нормальных условиях элемент буфера не обладает информацией о скорости мультимедийного потока, но он может получить эту информацию с помощью запроса.
  • Можно начинать проигрывание мультимедийного потока, используя буфер для фиксированного объема данных, после чего измерять время между повторными заполнениями буфера и увеличивать размер буфера до того момента, когда время между повторными заполнениями буфера будет укладываться в ограничения, заданные на уровне приложения.

Элемент буферизации может быть вставлен в любую часть конвейера. Вы можете, например, вставить элемент буферизации перед декодером. Это сделает возможным установку верхнего и нижнего ограничений объема данных на основе времени.

Флаг буферизации элемента playbin позволяет выполнять буферизацию разобранных данных. Другим преимуществом выполнения буферизации на позднем этапе является возможность перевода демультиплексора в режим заполнения. При приеме данных из медленного сетевого хранилища (с помощью элемента filesrc) этот способ буферизации может быть достаточно полезным.

15.2. Буферизация посредством загрузки файла

      +---------+     +---------+     +-------+
      | httpsrc |     | buffer  |     | demux |
      |       вых. - вход.    вых. - вход.    ....
      +---------+     +----|----+     +-------+
                           V
                          файл

В том случае, если известно, что сервер передает клиенту по сети файл фиксированного размера, приложение может скачать весь файл и сохранить его на диске. Элемент буфера позволит элементу демультиплексора получать данные или перемещаться по скачанному файлу с использованием своей выходной точки соединения.

Этот режим работы может использоваться только тогда, когда клиент может точно определить размер файла на сервере.

В данном случае сообщения буферизации будут как обычно генерироваться тогда, когда запрашиваемый диапазон данных не находится в рамках диапазона загруженных данных, расширенном на значение размера буфера. Сообщение буферизации также будет содержать указание на то, что выполняется дополнительная загрузка данных. Этот флаг может использоваться для того, чтобы позволить приложению контролировать процесс буферизацию более сложным способом, например, с использованием запроса BUFFERING. Обратитесь к разделу "Стратегии буферизации" для получения дополнительной информации.

15.3. Буферизация для сдвига по времени

      +---------+     +---------+     +-------+
      | httpsrc |     | buffer  |     | demux |
      |       вых. - вход.    вых. - вход.    ....
      +---------+     +----|----+     +-------+
                           V
                кольцевой буфер в файле

В данном режиме кольцевой буфер фиксированного размера используется для загрузки данных с сервера. Такое решение позволяет осуществлять перемещения в буферизированных данных потока. В зависимости от размера кольцевого буфера, приложение сможет осуществлять сдвиг по времени на определенный период в прошлое.

Этот режим работы подходит для всех мультимедийных потоков из источников данных реального времени. Как и в режиме дополнительной загрузки, сообщения буферизации генерируются вместе с указанием на то, что осуществляется загрузка данных, которые могут использоваться для сдвига по времени.

15.4. Буферизация при работе с конвейерами реального времени

В конвейерах реального времени обычно появляется некоторая фиксированная задержка между элементами захвата и вывода данных. Эта задержка может быть внесена элементом буфера (таким, как jitterbuffer) или другими элементами (например, элементом вывода аудиоданных).

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

15.4. Стратегии буферизации

Ниже описаны некоторые идеи относительно реализации различных стратегий буферизации на основе сообщений и запросов буферизации.

15.4.1. Стратегия без использования повторной буферизации

Нам хотелось бы средствами конвейера сохранить в буфере достаточный объем данных для того, чтобы проигрывание мультимедийного потока продолжилось без прерываний. Чтобы реализовать такой механизм буферизации нам необходимо знать все оставшееся время проигрывания потока из файла, а также все оставшееся время его загрузки. В том случае, если время буферизации меньше времени проигрывания, мы можем начать проигрывание без прерываний.

Вся эта информация станет доступной для нас после выполнения запросов DURATION, POSITION и BUFFERING. Мы должны периодически выполнять запрос состояния буферизации (BUFFERING) для получения данных о текущем состоянии процесса буферизации. Нам также нужен буфер достаточного размера для сохранения всего файла, который может быть полностью занят в самом худшем случае. Данная стратегия лучшим образом сочетается с методикой буферизации посредством загрузки файла (обратитесь к разделу "Буферизация посредством загрузки файла").

Код, реализующий описанную стратегию, будет выглядеть следующим образом:

Обратите внимание на то, что мы в первую очередь переводим конвейер в состояние "пауза" (PAUSED). Мы будем принимать сообщения буферизации в процессе подготовки к воспроизведению в случае необходимости буферизации. После завершения подготовки конвейера (on_message_async_done) мы проверяем, выполняется ли буферизация, а в том случае, если она не выполняется, мы начинаем проигрывать поток. В том случае, если буферизация выполняется мы устанавливаем таймер для получения данных о состоянии процесса буферизации. Если примерное время загрузки файла меньше оставшегося времени проигрывания, мы начинаем проигрывание.


Следующий раздел : Динамически изменяемые значения параметров объектов.