Представляем самый быстрый декодер VP8 в мире: ffvp8

http://x264dev.multimedia.cx/?p=499
  • Перевод
Ещё в тот момент, когда я писал первоначальный обзор VP8, я обратил внимание на то, что официальный декодер, libvpx, весьма медленный. Нет особенных причин, по которым он должен быть ощутимо быстрее хорошего декодера H.264, но и таким медленным ему тоже быть не с чего! Так что у меня возник план написать луший вариант для FFmpeg вместе с Рональдом Балтьи (Ronald Bultje) и Дэвидом Конрадом (David Conrad). Эта реализация декодера должна была разрабатываться сообществом и быть свободной с самого начала, в отличии от свалки проприетарного кода, которую представла собой библиотека libvpx. Несколько недель назад декодер был достаточно завершен для обеспечения бинарной совместимости видеопотока с libvpx, что сделало его первой независимой и свободной реализацией декодера VP8. Теперь, когда мы завершили первый цикл оптимизаций, он должен был готов к использованию в реальных условиях. Я расскажу о деталях процесса разработки позже, а сейчас давайте перейдем к самой соли этого поста: результатам сравнительного тестирования производительности кодеков.

Мы тестировали декодер на двух 1080p клипах: Parkjoy, снятый вживую, и Sintel trailer, созданный на компьютере. Тестирование выполнялось так:

time ffmpeg -vcodec {libvpx or vp8} -i input -vsync 0 -an -f null -

Мы использовали последнюю на момент этого поста сборку FFmpeg из SVN, последняя ревизия, содержащая оптимизации VP8 декодера была r24471.

image

image

Как показывают эти графики, ffvp8 значительно быстрее libvpx, в особенности, на 64-битных платформах. Даже на процессорах Atom он работает ощутимо быстрее, несмотря на то, что специально для Atom мы его ещё даже не оптимизировали. Во многих случаях от этой разницы в производительности будет зависеть, воспроизводится видео или нет, в особенности, в современных браузерах, движки которых отъедают значительную часть ресурсов процессора. Хотите, чтобы видео в VP8 играло быстрее? Новые версии плееров, основанные на FFmpeg (а это всем известный VLC и многие другие) будут включать библиотеку ffvp8. Хотите, чтобы видео в VP8 быстрее декодировалось в вашем браузере? Общайтесь с его разработчиками, и настаивайте, чтобы они использовали ffvp8 вместо libvpx. Я полагаю, что первым на использование ffvp8 перейдет Chrome, так как они уже используют libavcodec в своей подсистеме воспроизведения видео.

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

Разработка ffvp8

Первая задача, за которую взялись Дэвид и Рональд, заключалась в воссоздании ядра декодера и доведении его до бинарной совместимости потока с libvpx. Это было непросто, учитывая неполность официальной спецификации. Многие части спецификации вообще были неправильными и противоречили коду libvpx. И уж конечно никак не помог нашей работе тот факт, что набор официальных тестов совместимости даже не покрывает все особенности, которые использует официальный кодер! Для того, чтобы как-то работать дальше при таком положении вещей, нам пришлось начать добавлять свои собственные тесты. Но я уже жаловался на недостаточное качество спецификаций в своих предыдущих постах, так что давайте перейдём к нюансам.

Следующим шагом стало добавление кода SIMD для всех важных функций DSP. В основном нагрузку на процессор в декодере VP8 создает компенсация движения и фильтр деблокинга (компенсации артефактов кодирования, пер.) — так же, как и в H.264. Но, в отличие от H.264, фильтр деблокинга полагается на внутреннюю арифметику с насыщением, которая ничего не стоит в SIMD-реализации, но весьма «прожорлива» в отношении процессора в реализации на C. Разумеется, ни то ни другое не представляет серьезной проблемы, так как во всех нормальных кодеках эти процессы реализованы в виде кода SIMD.

Я помогал Рональду с SIMD для x86, а также написал большую часть компенсации движения, внутреннего предсказания и часть обратных преобразований. Рональд написал оставшуюся часть обратных преобразований и часть компенсации движания. Кроме того, он сделал самую трудную часть: фильтр деблокинга. Эти фильтры — всегда сложная часть, так как в каждом кодеке они разные. Реализация компенсации движения, для сравнения, обычно не слишком отличается в разных кодеках: 6-tap фильтр в любом случае будет 6-tap фильтром, и разница обычно только в коэффициентах.

