Chromium ffmpeg codecs что это

Обновлено: 04.07.2024

FFmpeg — это грандиозный Open Source проект, своего рода мультимедийная энциклопедия. С помощью FFmpeg можно решить огромное число задач компьютерного мультимедиа. Но все-таки иногда возникает необходимость в расширении FFmpeg. Стандартный способ — это внесение изменений в код проекта с последующей компиляцией новой версии. В статье подробно рассмотрено, как добавить новый кодек. Также рассмотрены некоторые возможности для подключения к FFmpeg внешних функций. Если нет необходимости добавлять кодек, то статья может оказаться полезной для лучшего понимания архитектуры кодеков FFmpeg и их настройки. Предполагается, что читатель знаком с архитектурой FFmpeg, процессом компиляции FFmpeg, а также имеет опыт программирования с использованием FFmpeg API. Описание актуально для FFmpeg 4.2 «Ada», август 2019.

Кодек (codec, происходит от объединения терминов COder и DECoder) является весьма распространенным термином и, как в таких случаях часто бывает, его значение несколько меняется в зависимости от контекста. Основное значение — это программное или аппаратное средство для сжатия/разжатия (compression/decompression) медиаданных. Вместо терминов сжатие/разжатие часто используют термины кодирование/декодирование (encoding/decoding). Но в ряде случаев под кодеком понимают скорее просто формат сжатия (говорят еще формат кодека), безотносительно к средствам, используемым для сжатия/разжатия. Посмотрим как термин кодек используется в FFmpeg.

FFmpeg кодеки собраны в библиотеке libavcodec.

1.1. Идентификатор кодека

В файле libavcodec/avcodec.h определено перечисление enum AVCodecID . Каждый элемент этого перечисления как раз и идентифицирует формат сжатия. Элементы этого перечисления должны иметь вид AV_CODEC_ID_XXX , где XXX уникальное имя идентификатора кодека в верхнем регистре. Вот примеры идентификаторов кодека: AV_CODEC_ID_H264 , AV_CODEC_ID_AAC . Для более подробного описания идентификатора кодека служит структура AVCodecDescriptor (объявлена в libavcodec/avcodec.h , приводится в сокращенном виде):

Ключевым членом этой структуры является id , остальные члены как раз и дают дополнительную информацию об идентификаторе кодека. Каждый идентификатор кодека однозначно связан с типом медиаданных (член type ) и имеет уникальное имя (член name ), записанное в нижнем регистре. В файле libavcodec/codec_desc.c определен массив типа AVCodecDescriptor . Для каждого идентификатора кодека имеется соответствующий элемент массива. Элементы этого массива должны быть упорядочены по значениям id , так как для поиска элементов используется двоичный поиск. Для получения информации об идентификаторе кодека можно использовать функции:

1.2. Кодек

Собственно кодек — набор средств, необходимых для выполнения кодирования/декодирования медиаданных, объединяет структура AVCodec (объявлена в libavcodec/avcodec.h ). Вот ее сокращенная версия, более полная будет рассматриваться ниже.

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

ffmpeg -codecs >codecs.txt

После выполнения команды, файл codecs.txt будет содержать этот список. Каждый идентификатор кодека будет представлен отдельной записью (строкой). Вот, например, запись для идентификатора кодека AV_CODEC_ID_H264 :

DEV.LS
h264
H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10
(decoders: h264 h264_qsv h264_cuvid)
(encoders: libx264 libx264rgb h264_amf h264_nvenc h264_qsv nvenc nvenc_h264)

Процедуру добавления нового кодека в FFmpeg рассмотрим на примере аудиокодека, который назовем FROX .

Шаг 1. Добавить новый элемент в перечисление enum AVCodecID .

Это перечисление находится в файле libavcodec/avcodec.h . При добавлении надо соблюдать правила:

  1. Значение элемента не должно совпадать со значениями существующих элементов перечисления;
  2. Не менять значения существующих элементов перечисления;
  3. Размещать новое значение в группе сходных кодеков.

В соответствии с шаблоном, идентификатор этого элемента должен быть AV_CODEC_ID_FROX . Разместим его перед AV_CODEC_ID_PCM_S64LE и дадим значение 0x10700 .

