Поддержка VPU VELcore-01

Драйвер avico

Драйвер avico управляет VPU VELcore-01 и реализует аппаратное кодирование и декодирование видео по стандарту H.264. Драйвер реализован с использованием подсистемы V4L2 и предоставляет стандартный программный интерфейс для кодирования/декодирования и управления.

Драйвер поддерживается в ядре Linux 4.4.

Кодирование видео

  1. Поддерживается входное несжатое видео с форматом пикселей M420.

  2. Максимальная ширина кадра — 1920 пикселей.

  3. Максимальная высота кадра — 4096 пикселей.

  4. Поддержка кодирования видео с разрешением кратным 2 по ширине и высоте.

  5. Возможность установки FPS видеопотока.

  6. Возможность установки параметра QP с помощью контролов:

    • V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP;

    • V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP;

    • V4L2_CID_MPEG_VIDEO_H264_CHROMA_QP_INDEX_OFFSET.

  7. Возможность установки IDR-кадра с помощью контрола V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME.

  8. Возможность установки размера GOP с помощью контрола V4L2_CID_MPEG_VIDEO_GOP_SIZE. Новый размер GOP применяется со следующего IDR-кадра после завершения текущего GOP. Чтобы применить новый размер GOP на следующем кадре, нужно запросить IDR-кадр с помощью контрола V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME.

  9. Поддержка более одного потока кодирования видео. Максимальное число поддерживаемых потоков кодирования зависит от ширины и высоты кадра, количества запрошенных V4L2-буферов и объема памяти, которая может быть выделена с помощью Contiguous Memory Allocator (CMA). Теоретическое максимальное число поддерживаемых потоков кодирования можно вычислить с помощью формулы:

    n = M / (W * (128 + (2 * B_c + 3/2 * (B_o + 1)) * H))

    где M — размер памяти, которая может быть выделена с помощью CMA, W — ширина кадра, H — высота кадра, B_o — количество V4L2-буферов output-интерфейса, B_c — количество V4L2-буферов capture-интерфейса. Дополнительно количество потоков n ограничивается фрагментацией CMA. Производительность кодирования каждого видео понижается с увеличением числа потоков, т.к. используется один аппаратный поток кодирования. Пример реального максимального числа потоков и достигаемой при этом производительности кодирования при QP 23, четырех V4L2-буферов output-интерфейса, четырех V4L2-буферов capture-интерфейса, размере CMA-памяти 128 МБ и частоте VPU 312 МГц:

    • 1920x1072 — 4 потока, ~15 FPS;

    • 1280x720 — 6 потоков, ~22 FPS;

    • 640x480 — 19 потоков, ~18 FPS.

    Пример ограничения числа потоков кодирования для обеспечения производительности кодирования ~30 FPS при QP 23, четырех V4L2-буферов output-интерфейса, четырех V4L2-буферов capture-интерфейса, размере CMA-памяти 128 МБ и частоте VPU 312 МГц:

    • 1920x1072 — 2 потока, ~30 FPS;

    • 1280x720 — 4 потока, ~30 FPS;

    • 640x480 — 12 потоков, ~30 FPS.

  10. Поддержка сжатия с постоянным битрейтом с помощью контролов:

    • V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE — включение/выключение контроля битрейта;

    • V4L2_CID_MPEG_VIDEO_BITRATE — битрейт, бит/с.

    Контроль битрейта будет выключен, если число кадров в GOP меньше трёх.

  11. Особенности очереди capture:

    • Поддерживаются буферы типов DMABUF и MMAP.

    • Буферы должны быть физически непрерывными.

    • Буферы типа MMAP выделяются драйвером с помощью CMA и являются физически непрерывными и некешируемыми.

  12. Особенности очереди output:

    • Поддерживаются буферы типов DMABUF, MMAP и USERPTR.

    • Буферы типов DMABUF и MMAP должны быть физически непрерывными.

    • Буферы типа MMAP выделяются драйвером с помощью CMA и являются физически непрерывными и некешируемыми.

    • Если буферы типа USERPTR не являются физически непрерывными, выполняется копирование данных из них в непрерывную память с помощью DMA. Это снижает производительность кодирования.