Самая большая сложность в фильтре деблокинга SIMD заключалась в том, чтобы избегать «распаковки», т.е. перехода от 8 битов к 16-ти. Многие операции в таких фильтрах изначально кажутся требующими точности, превышающей 8 бит. Простой пример для x86: abs(a-b), где a и b — целые 8-битные числа без знака. Результат «a-b» требует точности в 9 бит со знаком (так как может быть где угодно в пределах от -255 до 255), так что он не может поместиться в 8 бит. Но вполне возможно решить эту задачу без «распаковки»: (satsub(a,b) | satsub(b,a)), где «satsub» вычисляет разность с насыщением между двумя значениями. Если разница положительная, возвращается результат, в противном случае — ноль, так что выполнение логического ИЛи между результатами работы этих функций как раз дает нам то, что нужно. Это требует 4 ассемблерных инструкций на x86, «распаковка» потребовала бы по меньшей мере 10, включая собственно шаги «распаковки» и «упаковки».

Затем последовала SIMD-оптимизация кода на C, выполнение которого все еще занимало значительную часть времени декодирования. Одна из моих самых больших оптимизаций заключалась в добавлении «умной» предвартельной загрузки, сокращающей количество «промахов» кэша. ffvp8 предзапрашивает кадры, на которые ссылается текущий («ПРЕДЫДУЩИЙ», «ЗОЛОТОЙ» И «АЛЬТЕРНАТИВНАЯ ССЫЛКА», они же PREVIOUS, GOLD и ALTREF), но только тогда, когда они действительно ощутимо используются в данном кадре. Это позволяет нам предзапрашивать все, что нам нужно, и не запрашивать то, что мы вряд ли используем. libvpx, как правило, кодирует кадры, которые почти никогда (но не стоит понимать это как «совсем никогда») не используют кадры GOLDEN или ALTREF, так что эта оптимизация значительно сокращает время, затрачиваемое на предзапросы во многих реальных видеороликах. Кроме того, мы сделали столько оптимизаций в разных местах кода, что все их здесь не перечислить, как, например, оптимизация энтропийного декодера, которую сделал Дэвид. Я также хотел бы поблагодарить Эли Фридмана за его неоценимую помощь в тестировании производительности большинства этих улучшений.

Что дальше? Ассемблерный код Altivec (PPC) фактически отсутствует, есть всего несколько функций из кода компенсации движения Дэвида. Ассемблерного кода для NEON (ARM) нет вообще, а нам он нужен, чтобы работать быстро и на мобильных устройствах. Конечно, все это будет со временем, и, как обычно, мы всегда рады патчам!

Приложение: голые цифры

Вот цифры, соответствующие приведенным выше графикам, в кадрах в секунду и со стандартными ошибками:

Core i7 620QM (1.6Ghz), Windows 7, 32-bit:
Parkjoy ffvp8: 44.58 ± 0.44
Parkjoy libvpx: 33.06 ± 0.23
Sintel ffvp8: 74.26 ± 1.18
Sintel libvpx: 56.11 ± 0.96

Core i5 520M (2.4Ghz), Linux, 64-bit:
Parkjoy ffvp8: 68.29 ± 0.06
Parkjoy libvpx: 41.06 ± 0.04
Sintel ffvp8: 112.38 ± 0.37
Sintel libvpx: 69.64 ± 0.09

Core 2 T9300 (2.5Ghz), Mac OS X 10.6.4, 64-bit:
Parkjoy ffvp8: 54.09 ± 0.02
Parkjoy libvpx: 33.68 ± 0.01
Sintel ffvp8: 87.54 ± 0.03
Sintel libvpx: 52.74 ± 0.04

Core Duo (2Ghz), Mac OS X 10.6.4, 32-bit:
Parkjoy ffvp8: 21.31 ± 0.02
Parkjoy libvpx: 17.96 ± 0.00
Sintel ffvp8: 41.24 ± 0.01
Sintel libvpx: 29.65 ± 0.02

Atom N270 (1.6Ghz), Linux, 32-bit:
Parkjoy ffvp8: 15.29 ± 0.01
Parkjoy libvpx: 12.46 ± 0.01
Sintel ffvp8: 26.87 ± 0.05
Sintel libvpx: 20.41 ± 0.02



Примечания переводчика

Некоторые термины остались для меня загадкой, например, если кто-нибудь сможет подсказать верный русский перевод 6-tap filter, я буду очень признателен.

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

В: Сможет ли ffvp8 использовать улучшения, которые вносятся в libvpx?
О: Фактически, все оптимизации, которые показались интересными — уже взяты оттуда. Но надо понимать, что простым слиянием (merge) исходников тут не обходится, поскольку архитектура у декодеров принципиально различается.

В: Нет ли опасности, что ffvp8 не сможет поддерживать совместимость с экспериментальной веткой разработки libvpx?
О: Такая задача и не стоит, так как на данный момент экспериментальная ветка не предназначена для использования в реальных условиях. Не гарантируется даже совместимость экспериментальной ветки с текущей libvpx.

В: Кто спонсирует разработку FFmpeg?
О: Целиком проект — никто, но некоторые разработчики получают деньги за реализацию фич, необходимых конкретным заказчикам. Насколько известно автору, разработка ffvp8 была полностью некоммерческой.

В: Увеличение производительности связано с одним каким-то глобальным недостатком libvpx, или просто сложилось множество оптимизаций тут и там?
О: В целом, скорее второе. Но основной прирост производительности дало то, что libvpx проходит по кадру несколько раз (аналогичным образом поступают и все предыдущие кодеки On2), а ffvp8 делает все операции за один проход.

В: Планируется ли разработка собственного энкодера VP8 в FFmpeg?
О: Это очень большая работа, и, если честно, я сомневаюсь, что она когда-нибудь будет сделана. Фактически, единственный «родной» энкодер, который есть в FFmpeg — это энкодер mpeg, и вряд ли найдется способ сделать энкодер VP8 только на базе имеющегося фреймворка, во всяком случае, простым этот способ не будет. Но, конечно, если кто-то хочет попробовать…

В: Но если для FFmpeg единственный родной энкодер — mpeg, тогда каким образом эта библиотека поддерживает кодирование видео не только в mpeg, но и в WMV 7/8, H.261/3 и другие форматы без использования других библиотек?
О: Все эти энкодеры фактически используют внутренний mpeg энкодер с небольшими вариациями для каждого формата. Следует иметь в виду, что энкодер — большая и сложная программа, состоящая из многих частей, и единственная значительная разница между энкодерами перечисленных форматов — это алгоритм энтропийного кодирования и заголовки. И то и другое может быть легко заменено без необходимости менять весь остальной код. Вот почему в FFmpeg столько «энкодеров», которые все основаны на основном энкодере mpeg: фактически, разница между этими алгоритмами не столь существенна (все они представляют собой подобия MPEG, основанные на дискретном косинусном преобразовании блоков 8х8 пикселей), так что для всех них может быть использован в значительной степени один и тот же код.
Этим, кстати, и объясняется отсутствие в FFmpeg энкодера WMV9 — этот алгоритм слишком отличается от предыдущих версий, чтобы его можно было легко реализовать на базе того, что есть.

В: Может ли ffvp8 также декодировать VP4, 5, 6 и 7?
О: Может, но только VP4, 5 и 6, так как никто пока не подвергал VP7 обратной разработке. Но, скорее всего, поддержка VP7 появится в ближайшем будущем, учитывая открытие VP8, так как есть у меня подозрение, что VP7 и VP8 по большей части совпадают.

В: Где можно взять свежие SVN-сборки Media Player Classic HomeCinema и FFDshow tryouts, чтобы посмотреть самим на новый декодер под Windows?
О: xhmikosr.1f0.de