Шаг 2. Добавить элемент в массив codec_descriptors (файл libavcodec/codec_desc.c ).

Добавить элемент надо в «правильное» место, не должна нарушаться монотонность элементов массива по значению id .

Шаг 3. Определить экземпляры AVCodec отдельно для кодера и декодера.

Для этого предварительно надо определить структуру для контекста кодека и несколько функций, которые и будут выполнять фактическое кодирование/декодирование и некоторые другие необходимые операции. В данном разделе эти определения будут сделаны предельно схематично, более детальное описание будет сделано дальше. Код разместим в файле libavcodec/frox.c .

Для простоты в этом примере кодер и декодер имеют один и тот же один контекст — FroxContext , но чаще всего кодер и декодер имеют разные контексты. Также обратим внимание на то, что имена экземпляров AVCodec должны следовать специальному шаблону.

Шаг 4. Добавить экземпляры AVCodec в список регистрации.

Переходим в файл libavcodec/allcodecs.c . В начале этого файла находятся список объявлений всех регистрируемых кодеков. Добавляем в этот список наши кодеки:

В процессе выполнения скрипт configure находит все такие объявления и генерирует файл libavcodec/codec_list.c , который содержит массив указателей на кодеки, объявленные в libavcodec/allcodecs.c . После выполнения скрипта в файле libavcodec/codec_list.c мы увидим:

Также в процессе выполнения скрипт configure генерирует файл config.h , в котором мы найдем объявления

Шаг 5. Отредактировать libavcodec/Makefile

Шаг 6. Отредактировать код мультиплексора и демультиплексора.

Мультиплексор (muxer) и демультиплексор (demuxer) должны «знать» новый кодек. При записи необходимо записать идентифицирующую информацию для этого кодека, при чтении определить идентификатор кодека по идентифицирующей информации. Вот что нужно сделать для формата matroska (файлы *.mkv ).

1. В файле libavformat/matroska.c в массив ff_mkv_codec_tags добавить элемент для нового кодека:

Строка "A_FROX" и будет записываться мультиплексором в файл в качестве идентифицирующей информации. В данном массиве она связывается с идентификатором кодека, поэтому демультиплексор при чтении сможет легко его определить. Демультиплексор записывает идентификатор кодека в член codec_id структуры AVCodecParameters . Указатель на эту структуру является членом структуры AVStream .

2. В файле libavformat/matroskaenc.c в массив additional_audio_tags добавить элемент:

Итак все готово. Сначала запускаем скрипт configure . После этого надо убедится, что описанные выше изменения в файлах libavcodec/codec_list.c и config.h сделаны. После чего можно запускать компиляцию:

Если компиляция прошла без ошибок, появляется исполняемый файл ffmpeg (или ffmpeg.exe , если целевой ОС является Windows). Выполняем команду

./ffmpeg -codecs >codecs.txt

и убеждаемся, что FFmpeg «видит» наши новые кодеки, в файле codecs.txt находим запись

DEA..S frox FROX audio (decoders: frox_dec) (encoders: frox_enc)

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

3.1. Контекст кодека

Контекст кодека может поддерживать установку опций. Для кодеров эта поддержка используется достаточно часто, для декодеров реже. Структура, поддерживающая установку опций, должна в качестве первого члена иметь указатель на структуру AVClass и далее сами опции.

Далее надо определить массив типа AVOption , каждый элемент которого и описывает конкретную опцию.

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

Далее надо определить экземпляр типа AVClass .

Указатель на этот экземпляр надо использовать для инициализации соответствующего члена AVCodec .

Теперь при выполнении функции

будет создан экземпляр структуры AVCodecContext и инициализирован член codec . Далее на основе значения codec->priv_data_size будет выделена необходимая память для экземпляра FroxContext , используя значение codec->priv_class первый член этого экземпляра будет инициализирован и после этого будет вызвана функция av_opt_set_defaults() , которая установит значений по умолчанию для опций. Указатель на экземпляр FroxContext будет доступен через член priv_data структуры AVCodecContext .

При работе с FFmpeg API значения для опций можно установить непосредственно.

Другой способ — это использование словаря опций, который будет передаваться третьим аргументом при вызове avcodec_open2() (см. ниже).