Декодирование видео

  1. Поддерживается выходное несжатое видео с форматом пикселей M420.

  2. Поддержка декодирования видео с разрешением до 1920x1072 кратным 16 по ширине и высоте.

  3. Поддержка контрола V4L2_CID_MPEG_VIDEO_GOP_SIZE.

  4. Поддержка события V4L2_EVENT_SRC_CH_RESOLUTION при смене разрешения видео (в т.ч. в начальный момент момент времени, когда разрешение видео неизвестно, см. Memory-to-Memory Stateful Video Decoder Interface).

  5. Особенности очередей capture и output:

    • Поддерживаются буферы типов DMABUF и MMAP.

    • Буферы должны быть физически непрерывными.

    • Буферы типа MMAP выделяются драйвером с помощью CMA и являются физически непрерывными и некешируемыми.

Ограничения драйвера

  1. Поддерживается только один аппаратный поток кодирования и один аппаратный поток декодирования.

  2. Несжатое видео имеет нестандартный формат пикселей (M420).

  3. Шаг между яркостными и/или цветовыми строками должен быть кратен 16 байтам.

  4. Для кодирования требуется 180 КиБ памяти XYRAM.

  5. Использование с драйвером delcore30m невозможно, т.к. драйвер avico использует SDMA через API DMA-engine, драйвер delcore30m — непосредственное управление SDMA.

  6. Поддерживается только контроль битрейта в режиме CBR. Контроль битрейта реализован на базе алгоритма, описанного в JVT-G012 и JVT-K049, только частично: при вычислении целевого параметра квантования для P-кадров не учитывается средняя абсолютная разница (MAD) кадра и его прогноза, т.к. VPU не предоставляет доступ к значению MAD, вычисляемому им на этапе оптимизации R-D. MAD может быть вычислен программно, но предполагается, что это повлечет значительное снижение производительности, поэтому вместо модели R-D, описанной в JVT-G012 и JVT-K049, используется модель R-D, описанная в Контроль битрейта при кодировании. Контроль битрейта возможен только при количестве кадров в GOP, равном 3 и более.

  7. Нет возможности менять FPS в процессе кодирования.

  8. Для декодирования требуется выделенная память в двух контроллерах DDR (по 8 МиБ в каждом DDR для поддержки разрешения 1920x1072).

  9. Вне зависимости от количества потоков кодирования/декодирования драйвер avico использует один канал SDMA. Количество используемых каналов SDMA ограничено для обхода ошибки зависания rf#12990.

  10. При декодировании сжатый кадр должен быть целиком расположен в одном output-буфере.

Примечание

Аппаратный блок декодера VPU поддерживает H.264 Constrained Baseline Profile с отключенной опцией Deblocking Filter. Видео с отключенным фильтром может быть создано кодером VPU. Возможность декодирования произвольного видео H.264 не гарантируется.

При кодировании для обхода проблемы rf#1382 драйвер использует промежуточные буферы в XYRAM для восстановленных и сжатых данных. Всего используется 4 буфера по 45 КиБ (строка макроблоков для кадра шириной 1920 пикселей в формате M420) — 2 буфера для восстановленных данных и 2 для сжатых. В результате реализации обхода проблемы, максимальная ширина кадров ограничилась 1920 пикселями.

При кодировании после каждой строки макроблоков VPU останавливается и драйвер выполняет следующие действия:

  1. Настраивает VPU на другой промежуточный буфер.

  2. Запускает SDMA для копирования данных из промежуточного буфера в DDR.

  3. Запускает VPU на обработку следующей строки макроблоков.

При кодировании для обхода проблемы rf#2003 в обработчике прерывания используется задержка, состоящая из следующих действий:

  1. Ожидание завершения чтения очередных данных исходного и референсного кадров.

  2. Ожидание завершения 80-кратного чтения регистра EVENTS.

  3. Ожидание снятия всех флагов регистра EVENTS, указывающих на текущую работу VDMA.

При декодировании для обхода проблемы зависания rf#1382 драйвер в начале декодирования выделяет буферы DDRx и DDRy в разных DDR, затем каждый кадр выполняет следующие действия:

  1. Копирование входных сжатых данных из буфера пользователя в буфер DDRx с помощью SDMA. DDRx — буфер, в котором находится референсный кадр.

  2. Копирование в VRAM первых двух строк макроблоков из буфера референсного кадра. Данное копирование стало необходимым после перемещения восстановленного кадра в отдельный буфер из общего буфера для референсного/восстановленного кадра. Восстановленный кадр теперь записывается в буфер DDRy.

  3. Запуск декодирования, при этом референсный кадр и сжатые данные считываются из DDRx, а восстановленный кадр записывается в DDRy.

  4. Выгрузка последней строки макроблоков из VRAM в буфер восстановленного кадра.

  5. Копирование полученного в результате декодирования восстановленного кадра из DDRy в буфер пользователя с помощью SDMA.

  6. Буферы DDRx и DDRy меняются местами, так что восстановленный кадр в DDRy используется как референсный кадр в DDRx для следующего кадра.

Использование драйвера

При инициализации аппаратного блока драйвер регистрирует два устройства V4L2:

  • index = 0 — для кодирования,

  • index = 1 — для декодирования.

В дистрибутиве Buildroot для устройств создаются символические ссылки в директории /dev/v4l/by-path:

# ls -l /dev/v4l/by-path/*codec*
lrwxrwxrwx ... /dev/v4l/by-path/platform-37100000.codec-video-index0 -> ../../video0
lrwxrwxrwx ... /dev/v4l/by-path/platform-37100000.codec-video-index1 -> ../../video1

Контроль битрейта при кодировании

Контроль битрейта основан на алгоритме, описанном в JVT-G012 и JVT-K049.

Битрейт контролируется на уровне GOP и на уровне кадра. В задачи контроля битрейта входит вычисление параметра квантования, так чтобы средний битрейт видео соответствовал заданному значению.

В последующем описании используются следующие обозначения:

  • f — частота кадров (предполагается, что не меняется в процессе кодирования);

  • w — ширина кадра в пикселях;

  • h — высота кадра в пикселях;

  • i\in\mathbb{N} — номер GOP;

  • j\in\mathbb{N} — номер кадра в пределах GOP;

  • N_i — количество кадров в i-ом GOP;

  • b_i(j) — размер j-го сжатого кадра в i-ом GOP;

  • B_i(j) — число бит, оставщихся в GOP, на момент кодирования j-го кадра в i-ом GOP;

  • QP_i(j) — параметр квантования j-го кадра в i-ом GOP;

  • \overline{QP}^p_i — усредненный параметр квантования по всем P-кадрам в i-ом GOP;

  • R_i(j) — целевой битрейт на момент кодирования j-го кадра в i-ом GOP;

  • S_i(j) — целевой уровень виртуального буфера (число оставшихся бит) после кодирования j-го карда в i-ом GOP;

  • V_i(j) — уровень заполнения виртуального буфера сжатых кадров (число бит в буфере сжатых кадров гипотетического референсного декодера) на момент кодирования j-го кадра в i-ом GOP;

  • bpp = \frac{R_1(1)}{fwh} — целевое число бит на пиксель.

Описание алгоритма

Общее число бит для оставшихся кадров в GOP в случае сжатия с константным битрейтом вычисляется по формуле:

B_i(j) = \begin{cases}
           \frac{R_i(j)}{f} \times N_i - V_i(j) & \quad j=1 \\
           B_i(j-1) - b_i(j-1) & \quad j = 2, 3, \dotsc, N_i
         \end{cases}

Уровень заполнения виртуального буфера вычисляется по формуле:

V_i(1) = \begin{cases}
           0 & \quad i=1\\
           V_{i-1}(N{i-1}) & \quad \text{other}
         \end{cases}

V_i(j) = V_i(j-1) + b_i(j-1) - \frac{R_i(j-1)}{f} \quad j=2, 3, \dotsc, N_i

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

QP_1(1) = \begin{cases}
           40 & \quad bpp \leq l1\\
           30 & \quad l1 < bpp \leq l2\\
           20 & \quad l2 < bpp \leq l3\\
           10 & \quad bpp > l3\\
         \end{cases}

Рекомендуемые значения:

  • l1=0.15, l2=0.45, l3=0.9 — для кадров размером QCIF/CIF;

  • l1=0.6, l2=1.4, l3=2.4 — для кадров больше QCIF/CIF.

Для последующих GOP:

QP_i(1) = max(QP_{i-1}(1) - 2, min(QP_{i-1}(1) + 2, \overline{QP}^p_{i-1} - min(2,
\frac{N_{i-1}}{15})))

\overline{QP}^p_i = \sum_{j=2}^{N_i} QP_i(j) / (N_i - 1)

Полученное значение параметра квантования корректируется по формуле:

QP_i(1) = QP_i(1) - 1 \quad \text{if} \quad QP_i(1) > QP_{i-1}(N_{i-1}) - 2

Перед вычислением параметра квантования P-кадров вычисляется целевой размер P-кадра.

Целевой размер P-кадра зависит от целевого уровня виртуального буфера. Целевой уровень виртуального буфера определяется для каждого P-кадра согласно размерам первого IDR-кадра и первого P-кадра.

После кодирования первого P-кадра в i-ом GOP начальное значение целевого уровня виртуального буфера устанавливается по формуле:

S_i(2) = V_i(2)

Целевой уровень виртуального буфера для последующих P-кадров вычисляется по формуле:

S_i(j+1) = S_i(j) - \frac{S_i(2)}{N_i - 2}

Размер, выделяемый для j-го P-кадра в i-ом GOP, вычисляется на основе целевого уровня виртуального буфера, частоты кадров, целевого битрейта и реального уровня заполненения виртуального буфера по формуле:

\tilde{T}_i(j)=\frac{R_i(j)}{f} + \gamma (S_i(j) - V_i(j))

где \gamma — константа, равная 0.5.

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

\hat{T}_i(j) = \frac{B_i(j)}{N_i - max(j - 1, 1)}

Целевой размер P-кадра — взвешенная комбинация \tilde{T} и \hat{T}, которая вычисляется по формуле:

T_i(j) = \beta \hat{T}_i(j) + (1 - \beta) \tilde{T}_i(j)

где \beta — константа, равная 0.5.

Для совместимости с гипотетическим референсным декодером целевой размер P-кадра должен также ограничиваться согласно Совместимость с гипотетическим референсным декодером.

В JVT-K049 и JVT-G012 целевой параметр квантования вычисляется на основе квадратичной модели R-D, в которой используется средняя абсолютная разница [1] (MAD) текущего базового элемента (кадр, макроблок или слайс) и его прогноза, полученного на этапе оптимизации R-D. VPU не предоставляет значение MAD для кадра, поэтому вычисление целевого параметра квантования выполняется другим методом.

Согласно Rate-Distortion Analysis for H.264/AVC Video Coding and its Application to Rate Control увеличение параметра квантования на единицу приводит к уменьшению битрейта на ~12.5%, таким образом целевой параметр квантования QP может быть вычислен из формулы:

T = c_1 \times 0.875^{(QP-QP_c)}T_c + c_2

где T — целевой размер кадра, T_c — размер кадра, полученный при значении QP_c параметра квантования, c_1, c_2 — коэффициенты, начальные значения которых соответственно равны 1 и 0. Коэффициенты обновляются после кодирования каждого кадра согласно методу наименьших квадратов.

Данный метод требует двух проходов кодирования каждого кадра, т.к. сначала требуется вычислить размер кадра для заданного QP и в случае необходимости скорректировать QP и повторно выполнить кодирование. Для выполнения одного прохода кодирования предлагается прогнозировать размер текущего кадра для заданного QP на основе размера предыдущего P-кадра по формуле [2]:

\tilde{T}_c = a_1 T_c + a_2

где a_1 и a_2 — коэффициенты модели прогнозирования размера кадра, T_c — размер предыдущего кадра. Начальные значения коэффициентов соответственно равны 1 и 0. Коэффициенты обновляются после кодирования каждого кадра согласно методу наименьших квадратов.

Для предотвращения резкого изменения качества видео вычисленный параметр квантования корректируется по формуле:

QP_i(j) = min(QP_i(j-1) + 2, max(QP_i(j-1) - 2, QP_i(j)))

Полученное значение параметра квантования ограничивается диапазоном [0; 51] и передается в VPU, который выполняет оптимизацию R-D согласно значению QP.

После завершения кодирования кадра значения коэффициентов a_1, a_2, c_1, c_2 обновляются.

Примечание - В текущей реализации алгоритма контроля битрейта коэффициенты a_1, a_2, c_1, c_2 всегда равны начальным значениям.

Совместимость с гипотетическим референсным декодером

Чтобы удовлетворять требованиям гипотетического референсного декодера целевой размер P-кадра также ограничивается нижней границей (Z_i(j)) и верхней границей (U_i(j)) по формуле:

T_i(j) = min(U_i(j), max(Z_i(j), T_i(j)))

Верхняя и нижняя границы инициализируются по формулам:

Z_i(1) = B_{i-1}(N_{i-1}) + \frac{R_i(1)}{f}

U_i(1) = B_{i-1}(N_{i-1}) + be(t_{r,1}(1)) \times \omega

где B_{i-1}(N_{i-1}) — число бит для оставшихся кадров в GOP с номером (i-1), B_0(N_0)=0, \omega — константа, равная 0.9, t_{r,1}(1) — длительность удаления 1-го кадра из виртуального буфера, be(t) — размер данных (в битах), эквивалентный длительности t с коэффициентом преобразования, равным битрейту.

Последующие значения Z_i(j) и U_i(j) вычисляются по формулам:

Z_i(j) = Z_i(j-1) + \frac{R_i(j)}{f} - b_i(j-1)

U_i(j) = U_i(j-1) + (\frac{R_i(j)}{f} - b_i(j-1)) \times \omega

Примечание - Формулы для Z_i(j) и U_i(j), описанные выше, представлены в Adaptive rate control for H.264. Предполагается, что в JVT-K049 даны некорректные формулы Z_i(j) и U_i(j) (в формулах вместо размера предыдущего кадра используется размер текущего кадра, который не может быть известен на данном этапе). В документе JVT-G012 целевой размер P-кадра не ограничивается нижней и верхней границами, поэтому формулы Z_i(j) и U_i(j) там отсутствуют.

Пакеты пространства пользователя

Для поддержки VPU используются следующие пакеты и утилиты (все пакеты и утилиты распространяются в составе MCom-02 Buildroot):

Пакет m2m-test

Набор утилит для тестирования устройств V4L2 memory-to-memory. Дополнительно пакет распространяется в репозитории https://github.com/elvees/m2m-test. README пакета содержит описание и примеры вызова утилит.

Пакет v4l-utils

Стандартный пакет v4l-utils для управления устройствами V4L2.

Скрипт fc-avico

Shell-скрипт для проверки кодирования из файла в файл. Содержится в Buildroot-пакете mcom02-linux-tests.

Пакет ffmpeg

Стандартный пакет ffmpeg пропатчен для поддержки формата M420.

Пакет gstreamer1

Стандартный пакет gstreamer1 пропатчен для поддержки формата M420.

Тесты кодирования

См. также

Инструкция Захват видео и RTSP-вещание

fc-avico

Скрипт fc-avico выполняет:

  1. Сгенерировать тестовое видео с помощью ffmpeg.

  2. Конвертировать тестовое видео в формат M420 с помощью any2m420.

  3. Сжать тестовое видео на VPU с помощью m2m-test.

  4. Проверить, что скорость сжатия больше 30 кадров в секунду.

Запуск скрипта и пример вывода:

$ fc-avico -c
/tmp/fc-avico /tmp/test
Input #0, yuv4mpegpipe, from 'm420.y4m':
Input #0, yuv4mpegpipe, from 'm420.y4m':
  Duration:   Duration: 00:00:02.00, start: 00:00:02.00, start: 0.000000, bitrate: 0.000000276481 kb/s, bitrate: 276481 kb/s
    Stream #0:0    Stream #0:0: Video: rawvideo (I420 / 0x30323449), yuv420p(progressive), 1280x720: Video: rawvideo (I420 / 0x30323449), yuv420p(progressive), 1280x720, , 25 fps, 25 fps, 25 tbr, 25 tbr, 25 tbn, 25 tbn, 25 tbc25 tbc

Card: avico
V4L2: Control: h264_i_frame_qp_value = 28
V4L2: Control: h264_p_frame_qp_value = 28
V4L2: Control: h264_chroma_qp_index_offset = 0
V4L2: Control: video_gop_size = 60
V4L2: Control: frame_level_rate_control_enable = 0
V4L2: Control: video_bitrate = 524288
Encoding framerate: 25.00 -> 25.00 FPS
Output size: 85 KiB
Total time in main loop: 0.7 s (69.1 FPS)
Card: avico
V4L2: Control: h264_i_frame_qp_value = 28
V4L2: Control: h264_p_frame_qp_value = 28
V4L2: Control: h264_chroma_qp_index_offset = 0
V4L2: Control: video_gop_size = 60
V4L2: Control: frame_level_rate_control_enable = 0
V4L2: Control: video_bitrate = 524288
Encoding framerate: 25.00 -> 25.00 FPS
Output size: 85 KiB
Total time in main loop: 0.7 s (68.8 FPS)
Checking results for thread #0
encoded_0.264: OK
Checking results for thread #1
encoded_1.264: OK
TEST PASSED

После окончания работы тест сохранит сжатое видео в файлах /tmp/fc-avico/encoded_0.264 и /tmp/fc-avico/encoded_1.264. Файл можно проиграть на HDMI-мониторе с помощью команды:

ffmpeg -re -i /tmp/fc-avico/encoded_0.264 -pix_fmt bgra -f fbdev /dev/fb0

v4l2-compliance

Запуск и пример вывода стандартной утилиты проверки устройств V4L2:

$ v4l2-compliance --device=/dev/v4l/by-path/platform-37100000.codec-video-index0
v4l2-compliance SHA   : c7dfb39ae7305d7118bb208598c2be47d1ddcf52

Driver Info:
   Driver name   : avico
   Card type     : avico
   Bus info      : platform:avico
   Driver version: 4.4.237
   Capabilities  : 0x84208000
      Video Memory-to-Memory
      Streaming
      Extended Pix Format
      Device Capabilities
   Device Caps   : 0x04208000
      Video Memory-to-Memory
      Streaming
      Extended Pix Format

Compliance test for device /dev/v4l/by-path/platform-37100000.codec-video-index0 (not using libv4l2):
...
Total: 43, Succeeded: 43, Failed: 0, Warnings: 10

Тесты декодирования

v4l-compliance для устройства декодера не поддерживается.

Примеры декодирования приведены в файле README в составе пакета m2m-test.