Если возникнут какие-нибудь вопросы к автору заметки, я готов перевести их и опубликовать в его блоге.
Поделиться публикацией
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама
Комментарии 38
  • +5
    Оставьте деблокинг деблокингом, пришлось смотреть оригинал, чтобы понять, что имеется в виду под «фильтром артефактов кодирования».
  • 0
    Молодцы. Но свежий mplayer заикается на втором файле (который sintel). Ещё пилить и пилить.
    • 0
      А вы используете mplayer с ffmpeg из svn? Может быть, там эти ошибки уже исправлены?
  • +1
    … учитывая неполность официальной спецификации. Многие части спецификации вообще были неправильными и противоречили коду…

    В начале 21-ого столетия в психиатрии произошло открытие нового заболевания, распространявшегося небывалыми темпами, опережавшими депрессию: «венда головного мозга» — врачи бьют тревогу.

    Энциклопедия истории психиатрии. Том 1024. Июль 2210 год.
    • –8
      А так-же луникс мозжечка
      • +9
        БСДя правого яичка )
    • +1
      Термин «saturation» не надо переводить как «насыщенность цвета». Он в данном контексте к цвету не имеет отношения.

      Автор про обычную арифметику с насыщением говорил, когда int8(150) + int8(150) == 255
      • +1
        Ага. И тут
        > где «satsub» вычисляет разницу насыщенности между двумя значениями.
        следует писать «насыщенную разность» или «разность с насыщением».
        • 0
          И Вам спасибо. Исправил.
        • 0
          Спасибо! Сейчас-правильно?
        • +1
          Ждём ответа от Гугла)
          • –1
            Выйдут дрова Ati Catalyst 10.7 буду тестить DXVA2 в VLC 1.1.1
            • +1
              Посмотрим поближе, пока собрал ffmpeg из svn, понаблюдаем.
              • 0
                Вообще конечно данная новость напоминает о том, что переход на html5 будет еще не таким быстрым, как хотелось, т.к. очень медленно стандарты устаканиваются, появляются новые инструменты кодирования (енкодеры), развиваются браузеры.

                Наверное еще пройдет года два пока можно будет на HTML5 переходить веб-хостингам, а то так настроишь кодирование видео через кодек X для перегонки в формат Y, который поддерживает RANDOM из N браузеров, а потом появляется кодек Z и все начинай сначала…

                Но безусловно радует, что уже что-то начинает вырисовываться, год назад еще все было довольно печально.
              • +1
                Правильно ли я понял, что ffvp8 был сделан при участии автора x264?
              • +2
                А пиписка у линуксах на графиках нефигово длинная, завидую
                • 0
                  Там пиписька не и линухов, а у процессора.
                  + «ffvp8 значительно быстрее libvpx, в особенности, на 64-битных платформах.»
                  • 0
                    FinikWasHere видимо имеет ввиду, что по сравнению с виндой.
                • 0
                  На адекватность не претендую, но у меня вышло такое на четырехядерника, x86-64, Debian:

                  libvpx — 29s
                  vp8 — 4.7s

                  0_o

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

                  Видео взял первое попавшееся, в mp4
                  • 0
                    Intel, AMD? А то в заметке тесты на исключительно Intel'овских процессорах, может быть, на AMD'шных ffvp8 ведет себя лучше?

                    Под mp4 Вы контейнер имеете в виду? Вряд ли он существенно влияет.
                    • 0
                      да, контейнер, подразумевая, что внутри x264

                      AMD, забыл уточнить. Скорее всего вы правы — на AMD производительнее выходит.
                      • 0
                        Стоп. Я теряю нить. Внутри — x264? Тогда причём тут декодеры для потока VP8?
                        • +1
                          «перегоняем» из x264 в webm. По сути идиотский тест, о чем я изначально и сказал, но разница удивляет даже на таком простом случае.
                          • 0
                            А, всё, въехал :)

                            Нормальный тест при соблюдении равных условий, в связи с чем вопрос: а декодирование 264 точно шло одним и тем же декодером?
                            • 0
                              Я не делал несколько тестов, сделал по одному на каждый из предлагаемых — libvpx и vp8

                              • 0
                                Т.е. условия были равные? А чем, все-таки, декодировался 264-поток?
                                • 0
                                  Условия были равные. Что вы имеете ввиду под «чем декодировался 264-поток»?
                                  • 0
                                    Ну, чтобы пережать H.264 в VP8, нужно:
                                    — распаковать поток H.264 в RAW видео
                                    — запаковать RAW видео в поток VP8

                                    • 0
                                      не знаю, за меня всем этим занимался ffmpeg, я ему только задал кодек, которым мне нужно запаковать результирующее видео.
                                      • 0
                                        Всё, ситуацию понял. Значит, ffmpeg'овский h264-декодер работал в обоих случаях. Значит, результат можно считать честным.
                  • 0
                    Кстати, интересный момент. VLC 1.1.1 падает на sintel_trailer. Причем внутри VLC 1.1.1, по идее, ещё libvpx, а не ffvp8. Интересно, беда — в либе, или в VLC?
                    • 0
                      Хм, да он и на parkjoy падает! Ну, дела!
                      AMD A64x2 4200+, WinXP32
                      • +1
                        А вот MPC HC svn 2152 (в котором уже есть ffvp8) — играет, и на приемлемой скорости. Athlon 64 X2 4200+, XP32.

                        (offtopic) Качество картинки, к слову, весьма приятное. Впрочем, 3d жмётся, конечно, лучше чем реальные съемки. (/offtopic)
                        • 0
                          А если отключить встроенный кодек MPC, и играть через последний ffdshow, включив буферизацию кадров на выходе, Sintel вообще играет плавно и без тормозов. Железо то же. А вот parkjoy уже не тянет.

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