Мы тестировали Khadas VIM4 Amogic A311D2 SBC с Ubuntu 22.04 немного дольше обычного, и хотя производительность в целом хорошая, такие функции, как ускорение 3D-графики и аппаратное декодирование видео, отсутствуют. Но нам бы хотелось увидеть раздел аппаратного кодирования видео Linux в Wiki, так как это не часто увидишь на ранних этапах. Итак, пробуем…
Во-первых, нам нужно сделать видео в формате пикселей NV12, которое обычно выводится с камер. Мы загрузили 45-секундный образец видео 1080p H.264 с Linaro и преобразовали его с помощью ffmpeg:
1 |
ffmpeg -i big_buck_bunny_1080p_H264_AAC_25fps_7200K.MP4 -pix_fmt nv12 big_buck_bunny_1080p_H264_AAC_25fps_7200K-nv12.yuv |
Мы сделали это на ноутбуке. Как необработанное видео, оно довольно большое: 3,3 ГБ памяти используется для 45-секундного видео:
1 2 3 4 5 |
ls -lh total 3.3G -rw-rw-r-- 1 jaufranc jaufranc 40M Aug 5 2011 big_buck_bunny_1080p_H264_AAC_25fps_7200K.MP4 -rw-rw-r-- 1 jaufranc jaufranc 3.3G May 21 15:03 big_buck_bunny_1080p_H264_AAC_25fps_7200K-nv12.yuv |
Теперь давайте попробуем закодировать видео в H.264 на плате Khadas VIM4, используя пример аппаратного кодирования видео aml_enc_test:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
khadas@Khadas:~$ time aml_enc_test 1080p.nv12 dump.h264 1920 1080 30 25 6000000 1125 1 0 2 4 src_url is : 1080p.nv12 ; out_url is : dump.h264 ; width is : 1920 ; height is : 1080 ; gop is : 30 ; frmrate is : 25 ; bitrate is : 6000000 ; frm_num is : 1125 ; fmt is : 1 ; buf_type is : 0 ; num_planes is : 2 ; codec is : 4 ; codec is H264 Set log level to 4 [initEncParams:177] enc_feature_opts is 0x0 , GopPresetis 0x0 [SetupEncoderOpenParam:513] GopPreset GOP format (2) period 30 LongTermRef 0 [vdi_sys_sync_inst_param:618] [VDI] fail to deliver sync instance param inst_idx=0 [AML_MultiEncInitialize:1378] VPU instance param sync with open param failed [SetSequenceInfo:979] Required buffer fb_num=3, src_num=1, actual src=3 1920x1080 Encode End!width:1920 real 0m26.074s user 0m1.832s sys 0m4.883s |
Вывод поясняет используемые параметры. Есть несколько сообщений об ошибках, но видео можно без проблем воспроизвести с помощью ffplay на компьютере.
Мы также можем видеть, что кодирование произошло за 26 секунд, что быстрее, чем в реальном времени, поскольку видео длится 45 секунд.
Попробуем то же самое с кодировкой H.265:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
time aml_enc_test 1080p.nv12 dump.h265 1920 1080 30 25 6000000 1125 1 0 2 5 src_url is : 1080p.nv12 ; out_url is : dump.h265 ; width is : 1920 ; height is : 1080 ; gop is : 30 ; frmrate is : 25 ; bitrate is : 6000000 ; frm_num is : 1125 ; fmt is : 1 ; buf_type is : 0 ; num_planes is : 2 ; codec is : 5 ; codec is H265 Set log level to 4 [initEncParams:177] enc_feature_opts is 0x0 , GopPresetis 0x0 [SetupEncoderOpenParam:513] GopPreset GOP format (2) period 30 LongTermRef 0 [vdi_sys_sync_inst_param:618] [VDI] fail to deliver sync instance param inst_idx=0 [AML_MultiEncInitialize:1378] VPU instance param sync with open param failed [SetSequenceInfo:979] Required buffer fb_num=3, src_num=1, actual src=3 1920x1080 Encode End!width:1920 real 0m9.561s user 0m1.348s sys 0m2.576s |
Это удивительно, но кодирование видео H.265 намного быстрее, чем кодирование видео H.264. Давайте снова попробуем кодировку H.264:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
$ time aml_enc_test 1080p.nv12 dump2.h264 1920 1080 30 25 6000000 1125 1 0 2 4 src_url is : 1080p.nv12 ; out_url is : dump2.h264 ; width is : 1920 ; height is : 1080 ; gop is : 30 ; frmrate is : 25 ; bitrate is : 6000000 ; frm_num is : 1125 ; fmt is : 1 ; buf_type is : 0 ; num_planes is : 2 ; codec is : 4 ; codec is H264 Set log level to 4 [initEncParams:177] enc_feature_opts is 0x0 , GopPresetis 0x0 [SetupEncoderOpenParam:513] GopPreset GOP format (2) period 30 LongTermRef 0 [vdi_sys_sync_inst_param:618] [VDI] fail to deliver sync instance param inst_idx=0 [AML_MultiEncInitialize:1378] VPU instance param sync with open param failed [SetSequenceInfo:979] Required buffer fb_num=3, src_num=1, actual src=3 1920x1080 Encode End!width:1920 real 0m8.780s user 0m1.416s sys 0m2.274s |
Теперь это занимает менее 9 секунд. В первый раз он считывает данные с флэш-памяти eMMC медленно, но, поскольку файл имеет размер 3,3 ГБ, он может поместиться в кеш, поэтому во второй раз узкого места в хранилище нет.
Тем не менее, файл dump.h265 также мог нормально воспроизводиться на компьютере, поэтому преобразование прошло успешно.
Спецификации Amlogic A311D2 говорят, что поддерживается кодирование видео «H.265 и H.264 при 4Kp50». Итак, давайте создадим 45-секундное видео 4Kp50 и конвертируем его в формат NV12 YUV. К сожалению, размер необработанного видео составляет 27 ГБ, и оно не поместится во флэш-память eMMC платы… Давайте сократим это до 30 секунд (около 18 ГБ)…
Теперь мы можем закодировать видео в H.264:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
khadas@Khadas:~$ time aml_enc_test 4k.nv12 dump4k.h264 3840 2160 30 50 10000000 1501 1 0 2 4 src_url is : 4k.nv12 ; out_url is : dump4k.h264 ; width is : 3840 ; height is : 2160 ; gop is : 30 ; frmrate is : 50 ; bitrate is : 10000000 ; frm_num is : 1501 ; fmt is : 1 ; buf_type is : 0 ; num_planes is : 2 ; codec is : 4 ; codec is H264 Set log level to 4 [initEncParams:177] enc_feature_opts is 0x0 , GopPresetis 0x0 [SetupEncoderOpenParam:513] GopPreset GOP format (2) period 30 LongTermRef 0 [vdi_sys_sync_inst_param:618] [VDI] fail to deliver sync instance param inst_idx=0 [AML_MultiEncInitialize:1378] VPU instance param sync with open param failed [SetSequenceInfo:979] Required buffer fb_num=3, src_num=1, actual src=3 3840x2160 Encode End!width:3840 real 2m10.611s user 0m5.819s sys 0m26.130s |
Две минуты, чтобы закодировать 30-секундное видео! Но, увы, это не работает, поэтому давайте снова запустим пример:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
$ time aml_enc_test 4k.nv12 dump4k.h264 3840 2160 30 50 10000000 1501 1 0 2 4 src_url is : 4k.nv12 ; out_url is : dump4k.h264 ; width is : 3840 ; height is : 2160 ; gop is : 30 ; frmrate is : 50 ; bitrate is : 10000000 ; frm_num is : 1501 ; fmt is : 1 ; buf_type is : 0 ; num_planes is : 2 ; codec is : 4 ; codec is H264 Set log level to 4 [initEncParams:177] enc_feature_opts is 0x0 , GopPresetis 0x0 [SetupEncoderOpenParam:513] GopPreset GOP format (2) period 30 LongTermRef 0 [vdi_sys_sync_inst_param:618] [VDI] fail to deliver sync instance param inst_idx=0 [AML_MultiEncInitialize:1378] VPU instance param sync with open param failed [SetSequenceInfo:979] Required buffer fb_num=3, src_num=1, actual src=3 3840x2160 Encode End!width:3840 real 2m22.420s user 0m6.543s sys 0m28.102s |
Это еще медленнее… Мы думаем, что хранилище является узким местом здесь, потому что требуемая скорость чтения для этого файла будет более 600 МБ/с для кодирования в реальном времени. Обычно система кодирует видео из потока камеры, а не из флэш-памяти eMMC. Мы должны были сначала запустить iozone:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
$ iozone -e -I -a -s 1000M -r 4k -r 16k -r 512k -r 1024k -r 16384k -i 0 -i 1 -i 2 Iozone: Performance Test of File I/O Version $Revision: 3.489 $ Compiled for 64 bit mode. Build: linux Output is in kBytes/sec Time Resolution = 0.000001 seconds. Processor cache size set to 1024 kBytes. Processor cache line size set to 32 bytes. File stride size set to 17 * record size. random random bkwd record stride kB reclen write rewrite read reread read write read rewrite read fwrite frewrite fread freread 1024000 4 42448 49401 33738 35273 30351 33959 1024000 16 95388 84746 83386 87949 78675 72818 1024000 512 109351 90438 166659 166804 144584 70463 1024000 1024 68088 98663 175108 174902 164769 58980 1024000 16384 71086 109715 178448 178144 182913 87181 iozone test complete. |
Скорость последовательного чтения составляет около 178 МБ/с. У нас есть USB-концентратор MINIX с твердотельным накопителем на 480 ГБ, который мы тестировали со скоростью 400 МБ/с. Не совсем то, что нам нужно, но это должно привести к улучшениям.
К сожалению, диск не был смонтирован и даже не распознан даже такими инструментами, как fdisk и GParted. При перепроверке спецификаций Khadas VIM4 мы поняли, что порт USB Type-C — это интерфейс USB 2.0 OTG, который должен распознавать накопитель, но поддерживать только 480 Мбит/с, так что в любом случае это безнадежное дело… Единственный способ достичь более 600 МБ/с было бы использовать USB 3.0 NVMe SSD, но у нас его нет.
Вместо этого мы сделаем 5-секундное видео 4Kp50 размером около 2,9 ГБ.
Первый запуск с использованием H.265:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
$ time aml_enc_test 4Kp50-5s.nv12 dump4k-5s.h265 3840 2160 30 50 10000000 249 1 0 2 5 src_url is : 4Kp50-5s.nv12 ; out_url is : dump4k-5s.h265 ; width is : 3840 ; height is : 2160 ; gop is : 30 ; frmrate is : 50 ; bitrate is : 10000000 ; frm_num is : 249 ; fmt is : 1 ; buf_type is : 0 ; num_planes is : 2 ; codec is : 5 ; codec is H265 Set log level to 4 [initEncParams:177] enc_feature_opts is 0x0 , GopPresetis 0x0 [SetupEncoderOpenParam:513] GopPreset GOP format (2) period 30 LongTermRef 0 [vdi_sys_sync_inst_param:618] [VDI] fail to deliver sync instance param inst_idx=0 [AML_MultiEncInitialize:1378] VPU instance param sync with open param failed [SetSequenceInfo:979] Required buffer fb_num=3, src_num=1, actual src=3 3840x2160 Encode End!width:3840 real 0m6.905s user 0m0.661s sys 0m1.885s |
Второй запуск:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
$ time aml_enc_test 4Kp50-5s.nv12 dump4k-5s-2.h265 3840 2160 30 50 10000000 249 1 0 2 5 src_url is : 4Kp50-5s.nv12 ; out_url is : dump4k-5s-2.h265 ; width is : 3840 ; height is : 2160 ; gop is : 30 ; frmrate is : 50 ; bitrate is : 10000000 ; frm_num is : 249 ; fmt is : 1 ; buf_type is : 0 ; num_planes is : 2 ; codec is : 5 ; codec is H265 Set log level to 4 [initEncParams:177] enc_feature_opts is 0x0 , GopPresetis 0x0 [SetupEncoderOpenParam:513] GopPreset GOP format (2) period 30 LongTermRef 0 [vdi_sys_sync_inst_param:618] [VDI] fail to deliver sync instance param inst_idx=0 [AML_MultiEncInitialize:1378] VPU instance param sync with open param failed [SetSequenceInfo:979] Required buffer fb_num=3, src_num=1, actual src=3 3840x2160 Encode End!width:3840 real 0m6.828s user 0m0.663s sys 0m1.822s |
Последняя попытка с H.264:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
$ time aml_enc_test 4Kp50-5s.nv12 dump4k-5s.h264 3840 2160 30 50 5000000 249 1 0 2 4 src_url is : 4Kp50-5s.nv12 ; out_url is : dump4k-5s.h264 ; width is : 3840 ; height is : 2160 ; gop is : 30 ; frmrate is : 50 ; bitrate is : 5000000 ; frm_num is : 249 ; fmt is : 1 ; buf_type is : 0 ; num_planes is : 2 ; codec is : 4 ; codec is H264 Set log level to 4 [initEncParams:177] enc_feature_opts is 0x0 , GopPresetis 0x0 [SetupEncoderOpenParam:513] GopPreset GOP format (2) period 30 LongTermRef 0 [vdi_sys_sync_inst_param:618] [VDI] fail to deliver sync instance param inst_idx=0 [AML_MultiEncInitialize:1378] VPU instance param sync with open param failed [SetSequenceInfo:979] Required buffer fb_num=3, src_num=1, actual src=3 3840x2160 Encode End!width:3840 real 0m6.422s user 0m0.644s sys 0m1.879s |
Не совсем в реальном времени, но приближается, а это значит, что 4Kp30 должно быть возможно. Вот результат с 5-секундным видео 4Kp30 NV12, закодированным с помощью H.264:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
$ time aml_enc_test 4Kp30-5s.nv12 dump4kp30-5s.h264 3840 2160 30 30 5000000 150 1 0 2 4 src_url is : 4Kp30-5s.nv12 ; out_url is : dump4kp30-5s.h264 ; width is : 3840 ; height is : 2160 ; gop is : 30 ; frmrate is : 30 ; bitrate is : 5000000 ; frm_num is : 150 ; fmt is : 1 ; buf_type is : 0 ; num_planes is : 2 ; codec is : 4 ; codec is H264 Set log level to 4 [initEncParams:177] enc_feature_opts is 0x0 , GopPresetis 0x0 [SetupEncoderOpenParam:513] GopPreset GOP format (2) period 30 LongTermRef 0 [vdi_sys_sync_inst_param:618] [VDI] fail to deliver sync instance param inst_idx=0 [AML_MultiEncInitialize:1378] VPU instance param sync with open param failed [SetSequenceInfo:979] Required buffer fb_num=3, src_num=1, actual src=3 3840x2160 Encode End!width:3840 real 0m3.931s user 0m0.378s sys 0m1.161s |
Меньше четырех секунд. Таким образом, аппаратное кодирование видео 4Kp30 H.264 в реальном времени определенно работает на процессоре Amlogic A311D2.
На нашем компьютере играет нормально.
Также возможно кодировать изображения NV12 YUV в JPEG, но это не будет работать с пользователем khadas:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
$ jpeg_enc_test screenshot-1920x1080.nv12 dump.jpg 1920 1080 100 3 0 16 16 0 screenshot-1920x1080.nv12 dump.jpg src url: screenshot-1920x1080.nv12 out url: dump.jpg width : 1920 height : 1080 quality: 100 iformat: 3 oformat: 0 width alignment: 16 height alignment: 16 memory type: VMALLOC align: 1920->1920 align: 1080->1088 hw_encode open device fail, 13:Permission denied jpegenc_init failed |
Но нет проблем с sudo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
khadas@Khadas:~$ time sudo jpeg_enc_test screenshot-1920x1080.nv12 dump.jpg 1920 1080 100 3 0 16 16 0 screenshot-1920x1080.nv12 dump.jpg src url: screenshot-1920x1080.nv12 out url: dump.jpg width : 1920 height : 1080 quality: 100 iformat: 3 oformat: 0 width alignment: 16 height alignment: 16 memory type: VMALLOC align: 1920->1920 align: 1080->1088 mapped address is 0xffffb27f0000 hw_info->mmap_buff.size, 0x2300000, hw_info->input_buf.addr:0x0xffffb27f0000 hw_info->assit_buf.addr, 0x0xffffb466c000, hw_info->output_buf.addr:0x0xffffb46f0000 frame_size=3110400 rd_size=3110400, frame_size=3110400 offset=2088960 luma_stride=1920, h_stride=1088, hw_info->bpp=12 real 0m0.044s user 0m0.004s sys 0m0.009s |
Вероятно, просто проблема с разрешением, задача была выполнена за 44 мс, и мы без проблем смогли открыть dump.jpg (скриншот).
Если используем ffmpeg для преобразования файла NV12 в jpeg, предположительно с программным кодированием, это занимает чуть менее 200 мс:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
khadas@Khadas:~$ time ffmpeg -pix_fmt nv12 -s 1920x1080 -i screenshot-1920x1080-nv12.yuv dump-ffmpeg.jpg ffmpeg version 4.4.1-3ubuntu5 Copyright (c) 2000-2021 the FFmpeg developers built with gcc 11 (Ubuntu 11.2.0-18ubuntu1) configuration: --prefix=/usr --extra-version=3ubuntu5 --toolchain=hardened --libdir=/usr/lib/aarch64-linux-gnu --incdir=/usr/include/aarch64-linux-gnu --arch=arm64 --enable-gpl --disable-stripping --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libdav1d --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librabbitmq --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzimg --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opencl --enable-opengl --enable-sdl2 --enable-pocketsphinx --enable-librsvg --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libx264 --enable-shared libavutil 56. 70.100 / 56. 70.100 libavcodec 58.134.100 / 58.134.100 libavformat 58. 76.100 / 58. 76.100 libavdevice 58. 13.100 / 58. 13.100 libavfilter 7.110.100 / 7.110.100 libswscale 5. 9.100 / 5. 9.100 libswresample 3. 9.100 / 3. 9.100 libpostproc 55. 9.100 / 55. 9.100 [rawvideo @ 0xaaaad7c07100] Estimating duration from bitrate, this may be inaccurate Input #0, rawvideo, from 'screenshot-1920x1080-nv12.yuv': Duration: 00:00:00.04, start: 0.000000, bitrate: 622080 kb/s Stream #0:0: Video: rawvideo (NV12 / 0x3231564E), nv12, 1920x1080, 622080 kb/s, 25 tbr, 25 tbn, 25 tbc Stream mapping: Stream #0:0 -> #0:0 (rawvideo (native) -> mjpeg (native)) Press [q] to stop, [?] for help [swscaler @ 0xaaaad7c1d2a0] deprecated pixel format used, make sure you did set range correctly Output #0, image2, to 'dump-ffmpeg.jpg': Metadata: encoder : Lavf58.76.100 Stream #0:0: Video: mjpeg, yuvj420p(pc, progressive), 1920x1080, q=2-31, 200 kb/s, 25 fps, 25 tbn Metadata: encoder : Lavc58.134.100 mjpeg Side data: cpb: bitrate max/min/avg: 0/0/200000 buffer size: 0 vbv_delay: N/A frame= 1 fps=0.0 q=10.8 size=N/A time=00:00:00.04 bitrate=N/A speed=4e+04x frame= 1 fps=0.0 q=10.8 Lsize=N/A time=00:00:00.04 bitrate=N/A speed=0.514x video:123kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown real 0m0.190s user 0m0.150s sys 0m0.037s |
aml_enc_test и jpeg_enc_test — небольшие утилиты для тестирования аппаратного кодирования видео/изображений в Linux на Amlogic A311D2, но исходный код был бы хорош для интеграции этого в приложение. Но в настоящее время он не является общедоступным, поэтому мы предполагаем, что он является частью Amlogic SDK. Мы попросим у компании Khadas исходный код или способ его получения.
Выражаем свою благодарность источнику из которого взята и переведена статья, сайту cnx-software.com.
Оригинал статьи вы можете прочитать здесь.