Может сталкивался кто с сабжем? Нормальных док по теме не нашел, а примеры по большей части для программы, а не для либы.
Из примера выдрал код и он, в принципе, работает, но возникли вопросы:
1. Сжатое видео потом открывает только один плеер из 3 (ну и сама либа). Есть подозрение, что это связано с варнингом "not enough frames to estimate rate; consider increasing probesize". Но где искать этот probesize и что это такое - неясно. Все найденные примеры только для консольного ffmpeg, для либы не нашел. Параметра похожего в хедерах тоже не заметил.
2. Непонятная ошибка "Invalid NAL unit 8, skipping". Вроде не на что не влияет, но непорядок...
3. Как задавать компрессию видео? В AVCodecContext есть параметр bit_rate, но он, похоже, влияет только на отображаемое в свойствах файла значение. Реально же никакого эффекта не имеет. При этом у каждого кадра есть странный параметр pts, изменение которого как раз влияет на размер. Но что он из себя представляет и как считается неясно. Во многих примерах (в т.ч. из комплекта либы) он тупо инкрементится на 1 для каждого кадра, что даёт просто адовую компрессию с соответствующим результатом. Остальные считают по непонятным формулам из констант и номера кадра, что тоже мало информативно.
Grobozavr
> Сжатое видео потом открывает только один плеер из 3 (ну и сама либа)
Потому что оно не "сжатое" а перекодированное.
> это связано с варнингом "not enough frames to estimate rate; consider
> increasing probesize
Кадров для указанного битрейта не хватает.
> параметр pts, изменение которого как раз влияет на размер. Но что он из себя
> представляет и как считается неясно.
pts - presentation time stamp
dts - decoding time stamp
Вот:
Только больше вопросов стало.
>Потому что оно не "сжатое" а перекодированное.
А в чём в данном случае разница? Тут это один процесс, в котором оно при кодировании и жмётся ещё.
>Кадров для указанного битрейта не хватает.
Каких кадров? Как исправить? В поиске в этот probesize явно не кадры пишут. Вроде это что-то типа предвыбрки или как-то так. Ну и куда его всё-таки писать. И почему вообще этот параметр хранится в видео, а не определяется плеером самостоятельно?
>pts - presentation time stamp
>dts - decoding time stamp
Вот это немного прояснило, спасибо.
Но не надолго. Для декодирования понятно, а для кодирования? Энкодер требует туда монотонную последовательность и от шага этой последовательности зависит коэф. сжатия видео (проверено).
При шаге в 1 (как в примерах) получается примерно как жпег с качеством пару процентов и размер файла в пару пару десятков килобайт (оригинал 30М). Кстати в этом случае первой ошибки не выдаётся, но посмотреть всё равно получается только ffmpeg
Нашел вот такую формулу:
Calculate PTS: (1 / FPS) * sample rate * frame number
Теперь вопрос - как считать sample rate...
Grobozavr
Так ведь sample rate это аудио, а видео это frame rate.
Я так понимаю что цель - перекодирование а значит нужно взять поток от одного кодека (декодера)
и передать в другой(декодер) так?
TheLightWay
Учитывая, что это передаётся в параметрах кадра - очень вряд-ли.
http://thompsonng.blogspot.ru/2011/09/ffmpeg-avinterleavedwritefr… e-return.html
Тут нашел. Но непонятно, откуда он берёт его. Framerate тут уже учитывается через fps как я понимаю. Короче - загадочная хрень...
Перекодировать я мог бы и консольной командой, для этого всё это городить не обязательно. У меня в общем случае генерируется новое.
Из доков.
>Presentation timestamp in time_base units (time when frame should be shown to user).
Однако непонятно, что за юниты такие и почему это влияет на размер файла.
Пишут, что 90000 - константа для mpeg т.е. pts = frame_cnt*90000/fps
Но как изменится для других кодеков и как она всё-таки влияет на компрессию - хз.
И почему не влияет никак битрейт.
Grobozavr
> time_base units
> что за юниты такие
Это по сути 1/FPS - то есть при 30 кадрах
time_base = 1 / 30000
И все это еще и замешано на p(rogressive)/i(nterleaved).
Grobozavr
> Может сталкивался кто с сабжем?
Регулярно.
> not enough frames to estimate rate; consider increasing probesize
Это откуда сообщение? Оно может выдаваться только из demuxera, а ты как я понимаю, сжимаешь.
> Но где искать этот probesize
probesize это обычно опция demuxera, не нужна она тебе.
> Как задавать компрессию видео?
Смотря какой ffmpeg. Если из свежих, то качество задается через опции кодека при открытии.
> При этом у каждого кадра есть странный параметр pts
Есть time_base кодека - это расстояние между кадрами по времени, как его рассматривает кодек. Расстояние между кадрами для кодека - постоянная величина (обычно 1). То есть если у тебя 25 кадров в секунду, то time_base будет равно {1, 25}. И AVFrame::pts ты должен инкрементировать ровно на 1.
Есть time_base стрима (AVStream) - это расстояние между фреймами в контейнере. AVStream::time_base в нормальных контейнерах значительно меньше (например, {1, 90000}). Когда к тебе приходит сжатый пакет после encode, его pts/dts еще измеряются в AVCodecContext::time_base и тебе нужно перевести их в единицы AVStream::time_base. Делается при помощи функции av_rescale_q.
Короче, рассказывай по порядку, что сжимаешь и какая вообще стоит задача. А то тебе тут насоветуют.
Начать лучше с того, какая у тебя версия ffmpeg и где ты ее взял.
>И все это еще и замешано на p(rogressive)/i(nterleaved).
А тут то что? Ему пофиг должно быть, полный кадр или полукадр показывать. Но это пофиг, i вроде сейчас особо не используется уже.
Как это связано с компрессией?
Ну и забытый вопрос - как заставить проигрываться видео в плеере?
>Это откуда сообщение? Оно может выдаваться только из demuxera, а ты как я понимаю, сжимаешь.
Это выдаёт ffmpeg при декодировании.
>Смотря какой ffmpeg. Если из свежих, то качество задается через опции кодека при открытии.
Качал последний... А поподробнее можно? Я только bit_rate нашел, от которого эффекта нет. Есть ещё какие-то настройки b и p кадров, но я пока туда не лез, брал из примера. В видео я мало что понимаю.
>Есть time_base кодека - это расстояние между кадрами по времени, как его рассматривает кодек. Расстояние между кадрами для кодека - постоянная величина (обычно 1). То есть если у тебя 25 кадров в секунду, то time_base будет равно {1, 25}. И AVFrame::pts ты должен инкрементировать ровно на 1.
Да, он. Но с ним как раз вот эта эпопея. Его значение у меня почему-то влияет на сжатие :(
В том плеере, который всё-таки согласился проигрывать видео скорость была вполне похожая на оригинал. (при расчёте по формуле выше)
Версия от 2 янв, качал не помню уже откуда. То ли с офиц сайт, то ли с гита.
Задача - программа генерит видео (иногда из другого видео, иногда сама по себе) и надо его сохранить в заданном качестве. Иногда для обработки в высоком, иногда как конечное - в компактном.
Grobozavr
> Это выдаёт ffmpeg при декодировании.
Так, это уже интереснее. probesize по умолчанию 5 МБ. Я сильно сомневаюсь, что ему их не хватает.
После вызова какой функции он это пишет?
> Его значение у меня почему-то влияет на сжатие
Видимо, через pts ты неявно изменяешь расстояние между ключевыми кадрами.
> Качал последний
Если последний, то в функцию avcodec_open2 последним параметром попадают некие опции. Так вот с их помощью можно менять много чего в кодеке. В том числе качество, интервал между ключевыми кадрами и time_base, т.к. стандартного способа это сделать не существует с момента изобретения AVCodecParameters. Делается примерно так:
AVDictionary* opt = 0; av_dict_set(&opt, "qmin", 1, 0); av_dict_set(&opt, "qmax", quality, 0); av_dict_set(&opt, "time_base", 1.0 / fps); int res = avcodec_open2(context, encoder, &opt);
Описалово опций можно найти тут: https://ffmpeg.org/ffmpeg-codecs.html
>После вызова какой функции он это пишет?
avformat_find_stream_info
>Видимо, через pts ты неявно изменяешь расстояние между ключевыми кадрами.
Было такое подозрение. Однако (как писал выше) если задавать его инкремент в 1 - то он 30Мб (960*540) видео ужимает в 15кб, с соотв качеством. Однако тут даже один кадр больше по размеру. Ну и первый кадр видео (на сколько я понял именно его показывает плеер при открытии) так же сильно пожат при любых настройках, Похоже там даже для первого кадра надо ставить большое значение.
>Описалово опций можно найти тут: https://ffmpeg.org/ffmpeg-codecs.html
Спасибо, поиграюсь. Правда больше методом тыка, т.к. о кодировании видео представления имею весьма общие. А там ещё описаний нет, только названия. И (судя по их количеству) это на долго.
Grobozavr
> Похоже там даже для первого кадра надо ставить большое значение
Да не влияет никак pts на качество. А bitrate в кодеке вообще не трогай, ставь 0.
Если перекодируешь, крути qmin/qmax.
> А там ещё описаний нет, только названия
Под каждой опцией есть описание.
qmin integer (encoding,video)
Set min video quantizer scale (VBR). Must be included between -1 and 69, default value is 2.
qmax integer (encoding,video)
Set max video quantizer scale (VBR). Must be included between -1 and 1024, default value is 31.
qdiff integer (encoding,video)
Set max difference between the quantizer scale (VBR).
Тема в архиве.