С помощью функции

можно получить список всех опций, поддерживаемых контекстом кодека. Это бывает полезно при исследовании кодека. Но перед этим надо обязательно проверить, что codec_ctx->codec->priv_class установлен в ненулевое значение, в противном случае контекст не поддерживает опций и при любой операции с опциями произойдет аварийное завершение программы.

3.2. Функции

Рассмотрим теперь подробнее, как устроены функции, используемые при инициализации кодека и фактического кодирования/декодирования. В них обычно всегда требуется получить указатель на FroxContext .

Функции frox_decode_init() и frox_encode_init() будут вызваны при выполнении функции

В них надо выделить необходимые ресурсы для работы кодека, и при необходимости инициализировать некоторые члены структуры AVCodecContext , например frame_size для аудиокодера.

Функции frox_decode_close() и frox_encode_close() будут вызваны при выполнении

В них надо освободить выделенные ресурсы.

Рассмотрим функцию для реализации декодирования

Она должна реализовать следующие операции:

  1. Фактическое декодирование;
  2. Выделение необходимого буфера для выходного кадра;
  3. Копирование декодированных данных в буфер кадра.

Рассмотрим, как надо выделять необходимый буфер для выходного кадра. Параметр outdata на самом деле указывает на AVFrame , поэтому сначала надо выполнить преобразование типа:

Далее надо выделить буфер для хранения данных кадра. Для этого надо инициализировать члены AVFrame , определяющие размер буфера кадра. Для аудио это nb_samples , channel_layout , format (для видео width , height , format ).

После этого надо вызвать функцию

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

Функция frox_decode() должна возвращать количество байт, использованных для декодирования, из пакета, на который указывает pkt . Если формирование кадра завершено, то переменной, на которую указывает outdata_size присваивается ненулевое значение, иначе эта переменная получает значение 0 .

Рассмотрим функцию для реализации кодирования

Она должна реализовать следующие операции:

  1. Фактическое кодирование;
  2. Выделение необходимого буфера для выходного пакета;
  3. Копирование закодированных данных в буфер пакета.

Для выделения необходимого буфер используется функция

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

Если формирование пакета завершено, то переменной, на которую указывает got_pkt_ptr присваивается ненулевое значение, иначе эта переменная получает значение 0 . В случае отсутствия ошибки, функция возвращает ноль, иначе код ошибки.

При реализации кодека обычно используется логгирование (для ошибок это можно считать обязательным требованием). Вот пример:

В этом случае при выводе в лог в качестве имени контекста будет использовано имя кодека.

3.3. Метки времени

Для задания времени в FFmpeg используется единица времени (time base), задаваемая в секундах с помощью рационального числа, представляемого типом AVRational . (Аналогичный подход используется в C++11. Например 1/1000 задает миллисекунду.) Кадры и пакеты имеют метки времени (timestamps), имеющие тип int64_t , их значения содержат время в соответствующих единицах времени. Кадр, то есть структура AVFrame , имеет член pts (presentation timestamp), значение которого определяет относительное время сцены, запечатленной в кадре. Пакет, то есть структура AVPacket , имеет члены pts (presentation timestamp) и dts (decompression timestamp). Значение dts определяет относительное время передачи пакета на декодирование. Для простых кодеков оно совпадает с pts , но для сложных кодеков может отличатся (например для h264 при использовании B-frames), то есть пакеты могут декодироваться не в том порядке в котором должны использоваться кадры.

Единица времени определена для потока и кодека, структура AVStream имеет соответствующий член — time_base , такой же член имеет структура AVCodecContext .

Метки времени пакета, извлеченного из потока с помощью av_read_frame() , будут заданы в единицах времени этого потока. При декодировании единица времени кодека не используется. Для видеодекодера она обычно просто не задана, для аудиодекодера имеет стандартное значение — обратное к частоте дискретизации. Декодер должен установить метку времени для выходного кадра основываясь на метках времени пакета. FFmpeg самостоятельно определяет такую метку и записывает ее в член best_effort_timestamp структуры AVFrame . Все эти метки времени будут использовать единицу времени потока, из которого извлечен пакет.

Для кодера необходимо задавать единицу времени. В клиентском коде, организующем декодирование, надо установить значение для члена time_base структуры AVCodecContext перед вызовом avcodec_open2() . Обычно берут единицу времени, используемую для меток времени кодируемого кадра. Если этого не сделать, то видеокодеры обычно выдают ошибку, аудиокодеры устанавливают значение по умолчанию — обратное к частоте дискретизации. Может ли кодек изменить заданную единицу времени, не вполне ясно. На всякий случай лучше всегда проверять значение time_base после вызова avcodec_open2() и, если оно изменилось, пересчитывать метки времени входных кадров на единицу времени кодека. В процессе кодирования необходимо установить pts и dts пакета. После кодирования, перед записью пакета в выходной поток необходимо пересчитать метки времени пакета с единицы времени кодека на единицу времени потока. Для этого можно воспользоваться функцией

При записи пакетов в поток необходимо гарантировать, чтобы значения dts строго возрастали, иначе мультиплексор выдаст ошибку. (Подробнее см. документацию на функцию av_interleaved_write_frame() .)

3.4. Другие функции, используемые кодеком

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

Первая из них вызывается один раз при регистрации кодека.

Вторая сбрасывает внутреннее состояние кодека, она будет вызывается во время выполнения функции

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

4.1. Подключение внешней функции

Такого решение может быть желательно по многим причинам. Вот некоторые из них:

  1. Кодек носит экспериментальный характер и часто меняется, а компиляция FFmpeg является довольно трудоемким процессом;
  2. Кодек написан не на C, а на другом языке, например на C++;
  3. Кодек использует библиотеки или framework, которые трудно интегрировать в FFmpeg.

Не смотря на закрытую, монолитную архитектуру FFmpeg такой вариант возможен и является вполне «законным», то есть для его реализации требуется только стандартный FFmpeg API. И ключом для решения этой задачи является механизм опций с помощью которого «внутрь» FFmpeg можно передать указатель на внешнюю функцию (или указатель структуру, содержащую указатели на внешние функции), которая и реализует требуемый функционал. Наиболее естественный вариант — это использование опций бинарного типа. В нашем примере для декодера можно предложить примерно следующее.

На стороне клиента FFmpeg API (в данном примере написан на C++) можно предложить примерно следующее.

4.2. Внешний декодер

Она из важных идей компьютерного мультимедиа — это отделение кодека от медиаконтейнера. В идеале медиаконтейнер любого типа может хранить медиапотоки, закодированные любым кодеком. Конечно, в реальности это не всегда выполняется. Мы видели, что для того, чтобы FFmpeg мог записать в контейнер медиапоток, мультиплексор должен «знать» кодек, так как необходимо записать идентифицирующую информацию о кодеке. А вот при чтении это уже не совсем так. Демультиплексор без проблем извлекает пакеты, закодированные неизвестным кодеком. Если клиент FFmpeg API может как-то идентифицировать этот кодек и умеет декодировать медиаданные, закодированные этим кодеком, то становится возможным воспроизведение таких медиаданных. У автора имеется подобный опыт. В свое время пришлось работать с одним видеорегистратором, который использовал аппаратное сжатие в некотором проприетарном формате. Сжатые данные переносились на PC (Windows) и затем записывались с помощью DirectShow в AVI файл. На PC имелся программный декодер для этого формата и на его основе был написан фильтр-декодер в стандарте DirectShow. Формат идентифицировался с помощью 32-битного FourCC. (Записывался в член biCompression структуры BITMAPINFOHEADER .) Таким образом, эти файлы воспроизводились на любом DirectShow проигрывателе при условии, что на PC был инсталлирован этот фильтр-декодер. При попытке воспроизвести такой файл с помощью FFmpeg проигрывателя декодер, естественно, не был найден, но член codec_tag структуры AVCodecParameters содержал вышеупомянутый FourCC, что решало проблему идентификации кодека. На основе имеющегося декодера для клиента FFmpeg API был написан дополнительный декодер, которому и передавался пакет. Таким образом проблема воспроизведения таких файлов была решена с помощью стандартной сборки FFmpeg и использования FFmpeg API.

В ряде случаев неизвестный кодек можно идентифицировать по метаданным потока, например в *.mkv файлах FFmpeg записывает туда имя кодека (свойство ENCODER ).

В данной статье рассматривались только изменения в коде, не рассмотрены изменения, которые необходимо внести в другие части FFmpeg: документации, changelog, систему контроля версий и т.д. Но если вы планируете «домашнюю» сборку FFmpeg, предназначенную только для конкретного проекта, то этого можно не делать.

Общие вопросы архитектуры FFmpeg

[5] FFmpeg Compilation Guide
[6] Compilation of FFmpeg 4.0 in Windows 10

yandex-browser

После обновления браузера от Яндекса на MX Linux (Debian 10) перестали воспроизводится видео на сайтах и на Youtube. Браузер при воспроизведении видео выдает: «Не обнаружены необходимые видеокодеки …»

Если у вас еще не установлен данный браузера, то вот ссылка как установить yandex.browser на Ubuntu/Debian

[Решение] Не обнаружены необходимые видеокодеки

Из за того, что в системе установлена устаревшая версия кодеков Вы получаете данное предупреждение. На данный момент свежая версия 92.0.4515. Дело в том, что для корректной работы библиотека libffmpeg.so должна соответствовать версии Chromium. Так как Яндекс.Браузера лежит в основе той или иной версии Chromium.

Кстати, флеш плеер в Я.Браузере появился из коробки. После установки браузера его ставить не надо.
А вот для просмотра видео в Вконтакте нужны кодеки.

Прежде всего нам необходимо узнать путь где лежит наш кодек. Для этого в терминале набираем команду:

Из данного вывода нам необходимо только знать расположение ffmpeg кодека. У меня в данном случае он расположен по пути /opt/yandex/browser-beta/lib/libffmpeg.so .

Скачаем актуальную версию. Для этого переходим по ссылке и скачиваем необходимый кодек для вашей разрядности ОС (посмотреть разрядность можно командой uname -m ).

ffmpeg

Другой способ — это воспользоваться командой wget:

Для x64

Для x86

Далее извлекаем библиотеку ffmpeg.so . Я данную операцию буду производить для x64 разрядной ОС:

не забудьте указать правильное название *.deb пакета и директорию (в различных ОС она может отличаться).

Новый способ обновить ffmpeg кодек

Если не воспроизводится видео в формате HTML5 или видео c защищенным контентом

  1. Проверьте версию браузера.
  2. Если версия ниже 20.4.3, обновите браузер.
  3. Если у вас актуальная версия браузера, выполните в консоли команду:

Также кому интересно вот официальная документация на эту тему от яндекса.

Если есть вопросы, то пишем в комментариях.

Также можете вступить в Телеграм канал, ВК или подписаться на Twitter. Ссылки в шапки страницы.
Заранее всем спасибо.

Simply Linux установка Яндекс Бразуера

Linux

подписывайтесь на яндекс дзен

подписывайтесь на мой канал Яндекс дзена!Вы будете первым узнавать о новых материалах!

В данной статье мы с вами познакомимся как:

  1. Установка Яндекс Браузера
  2. Решаем проблему при которой не проигрывается видео в Яндекс Браузере

Установка Яндекс Браузера в Linux

Установка Яндекс Браузера в Linux

Браузер яндекс был первой программой которую я устанавливал на Alt Linux и все потому что, у нас в компании очень много завязано на Яндекс сервисах и серверах, поэтому это был принципиальный вопрос.

    Для установки яндекс браузера нам необходимо установить пакет eepm

Яндекс браузер не воспроизводит видео

ошибки при воспроизведение видео

Первая проблема с которой я столкнулся при тестировании Яндекс Браузера это, то что у меня не проигрывалось видео в соцсетях и новостях и висела ошибка:

хотя на Youtube видео проигрывалось, что указывало на то, что проблемы с кодеками. Но как такое может быть, когда мы только что установили последнюю версию Браузера? Кстати если запустить стандартный браузер Хромиус который есть уже по умолчанию в Simply таких проблем нет и там все видео проигрывается!

Яндекс браузер построен на ядре такого самого хромиус, но яндекс специалисты не особо торопятся с обновлениями и придется эту процедуру делать самим (если у вас после установки не вопроизводится видео)

что бы решить проблему с видео в яндекс браузере делаем следующее:

Читайте также: