iFrolov
@iFrolov

Как работать с libavformat, не сваливаясь в большие задержки?

Задача у меня простая: написать простой аудиоплеер с поддержкой http и rtmp. Главное — минимальные задержки и работа с низкими битрейтами. Для таких вещей неплохо подходит набор «все в одном», а именно libav*, где работать с медиаданными достаточно просто. У меня однако возникли проблемы:

1. Отсутствие поддержки протокола ICY, поэтому просто ffurl_open() не вызвать. Не проблема, есть libcurl и далее можно руками разобрать.

2. Парсинг FLV-потока (а именно он внутри RTMP) идет после загрузки приличного куска данных (max_analyze_duration тут не поможет). Для низкобитрейтных потоков 64кб — это слишком много.


На данный момент пытаюсь получать данные руками (libcurl/librtmp) и скармливать данные через AVIOContext:
AVIOContext *io=avio_alloc_context(buffer, BUFFER_SIZE, 0, NULL, my_byte_reader_callback, NULL, NULL);
context=avformat_alloc_context();
context->pb=io;
...
while(1){
av_read_frame...
}


И вот тут у меня большая проблема: коллбек чтения вызывается со слишком большими размерами буфера. Зачастую идут запросы на пакеты по 4мб (в случае низких битрейтов это может быть целый час аудиопотока). Решил поиграть с отдаваемыми значениями (ведь не обязательно заполнять весь буфер сразу), получил примерно такое:

Отдавал буфер по 1280 байт, не болееgot request for 2816 bytes, sent 1280

got packet size 105

got packet size 108

got packet size 93

got packet size 106

got packet size 101

got packet size 106

got packet size 106

got packet size 107

got packet size 100

got packet size 101

got packet size 100

got request for 1536 bytes, sent 1280

got packet size 101

got packet size 101

got packet size 105

got packet size 99

got packet size 109

got packet size 105

got packet size 100

got packet size 107

got packet size 103

got packet size 99

got request for 256 bytes, sent 256

got packet size 100

got packet size 103

got packet size 99

got request for 4096 bytes, sent 1280

got packet size 105

got request for 7339101 bytes, sent 1280

got request for 7337821 bytes, sent 1280

got request for 7336541 bytes, sent 1280

got request for 7335261 bytes, sent 1280

got request for 7333981 bytes, sent 1280



Сначала все работает отлично, потом оно срывается и запрашивает большие куски. Поток само собой валидный, без скачков.

Отдавал буфер по 128 байтgot request for 4096 bytes, sent 128

got request for 3968 bytes, sent 128

got packet size 104

got request for 3840 bytes, sent 128

got request for 6711586 bytes, sent 128

got request for 6711458 bytes, sent 128

got request for 6711330 bytes, sent 128

got request for 6711202 bytes, sent 128

got request for 6711074 bytes, sent 128

got request for 6710946 bytes, sent 128

got request for 6710818 bytes, sent 128

got request for 6710690 bytes, sent 128

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


Зависаю на простой задаче уже третью неделю, есть идеи?
  • Вопрос задан
  • 2910 просмотров
Пригласить эксперта
Ответы на вопрос 3
@egorinsk
Видимо, стоит банально заглянуть в исходники и посмотреть, из чего и почему формируется такой размер буфера. Опен сурс же.
Ответ написан
@motl
а зачем возвращать все 4 мегабайта из коллбэка? Возвращайтe столько, сколько есть, и потом коллбэк вызовется еще нужное количество раз.
Ответ написан
Комментировать
@xaoc80
А почему вы не используете avformat_open_input, etc?
Ведь ей можно скормить любую ссылку, которую понимает ffmpeg
Или все упирается в ICY?
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы