summaryrefslogtreecommitdiff
path: root/meta-raspberrypi
diff options
context:
space:
mode:
authorAndrew Geissler <geissonator@yahoo.com>2023-01-13 17:55:19 +0300
committerAndrew Geissler <geissonator@yahoo.com>2023-01-13 21:05:42 +0300
commit517393d903089f921915530ffa689a7a1d113420 (patch)
tree8bac829cbf7fe13f7f1a4d937e1997d923755ed6 /meta-raspberrypi
parent98ccb1903bfb490dc6075e694664d8f1edef74dd (diff)
downloadopenbmc-517393d903089f921915530ffa689a7a1d113420.tar.xz
subtree updates Jan-13-2023
meta-openembedded: d04444509a..cd13881611: Alex Kiernan (10): mdns: Upgrade 1310.140.1 -> 1790.40.31 mdns: Set MDNS_VERSIONSTR_NODTS mdns: Upgrade 1790.40.31 -> 1790.60.25 ostree: Upgrade 2022.5 -> 2022.7 ostree: Use systemd_system_unitdir for systemd units ostree: Switch to fuse3 which is supported in ostree now ostree: Fix comments for configuration/ptest ostree: Handle musl's ERANGE mapping usbguard: Remove pegtl from DEPENDS usbguard: Upgrade 1.1.1 -> 1.1.2 Alex Stewart (2): gvfs: stylize DEPENDS gvfs: obviate the ssh-client requirement for gvfs Alexander Kanavin (5): frr: add a patch to correctly check presence of python from pkg-config lirc: correctly use PYTHONPATH libportal: move to oe-core packagegroup-meta-python: drop python3-strict-rfc3339 nftables: fix builds with latest setuptools Alexander Stein (1): dool: Add patch to fix rebuild Archana Polampalli (1): Nodejs - Upgrade to 16.18.1 Bartosz Golaszewski (3): python3-kmod: new package python3-watchdogdev: new package packagegroup-meta-python: add missing packages Bruce Ashfield (1): zfs: update to 2.1.7 Changqing Li (5): linuxptp: fix do_compile error keyutils: fix ptest failed since "+++ Can't Determine Endianness" graphviz: Do not build tcl support for native redis: 6.2.7 -> 6.2.8 redis: 7.0.5 -> 7.0.7 Chen Pei (2): suitesparse:fix git branch in SRC_URI botan: upgrade 2.19.2 -> 2.19.3 Chen Qi (4): xfce4-verve-plugin: fix do_configure faiure about missing libpcre networkmanager: fix dhcpcd PACKAGECONFIG networkmanager: install config files into correct place networkmanager: fix /etc/resolv.conf handling Christian Eggers (1): boost-url: remove recipe Clément Péron (3): navigation: bump proj to 9.1.0 library proj: add a packageconfig to build as a static library proj: avoid leaking host path in libproj Devendra Tewari (1): android-tools: Use echo instead of bbnote Dmitry Baryshkov (1): nss: fix cross-compilation error Erwann Roussy (3): python3-schedutils: add recipe python3-linux-procfs: add recipe tuna: add recipe Fabio Estevam (2): remmina: Update to 1.4.28 crucible: Upgrade to 2022.12.06 Geoff Parker (1): python3-yappi: upgrade 1.3.6 -> 1.4.0, python 3.11 compatible Gerbrand De Laender (1): python3-aioserial: new package Gianfranco Costamagna (2): vbxguestdrivers: upgrade 7.0.2 -> 7.0.4 boinc-client: Update boinc from 7.18.1 to 7.20.4 Gianluigi Spagnuolo (1): libbpf: add native and nativesdk BBCLASSEXTEND Hains van den Bosch (2): python3-twisted: Add python3-asyncio to RDEPENDS python3-twisted: Add python3-typing-extensions to RDEPENDS He Zhe (1): protobuf: upgrade 3.21.5 -> 3.21.10 Jose Quaresma (1): lshw: bump to 42fef565 Kai Kang (31): freeradius: fix multilib systemd service start failure wxwidgets: 3.1.5 -> 3.2.1 python3-attrdict3: add recipe with version 2.0.2 python3-wxgtk4: 4.1.1 -> 4.2.0 xfce4-settings: 4.16.3 -> 4.16.5 python3-m2crypto: fix CVE-2020-25657 and buildpaths qa issue fixup! wxwidgets: 3.1.5 -> 3.2.1 postfix: fix multilib conflict of sample-main.cf python3-wxgtk4: replace deprecated inspect.getargspec libxfce4ui: 4.16.1 -> 4.18.0 thunar-volman: 4.16.0 -> 4.18.0 xfce4-cpufreq-plugin: 1.2.7 -> 1.2.8 xfce4-wavelan-plugin: 0.6.2 -> 0.6.3 xfce4-cpugraph-plugin: 1.2.6 -> 1.2.7 xfce4-sensors-plugin: 1.4.3 -> 1.4.4 thunar-shares-plugin: Bump GLib minimum required to 2.26 xfce4-dev-tools: 4.16.0 -> 4.18.0 libxfce4util: 4.16.0 -> 4.18.0 exo: 4.16.4 -> 4.18.0 garcon: 4.16.1 -> 4.18.0 xfce4-panel: 4.16.3 -> 4.18.0 thunar: 4.16.9 -> 4.18.0 tumbler: 4.16.0 -> 4.18.0 xfconf: 4.16.0 -> 4.18.0 xfce4-appfinder: 4.16.1 -> 4.18.0 xfce4-settings: 4.16.5 -> 4.18.0 xfce4-power-manager: 4.16.0 -> 4.18.0 xfce4-session: 4.16.0 -> 4.18.0 xfwm4: 4.16.1 -> 4.18.0 xfdesktop: 4.16.0 -> 4.18.0 xorg-lib: set XORG_EXT for recipes Khem Raj (91): gnome-text-editor: Add missing libpcre build time depenedency ettercap: Add missing dependency on libpcre xcb-util-cursor: Update to 0.1.4 lldpd: Use github release assets for SRC_URI aufs-util: Fix build with large file support enabled systems volume-key: Inherit python3targetconfig proj: Enable apps when building native variant python3-pyproj: Export PROJ_DIR satyr: Inherit python3targetconfig rest: Re-add 0.8.1 gfbgraph: Use rest 0.8.1 audit: Inherit python3targetconfig opensaf: Check for _FILE_OFFSET_BITS instead of __TIMESIZE flite: Add missing deps on alsa-lib and chrpath python3-pystemd: Regenerate .c sources using newer cython libreport: Inherit python3targetconfig uw-imap: Disable parallelism gnome-calendar: Upgrade to 43.1 gnome-photos: Upgrade to 43.0 libgweather: Remove 40.0 waf-samba.bbclass: point PYTHON_CONFIG to target python3-config amtk: Add missing dep on python3-pygments-native fontforge: Inherit python3targetconfig tepl: Add missing dep on python3-pygments-native alsa-oss: Remove recipe opencv: Check for commercial_ffmpeg as well to enable ffmpeg opencv: Fix build with ffmpeg 5.1+ fwts: Upgrade to 22.11.00 minio: Disable on mips sip: Add recipe for 6.7.5 imapfilter: Upgrade to 2.7.6 perfetto: Do not pass TUNE_CCARGS to native/host compiler stressapptest: Upgrade to latest tip mariadb: Upgrade to 10.11.1 surf: Depend on gcr3 fatcat: Enable 64bit off_t stressapptest: Fix build with largefile support and musl nspr: Upgrade to 4.35 cryptsetup: Upgrade to 2.6.0 libyui,libyui-ncurses: Upgrade to 4.2.3 inotify-tools: Fix build on musl and lfs64 sdbus-c++-libsystemd: Upgrade to 250.9 systemd release xfsprogs: Upgrade to 6.0.0 drbd,drbd-utils: Upgrade to 9.2.1 and drbd-utils to 9.22.0 libtraceevent: Add recipe libtracefs: Add recipe trace-cmd: Remove use of off64_t and lseek64 xfsdump: Add -D_LARGEFILE64_SOURCE on musl xfstests: Add -D_LARGEFILE64_SOURCE on musl mariadb: Alias lseek64/open64/ftruncate64 on musl systems gperftools: Define off64_t on musl android-tools: Define lseek64 = lseek on musl php: Add -D_LARGEFILE64_SOURCE to cflags spice-gtk: Use libucontext for coroutines on musl wxwidgets: Fix build with musl wxwidgets: Fix locale on musl wxwidgets: Set HAVE_LARGEFILE_SUPPORT python3-wxgtk4: Do not use GetAssertStackTrace with USE_STACKWALKER disabled f2fs-tools: Upgrade to 1.15.0 trace-cmd: Pass ldflags to compiler parole: Define DATADIRNAME abseil-cpp: Replace off64_t with off_t vsftpd_3.0.5.bb: Define _LARGEFILE64_SOURCE on musl mozjs-102: Disable mozilla stackwalk on musl fatresize: Fix build when 64bit time_t is enabled boinc-client: Fix build when using 64bit time_t python3-grpcio: Define -D_LARGEFILE64_SOURCE only for musl gnome-online-accounts: Fix build race seen on musl systems imagemagick: Do not set ac_cv_sys_file_offset_bits spdlog: Do not use LFS64 functions with musl mongodb: Do not use off64_t on musl dracut: Do not undefine _FILE_OFFSET_BITS libcamera: Diable 64bit time_t on glibc targets v4l-utils: Diable 64bit time_t on glibc targets opensaf: Fix the check for __fsblkcnt64_t size libcereal,poco: Link with -latomic on ppc32 as well sshpass: Use SPDX identified string for GPLv2 nftables: Upgrade to 1.0.6 mycroft: Check for pulseaudio in distro features trace-cmd: Build libs before building rest open-vm-tools: Fix build with 64-bit time_t libtraceevent: Move plugins into package of its own trace-cmd: Upgrade to 3.1.5 luajit: Update to latest on v2.1 branch concurrencykit: Update to 0.7.0 concurrencykit: Set correct PLAT value for riscv32 concurrencykit: Fix build on riscv32 and riscv64 sysbench: Enable only on architectures supporting LuaJIT packagegroup-meta-oe: Ensure sysbench is included in limited arches hwloc: Update to 2.9.0 fluentbit: Link with libatomic on ppc32 Lei Maohui (1): polkit: Fix multilib builds Leon Anavi (9): python3-watchdog: Upgrade 2.2.0 -> 2.2.1 python3-zeroconf: Upgrade 0.39.4 -> 0.47.1 python3-croniter: Upgrade 1.3.7 -> 1.3.8 python3-coverage: Upgrade 7.0.1 -> 7.0.3 python3-prompt-toolkit: Upgrade 3.0.31 -> 3.0.36 python3-simplejson: Upgrade 3.18.0 -> 3.18.1 python3-termcolor: Upgrade 2.1.1 -> 2.2.0 python3-cantools: Upgrade 37.2.0 -> 38.0.0 python3-marshmallow: Upgrade 3.18.0 -> 3.19.0 Livin Sunny (1): libwebsockets: add ipv6 in PACKAGECONFIG Markus Volk (88): blueman: add RDEPEND on python3-fcntl hwdata: add patch to use sysroot prefix for pkgdatadir pipewire: upgrade 0.3.59 -> 0.3.60 spirv-cross: upgrade; fix build blueman: upgrade 2.34 -> 2.35 pipewire: upgrade 0.3.60 -> 0.3.61 iwd: upgrade 1.30 -> 2.0 libgdata: use gcr3 libgweather: update 4.0.0 -> 4.2.0 gnome-online-accounts: use gcr3 geary: build with gcr3 gnome-keyring: use gcr3 evolution-data-server: update 3.44.2 -> 3.46.1 gnome-settings-daemon: update 42.1 -> 43.0 libnma: update 1.8.38 -> 1.10.4 geocode-glib: build with libsoup-3.0 gjs: update 1.72.2 -> 1.75.1 gnome-shell: update 42.0 -> 43.1 mutter: update 42.0 -> 43.1 polkit: add recipe for v122 mozjs: update 98 -> 102 appstream-glib: update 0.7.18 -> 0.8.2 gthumb: build with libsoup-3 amtk: update 5.3.1 -> 5.6.1 gedit: update 42.2 -> 43.2 evolution-data-server: remove libgdata dependency tepl: update 6.0.0 -> 6.2.0 perfetto: pass TUNE_CCARGS to use machine tune gnome-photos: update dependencies thunar-archive-plugin: update 0.4.0 -> 0.5.0 libadwaita: remove deprecated sassc-native dependency gnome-shell: remove deprecated sassc-native dependency spice-gtk: add missing license information pipewire: update 0.3.61 -> 0.3.62 gdm: update 42.0 -> 43.0 gnome-session: update 42.0 -> 43-0 geoclue: update to latest commit to allow to build with libsoup-3.0 gvfs: fix polkit homedir editorconfig: add recipe tracker: update 3.4.1 -> 3.4.2 gvfs: fix dependencies gnome-calculator: update 42.2 -> 43.0.1 tracker-miners: update 3.4.1 -> 3.4.2 gnome-photos: add missing runtime dependency on tracker-miners gtksourceview5: update 5.4.2 -> 5.6.1 remmina: build with libsoup-3.0 ostree: replace libsoup-2.4 by curl gnome-text-editor: update 42.2 -> 43.1 gtk4: remove recipe libxmlb: allow to build native pipewire: update 0.3.62 -> 0.3.63 gnome-shell-extensions: update SRC_URI and remove sassc-native dep grilo: update 0.3.14 -> 0.3.15 libstemmer: move recipe to meta-oe xdg-desktop-portal: add recipe bubblewrap: import recipe from meta-security gnome-software: add recipe basu: import recipe from meta-wayland xdg-desktop-portal-wlr: add recipe appstream: add recipe flatpak: add recipe flatpak-xdg-utils: add recipe flatpak: add runtime dependency on flatpak-xdg-utils wireplumber: update 0.4.12 -> 0.4.13 wireplumber: build with dbus support by default xdg-desktop-portal-gnome: add recipe libcloudproviders: add recipe evince: update 42.3 -> 43.1 libportal: build libportal-gtk4 and vala support nautilus: update 42.2 -> 43.1 gnome-desktop: update 42.0 -> 43 file-roller: update 3.42.0 -> 43.0 wireplumber: dont start systemd system service by default gnome-bluetooth: update 42.4 -> 42.5 gnome-flashback: update 3.44.0 -> 3.46.0 libwnck3: update 40.1 -> 43.0 gnome-panel: update 3.44.0 -> 3.47.1 gnome-terminal: update 3.42.2 -> 3.46.7 dconf-editor: update 3.38.3 -> 43.0 gnome-shell: add missing RDEPENDS gnome-control-center: update 42.0 -> 43.2 gnome-shell: add runtime dependency on adwaita-icon-theme xdg-desktop-portal-gtk: add recipe thunar: add tumbler to RRECOMMENDS gnome:terminal add missing inherit meson gnome-disk-utility: update 42.0 -> 43.0 eog: add recipe libdecor: import recipe Martin Jansa (3): nss: fix SRC_URI geoclue: fix polkit files only with modem-gps PACKAGECONFIG layer.conf: update LAYERSERIES_COMPAT for mickledore Mathieu Dubois-Briand (2): nss: Add missing CVE product nss: Whitelist CVEs related to libnssdbm Matthias Klein (1): paho-mqtt-c: upgrade 1.3.11 -> 1.3.12 Max Krummenacher (1): opencv: follow changed name license_flags_accepted Mingli Yu (25): gnome-calculator: add opengl to REQUIRED_DISTRO_FEATURES waylandpp: add opengl to REQUIRED_DISTRO_FEATURES libnma: add opengl to REQUIRED_DISTRO_FEATURES network-manager-applet: add opengl to REQUIRED_DISTRO_FEATURES gssdp: check opengl is enabled or not gtksourceview5: add opengl to REQUIRED_DISTRO_FEATURES gnome-font-viewer: add opengl to REQUIRED_DISTRO_FEATURES libxfce4ui: check opengl DISTRO_FEATURES gnome-desktop: add opengl to REQUIRED_DISTRO_FEATURES ibus: add opengl related check nautilus: add opengl to REQUIRED_DISTRO_FEATURES gnome-bluetooth: add opengl to REQUIRED_DISTRO_FEATURES evince: add opengl to REQUIRED_DISTRO_FEATURES gnome-calendar: add opengl to REQUIRED_DISTRO_FEATURES xf86-video-amdgpu: add opengl to REQUIRED_DISTRO_FEATURES spice-gtk: add opengl to REQUIRED_DISTRO_FEATURES grail: add opengl to REQUIRED_DISTRO_FEATURES frame: add opengl to REQUIRED_DISTRO_FEATURES geis: add opengl to REQUIRED_DISTRO_FEATURES evolution-data-server: add opengl to REQUIRED_DISTRO_FEATURES libgweather4: add opengl to REQUIRED_DISTRO_FEATURES geary: add opengl to REQUIRED_DISTRO_FEATURES file-roller: add opengl to REQUIRED_DISTRO_FEATURES gnome-photos: add opengl to REQUIRED_DISTRO_FEATURES xdg-desktop-portal-wlr: add opengl to REQUIRED_DISTRO_FEATURES Naveen Saini (3): opencl-headers: add native and nativesdk tcsh: add native nativesdk BBCLASSEXTEND tbb: upgrade 2021.5.0 -> 2021.7.0 Omkar Patil (1): ntfs-3g-ntfsprogs: Upgrade 2022.5.17 to 2022.10.3 Ovidiu Panait (1): multipath-tools: upgrade 0.8.4 -> 0.9.3 Peter Bergin (1): sysbench: Upgrade 0.4.12 -> 1.0.20 Peter Kjellerstedt (4): chrony: Make it possible to enable editline support again chrony: Remove the libcap and nss PACKAGECONFIGs Revert "lldpd: Use github release assets for SRC_URI" lldpd: Correct the checksum for the tar ball to match 1.0.16 Preeti Sachan (1): fluidsynth: update SRC_URI to remove non-existing 2.2.x branch Roger Knecht (1): python3-rapidjson: add recipe Sakib Sajal (1): minio: fix license information Samuli Piippo (1): protobuf: stage protoc binary to sysroot Tim Orling (4): libio-pty-perl: upgrade 1.16 -> 1.17; enable ptest libmozilla-ca-perl: add recipe for 20221114 libio-socket-ssl-perl: upgrade 2.075 -> 2.076 libtest-warnings-perl: move to oe-core Tomasz Żyjewski (2): python3-binwalk: add recipe for version 2.3.3 python3-uefi-firmware: add recipe for version 1.9 Wang Mingyu (190): byacc: upgrade 20220128 -> 20221106 libforms: upgrade 1.2.4 -> 1.2.5pre1 libnftnl: upgrade 1.2.3 -> 1.2.4 mpich: upgrade 4.0.2 -> 4.0.3 python3-u-msgpack-python: upgrade 2.7.1 -> 2.7.2 python3-aiosignal: upgrade 1.2.0 -> 1.3.1 python3-eth-hash: upgrade 0.5.0 -> 0.5.1 python3-frozenlist: upgrade 1.3.1 -> 1.3.3 python3-google-auth: upgrade 2.14.0 -> 2.14.1 python3-greenlet: upgrade 2.0.0 -> 2.0.1 python3-imageio: upgrade 2.22.3 -> 2.22.4 python3-pycocotools: upgrade 2.0.5 -> 2.0.6 babl: upgrade 0.1.96 -> 0.1.98 ctags: upgrade 5.9.20221106.0 -> 5.9.20221113.0 gegl: upgrade 0.4.38 -> 0.4.40 freerdp: upgrade 2.8.1 -> 2.9.0 glibmm-2.68: upgrade 2.72.1 -> 2.74.0 googlebenchmark: upgrade 1.7.0 -> 1.7.1 gnome-backgrounds: upgrade 42.0 -> 43 nano: upgrade 6.4 -> 7.0 networkmanager-openvpn: upgrade 1.10.0 -> 1.10.2 python3-django: upgrade 4.1 -> 4.1.3 python3-flask-migrate: upgrade 3.1.0 -> 4.0.0 python3-eth-utils: upgrade 2.0.0 -> 2.1.0 python3-eventlet: upgrade 0.33.1 -> 0.33.2 python3-googleapis-common-protos: upgrade 1.56.4 -> 1.57.0 python3-google-api-python-client: upgrade 2.65.0 -> 2.66.0 python3-pymongo: upgrade 4.3.2 -> 4.3.3 lldpd: upgrade 1.0.15 -> 1.0.16 audit: upgrade 3.0.8 -> 3.0.9 ccid: upgrade 1.5.0 -> 1.5.1 colord: upgrade 1.4.5 -> 1.4.6 ctags: upgrade 5.9.20221113.0 -> 5.9.20221120.0 flatbuffers: upgrade 22.10.26 -> 22.11.23 libglvnd: upgrade 1.5.0 -> 1.6.0 gensio: upgrade 2.5.2 -> 2.6.1 mg: upgrade 20220614 -> 20221112 nbdkit: upgrade 1.33.2 -> 1.33.3 xfstests: upgrade 2022.10.30 -> 2022.11.06 pcsc-lite: upgrade 1.9.8 -> 1.9.9 python3-matplotlib-inline: upgrade 0.1.2 -> 0.1.6 python3-astroid: upgrade 2.12.12 -> 2.12.13 python3-asyncinotify: upgrade 2.0.5 -> 2.0.8 python3-charset-normalizer: upgrade 3.0.0 -> 3.0.1 python3-dateparser: upgrade 1.1.0 -> 1.1.4 python3-can: upgrade 4.0.0 -> 4.1.0 python3-flask-socketio: upgrade 5.3.1 -> 5.3.2 python3-ipython: upgrade 8.2.0 -> 8.6.0 python3-langtable: upgrade 0.0.60 -> 0.0.61 python3-jedi: upgrade 0.18.1 -> 0.18.2 python3-grpcio-tools: upgrade 1.50.0 -> 1.51.0 python3-grpcio: upgrade 1.50.0 -> 1.51.0 python3-networkx: upgrade 2.8.7 -> 2.8.8 python3-pyatspi: upgrade 2.38.2 -> 2.46.0 python3-pandas: upgrade 1.5.1 -> 1.5.2 python3-pybind11-json: upgrade 0.2.11 -> 0.2.13 python3-pychromecast: upgrade 12.1.4 -> 13.0.1 python3-pycodestyle: upgrade 2.9.1 -> 2.10.0 xterm: upgrade 373 -> 377 smarty: upgrade 4.2.1 -> 4.3.0 spdlog: upgrade 1.10.0 -> 1.11.0 python3-pyperf: upgrade 2.4.1 -> 2.5.0 python3-pyflakes: upgrade 2.5.0 -> 3.0.1 python3-pymisp: upgrade 2.4.157 -> 2.4.165.1 capnproto: upgrade 0.10.2 -> 0.10.3 libass: upgrade 0.16.0 -> 0.17.0 ctags: upgrade 5.9.20221120.0 -> 5.9.20221127.0 libio-socket-ssl-perl: upgrade 2.076 -> 2.077 python3-grpcio-tools: upgrade 1.51.0 -> 1.51.1 python3-asyncinotify: upgrade 2.0.8 -> 3.0.1 python3-grpcio: upgrade 1.51.0 -> 1.51.1 opensc: upgrade 0.22.0 -> 0.23.0 python3-ipython: upgrade 8.6.0 -> 8.7.0 ply: upgrade 2.2.0 -> 2.3.0 python3-apt: upgrade 2.3.0 -> 2.5.0 poppler: upgrade 22.11.0 -> 22.12.0 python3-asttokens: upgrade 2.1.0 -> 2.2.0 python3-cbor2: upgrade 5.4.3 -> 5.4.5 python3-geomet: upgrade 0.3.0 -> 1.0.0 python3-google-api-core: upgrade 2.10.2 -> 2.11.0 python3-google-api-python-client: upgrade 2.66.0 -> 2.68.0 python3-path: upgrade 16.5.0 -> 16.6.0 python3-google-auth: upgrade 2.14.1 -> 2.15.0 zabbix: upgrade 6.2.4 -> 6.2.5 xmlsec1: upgrade 1.2.36 -> 1.2.37 smcroute: upgrade 2.5.5 -> 2.5.6 python3-protobuf: upgrade 4.21.9 -> 4.21.10 python3-traitlets: upgrade 5.5.0 -> 5.6.0 python3-twine: upgrade 4.0.1 -> 4.0.2 python3-web3: upgrade 5.31.1 -> 5.31.2 python3-ujson: upgrade 5.5.0 -> 5.6.0 ctags: upgrade 5.9.20221127.0 -> 5.9.20221204.0 dnsmasq: upgrade 2.87 -> 2.88 flatbuffers: upgrade 22.11.23 -> 22.12.06 nbdkit: upgrade 1.33.3 -> 1.33.4 hwdata: upgrade 0.364 -> 0.365 evolution-data-server: update 3.46.1 -> 3.46.2 xfstests: upgrade 2022.11.06 -> 2022.11.27 python3-protobuf: upgrade 4.21.10 -> 4.21.11 python3-traitlets: upgrade 5.6.0 -> 5.7.0 python3-redis: upgrade 4.3.5 -> 4.4.0 python3-web3: upgrade 5.31.2 -> 5.31.3 python3-asttokens: upgrade 2.2.0 -> 2.2.1 python3-cbor2: upgrade 5.4.5 -> 5.4.6 python3-google-api-python-client: upgrade 2.68.0 -> 2.69.0 python3-gmpy2: upgrade 2.1.2 -> 2.1.3 python3-multidict: upgrade 6.0.2 -> 6.0.3 python3-watchdog: upgrade 2.1.9 -> 2.2.0 python3-pychromecast: upgrade 13.0.1 -> 13.0.2 python3-pymisp: upgrade 2.4.165.1 -> 2.4.166 python3-pytest-xdist: upgrade 3.0.2 -> 3.1.0 python3-yarl: upgrade 1.8.1 -> 1.8.2 zabbix: upgrade 6.2.5 -> 6.2.6 python3-yamlloader: upgrade 1.1.0 -> 1.2.2 tio: upgrade 2.3 -> 2.4 ctags: upgrade 5.9.20221204.0 -> 6.0.20221218.0 dash: upgrade 0.5.11.5 -> 0.5.12 nanopb: upgrade 0.4.6.4 -> 0.4.7 libio-socket-ssl-perl: upgrade 2.077 -> 2.078 libfile-slurper-perl: upgrade 0.013 -> 0.014 protobuf: upgrade 3.21.10 -> 3.21.12 python3-alembic: upgrade 1.8.1 -> 1.9.0 nano: upgrade 7.0 -> 7.1 python3-gmpy2: upgrade 2.1.3 -> 2.1.5 python3-eth-account: upgrade 0.7.0 -> 0.8.0 python3-google-api-python-client: upgrade 2.69.0 -> 2.70.0 python3-protobuf: upgrade 4.21.11 -> 4.21.12 python3-pycares: upgrade 4.2.2 -> 4.3.0 python3-pycurl: upgrade 7.45.1 -> 7.45.2 python3-pychromecast: upgrade 13.0.2 -> 13.0.4 python3-pyproj: upgrade 3.4.0 -> 3.4.1 python3-pydicti: upgrade 1.1.6 -> 1.2.0 python3-sentry-sdk: upgrade 1.11.1 -> 1.12.0 python3-traitlets: upgrade 5.7.0 -> 5.7.1 tio: upgrade 2.4 -> 2.5 python3-sqlalchemy: upgrade 1.4.44 -> 1.4.45 xfsdump: upgrade 3.1.11 -> 3.1.12 python3-isort: upgrade 5.10.1 -> 5.11.3 xfstests: upgrade 2022.11.27 -> 2022.12.11 ctags: upgrade 6.0.20221218.0 -> 6.0.20221225.0 gst-editing-services: upgrade 1.20.4 -> 1.20.5 logcheck: upgrade 1.3.24 -> 1.4.0 memtester: upgrade 4.5.1 -> 4.6.0 libmime-types-perl: upgrade 2.22 -> 2.23 metacity: upgrade 3.46.0 -> 3.46.1 python3-alembic: upgrade 1.9.0 -> 1.9.1 xfstests: upgrade 2022.12.11 -> 2022.12.18 python3-cytoolz: upgrade 0.12.0 -> 0.12.1 python3-asgiref: upgrade 3.5.2 -> 3.6.0 python3-autobahn: upgrade 22.7.1 -> 22.12.1 python3-coverage: upgrade 6.5.0 -> 7.0.1 python3-bitarray: upgrade 2.6.0 -> 2.6.1 python3-imageio: upgrade 2.22.4 -> 2.23.0 python3-isort: upgrade 5.11.3 -> 5.11.4 python3-multidict: upgrade 6.0.3 -> 6.0.4 python3-traitlets: upgrade 5.7.1 -> 5.8.0 python3-pymisp: upgrade 2.4.166 -> 2.4.167 python3-sentry-sdk: upgrade 1.12.0 -> 1.12.1 python3-supervisor: upgrade 4.2.4 -> 4.2.5 wolfssl: upgrade 5.5.3 -> 5.5.4 remmina: upgrade 1.4.28 -> 1.4.29 ser2net: upgrade 4.3.10 -> 4.3.11 tesseract: upgrade 5.2.0 -> 5.3.0 network-manager-applet: upgrade 1.26.0 -> 1.30.0 byacc: upgrade 20221106 -> 20221229 ctags: upgrade 6.0.20221225.0 -> 6.0.20230101.0 flashrom: upgrade 1.2 -> 1.2.1 fontforge: upgrade 20220308 -> 20230101 hunspell: upgrade 1.7.1 -> 1.7.2 libmime-types-perl: upgrade 2.23 -> 2.24 libnet-dns-perl: upgrade 1.35 -> 1.36 tepl: upgrade 6.2.0 -> 6.4.0 tcpdump: upgrade 4.99.1 -> 4.99.2 traceroute: upgrade 2.1.0 -> 2.1.1 openwsman: upgrade 2.7.1 -> 2.7.2 pcsc-tools: upgrade 1.6.0 -> 1.6.1 poppler: upgrade 22.12.0 -> 23.01.0 rsnapshot: upgrade 1.4.4 -> 1.4.5 tree: upgrade 2.0.4 -> 2.1.0 python3-bidict: upgrade 0.22.0 -> 0.22.1 python3-bitarray: upgrade 2.6.1 -> 2.6.2 python3-dateparser: upgrade 1.1.4 -> 1.1.5 python3-lz4: upgrade 4.0.2 -> 4.3.2 python3-mock: upgrade 4.0.3 -> 5.0.0 python3-pillow: upgrade 9.3.0 -> 9.4.0 python3-pydantic: upgrade 1.10.2 -> 1.10.4 python3-pyephem: upgrade 4.1.3 -> 4.1.4 python3-xlsxwriter: upgrade 3.0.3 -> 3.0.5 python3-xxhash: upgrade 3.1.0 -> 3.2.0 dnf-plugins/rpm.py: Fix grammar when RPM_PREFER_ELF_ARCH doesn't exit. Xiangyu Chen (1): lldpd: add ptest for lldpd package Yi Zhao (13): libpwquality: set correct pam plugin directory ostree: add runtime dependency bubblewrap for PACKAGECONFIG[selinux] ostree: fix selinux policy rebuild error on first deployment frr: upgrade 8.3.1 -> 8.4.1 open-vm-tools: upgrade 12.1.0 -> 12.1.5 libtdb: upgrade 1.4.3 -> 1.4.7 libldb: upgrade 2.3.4 -> 2.6.1 libtalloc: upgrade 2.3.3 -> 2.3.4 libtevent: upgrade 0.10.2 -> 0.13.0 samba upgrade 4.14.14 -> 4.17.4 krb5: upgrade 1.17.2 -> 1.20.1 grubby: update to latest git rev grubby: drop version 8.40 Zheng Qiu (1): python3-inotify: add ptest persianpros (1): samba: Remove samba related PYTHONHASHSEED patches and use export function zhengrq.fnst@fujitsu.com (15): python3-pymodbus: upgrade 3.0.0 -> 3.0.2 python3-pywbemtools: upgrade 1.0.1 -> 1.1.0 python3-stevedore: upgrade 4.1.0 -> 4.1.1 ser2net: upgrade 4.3.9 -> 4.3.10 yelp-tools: upgrade 42.0 -> 42.1 python3-python-vlc: upgrade 3.0.16120 -> 3.0.18121 python3-sqlalchemy: upgrade 1.4.43 -> 1.4.44 python3-zopeinterface: upgrade 5.5.1 -> 5.5.2 python3-simplejson: upgrade 3.17.6 -> 3.18.0 python3-pywbemtools: upgrade 1.0.1 -> 1.1.1 python3-redis: upgrade 4.3.4 -> 4.3.5 python3-texttable: upgrade 1.6.4 -> 1.6.7 python3-sentry-sdk: upgrade 1.9.10 -> 1.11.1 python3-twitter: upgrade 4.10.1 -> 4.12.1 python3-termcolor: upgrade 2.1.0 -> 2.1.1 meta-security: 2aa48e6f4e..f991b20f56: Alex Kiernan (1): bubblewrap: Update 0.6.2 -> 0.7.0 Armin Kuster (2): python3-privacyidea: update to 2.7.4 chipsec: update to 1.9.1 Michael Haener (1): tpm2-tools: update to 5.3 meta-arm: d5f132b199..5c42f084f7: Adam Johnston (1): arm/trusted-services: Fix 'no such file' when building libts Adrian Herrera (2): atp: decouple m5readfile from m5ops atp: move m5readfile to meta-gem5 Adrián Herrera Arcila (5): atp: fix failing test_readme gem5: support for EXTRAS atp: separate recipe for gem5 models atp: fix machine overrides in recipes ci: add meta-atp to check-layers David Bagonyi (1): meta-arm-toolchain: Drop calls to datastore finalize Diego Sueiro (2): arm/classes: Introduce apply_local_src_patches bbclass arm/trusted-firmware-m: Fix local source patches application Emekcan (1): arm/fvp: Upgrade Corstone1000 FVP Emekcan Aras (6): arm-bsp/documentation: corstone1000: update the user guide arm/optee: Move optee-3.18 patches arm/optee: support optee 3.19 arm-bsp/optee-os: Adds 3.19 bbappend arm-bsp/optee-os: N1SDP support for optee-os 3.19 arm/qemuarm-secureboot: pin optee-os version Jon Mason (5): arm-bsp/trusted-services: rename bbappends with git version arm/trusted-services: limit the ts compatible machines arm-bsp/trusted-services: add n1sdp support arm/trusted-firmware-m: update to 1.6.1 CI: define DEFAULT_TAG and CPU_REQUEST Khem Raj (1): gn: Replace lfs64 functions with original counterparts Mohamed Omar Asaker (5): arm-bsp/trusted-services: corstone1000: Use the stateless platform service calls arm-bsp/trusted-firmware-m: Bump TFM to v1.7 arm-bsp/trusted-firmware-m: corstone1000: TFM 1.7 arm-bsp/musca_b1: Edit the platform name arm-bsp/trusted-firmware-m: Remove TF-M 1.6 recipe Peter Hoyes (3): arm/fvp: Backport shlex.join from Python 3.8 arm/fvpboot: Disable timing annotation by default arm/classes: Ensure patch files are sorted in apply_local_src_patches Robbie Cao (1): arm/fvp-base-r-aem: upgrade to version 11.20.15 Ross Burton (17): CI: revert a meta-clang change which breaks pixman (thus, xserver) CI: add variables needed for k8s runners CI: add tags to all jobs CI: no need to install telnet CI: fix builds with clang CI: use the .setup fragment in machine-coverage arm/fvp-base-a-aem: upgrade to 11.20.15 arm-bsp/edk2-firmware: allow clang builds on juno ci/get-binary-toolchains: rewrite, slightly arm-bsp/documentation: update fvp-base documentation to use runfvp CI: use qemuarm64 for pending-updates report job meta-atp: remove meta-gem5: remove arm/fvp-envelope: name the FVP tarballs for checksums arm/fvp-envelope: update HOMEPAGE arm/fvp-base-a-aem: add support for aarch64 binaries CI: don't pin fvp-base jobs to x86-64 poky: 44bb88cc86..0ce159991d: Alejandro Hernandez Samaniego (6): baremetal-image: Avoid overriding qemu variables from IMAGE_CLASSES rust: Enable building rust from stable, beta and nightly channels rust: Enable baremetal targets baremetal-helloworld: Enable x86 and x86-64 ports baremetal-helloworld: Move from skeleton to recipes-extended matching what rust-hello-world is doing oe-selftest: Add baremetal toolchain test Alex Kiernan (20): rust: Install target.json for target rustc rust: update 1.65.0 -> 1.66.0 oeqa/runtime/rust: Add basic compile/run test libstd-rs: Merge .inc into .bb libstd-rs: Move source directory to library/test rust-llvm: Merge .inc into .bb rust-llvm: Update LLVM_VERSION to match embedded version packagegroup-rust-sdk-target: Add Rust SDK target packagegroup packagegroup-core-sdk: Add SDK toolchain language selection support rust: Merge .inc into .bb rust: Move musl-x86 fix for `__stack_chk_fail_local` to rust-source cargo: Merge .inc into .bb cargo: Extend DEBUG_PREFIX_MAP to cover vendor cargo: Include crossbeam-utils patch cargo: Drop exclude from world packagegroup-rust-sdk-target: Add cargo oeqa/runtime/rust: Add cargo test classes: image: Set empty weak default IMAGE_LINGUAS default-distrovars: Include "c" in IMAGE_LINGUAS for glibc rust: Merge all rustc-source patches into rust-source.inc Alex Stewart (2): lsof: add update-alternatives logic opkg: upgrade to version 0.6.1 Alexander Kanavin (155): elfutils: update 0.187 -> 0.188 rsync: update 3.2.5 -> 3.2.7 swig: update 4.0.2 -> 4.1.0 tcl: update 8.6.11 -> 8.6.12 quota: update 4.06 -> 4.09 shadow: update 4.12.3 -> 4.13 texinfo: update 6.8 -> 7.0 libhandy: update 1.6.3 -> 1.8.0 xf86-input-mouse: update 1.9.3 -> 1.9.4 flac: update 1.4.0 -> 1.4.2 icu: update 71.1 -> 72-1 libgpg-error: update 1.45 -> 1.46 popt: update 1.18 -> 1.19 vte: update 0.68.0 -> 0.70.1 webkitgtk: update 2.36.7 -> 2.38.2 man-db: update 2.10.2 -> 2.11.1 gawk: update 5.1.1 -> 5.2.1 unfs: update 0.9.22 -> 0.10.0 qemu-helper: depend on unfs3 and pseudo directly runqemu: do not hardcode the ip address of the nfs server when using tap selftest/runqemu: reenable the nfs rootfs test glibc-tests: correctly pull in the actual tests when installing -ptest package python3: fix tests on x86 (32 bit) ptest-packagelists.inc: do not run valgrind ptests on 32 bit x86 python3: use the standard shell version of python3-config python3targetconfig.bbclass: use PYTHONPATH to point to the target config bitbake: fetch2/wget.py: correctly match versioned directories devtool/upgrade: correctly handle recipes where S is a subdir of upstream tree python3-numpy: fix upstream version check python3-poetry-core: update 1.3.2 -> 1.4.0 tcl: update 8.6.12 -> 8.6.13 libnewt: update 0.52.21 -> 0.52.23 libxdmcp: update 1.1.3 -> 1.1.4 libxpm: update 3.5.13 -> 3.5.14 libxrandr: update 1.5.2 -> 1.5.3 bluez: update 5.65 -> 5.66 libxcrypt: update PV to match SRCREV python3-dbusmock: update 0.28.4 -> 0.28.6 ruby: merge .inc into .bb ruby: update 3.1.2 -> 3.1.3 ghostscript: update 9.56.1 -> 10.0.0 tzdata: update 2022d -> 2022g systemtap: upgrade 4.7 -> 4.8 gnupg: upgrade 2.3.7 -> 2.3.8 ptest-packagelists.inc: correctly assign fast and slow tests ovmf: update edk2-stable202208 -> edk2-stable202211 llvm: update 15.0.4 -> 15.0.6 tcmode-default.inc: set LLVMVERSION to a major version wildcard cmake: update 3.24.2 -> 3.25.1 python3-native: further tweak to sysconfig.py to find python includes correctly libslirp: add recipe to continue slirp support in qemu qemu: update 7.1.0 -> 7.2.0 systemd: update 251.8 -> 252.4 dpkg: update 1.21.9 -> 1.21.13 python3-installer: update 0.5.1 -> 0.6.0 python3: update 3.11.0 -> 3.11.1 weston: update 11.0.0 -> 11.0.1 xhost: update 1.0.8 -> 1.0.9 xinit: update 1.4.1 -> 1.4.2 xkbcomp: update 1.4.5 -> 1.4.6 xprop: update 1.2.5 -> 1.2.6 xset: update 1.2.4 -> 1.2.5 xvinfo: update 1.1.4 -> 1.1.5 xf86-video-vesa: update 2.5.0 -> 2.6.0 libice: update 1.0.10 -> 1.1.1 libxcomposite: update 0.4.5 -> 0.4.6 libxdamage: update 1.1.5 -> 1.1.6 libxres: update 1.2.1 -> 1.2.2 libxscrnsaver: update 1.2.3 -> 1.2.4 libxv: update 1.0.11 -> 1.0.12 jquery: upgrade 3.6.1 -> 3.6.2 libmodule-build-perl: update 0.4231 -> 0.4232 python3-chardet: upgrade 5.0.0 -> 5.1.0 libarchive: upgrade 3.6.1 -> 3.6.2 stress-ng: upgrade 0.15.00 -> 0.15.01 vulkan: upgrade 1.3.231.1 -> 1.3.236.0 Revert "python3-native: further tweak to sysconfig.py to find python includes correctly" conf/machine/include: add x86-64-v3 tunes (AVX, AVX2, BMI1, BMI2, F16C, FMA, LZCNT, MOVBE, XSAVE) go: update 1.19.3 -> 1.19.4 vulkan-samples: update to latest revision boost-build-native: update 1.80.0 -> 1.81.0 qemu: disable sporadically failing test-io-channel-command devtool: process local files only for the main branch libportal: add from meta-openembedded/meta-gnome libportal: convert from gtk-doc to gi-docgen epiphany: update 42.4 -> 43.0 qemux86-64: build for x86-64-v3 (2013 Haswell and later) rather than Core 2 from 2006 valgrind: disable tests that started failing after switching to x86-64-v3 target glib-2.0: upgrade 2.74.3 -> 2.74.4 jquery: upgrade 3.6.2 -> 3.6.3 nasm: update 2.15.05 -> 2.16.01 ffmpeg: use nasm patched-in debug-prefix-map option to restore reproducibility gtk+3: update 3.24.35 -> 3.24.36 libva-utils: update 2.16.0 -> 2.17.0 xcb-util: update 0.4.0 -> 0.4.1 gnupg: update 2.3.8 -> 2.4.0 libksba: update 1.6.2 -> 1.6.3 python3-pycryptodomex: upgrade 3.15.0 -> 3.16.0 piglit: upgrade to latest revision python3-setuptools-scm: upgrade 7.0.5 -> 7.1.0 python3-attrs: upgrade 22.1.0 -> 22.2.0 webkitgtk: upgrade 2.38.2 -> 2.38.3 linux-firmware: upgrade 20221109 -> 20221214 harfbuzz: upgrade 5.3.1 -> 6.0.0 python3-pytz: upgrade 2022.6 -> 2022.7 strace: upgrade 6.0 -> 6.1 python3-pycryptodome: upgrade 3.15.0 -> 3.16.0 meson: upgrade 0.64.0 -> 1.0.0 xwayland: upgrade 22.1.5 -> 22.1.7 python3-pyrsistent: upgrade 0.19.2 -> 0.19.3 file: upgrade 5.43 -> 5.44 python3-subunit: upgrade 1.4.1 -> 1.4.2 python3-zipp: upgrade 3.10.0 -> 3.11.0 python3-cryptography: upgrade 38.0.3 -> 38.0.4 logrotate: upgrade 3.20.1 -> 3.21.0 python3-importlib-metadata: upgrade 5.0.0 -> 5.2.0 python3-numpy: upgrade 1.23.4 -> 1.24.1 xserver-xorg: upgrade 21.1.4 -> 21.1.6 puzzles: upgrade to latest revision vte: upgrade 0.70.1 -> 0.70.2 libpsl: upgrade 0.21.1 -> 0.21.2 libtest-fatal-perl: upgrade 0.016 -> 0.017 python3-urllib3: upgrade 1.26.12 -> 1.26.13 python3-cryptography-vectors: upgrade 38.0.3 -> 38.0.4 python3-setuptools: upgrade 65.5.1 -> 65.6.3 libsdl2: upgrade 2.26.0 -> 2.26.1 python3-gitdb: upgrade 4.0.9 -> 4.0.10 diffoscope: upgrade 224 -> 230 python3-mako: upgrade 1.2.3 -> 1.2.4 python3-sphinx: upgrade 5.3.0 -> 6.0.0 libsolv: upgrade 0.7.22 -> 0.7.23 ruby: upgrade 3.1.3 -> 3.2.0 python3-lxml: upgrade 4.9.1 -> 4.9.2 python3-git: upgrade 3.1.29 -> 3.1.30 curl: upgrade 7.86.0 -> 7.87.0 kmscube: upgrade to latest revision gobject-introspection: upgrade 1.72.0 -> 1.74.0 python3-dtschema: upgrade 2022.11 -> 2022.12 bash: upgrade 5.2.9 -> 5.2.15 kexec-tools: upgrade 2.0.25 -> 2.0.26 python3-jsonschema: upgrade 4.17.0 -> 4.17.3 python3-pycairo: upgrade 1.21.0 -> 1.23.0 nghttp2: upgrade 1.50.0 -> 1.51.0 python3-certifi: upgrade 2022.9.24 -> 2022.12.7 python3-hypothesis: upgrade 6.57.1 -> 6.61.0 libsndfile1: upgrade 1.1.0 -> 1.2.0 repo: upgrade 2.29.9 -> 2.31 libpcap: upgrade 1.10.1 -> 1.10.2 python3-jsonschema: depend on rfc3339-validator in all cases python3-strict-rfc3339: remove the recipe elfutils: do not error out on deprecated declarations gcr3: limit version check to 3.x versions without odd-even rule ncurses: restore version check as it's now again working due to release of 6.4 tiff: update 4.4.0 -> 4.5.0 qemu: fix recent reproducibility issues Alexey Smirnov (1): classes: make TOOLCHAIN more permissive for kernel Anton Antonov (1): rust: Do not use default compiler flags defined in CC crate Antonin Godard (2): busybox: always start do_compile with orig config files busybox: rm temporary files if do_compile was interrupted Atanas Bunchev (1): qemu.rst: slirp port forwarding details Bruce Ashfield (30): linux-yocto-dev: bump to v6.0+ linux-yocto/5.19: update to v5.19.16 linux-yocto/5.15: update to v5.15.74 linux-yocto/5.19: update to v5.19.17 linux-yocto/5.15: update to v5.15.76 linux-yocto/5.19: cfg: intel and vesa updates kern-tools: integrate ZFS speedup patch linux-yocto-dev: bump to v6.1 kernel-devsrc: fix for v6.1+ lttng-modules: fix build for v6.1+ linux-yocto/5.19: security.cfg: remove configs which have been dropped linux-yocto/5.15: update to v5.15.78 linux-yocto/5.19: fix CONFIG_CRYPTO_CCM mismatch warnings linux-yocto/5.15: fix CONFIG_CRYPTO_CCM mismatch warnings linux-yocto/5.19: fix elfutils run-backtrace-native-core ptest failure linux-libc-headers: add 6.x fetch location linux-libc-headers: bump to 6.1 linux-yocto/5.19: fix perf build with clang linux-yocto/5.15: ltp and squashfs fixes linux-yocto: introduce v6.1 reference kernel recipes linux-yocto/5.15: fix perf build with clang linux-yocto/5.15: libbpf: Fix build warning on ref_ctr_off linux-yocto/5.15: update to v5.15.84 linux-yocto/6.1: update to v6.1.1 linux-yocto/5.15: powerpc: Fix reschedule bug in KUAP-unlocked user copy linux-yocto/5.19: powerpc: Fix reschedule bug in KUAP-unlocked user copy linux-yocto/6.1: update to v6.1.3 linux-yocto/6.1: cfg: remove CONFIG_ARM_CRYPTO yocto-bsps/5.15: update to v5.15.78 linux-yocto/5.15: update to v5.15.80 Carlos Alberto Lopez Perez (3): xwayland: libxshmfence is needed when dri3 is enabled recipes: Enable nativesdk for gperf, unifdef, gi-docgen and its dependencies mesa-gl: gallium is required when enabling x11 Changqing Li (2): base.bbclass: Fix way to check ccache path sqlite3: upgrade 3.40.0 -> 3.40.1 Charlie Johnston (1): opkg: ensure opkg uses private gpg.conf when applying keys. Chee Yang Lee (1): migration-guides: add release-notes for 4.1.1 Chen Qi (10): kernel.bbclass: make KERNEL_DEBUG_TIMESTAMPS work at rebuild resolvconf: make it work dhcpcd: fix to work with systemd bitbake: command.py: cleanup bb.cache.parse_recipe psplash: consider the situation of psplash not exist for systemd bc: extend to nativesdk rm_work: adjust dependency to make do_rm_work_all depend on do_rm_work selftest: allow '-R' and '-r' be used together dhcpcd: backport two patches to fix runtime error libseccomp: fix typo in DESCRIPTION Christian Eggers (1): boost: add url lib David Bagonyi (1): u-boot: Fix u-boot signing when building with multiple u-boot configs Dmitry Baryshkov (2): linux-firmware: upgrade 20221012 -> 20221109 linux-firmware: add new fw file to ${PN}-qcom-adreno-a530 Enguerrand de Ribaucourt (1): bitbake-layers: fix a typo Enrico Jörns (1): sstatesig: emit more helpful error message when not finding sstate manifest Enrico Scholz (1): sstate: show progress bar again Fabre Sébastien (1): u-boot: Add /boot in SYSROOT_DIRS Frank de Brabander (4): bitbake: README: Improve explanation about running the testsuite bitbake: bin/utils: Ensure locale en_US.UTF-8 is available on the system bitbake: process: log odd unlink events with bitbake.sock bitbake: README: add required python version for bitbake Harald Seiler (1): opkg: Set correct info_dir and status_file in opkg.conf Jagadeesh Krishnanjanappa (1): qemuboot.bbclass: make sure runqemu boots bundled initramfs kernel image Jan Kircher (1): toolchain-scripts: compatibility with unbound variable protection Javier Tia (1): poky.conf: Add Fedora 36 as supported distro Joe Slater (2): python3: Fix CVE-2022-37460 libarchive: fix CVE-2022-36227 Jose Quaresma (2): Revert "gstreamer1.0: disable flaky gstbin:test_watch_for_state_change test" gstreamer1.0: Fix race conditions in gstbin tests Joshua Watt (4): qemu-helper-native: Correctly pass program name as argv[0] bitbake: cooker: Use event to terminate parser threads bitbake: cooker: Start sync thread a little earlier bitbake: bitbake: Convert to argparse Kai Kang (4): xorg-lib-common.inc: set default value of XORG_EXT libx11-compose-data: 1.6.8 -> 1.8.3 libx11: 1.8.1 -> 1.8.3 libsm: 1.2.3 > 1.2.4 Kasper Revsbech (1): bitbake: fetch2/wget: handle username/password in uri Khem Raj (47): rsync: Delete pedantic errors re-ordering patch pseudo: Disable LFS on 32bit arches libxkbcommon: Extend to build native package iso-codes: Extend to build native packages xkeyboard-config: Extend to build native package bluez5: enable position independent executables flag rpcsvc-proto: Use autoconf knob to enable largefile support gptfdisk: Enable largefile support functions libpcre2: Upgrade to 10.42 erofs-utils: Convert from off64_t to off_t pseudo: Remove 64bit time_t flags unfs3: Define off64_t in terms of off_t on musl acpid: Fix largefile enabled build efivar: Replace off64_t with off_t ltp: Fix largefile support acl: Enable largefile support by default libpciaccess: Do not use 64bit functions for largefile support mdadm: Use _FILE_OFFSET_BITS to use largefile support btrfs-tools: Do not use 64bit functions for largefile support e2fsprogs: Do not use 64bit functions for largefile support libbsd: Fix build with largefile support gpgme: Fix with with largefile support virglrenderer: Replace lseek64 with lseek nfs-utils: Replace statfs64 with statfs alsa-utils: Replace off64_t with off_t lttng-tools: Fix build with largefile support strace: Add knob to enable largefile support numactl: Enable largefile support qemu: Fix build with largefile support systemd: Fix 252 release build on musl rust: Do not use open64 on musl in getrandom crate rust,libstd-rs: Fix build with latest musl rust-llvm: Fix build on latest musl cargo: Do not use open64 on musl anymore llvm: Do not use lseek64 strace: Replace off64_t with off_t in sync_file_range.c test vulkan-samples: Do not use LFS64 APIs in spdlog pulseaudio: Do not use 64bit time_t flags musl: Update to latest on tip of trunk rust: Fix build with 64bit time_t stress-ng: Do not enforce gold linker time64.inc: Add GLIBC_64BIT_TIME_FLAGS on ppc/x86 as well time64: Remove leading whitespace from GLIBC_64BIT_TIME_FLAGS mpg123: Enable largefile support site/powerpc32-linux: Do not cache statvfs64 across glibc and musl tiff: Add packageconfig knob for webp site/common-musl: Set ac_cv_sys_file_offset_bits default to 64 Lee Chee Yang (1): migration-guides: add release-notes for 4.0.6 Luca Boccassi (2): systemd: refresh patch to remove fuzz introduced by rebase on v252 systemd: ship pcrphase/measure tools and units in systemd-extra-utils Luis (1): rm_work.bbclass: use HOSTTOOLS 'rm' binary exclusively Marek Vasut (5): bitbake: fetch2/git: Prevent git fetcher from fetching gitlab repository metadata package_rpm: Fix Linux 6.1.0 perf 1.0 version mistranslation systemd: Make importd depend on glib-2.0 again bitbake: bitbake-user-manual: Document override :append, :prepend, :remove order bitbake: fetch2/git: Clarify the meaning of namespace Markus Volk (12): ell: upgrade 0.53 -> 0.54 libsdl2: update 2.24.2 -> 2.26.0 graphene: import from meta-oe gtk4: import recipe from meta-gnome gcr: rename gcr -> gcr3 gcr: add recipe for gcr-4, needed to build with gtk4 epiphany: use gcr3 gtk4: add tracker-miners runtime dependency python3-dbusmock: allow to build native gtk4: update 4.8.2 -> 4.8.3 gcr3: update 3.40.0 -> 3.41.1 librsvg: enable vapi build Marta Rybczynska (2): efibootmgr: update compilation with musl cve-update-db-native: avoid incomplete updates Martin Jansa (4): libxml2: upgrade test data from 20080827 to 20130923 nativesdk-rpm: export RPM_ETCCONFIGDIR and MAGIC in environment like RPM_CONFIGDIR nativesdk-rpm: don't create wrappers for WRAPPER_TOOLS tune-x86-64-v3.inc: set QEMU_EXTRAOPTIONS like other tune-* files Mathieu Dubois-Briand (1): dbus: Add missing CVE product name Michael Halstead (1): uninative: Upgrade to 3.8.1 to include libgcc Michael Opdenacker (34): manuals: add missing references to classes manuals: fix paragraphs with the "inherit" word ref-manual/classes.rst: remove reference to sip.bbclass manuals: simplify .gitignore files manuals: split dev-manual/common-tasks.rst dev-manual/sbom.rst: minor corrections bitbake: bitbake-user-manual: update references to Yocto Project manual bitbake.conf: remove SERIAL_CONSOLE variable bitbake: bitbake-user-manual: add reference to bitbake git repository ref-manual: add references to variables only documented in the BitBake manual manuals: add reference to yocto-docs git repository to page footer manuals: add missing references to variables manuals: add missing SPDX license header to source files manuals: fix double colons ref-manual/resources.rst: fix formating ref-manual: update references to release notes manual: improve documentation about using external toolchains ref-manual/images.rst: fix unnumbered list manuals: define proper numbered lists manuals: final removal of SERIAL_CONSOLE variable ref-manual/resources.rst: improve description of mailing lists ref-manual/system-requirements.rst: update buildtools instructions manuals: create references to buildtools documentation/poky.yaml.in: update minimum python version to 3.8 manuals: prepare 4.2 migration notes bitbake: bitbake-user-manual: double colon fix bitbake: bitbake-user-manual: remove "OEBasic" signature generator migration-guides: fix 4.2 migration note issues toaster-manual: fix description of introduction video ref-manual/classes.rst: remove .bbclass from section titles manuals: simplify references to classes migration-1.6.rst: fix redundant reference ref-manual/system-requirements.rst: recommend buildtools for not supported distros .gitignore: ignore files generated by Toaster Mikko Rapeli (5): qemurunner.py: support setting slirp host IP address runqemu: limit slirp host port forwarding to localhost 127.0.0.1 qemurunner.py: use IP address from command line dev-manual/runtime-testing.rst: fix oeqa runtime test path runqemu: add QB_SETUP_CMD and QB_CLEANUP_CMD Mingli Yu (8): tcl: correct the header location in tcl.pc python3: make tkinter available when enabled sudo: add selinux and audit PACKAGECONFIG iproute2: add selinux PACKAGECONFIG util-linux: add selinux PACKAGECONFIG cronie: add selinux PACKAGECONFIG psmisc: add selinux PACKAGECONFIG gcr: add opengl to REQUIRED_DISTRO_FEATURES Narpat Mali (2): ffmpeg: fix for CVE-2022-3964 ffmpeg: fix for CVE-2022-3965 Ola x Nilsson (4): kbd: Don't build tests glibc: Add ppoll fortify symbol for 64 bit time_t insane: Add QA check for 32 bit time and file offset functions time64.conf: Include to enable 64 bit time flags Ovidiu Panait (1): kernel.bbclass: remove empty module directories to prevent QA issues Patrick Williams (1): kernel-fitimage: reduce dependency to the cpio Pavel Zhukov (1): oeqa/rpm.py: Increase timeout and add debug output Peter Kjellerstedt (1): recipes, classes: Avoid adding extra whitespace to PACKAGESPLITFUNCS Peter Marko (2): externalsrc: fix lookup for .gitmodules oeqa/selftest/externalsrc: add test for srctree_hash_files Petr Kubizňák (1): harfbuzz: remove bindir only if it exists Petr Vorel (1): iputils: update to 20221126 Polampalli, Archana (1): libpam: fix CVE-2022-28321 Qiu, Zheng (3): valgrind: remove most hidden tests for arm64 tiff: Security fix for CVE-2022-3970 vim: upgrade 9.0.0820 -> 9.0.0947 Quentin Schulz (4): cairo: update patch for CVE-2019-6461 with upstream solution cairo: fix CVE patches assigned wrong CVE number docs: kernel-dev: faq: update tip on how to not include kernel in image docs: migration-guides: migration-4.0: specify variable name change for kernel inclusion in image recipe Randy MacLeod (1): valgrind: skip the boost_thread test on arm Ranjitsinh Rathod (1): curl: Correct LICENSE from MIT-open-group to curl Ravula Adhitya Siddartha (2): linux-yocto/5.15: update genericx86* machines to v5.15.78 linux-yocto/5.19: update genericx86* machines to v5.19.17 Richard Purdie (97): bitbake: cache/cookerdata: Move recipe parsing functions from cache to databuilder bitbake: cache: Drop broken/unused code bitbake: cache: Drop unused function bitbake: server: Ensure cooker profiling works bitbake: worker/runqueue: Reduce initial data transfer in workerdata bitbake: cache: Drop support for not saving the cache file bitbake: runqueue: Add further debug for sstate reuse issues bitbake: runqueue: Fix race issues around hash equivalence and sstate reuse bitbake: data/siggen: Switch to use frozensets and optimize bitbake: data_smart: Add debugging for overrides stability issue bitbake: utils: Allow to_boolean to support int values base: Drop do_package base definition bitbake: data: Drop obsolete pydoc/path code bitbake: BBHandler: Remove pointless global variable declarations bitbake: runqueue: Improve error message for missing multiconfig bitbake: data_smart: Small cache reuse optimization bitbake.conf: Simplify CACHE setting oeqa/selftest/tinfoil: Add test for separate config_data with recipe_parse_file() qemu: Ensure libpng dependency is deterministic bitbake: data: Tweak code layout bitbake: cache/siggen: Simplify passing basehash data into the cache bitbake: siggen/cache: Optionally allow adding siggen hash data to the bitbake cache bitbake: parse: Add support for addpylib conf file directive and BB_GLOBAL_PYMODULES bitbake: cookerdata: Ensure layers use LAYERSERIES_COMPAT fairly base: Switch to use addpylib directive and BB_GLOBAL_PYMODULES devtool/friends: Use LAYERSERIES_CORENAMES when generating LAYERSERIES_COMPAT entries scripts/checklayer: Update to match bitbake changes yocto-check-layer: Allow OE-Core to be tested bitbake: main: Add timestamp to server retry messages bitbake: main/server: Add lockfile debugging upon server retry poky/poky-tiny: Drop largefile mentions lib/sstatesig: Drop OEBasic siggen bitbake: siggen: Drop non-multiconfig aware siggen support bitbake: build/siggen/runqueue: Drop do_setscene references bitbake: bitbake: Bump minimum python version requirement to 3.8 sanity: Update minimum python version to 3.8 bitbake: main/process: Add extra sockname debugging Revert "kernel-fitimage: reduce dependency to the cpio" bitbake: siggen: Directly store datacaches reference bitbake: bitbake: siggen/runqueue: Switch to using RECIPE_SIGGEN_INFO feature for signature dumping bitbake: siggen: Add dummy dataCaches from task context/datastore bitbake: build/siggen: Rework stamps functions bitbake: siggen: Clarify which fn is meant bitbake: ast/data/codeparser: Add dependencies from python module functions bitbake: codeparser/data: Add vardepsexclude support to module dependency code bitbake.conf: Add module function vardepsexclude entries time64: Rename to a .inc file to match the others bitbake: command: Add ping command bitbake: cache: Allow compression of the data in SiggenRecipeInfo bitbake: siggen: Minor code improvement bitbake: server/process: Add bitbake.sock race handling oeqa/concurrencytest: Add number of failures to summary output python3-poetry-core: Fix determinism issue breaking reproducibility bitbake: cache/siggen: Fix cache issues with signature handling bitbake: event: builtins fix for 'd' deletion bitbake: cooker: Ensure cache is cleared for partial resets bitbake: tinfoil: Ensure CommandExit is handled bitbake: cache: Drop reciever side counting for SiggenRecipeInfo bitbake: knotty: Avoid looping with tracebacks bitbake: event: Add enable/disable heartbeat code bitbake: cooker/cookerdata: Rework the way the datastores are reset bitbake: server/process: Improve exception and idle function logging bitbake: command: Tweak finishAsyncCommand ordering to avoid races bitbake: cooker: Ensure commands clean up any parser processes bitbake: server/process: Improve idle loop exit code bitbake: event: Always use threadlock bitbake: server/process: Add locking around idle functions accesses bitbake: server/process: Run idle commands in a separate idle thread bitbake: knotty: Ping the server/cooker periodically bitbake: cookerdata: Fix cache/reparsing issue bitbake: cookerdata: Fix previous commit to use a string, not a generator bitbake: command: Ensure that failure cases call finishAsyncComand layer.conf: Update to use mickledore as the layer series name layer.conf: Mark master as compatible with mickledore bitbake: lib/bb: Update thread/process locks to use a timeout package: Move fixup_perms function to bb function library package: Move get_conffiles/files_from_filevars functions to lib package: Move pkgdata handling functions to oe.packagedata package: Move emit_pkgdata to packagedata.py package: Move package functions to function library package: Drop unused function and obsolete comment package: Move mapping_rename_hook to packagedata function library python3-cython: Use PACKAGESPLITFUNCS instead of PACKAGEBUILDPKGD package: Drop support for PACKAGEBUILDPKGD function customisation recipes/classes: Drop prepend/append usage with PACKAGESPLITFUNCS bitbake: cooker: Rework the parsing results submission bitbake: cooker: Clean up inotify idle handler uninative-tarball: Add libgcc patchelf: Add fix submitted upstream for uninative segfaults bitbake: cooker/command: Drop async command handler indirection via cooker bitbake: process/cooker/command: Fix currentAsyncCommand locking/races uninative: Ensure uninative is enabled in all cases for BuildStarted event qemux86-64: Reduce tuning to core2-64 bitbake: tinfoil: Don't wait for events indefinitely bitbake: knotty: Improve shutdown handling bitbake: cooker: Fix exit handling issues bitbake: server/process: Move heartbeat to idle thread Robert Andersson (1): go-crosssdk: avoid host contamination by GOCACHE Ross Burton (28): build-appliance-image: Update to master head revision lib/buildstats: fix parsing of trees with reduced_proc_pressure directories combo-layer: remove unused import combo-layer: dont use bb.utils.rename combo-layer: add sync-revs command libxml2: upgrade 2.9.14 -> 2.10.3 libxml2: add more testing python3-packaging: upgrade to 22.0 python3-hatchling: remove python3-tomli DEPENDS python3-cryptography: remove python3-tomli RDEPENDS meson: drop redundant is_debianlike() patch meson: always use meson subcommands libepoxy: remove upstreamed patch gtk+3: upgrade 3.24.34 -> 3.24.35 gtk+3: port to Meson meson: no need to rebuild on install at-spi2-core: clean up x11 enabling at-spi2-core: disable API docs if x11 is disabled gtk+3: fix reproducible builds lsof: upgrade 4.96.4 -> 4.96.5 pango: upgrade 1.50.11 -> 1.50.12 python3-hatch-vcs: upgrade 0.2.0 -> 0.3.0 python3-hatchling: upgrade 1.11.1 -> 1.12.1 python3-pathspec: upgrade 0.10.1 -> 0.10.3 rm_work: handle non-existant stamps directory oeqa/selftest/debuginfod: improve testcase elfutils: disable deprecation errors in all builds, not just native curl: don't enable debug builds Ryan Eatmon (1): go: Update reproducibility patch to fix panic errors Sandeep Gundlupet Raju (3): libdrm: Remove libdrm-kms package kernel-fitimage: Adjust order of dtb/dtbo files kernel-fitimage: Allow user to select dtb when multiple dtb exists Saul Wold (1): at: Change when files are copied Sergei Zhmylev (1): oeqa/qemurunner: implement vmdk images support Tim Orling (7): python3-hypothesis: upgrade 6.56.4 -> 6.57.1 at-spi2-core: upgrade 2.44.1 -> 2.46.0 mirrors.bbclass: update CPAN_MIRROR libtry-tiny-perl: add recipe for 0.31 libtest-fatal-perl: add recipe for 0.016 libtest-warnings-perl: move from meta-perl liburi-perl: upgrade 5.08 -> 5.17 Trevor Woerner (1): local.conf.sample: update bbclass locations Vincent Davis Jr (1): mesa: enable glvnd support Wang Mingyu (49): btrfs-tools: upgrade 6.0 -> 6.0.1 libpipeline: upgrade 1.5.6 -> 1.5.7 btrfs-tools: upgrade 6.0.1 -> 6.0.2 bind: upgrade 9.18.8 -> 9.18.9 ccache: upgrade 4.7.2 -> 4.7.4 dropbear: upgrade 2022.82 -> 2022.83 libinput: upgrade 1.21.0 -> 1.22.0 libxft: upgrade 2.3.6 -> 2.3.7 mpfr: upgrade 4.1.0 -> 4.1.1 glib-2.0: upgrade 2.74.1 -> 2.74.3 libxcrypt-compat: upgrade 4.4.30 -> 4.4.33 patchelf: upgrade 0.16.1 -> 0.17.0 pciutils: upgrade 3.8.0 -> 3.9.0 shaderc: upgrade 2022.3 -> 2022.4 sqlite3: upgrade 3.39.4 -> 3.40.0 stress-ng: upgrade 0.14.06 -> 0.15.00 swig: upgrade 4.1.0 -> 4.1.1 texinfo: upgrade 7.0 -> 7.0.1 usbutils: upgrade 014 -> 015 xz: upgrade 5.2.7 -> 5.2.9 wayland-protocols: upgrade 1.28 -> 1.31 gnu-config: upgrade to latest revision libfontenc: upgrade 1.1.6 -> 1.1.7 libpcre2: upgrade 10.40 -> 10.41 libpng: upgrade 1.6.38 -> 1.6.39 libxau: upgrade 1.0.10 -> 1.0.11 libxkbfile: upgrade 1.1.1 -> 1.1.2 libxshmfence: upgrade 1.3.1 -> 1.3.2 xrandr: upgrade 1.5.1 -> 1.5.2 boost: upgrade 1.80.0 -> 1.81.0 ell: upgrade 0.54 -> 0.55 git: upgrade 2.38.1 -> 2.39.0 help2man: upgrade 1.49.2 -> 1.49.3 iproute2: upgrade 6.0.0 -> 6.1.0 libmpc: upgrade 1.2.1 -> 1.3.1 makedepend: upgrade 1.0.7 -> 1.0.8 psmisc: upgrade 23.5 -> 23.6 xz: upgrade 5.2.9 -> 5.4.0 gstreamer1.0: upgrade 1.20.4 -> 1.20.5 bind: upgrade 9.18.9 -> 9.18.10 btrfs-tools: upgrade 6.0.2 -> 6.1 librepo: upgrade 1.14.5 -> 1.15.1 libsdl2: upgrade 2.26.1 -> 2.26.2 libva-utils: upgrade 2.17.0 -> 2.17.1 libxkbcommon: upgrade 1.4.1 -> 1.5.0 mpfr: upgrade 4.1.1 -> 4.2.0 dpkg: upgrade 1.21.13 -> 1.21.17 rxvt-unicode: upgrade 9.30 -> 9.31 virglrenderer: upgrade 0.10.3 -> 0.10.4 Xiangyu Chen (3): grub: backport patches to fix CVE-2022-28736 openssh: remove RRECOMMENDS to rng-tools for sshd package grub2: backport patch to fix CVE-2022-2601 CVE-2022-3775 Yoann Congal (2): bitbake: Group and reorder options in bitbake help bitbake: main: Move --buildfile help at the end of "Execution" group leimaohui (1): libpng: Enable NEON for aarch64 to enensure consistency with arm32. pgowda (1): binutils: Add patch to fix CVE-2022-4285 张忠山 (1): bitbake: data_smart: Use regex consistently for override matching meta-raspberrypi: 93dadf336c..896566aa92: Carlos Alberto Lopez Perez (1): weston: disablepackageconfig options that fail to build with userland drivers Khem Raj (2): lirc: Drop upstreamed patch linux-raspberrypi.inc: Weakly assign COMPATIBLE_MACHINE Martin Jansa (2): bluez5: update patches to apply on 5.66 version layer.conf: update LAYERSERIES_COMPAT for mickledore Vincent Davis Jr (5): rpidistro-vlc,rpidistro-ffmpeg: update COMPATIBLE_HOST regex rpidistro-vlc: upgrade 3.0.12 -> 3.0.17 rpi-default-providers: add libav and libpostproc rpidistro-ffmpeg: upgrade 4.3.2 -> 4.3.4 rpidistro-ffmpeg: remove --enable-v4l2-request flag Signed-off-by: Andrew Geissler <geissonator@yahoo.com> Change-Id: Ied8537beedde0f83790e6e3595057db45f408107
Diffstat (limited to 'meta-raspberrypi')
-rw-r--r--meta-raspberrypi/conf/layer.conf2
-rw-r--r--meta-raspberrypi/conf/machine/include/rpi-default-providers.inc2
-rw-r--r--meta-raspberrypi/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc/lirc-gpio-ir-0.10.patch175
-rw-r--r--meta-raspberrypi/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc_0.10.%.bbappend1
-rw-r--r--meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0001-configure-fix-linking-on-RISC-V-ISA.patch8
-rw-r--r--meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0002-Revert-configure-Require-libmodplug-0.8.9.patch9
-rw-r--r--meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0003-CVE-2022-41325.patch83
-rw-r--r--meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0004-mmal_20.patch (renamed from meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0003-mmal_20.patch)583
-rw-r--r--meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0005-mmal_exit_fix.patch (renamed from meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0004-mmal_exit_fix.patch)7
-rw-r--r--meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0006-Use-packageconfig-to-detect-mmal-support.patch56
-rw-r--r--meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0006-mmal_chain.patch (renamed from meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0005-mmal_chain.patch)7
-rw-r--r--meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0007-armv6.patch53
-rw-r--r--meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0007-use-vorbisidec.patch18
-rw-r--r--meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0010-fix-numeric_limits-is-not-a-member-of-std.patch35
-rw-r--r--meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/2001-fix-luaL-checkint.patch (renamed from meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0008-fix-luaL-checkint.patch)5
-rw-r--r--meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/2002-use-vorbisidec.patch33
-rw-r--r--meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/3001-configure.ac-setup-for-OE-usage.patch124
-rw-r--r--meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/3002-fix-EGL-macro-undeclared-and-EGLImageKHR.patch (renamed from meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0009-fix-EGL-macro-undeclared-and-EGLImageKHR.patch)7
-rw-r--r--meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/3003-codec-omxil_core-replace-opt-vc-path-with-usr-lib.patch43
-rw-r--r--meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/3004-use-GLESv2-headers-over-GL-headers.patch60
-rw-r--r--meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/3005-modules-remove-glspectrum-usage.patch149
-rw-r--r--meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/3006-codec-omxil_core.h-fix-multiple-definition-of.patch43
-rw-r--r--meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/3007-remove-xorg-related-link-libs.patch36
-rw-r--r--meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/3008-vo-Makefile.am-exclude-libgl_plugin.patch97
-rw-r--r--meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/3009-vo-converter_vaapi-Fix-EGL-macro-undeclared.patch59
-rw-r--r--meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/rpidistro-vlc_3.0.17.bb (renamed from meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/rpidistro-vlc_3.0.12.bb)87
-rw-r--r--meta-raspberrypi/recipes-connectivity/bluez5/bluez5/0001-bcm43xx-Add-bcm43xx-3wire-variant.patch11
-rw-r--r--meta-raspberrypi/recipes-connectivity/bluez5/bluez5/0002-bcm43xx-The-UART-speed-must-be-reset-after-the-firmw.patch14
-rw-r--r--meta-raspberrypi/recipes-connectivity/bluez5/bluez5/0003-Increase-firmware-load-timeout-to-30s.patch11
-rw-r--r--meta-raspberrypi/recipes-connectivity/bluez5/bluez5/0004-Move-the-43xx-firmware-into-lib-firmware.patch25
-rw-r--r--meta-raspberrypi/recipes-connectivity/bluez5/bluez5/0004-Move-the-hciattach-firmware-into-lib-firmware.patch29
-rw-r--r--meta-raspberrypi/recipes-connectivity/bluez5/bluez5_%.bbappend2
-rw-r--r--meta-raspberrypi/recipes-graphics/wayland/weston_%.bbappend2
-rw-r--r--meta-raspberrypi/recipes-kernel/linux/linux-raspberrypi.inc2
-rw-r--r--meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/0001-avcodec-arm-sbcenc-avoid-callee-preserved-vfp-regist.patch40
-rw-r--r--meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/0002-Fix-build-on-powerpc-and-ppc64.patch7
-rw-r--r--meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/0003-avcodec-pngenc-remove-monowhite-from-apng-formats.patch8
-rw-r--r--meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/0004-ffmpeg-4.3.4-rpi_14.patch (renamed from meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/0004-ffmpeg-4.3.2-rpi_10.patch)11084
-rw-r--r--meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/0005-fix-flags.diff (renamed from meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/0005-fix_flags.diff)7
-rw-r--r--meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/2001-configure-setup-for-OE-core-usage.patch82
-rw-r--r--meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/2002-libavdevice-opengl_enc-update-dynamic-function-loader.patch111
-rw-r--r--meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/2003-libavcodec-fix-v4l2_req_devscan.patch45
-rw-r--r--meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/2004-libavcodec-omx-replace-opt-vc-path-with-usr-lib.patch35
-rw-r--r--meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/rpidistro-ffmpeg_4.3.4.bb (renamed from meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/rpidistro-ffmpeg_4.3.2.bb)37
44 files changed, 10957 insertions, 2377 deletions
diff --git a/meta-raspberrypi/conf/layer.conf b/meta-raspberrypi/conf/layer.conf
index 992ff18c76..85adf24eef 100644
--- a/meta-raspberrypi/conf/layer.conf
+++ b/meta-raspberrypi/conf/layer.conf
@@ -9,7 +9,7 @@ BBFILE_COLLECTIONS += "raspberrypi"
BBFILE_PATTERN_raspberrypi := "^${LAYERDIR}/"
BBFILE_PRIORITY_raspberrypi = "9"
-LAYERSERIES_COMPAT_raspberrypi = "kirkstone langdale"
+LAYERSERIES_COMPAT_raspberrypi = "mickledore"
LAYERDEPENDS_raspberrypi = "core"
# Additional license directories.
diff --git a/meta-raspberrypi/conf/machine/include/rpi-default-providers.inc b/meta-raspberrypi/conf/machine/include/rpi-default-providers.inc
index 67f2bf5662..3f810264b3 100644
--- a/meta-raspberrypi/conf/machine/include/rpi-default-providers.inc
+++ b/meta-raspberrypi/conf/machine/include/rpi-default-providers.inc
@@ -9,6 +9,8 @@ PREFERRED_PROVIDER_virtual/mesa ?= "${@bb.utils.contains("MACHINE_FEATURES", "vc
PREFERRED_PROVIDER_virtual/libgbm ?= "${@bb.utils.contains("MACHINE_FEATURES", "vc4graphics", "mesa", "mesa-gl", d)}"
PREFERRED_PROVIDER_vlc ?= "rpidistro-vlc"
PREFERRED_PROVIDER_ffmpeg ?= "rpidistro-ffmpeg"
+PREFERRED_PROVIDER_libav ?= "rpidistro-ffmpeg"
+PREFERRED_PROVIDER_libpostproc ?= "rpidistro-ffmpeg"
PREFERRED_PROVIDER_jpeg ?= "jpeg"
PREFERRED_PROVIDER_virtual/libomxil ?= "userland"
diff --git a/meta-raspberrypi/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc/lirc-gpio-ir-0.10.patch b/meta-raspberrypi/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc/lirc-gpio-ir-0.10.patch
deleted file mode 100644
index c0fdd189be..0000000000
--- a/meta-raspberrypi/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc/lirc-gpio-ir-0.10.patch
+++ /dev/null
@@ -1,175 +0,0 @@
-diff -ruN lirc-0.10.1.orig/lib/config_file.c lirc-0.10.1/lib/config_file.c
---- lirc-0.10.1.orig/lib/config_file.c 2017-09-10 17:52:19.000000000 +0900
-+++ lirc-0.10.1/lib/config_file.c 2019-06-26 00:39:45.734320696 +0900
-@@ -71,7 +71,7 @@
- typedef void* (*array_guest_func)(void* item, void* arg);
-
-
--#define LINE_LEN 1024
-+#define LINE_LEN 4096
- #define MAX_INCLUDES 10
-
- const char* whitespace = " \t";
-diff -ruN lirc-0.10.1.orig/lib/ir_remote.h lirc-0.10.1/lib/ir_remote.h
---- lirc-0.10.1.orig/lib/ir_remote.h 2017-09-10 17:52:19.000000000 +0900
-+++ lirc-0.10.1/lib/ir_remote.h 2019-06-26 00:39:45.714321224 +0900
-@@ -110,12 +110,17 @@
-
- static inline int is_pulse(lirc_t data)
- {
-- return data & PULSE_BIT ? 1 : 0;
-+ return ((data & LIRC_MODE2_MASK)==LIRC_MODE2_PULSE) ? 1 : 0;
- }
-
- static inline int is_space(lirc_t data)
- {
-- return !is_pulse(data);
-+ return ((data & LIRC_MODE2_MASK)==LIRC_MODE2_SPACE) ? 1 : 0;
-+}
-+
-+static inline int is_timeout(lirc_t data)
-+{
-+ return ((data & LIRC_MODE2_MASK)==LIRC_MODE2_TIMEOUT) ? 1 : 0;
- }
-
- static inline int has_repeat(const struct ir_remote* remote)
-diff -ruN lirc-0.10.1.orig/lib/irrecord.c lirc-0.10.1/lib/irrecord.c
---- lirc-0.10.1.orig/lib/irrecord.c 2017-09-10 17:52:19.000000000 +0900
-+++ lirc-0.10.1/lib/irrecord.c 2019-06-26 00:39:45.724320960 +0900
-@@ -1398,9 +1398,16 @@
- state->retval = 0;
- return STS_LEN_TIMEOUT;
- }
-+ if (is_timeout(state->data)) {
-+ return STS_LEN_AGAIN;
-+ }
- state->count++;
- if (state->mode == MODE_GET_GAP) {
-- state->sum += state->data & PULSE_MASK;
-+ if (state->sum != 0 || is_pulse(state->data)) {
-+ state->sum += state->data & PULSE_MASK;
-+ }else{
-+ return STS_LEN_AGAIN;
-+ }
- if (state->average == 0 && is_space(state->data)) {
- if (state->data > 100000) {
- state->sum = 0;
-@@ -1472,6 +1479,10 @@
- state->keypresses = lastmaxcount;
- return STS_LEN_AGAIN;
- } else if (state->mode == MODE_HAVE_GAP) {
-+ if (state->count==1 && is_space(state->data)) {
-+ state->count = 0;
-+ return STS_LEN_AGAIN;
-+ }
- if (state->count <= MAX_SIGNALS) {
- signals[state->count - 1] = state->data & PULSE_MASK;
- } else {
-@@ -1510,7 +1521,7 @@
- /* such long pulses may appear with
- * crappy hardware (receiver? / remote?)
- */
-- else {
-+ else if(is_pulse(state->data)) {
- remote->gap = 0;
- return STS_LEN_NO_GAP_FOUND;
- }
-@@ -1811,22 +1822,24 @@
-
- static int raw_data_ok(struct button_state* btn_state)
- {
-- int r;
-+ int r = 0;
- int ref;
-
-- if (!is_space(btn_state->data)) {
-+ if (is_pulse(btn_state->data)) {
- r = 0;
-- } else if (is_const(&remote)) {
-- if (remote.gap > btn_state->sum) {
-- ref = (remote.gap - btn_state->sum);
-- ref *= (100 - remote.eps);
-- ref /= 100;
-+ } else if (is_space(btn_state->data)) {
-+ if (is_const(&remote)) {
-+ if (remote.gap > btn_state->sum) {
-+ ref = (remote.gap - btn_state->sum);
-+ ref *= (100 - remote.eps);
-+ ref /= 100;
-+ } else {
-+ ref = 0;
-+ }
-+ r = btn_state->data > ref;
- } else {
-- ref = 0;
-+ r = btn_state->data > (remote.gap * (100 - remote.eps)) / 100;
- }
-- r = btn_state->data > ref;
-- } else {
-- r = btn_state->data > (remote.gap * (100 - remote.eps)) / 100;
- }
- return r;
- }
-@@ -1970,7 +1983,7 @@
- btn_state->data = remote.gap;
- }
- if (btn_state->count == 0) {
-- if (!is_space(btn_state->data)
-+ if (is_pulse(btn_state->data)
- || btn_state->data <
- remote.gap - remote.gap * remote.eps /
- 100) {
-diff -ruN lirc-0.10.1.orig/lib/lirc/ir_remote.h lirc-0.10.1/lib/lirc/ir_remote.h
---- lirc-0.10.1.orig/lib/lirc/ir_remote.h 2017-09-10 17:52:58.000000000 +0900
-+++ lirc-0.10.1/lib/lirc/ir_remote.h 2019-06-26 00:39:45.724320960 +0900
-@@ -110,12 +110,17 @@
-
- static inline int is_pulse(lirc_t data)
- {
-- return data & PULSE_BIT ? 1 : 0;
-+ return ((data & LIRC_MODE2_MASK)==LIRC_MODE2_PULSE) ? 1 : 0;
- }
-
- static inline int is_space(lirc_t data)
- {
-- return !is_pulse(data);
-+ return ((data & LIRC_MODE2_MASK)==LIRC_MODE2_SPACE) ? 1 : 0;
-+}
-+
-+static inline int is_timeout(lirc_t data)
-+{
-+ return ((data & LIRC_MODE2_MASK)==LIRC_MODE2_TIMEOUT) ? 1 : 0;
- }
-
- static inline int has_repeat(const struct ir_remote* remote)
-diff -ruN lirc-0.10.1.orig/tools/mode2.cpp lirc-0.10.1/tools/mode2.cpp
---- lirc-0.10.1.orig/tools/mode2.cpp 2017-09-10 17:52:19.000000000 +0900
-+++ lirc-0.10.1/tools/mode2.cpp 2019-06-26 00:45:38.840404976 +0900
-@@ -326,12 +326,24 @@
- void print_mode2_data(unsigned int data)
- {
- static int bitno = 1;
-+ static bool leading_space = true;
-+ unsigned int msg = data & LIRC_MODE2_MASK;
-
- switch (opt_dmode) {
- case 0:
-- printf("%s %u\n", (
-- data & PULSE_BIT) ? "pulse" : "space",
-- (uint32_t)(data & PULSE_MASK));
-+ if (leading_space && msg == LIRC_MODE2_SPACE ) {
-+ break;
-+ } else {
-+ leading_space = false;
-+ }
-+ if (msg == LIRC_MODE2_PULSE) {
-+ printf("pulse %u\n", (__u32)(data & PULSE_MASK));
-+ } else if (msg == LIRC_MODE2_SPACE) {
-+ printf("space %u\n", (__u32)(data & PULSE_MASK));
-+ } else if (msg == LIRC_MODE2_TIMEOUT) {
-+ printf("timeout %u\n", (__u32)(data & PULSE_MASK));
-+ leading_space = true;
-+ }
- break;
- case 1: {
- /* print output like irrecord raw config file data */
diff --git a/meta-raspberrypi/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc_0.10.%.bbappend b/meta-raspberrypi/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc_0.10.%.bbappend
index 22f8ce4107..0ccd4f701e 100644
--- a/meta-raspberrypi/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc_0.10.%.bbappend
+++ b/meta-raspberrypi/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc_0.10.%.bbappend
@@ -1,6 +1,5 @@
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
SRC_URI:append:rpi = " \
- file://lirc-gpio-ir-0.10.patch \
file://lircd.service \
"
diff --git a/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0001-configure-fix-linking-on-RISC-V-ISA.patch b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0001-configure-fix-linking-on-RISC-V-ISA.patch
index ac96efad84..3be8f1e026 100644
--- a/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0001-configure-fix-linking-on-RISC-V-ISA.patch
+++ b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0001-configure-fix-linking-on-RISC-V-ISA.patch
@@ -2,11 +2,17 @@ From: =?utf-8?q?R=C3=A9mi_Denis-Courmont?= <remi@remlab.net>
Date: Sat, 16 Jun 2018 21:31:45 +0300
Subject: configure: fix linking on RISC-V ISA
-Upstream-status: Pending
+Upstream-Status: Inappropriate
+
+RPI-Distro repo forks original vlc and applies patches
+to enable raspiberry pi support.
+
---
configure.ac | 1 +
1 file changed, 1 insertion(+)
+diff --git a/configure.ac b/configure.ac
+index 2037a9e..df26367 100644
--- a/configure.ac
+++ b/configure.ac
@@ -113,6 +113,7 @@ case "${host_os}" in
diff --git a/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0002-Revert-configure-Require-libmodplug-0.8.9.patch b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0002-Revert-configure-Require-libmodplug-0.8.9.patch
index 3dfcf853b0..61807b3e14 100644
--- a/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0002-Revert-configure-Require-libmodplug-0.8.9.patch
+++ b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0002-Revert-configure-Require-libmodplug-0.8.9.patch
@@ -2,13 +2,18 @@ From: Sebastian Ramacher <sramacher@debian.org>
Date: Mon, 19 Aug 2019 21:08:26 +0200
Subject: Revert "configure: Require libmodplug >= 0.8.9"
-This reverts commit 48f014768dc22ecad23d0e9f53c38805a3aff832.
+Upstream-Status: Inappropriate
+
+RPI-Distro repo forks original vlc and applies patches
+to enable raspiberry pi support.
-Upstream-status: Pending
+This reverts commit 48f014768dc22ecad23d0e9f53c38805a3aff832.
---
configure.ac | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
+diff --git a/configure.ac b/configure.ac
+index df26367..b8580ec 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2207,7 +2207,7 @@ AC_ARG_ENABLE(mod,
diff --git a/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0003-CVE-2022-41325.patch b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0003-CVE-2022-41325.patch
new file mode 100644
index 0000000000..41f7109679
--- /dev/null
+++ b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0003-CVE-2022-41325.patch
@@ -0,0 +1,83 @@
+From 4fcace61801f418786c42487c6b06b693ee87666 Mon Sep 17 00:00:00 2001
+From: Romain Vimont <rom1v@videolabs.io>
+Date: Mon, 19 Sep 2022 17:17:01 +0200
+Subject: [PATCH] vnc: fix possible buffer overflow
+
+Upstream-Status: Inappropriate
+
+RPI-Distro repo forks original vlc and applies patches
+to enable raspiberry pi support.
+
+Thanks to 0xMitsurugi [1] from Synacktiv [2] for the bug report and fix.
+
+[1] https://twitter.com/0xMitsurugi
+[2] https://www.synacktiv.com/
+
+Fixes #27335
+
+(cherry picked from commit 5eb783fd44ed6298db3e38f7765f21c42e4405f9)
+---
+ modules/access/vnc.c | 23 ++++++++++++++++-------
+ 1 file changed, 16 insertions(+), 7 deletions(-)
+
+--- a/modules/access/vnc.c
++++ b/modules/access/vnc.c
+@@ -33,6 +33,7 @@
+ #ifdef HAVE_CONFIG_H
+ # include "config.h"
+ #endif
++#include <assert.h>
+
+ #include <vlc_common.h>
+ #include <vlc_plugin.h>
+@@ -115,7 +116,7 @@
+ int i_cancel_state;
+
+ rfbClient* p_client;
+- int i_framebuffersize;
++ size_t i_framebuffersize;
+ block_t *p_block;
+
+ float f_fps;
+@@ -143,11 +144,16 @@
+ p_sys->es = NULL;
+ }
+
+- int i_width = p_client->width;
+- int i_height = p_client->height;
+- int i_depth = p_client->format.bitsPerPixel;
++ assert(!(p_client->width & ~0xffff)); // fits in 16 bits
++ uint16_t i_width = p_client->width;
+
+- switch( i_depth )
++ assert(!(p_client->height & ~0xffff)); // fits in 16 bits
++ uint16_t i_height = p_client->height;
++
++ uint8_t i_bits_per_pixel = p_client->format.bitsPerPixel;
++ assert((i_bits_per_pixel & 0x7) == 0); // multiple of 8
++
++ switch( i_bits_per_pixel )
+ {
+ case 8:
+ i_chroma = VLC_CODEC_RGB8;
+@@ -180,7 +186,10 @@
+ }
+
+ /* Set up framebuffer */
+- p_sys->i_framebuffersize = i_width * i_height * i_depth / 8;
++ if (mul_overflow(i_width, i_height * (i_bits_per_pixel / 8), &p_sys->i_framebuffersize)) {
++ msg_Err(p_demux, "VNC framebuffersize overflow");
++ return FALSE;
++ }
+
+ /* Reuse unsent block */
+ if ( p_sys->p_block )
+@@ -211,7 +220,7 @@
+ fmt.video.i_frame_rate_base = 1000;
+ fmt.video.i_frame_rate = 1000 * p_sys->f_fps;
+
+- fmt.video.i_bits_per_pixel = i_depth;
++ fmt.video.i_bits_per_pixel = i_bits_per_pixel;
+ fmt.video.i_rmask = p_client->format.redMax << p_client->format.redShift;
+ fmt.video.i_gmask = p_client->format.greenMax << p_client->format.greenShift;
+ fmt.video.i_bmask = p_client->format.blueMax << p_client->format.blueShift;
diff --git a/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0003-mmal_20.patch b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0004-mmal_20.patch
index 6038d0ee39..ab317303d9 100644
--- a/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0003-mmal_20.patch
+++ b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0004-mmal_20.patch
@@ -1,4 +1,7 @@
-Upstream-status: Pending
+Upstream-Status: Inappropriate
+
+RPI-Distro repo forks original vlc and applies patches
+to enable raspiberry pi support.
--- a/configure.ac
+++ b/configure.ac
@@ -26,13 +29,13 @@ Upstream-status: Pending
fi
AM_CONDITIONAL([HAVE_MMAL], [test "${have_mmal}" = "yes"])
+AM_CONDITIONAL([HAVE_MMAL_AVCODEC], [test "${enable_mmal_avcodec}" = "yes"])
-
+
dnl
dnl evas plugin
--- a/include/vlc_fourcc.h
+++ b/include/vlc_fourcc.h
@@ -365,6 +365,11 @@
-
+
/* Broadcom MMAL opaque buffer type */
#define VLC_CODEC_MMAL_OPAQUE VLC_FOURCC('M','M','A','L')
+#define VLC_CODEC_MMAL_ZC_SAND8 VLC_FOURCC('Z','S','D','8')
@@ -40,7 +43,7 @@ Upstream-status: Pending
+#define VLC_CODEC_MMAL_ZC_SAND30 VLC_FOURCC('Z','S','D','3')
+#define VLC_CODEC_MMAL_ZC_I420 VLC_FOURCC('Z','4','2','0')
+#define VLC_CODEC_MMAL_ZC_RGB32 VLC_FOURCC('Z','R','G','B')
-
+
/* DXVA2 opaque video surface for use with D3D9 */
#define VLC_CODEC_D3D9_OPAQUE VLC_FOURCC('D','X','A','9') /* 4:2:0 8 bpc */
--- a/modules/hw/mmal/Makefile.am
@@ -48,12 +51,12 @@ Upstream-status: Pending
@@ -1,23 +1,57 @@
include $(top_srcdir)/modules/common.am
mmaldir = $(pluginsdir)/mmal
-
+
-AM_CFLAGS += $(CFLAGS_mmal)
-AM_LDFLAGS += -rpath '$(mmaldir)' $(LDFLAGS_mmal)
+AM_CFLAGS += -pthread $(CFLAGS_mmal)
+AM_LDFLAGS += -pthread -rpath '$(mmaldir)' $(LDFLAGS_mmal)
-
+
-libmmal_vout_plugin_la_SOURCES = vout.c mmal_picture.c mmal_picture.h
+libmmal_vout_plugin_la_SOURCES = vout.c mmal_cma.c mmal_picture.c subpic.c\
+ mmal_cma.h mmal_picture.h subpic.h transform_ops.h\
@@ -63,7 +66,7 @@ Upstream-status: Pending
+libmmal_vout_plugin_la_LDFLAGS = $(AM_LDFLAGS) -lm -lX11 -lXrandr
libmmal_vout_plugin_la_LIBADD = $(LIBS_mmal)
mmal_LTLIBRARIES = libmmal_vout_plugin.la
-
+
-libmmal_codec_plugin_la_SOURCES = codec.c
+libmmal_codec_plugin_la_SOURCES = codec.c mmal_cma.c mmal_picture.c subpic.c\
+ mmal_cma.h mmal_picture.h subpic.h transform_ops.h\
@@ -72,7 +75,7 @@ Upstream-status: Pending
libmmal_codec_plugin_la_LDFLAGS = $(AM_LDFLAGS)
libmmal_codec_plugin_la_LIBADD = $(LIBS_mmal)
mmal_LTLIBRARIES += libmmal_codec_plugin.la
-
+
-libmmal_deinterlace_plugin_la_SOURCES = deinterlace.c mmal_picture.c
+libmmal_deinterlace_plugin_la_SOURCES = deinterlace.c mmal_picture.c mmal_cma.c\
+ mmal_cma.h mmal_picture.h transform_ops.h\
@@ -517,7 +520,7 @@ Upstream-status: Pending
@@ -26,267 +26,443 @@
#include "config.h"
#endif
-
+
+#include <stdatomic.h>
+
#include <vlc_common.h>
@@ -526,17 +529,17 @@ Upstream-status: Pending
#include <vlc_codec.h>
+#include <vlc_filter.h>
#include <vlc_threads.h>
-
+
-#include <bcm_host.h>
#include <interface/mmal/mmal.h>
#include <interface/mmal/util/mmal_util.h>
#include <interface/mmal/util/mmal_default_components.h>
-
+
+#include <interface/vcsm/user-vcsm.h>
+
+#include "mmal_cma.h"
#include "mmal_picture.h"
-
+
+#include "subpic.h"
+#include "blend_rgba_neon.h"
+
@@ -550,18 +553,18 @@ Upstream-status: Pending
#define NUM_EXTRA_BUFFERS 5
+//#define NUM_EXTRA_BUFFERS 10
#define NUM_DECODER_BUFFER_HEADERS 30
-
+
-#define MIN_NUM_BUFFERS_IN_TRANSIT 2
+#define CONVERTER_BUFFERS 4 // Buffers on the output of the converter
+
+#define MMAL_SLICE_HEIGHT 16
+#define MMAL_ALIGN_W 32
+#define MMAL_ALIGN_H 16
-
+
#define MMAL_OPAQUE_NAME "mmal-opaque"
#define MMAL_OPAQUE_TEXT N_("Decode frames directly into RPI VideoCore instead of host memory.")
#define MMAL_OPAQUE_LONGTEXT N_("Decode frames directly into RPI VideoCore instead of host memory. This option must only be used with the MMAL video output plugin.")
-
+
-static int OpenDecoder(decoder_t *dec);
-static void CloseDecoder(decoder_t *dec);
-
@@ -580,7 +583,7 @@ Upstream-status: Pending
+#define MMAL_ISP_NAME "mmal-isp"
+#define MMAL_ISP_TEXT N_("Use mmal isp rather than hvs.")
+#define MMAL_ISP_LONGTEXT N_("Use mmal isp rather than hvs. This may be faster but has no blend.")
-
+
-struct decoder_sys_t {
- bool opaque;
+typedef struct decoder_sys_t
@@ -593,11 +596,11 @@ Upstream-status: Pending
+ hw_mmal_port_pool_ref_t *ppr;
MMAL_ES_FORMAT_T *output_format;
- vlc_sem_t sem;
-
+
+ MMAL_STATUS_T err_stream;
bool b_top_field_first;
bool b_progressive;
-
+
+ bool b_flushed;
+
+ vcsm_init_type_t vcsm_init_type;
@@ -613,7 +616,7 @@ Upstream-status: Pending
atomic_bool started;
-};
+} decoder_sys_t;
-
+
-/* Utilities */
-static int change_output_format(decoder_t *dec);
-static int send_output_buffer(decoder_t *dec);
@@ -627,7 +630,7 @@ Upstream-status: Pending
-static void control_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer);
-static void input_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer);
-static void output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer);
-
+
-static int OpenDecoder(decoder_t *dec)
-{
- int ret = VLC_SUCCESS;
@@ -647,12 +650,12 @@ Upstream-status: Pending
+ {{MMAL_PARAMETER_SUPPORTED_ENCODINGS, sizeof(((supported_mmal_enc_t *)0)->supported)}, {0}}, \
+ -1 \
+}
-
+
- if (dec->fmt_in.i_codec != VLC_CODEC_MPGV &&
- dec->fmt_in.i_codec != VLC_CODEC_H264)
- return VLC_EGENERIC;
+static supported_mmal_enc_t supported_decode_in_enc = SUPPORTED_MMAL_ENC_INIT;
-
+
- sys = calloc(1, sizeof(decoder_sys_t));
- if (!sys) {
- ret = VLC_ENOMEM;
@@ -672,7 +675,7 @@ Upstream-status: Pending
- dec->p_sys = sys;
+ return false;
+}
-
+
- sys->opaque = var_InheritBool(dec, MMAL_OPAQUE_NAME);
- bcm_host_init();
+static bool set_and_test_enc_supported(supported_mmal_enc_t * const support, MMAL_PORT_T * port, const MMAL_FOURCC_T fcc)
@@ -684,7 +687,7 @@ Upstream-status: Pending
+ else
+ support->n = (support->supported.header.size - sizeof(support->supported.header)) /
+ sizeof(support->supported.encodings[0]);
-
+
- status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, &sys->component);
- if (status != MMAL_SUCCESS) {
- msg_Err(dec, "Failed to create MMAL component %s (status=%"PRIx32" %s)",
@@ -694,7 +697,7 @@ Upstream-status: Pending
- }
+ return is_enc_supported(support, fcc);
+}
-
+
- sys->component->control->userdata = (struct MMAL_PORT_USERDATA_T *)dec;
- status = mmal_port_enable(sys->component->control, control_port_cb);
- if (status != MMAL_SUCCESS) {
@@ -737,7 +740,7 @@ Upstream-status: Pending
}
+ return 0;
+}
-
+
- sys->input = sys->component->input[0];
- sys->input->userdata = (struct MMAL_PORT_USERDATA_T *)dec;
- if (dec->fmt_in.i_codec == VLC_CODEC_MPGV)
@@ -776,7 +779,7 @@ Upstream-status: Pending
+ }
+ return 0;
+}
-
+
- if (dec->fmt_in.i_codec == VLC_CODEC_H264) {
- if (dec->fmt_in.i_extra > 0) {
- status = mmal_format_extradata_alloc(sys->input->format,
@@ -804,7 +807,7 @@ Upstream-status: Pending
}
+}
+#endif
-
+
- status = mmal_port_format_commit(sys->input);
- if (status != MMAL_SUCCESS) {
- msg_Err(dec, "Failed to commit format for input port %s (status=%"PRIx32" %s)",
@@ -822,7 +825,7 @@ Upstream-status: Pending
- sys->input->buffer_size = sys->input->buffer_size_recommended;
- sys->input->buffer_num = sys->input->buffer_num_recommended;
+}
-
+
- status = mmal_port_enable(sys->input, input_port_cb);
- if (status != MMAL_SUCCESS) {
- msg_Err(dec, "Failed to enable input port %s (status=%"PRIx32" %s)",
@@ -830,7 +833,7 @@ Upstream-status: Pending
- ret = VLC_EGENERIC;
- goto out;
- }
-
+
- sys->output = sys->component->output[0];
- sys->output->userdata = (struct MMAL_PORT_USERDATA_T *)dec;
+static void draw_corners(void * pic_buf, size_t pic_stride, unsigned int x, unsigned int y, unsigned int w, unsigned int h)
@@ -846,7 +849,7 @@ Upstream-status: Pending
+ draw_line(pic_buf, pic_stride, x, y + h - 1, len, -(int)pic_stride);
+}
+#endif
-
+
- if (sys->opaque) {
- extra_buffers.hdr.id = MMAL_PARAMETER_EXTRA_BUFFERS;
- extra_buffers.hdr.size = sizeof(MMAL_PARAMETER_UINT32_T);
@@ -863,7 +866,7 @@ Upstream-status: Pending
+{
+ static const unsigned int primes[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 0};
+ const unsigned int * p = primes;
-
+
- msg_Dbg(dec, "Activate zero-copy for output port");
- MMAL_PARAMETER_BOOLEAN_T zero_copy = {
- { MMAL_PARAMETER_ZERO_COPY, sizeof(MMAL_PARAMETER_BOOLEAN_T) },
@@ -873,7 +876,7 @@ Upstream-status: Pending
+ if (num == 0 || den == 0) {
+ return (MMAL_RATIONAL_T){.num = 0, .den = 0};
+ }
-
+
- status = mmal_port_parameter_set(sys->output, &zero_copy.hdr);
- if (status != MMAL_SUCCESS) {
- msg_Err(dec, "Failed to set zero copy on port %s (status=%"PRIx32" %s)",
@@ -889,7 +892,7 @@ Upstream-status: Pending
}
+ return (MMAL_RATIONAL_T){.num = num, .den = den};
+}
-
+
- status = mmal_port_enable(sys->output, output_port_cb);
- if (status != MMAL_SUCCESS) {
- msg_Err(dec, "Failed to enable output port %s (status=%"PRIx32" %s)",
@@ -901,7 +904,7 @@ Upstream-status: Pending
+static picture_t * alloc_opaque_pic(decoder_t * const dec, MMAL_BUFFER_HEADER_T * const buf)
+{
+ decoder_sys_t *const dec_sys = dec->p_sys;
-
+
- status = mmal_component_enable(sys->component);
- if (status != MMAL_SUCCESS) {
- msg_Err(dec, "Failed to enable component %s (status=%"PRIx32" %s)",
@@ -919,11 +922,11 @@ Upstream-status: Pending
+ msg_Err(dec, "%s: Empty buffer", __func__);
+ goto fail2;
}
-
+
- sys->input_pool = mmal_pool_create(sys->input->buffer_num, 0);
+ if ((pic->context = hw_mmal_gen_context(buf, dec_sys->ppr)) == NULL)
+ goto fail2;
-
+
- if (sys->opaque) {
- dec->fmt_out.i_codec = VLC_CODEC_MMAL_OPAQUE;
- dec->fmt_out.video.i_chroma = VLC_CODEC_MMAL_OPAQUE;
@@ -961,22 +964,22 @@ Upstream-status: Pending
+ msg_Err(dec, "MMAL error %"PRIx32" \"%s\"", status,
+ mmal_status_to_string(status));
}
-
+
- dec->pf_decode = decode;
- dec->pf_flush = flush_decoder;
+ mmal_buffer_header_release(buffer);
+}
-
+
- vlc_sem_init(&sys->sem, 0);
+static void input_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
+{
+ block_t * const block = (block_t *)buffer->user_data;
-
+
-out:
- if (ret != VLC_SUCCESS)
- CloseDecoder(dec);
+ (void)port; // Unused
-
+
- return ret;
+#if TRACE_ALL
+ msg_Dbg((decoder_t *)port->userdata, "<<< %s: cmd=%d, data=%p, len=%d/%d, pts=%lld", __func__,
@@ -989,14 +992,14 @@ Upstream-status: Pending
+ if (block != NULL)
+ block_Release(block);
}
-
+
-static void CloseDecoder(decoder_t *dec)
+static void decoder_output_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
{
- decoder_sys_t *sys = dec->p_sys;
- MMAL_BUFFER_HEADER_T *buffer;
+ decoder_t * const dec = (decoder_t *)port->userdata;
-
+
- if (!sys)
+ if (buffer->cmd == 0 && buffer->length != 0)
+ {
@@ -1016,7 +1019,7 @@ Upstream-status: Pending
+ // Buffer released or attached to pic - do not release again
return;
+ }
-
+
- if (sys->component && sys->component->control->is_enabled)
- mmal_port_disable(sys->component->control);
+ if (buffer->cmd == MMAL_EVENT_FORMAT_CHANGED)
@@ -1024,7 +1027,7 @@ Upstream-status: Pending
+ decoder_sys_t * const sys = dec->p_sys;
+ MMAL_EVENT_FORMAT_CHANGED_T * const fmt = mmal_event_format_changed_get(buffer);
+ MMAL_ES_FORMAT_T * const format = mmal_format_alloc();
-
+
- if (sys->input && sys->input->is_enabled)
- mmal_port_disable(sys->input);
+ if (format == NULL)
@@ -1033,7 +1036,7 @@ Upstream-status: Pending
+ {
+ mmal_format_full_copy(format, fmt->format);
+ format->encoding = MMAL_ENCODING_OPAQUE;
-
+
- if (sys->output && sys->output->is_enabled)
- mmal_port_disable(sys->output);
+ // If no PAR in the stream - see if we've got one from the demux
@@ -1057,17 +1060,17 @@ Upstream-status: Pending
+ d = 1;
+ }
+ }
-
+
- if (sys->component && sys->component->is_enabled)
- mmal_component_disable(sys->component);
+ format->es->video.par = rationalize_sar(n, d);
+ }
-
+
- if (sys->input_pool)
- mmal_pool_destroy(sys->input_pool);
+ if (sys->output_format != NULL)
+ mmal_format_free(sys->output_format);
-
+
- if (sys->output_format)
- mmal_format_free(sys->output_format);
+ sys->output_format = format;
@@ -1077,7 +1080,7 @@ Upstream-status: Pending
+ char buf0[5];
+ msg_Warn(dec, "Unexpected output cb event: %s", str_fourcc(buf0, buffer->cmd));
+ }
-
+
- if (sys->output_pool)
- mmal_pool_destroy(sys->output_pool);
+ // If we get here then we were flushing (cmd == 0 && len == 0) or
@@ -1087,13 +1090,13 @@ Upstream-status: Pending
+ buffer->user_data = NULL;
+ mmal_buffer_header_release(buffer);
+}
-
+
- if (sys->component)
- mmal_component_release(sys->component);
-
+
- vlc_sem_destroy(&sys->sem);
- free(sys);
-
+
- bcm_host_deinit();
+static void fill_output_port(decoder_t *dec)
+{
@@ -1113,7 +1116,7 @@ Upstream-status: Pending
+ hw_mmal_port_pool_ref_fill(sys->ppr);
+ return;
}
-
+
static int change_output_format(decoder_t *dec)
{
MMAL_PARAMETER_VIDEO_INTERLACE_TYPE_T interlace_type;
@@ -1122,7 +1125,7 @@ Upstream-status: Pending
MMAL_STATUS_T status;
- int pool_size;
int ret = 0;
-
+
+#if TRACE_ALL
+ msg_Dbg(dec, "%s: <<<", __func__);
+#endif
@@ -1132,7 +1135,7 @@ Upstream-status: Pending
status = mmal_port_format_commit(sys->output);
@@ -300,7 +476,9 @@ static int change_output_format(decoder_
}
-
+
port_reset:
+#if TRACE_ALL
msg_Dbg(dec, "%s: Do full port reset", __func__);
@@ -1142,7 +1145,7 @@ Upstream-status: Pending
msg_Err(dec, "Failed to disable output port (status=%"PRIx32" %s)",
@@ -310,6 +488,7 @@ port_reset:
}
-
+
mmal_format_full_copy(sys->output->format, sys->output_format);
+
status = mmal_port_format_commit(sys->output);
@@ -1151,7 +1154,7 @@ Upstream-status: Pending
@@ -318,18 +497,10 @@ port_reset:
goto out;
}
-
+
- if (sys->opaque) {
- sys->output->buffer_num = NUM_DECODER_BUFFER_HEADERS;
- pool_size = NUM_DECODER_BUFFER_HEADERS;
@@ -1163,7 +1166,7 @@ Upstream-status: Pending
-
+ sys->output->buffer_num = NUM_DECODER_BUFFER_HEADERS;
sys->output->buffer_size = sys->output->buffer_size_recommended;
-
+
- status = mmal_port_enable(sys->output, output_port_cb);
+ status = mmal_port_enable(sys->output, decoder_output_cb);
if (status != MMAL_SUCCESS) {
@@ -1171,7 +1174,7 @@ Upstream-status: Pending
status, mmal_status_to_string(status));
@@ -338,25 +509,14 @@ port_reset:
}
-
+
if (!atomic_load(&sys->started)) {
- if (!sys->opaque) {
- sys->output_pool = mmal_port_pool_create(sys->output, pool_size, 0);
@@ -1179,7 +1182,7 @@ Upstream-status: Pending
- }
-
atomic_store(&sys->started, true);
-
+
/* we need one picture from vout for each buffer header on the output
* port */
- dec->i_extra_picture_buffers = pool_size;
@@ -1196,7 +1199,7 @@ Upstream-status: Pending
msg_Dbg(dec, "Request %d extra pictures", dec->i_extra_picture_buffers);
+#endif
}
-
+
apply_fmt:
@@ -366,8 +526,8 @@ apply_fmt:
dec->fmt_out.video.i_y_offset = sys->output->format->es->video.crop.y;
@@ -1208,7 +1211,7 @@ Upstream-status: Pending
+ dec->fmt_out.video.i_sar_den = sys->output_format->es->video.par.den;
dec->fmt_out.video.i_frame_rate = sys->output->format->es->video.frame_rate.num;
dec->fmt_out.video.i_frame_rate_base = sys->output->format->es->video.frame_rate.den;
-
+
@@ -382,12 +542,19 @@ apply_fmt:
sys->b_progressive = (interlace_type.eMode == MMAL_InterlaceProgressive);
sys->b_top_field_first = sys->b_progressive ? true :
@@ -1220,7 +1223,7 @@ Upstream-status: Pending
interlace_type.eMode);
+#endif
}
-
+
+ // Tell the rest of the world we have changed format
+ vlc_mutex_lock(&sys->pic_lock);
+ ret = decoder_UpdateVideoFormat(dec);
@@ -1232,7 +1235,7 @@ Upstream-status: Pending
@@ -395,144 +562,85 @@ out:
return ret;
}
-
+
-static int send_output_buffer(decoder_t *dec)
+static MMAL_STATUS_T
+set_extradata_and_commit(decoder_t * const dec, decoder_sys_t * const sys)
@@ -1244,7 +1247,7 @@ Upstream-status: Pending
MMAL_STATUS_T status;
- unsigned buffer_size = 0;
- int ret = 0;
-
+
- if (!sys->output->is_enabled)
- return VLC_EGENERIC;
-
@@ -1318,7 +1321,7 @@ Upstream-status: Pending
- return ret;
+ return status;
}
-
+
-static void fill_output_port(decoder_t *dec)
+static MMAL_STATUS_T decoder_send_extradata(decoder_t * const dec, decoder_sys_t *const sys)
{
@@ -1341,7 +1344,7 @@ Upstream-status: Pending
+ buf->length = dec->fmt_in.i_extra;
+ buf->data = dec->fmt_in.p_extra;
+ buf->flags = MMAL_BUFFER_HEADER_FLAG_CONFIG;
-
+
- if (sys->output_pool) {
- max_buffers_in_transit = __MAX(sys->output_pool->headers_num,
- MIN_NUM_BUFFERS_IN_TRANSIT);
@@ -1357,7 +1360,7 @@ Upstream-status: Pending
+ }
}
- buffers_to_send = max_buffers_in_transit - atomic_load(&sys->output_in_transit);
-
+
- if (buffers_to_send > buffers_available)
- buffers_to_send = buffers_available;
-
@@ -1373,14 +1376,14 @@ Upstream-status: Pending
- break;
+ return MMAL_SUCCESS;
}
-
+
static void flush_decoder(decoder_t *dec)
{
- decoder_sys_t *sys = dec->p_sys;
- MMAL_BUFFER_HEADER_T *buffer;
- MMAL_STATUS_T status;
+ decoder_sys_t *const sys = dec->p_sys;
-
+
- msg_Dbg(dec, "Flushing decoder ports...");
- mmal_port_flush(sys->output);
- mmal_port_flush(sys->input);
@@ -1404,7 +1407,7 @@ Upstream-status: Pending
+ msg_Dbg(dec, "%s: >>>", __func__);
+#endif
}
-
+
static int decode(decoder_t *dec, block_t *block)
{
decoder_sys_t *sys = dec->p_sys;
@@ -1414,7 +1417,7 @@ Upstream-status: Pending
- uint32_t flags = 0;
+ uint32_t flags = MMAL_BUFFER_HEADER_FLAG_FRAME_START;
MMAL_STATUS_T status;
-
+
+#if TRACE_ALL
+ msg_Dbg(dec, "<<< %s: %lld/%lld", __func__, block == NULL ? -1LL : block->i_dts, block == NULL ? -1LL : block->i_pts);
+#endif
@@ -1431,12 +1434,12 @@ Upstream-status: Pending
@@ -541,18 +649,50 @@ static int decode(decoder_t *dec, block_
msg_Err(dec, "Failed to change output port format");
}
-
+
- if (!block)
- goto out;
+ if (block == NULL)
+ return VLCDEC_SUCCESS;
-
+
/*
* Check whether full flush is required
*/
@@ -1453,7 +1456,7 @@ Upstream-status: Pending
block_Release(block);
return VLCDEC_SUCCESS;
}
-
+
+ // Reenable stuff if the last thing we did was flush
+ if (!sys->output->is_enabled &&
+ (status = mmal_port_enable(sys->output, decoder_output_cb)) != MMAL_SUCCESS)
@@ -1481,11 +1484,11 @@ Upstream-status: Pending
+ // reported the size & the output stages have been set up
if (atomic_load(&sys->started))
fill_output_port(dec);
-
+
@@ -563,18 +703,21 @@ static int decode(decoder_t *dec, block_
if (block->i_flags & BLOCK_FLAG_CORRUPTED)
flags |= MMAL_BUFFER_HEADER_FLAG_CORRUPTED;
-
+
- while (block && block->i_buffer > 0) {
- buffer = mmal_queue_timedwait(sys->input_pool->queue, 100);
+ while (block != NULL)
@@ -1506,7 +1509,7 @@ Upstream-status: Pending
buffer->dts = block->i_dts;
buffer->alloc_size = sys->input->buffer_size;
+ buffer->user_data = NULL;
-
+
len = block->i_buffer;
if (len > buffer->alloc_size)
@@ -585,94 +728,1808 @@ static int decode(decoder_t *dec, block_
@@ -1522,7 +1525,7 @@ Upstream-status: Pending
block = NULL;
}
buffer->flags = flags;
-
+
+#if TRACE_ALL
+ msg_Dbg(dec, "%s: -- Send buffer: cmd=%d, data=%p, size=%d, len=%d, offset=%d, flags=%#x, pts=%lld, dts=%lld", __func__,\
+ buffer->cmd, buffer->data, buffer->alloc_size, buffer->length, buffer->offset,
@@ -1542,17 +1545,17 @@ Upstream-status: Pending
+ flags &= ~MMAL_BUFFER_HEADER_FLAG_FRAME_START;
}
+ return VLCDEC_SUCCESS;
-
+
-out:
- if (need_flush)
- flush_decoder(dec);
+fail:
+ flush_decoder(dec);
+ return VLCDEC_ECRITICAL;
-
+
- return VLCDEC_SUCCESS;
}
-
+
-static void control_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
+
+static void CloseDecoder(decoder_t *dec)
@@ -1921,7 +1924,7 @@ Upstream-status: Pending
+#if TRACE_ALL
+ msg_Dbg(p_filter, "%s: <<< cmd=%d, data=%p, pic=%p", __func__, buffer->cmd, buffer->data, buffer->user_data);
+#endif
-
+
if (buffer->cmd == MMAL_EVENT_ERROR) {
- status = *(uint32_t *)buffer->data;
- msg_Err(dec, "MMAL error %"PRIx32" \"%s\"", status,
@@ -1932,10 +1935,10 @@ Upstream-status: Pending
+ msg_Err(p_filter, "MMAL error %"PRIx32" \"%s\"", status,
mmal_status_to_string(status));
}
-
+
mmal_buffer_header_release(buffer);
}
-
+
-static void input_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
+static void conv_input_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buf)
{
@@ -1967,14 +1970,14 @@ Upstream-status: Pending
+ vlc_mutex_lock(&sys->lock);
+ pic_fifo_put(&sys->ret_pics, pic);
+ vlc_mutex_unlock(&sys->lock);
-
+
- mmal_buffer_header_release(buffer);
- if (block)
- block_Release(block);
- atomic_fetch_sub(&sys->input_in_transit, 1);
vlc_sem_post(&sys->sem);
}
-
+
-static void output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
+static void conv_output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buf)
{
@@ -2006,7 +2009,7 @@ Upstream-status: Pending
- fmt = mmal_event_format_changed_get(buffer);
+ filter_t * const p_filter = (filter_t *)port->userdata;
+ filter_sys_t * const sys = p_filter->p_sys;
-
+
- format = mmal_format_alloc();
- mmal_format_full_copy(format, fmt->format);
+#if TRACE_ALL
@@ -2016,7 +2019,7 @@ Upstream-status: Pending
+#endif
+ if (buf->cmd == 0) {
+ picture_t * const pic = (picture_t *)buf->user_data;
-
+
- if (sys->opaque)
- format->encoding = MMAL_ENCODING_OPAQUE;
+ if (pic == NULL) {
@@ -2713,9 +2716,9 @@ Upstream-status: Pending
+ if (use_isp || use_resizer)
+ return VLC_EGENERIC;
+ }
-
+
- sys->output_format = format;
-
+
- mmal_buffer_header_release(buffer);
+ if (use_resizer) {
+ // use resizer overrides use_isp
@@ -3858,7 +3861,7 @@ Upstream-status: Pending
@@ -26,11 +26,12 @@
#include "config.h"
#endif
-
+
-#include <vlc_picture_pool.h>
+#include <stdatomic.h>
+
@@ -3867,31 +3870,31 @@ Upstream-status: Pending
#include <vlc_plugin.h>
#include <vlc_filter.h>
-#include <vlc_atomic.h>
-
+
#include "mmal_picture.h"
-
+
@@ -39,468 +40,814 @@
#include <interface/mmal/util/mmal_util.h>
#include <interface/mmal/util/mmal_default_components.h>
-
+
-#define MIN_NUM_BUFFERS_IN_TRANSIT 2
+#define MMAL_DEINTERLACE_NO_QPU "mmal-deinterlace-no-qpu"
+#define MMAL_DEINTERLACE_NO_QPU_TEXT N_("Do not use QPUs for advanced HD deinterlacing.")
+#define MMAL_DEINTERLACE_NO_QPU_LONGTEXT N_("Do not make use of the QPUs to allow higher quality deinterlacing of HD content.")
-
+
-#define MMAL_DEINTERLACE_QPU "mmal-deinterlace-adv-qpu"
-#define MMAL_DEINTERLACE_QPU_TEXT N_("Use QPUs for advanced HD deinterlacing.")
-#define MMAL_DEINTERLACE_QPU_LONGTEXT N_("Make use of the QPUs to allow higher quality deinterlacing of HD content.")
+#define MMAL_DEINTERLACE_ADV "mmal-deinterlace-adv"
+#define MMAL_DEINTERLACE_ADV_TEXT N_("Force advanced deinterlace")
+#define MMAL_DEINTERLACE_ADV_LONGTEXT N_("Force advanced deinterlace")
-
+
-static int Open(filter_t *filter);
-static void Close(filter_t *filter);
+#define MMAL_DEINTERLACE_FAST "mmal-deinterlace-fast"
+#define MMAL_DEINTERLACE_FAST_TEXT N_("Force fast deinterlace")
+#define MMAL_DEINTERLACE_FAST_LONGTEXT N_("Force fast deinterlace")
-
+
-vlc_module_begin()
- set_shortname(N_("MMAL deinterlace"))
- set_description(N_("MMAL-based deinterlace filter plugin"))
@@ -3915,7 +3918,7 @@ Upstream-status: Pending
+#define MMAL_DEINTERLACE_FULL_RATE "mmal-deinterlace-full-rate"
+#define MMAL_DEINTERLACE_FULL_RATE_TEXT N_("Full output framerate")
+#define MMAL_DEINTERLACE_FULL_RATE_LONGTEXT N_("Full output framerate. 1 output frame for each interlaced field input")
-
+
-struct filter_sys_t {
+
+typedef struct filter_sys_t
@@ -3940,14 +3943,14 @@ Upstream-status: Pending
+ bool use_passthrough;
+ unsigned int seq_in; // Seq of next frame to submit (1-15) [Init=1]
+ unsigned int seq_out; // Seq of last frame received (1-15) [Init=15]
-
+
- MMAL_QUEUE_T *filtered_pictures;
- vlc_sem_t sem;
+ vcsm_init_type_t vcsm_init_type;
-
+
- atomic_bool started;
+} filter_sys_t;
-
+
- /* statistics */
- int output_in_transit;
- int input_in_transit;
@@ -3958,9 +3961,9 @@ Upstream-status: Pending
-static void output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer);
-static picture_t *deinterlace(filter_t *filter, picture_t *picture);
-static void flush(filter_t *filter);
-
+
#define MMAL_COMPONENT_DEFAULT_DEINTERLACE "vc.ril.image_fx"
-
+
-static int Open(filter_t *filter)
+#define TRACE_ALL 0
+
@@ -3975,7 +3978,7 @@ Upstream-status: Pending
- bool use_qpu = var_InheritBool(filter, MMAL_DEINTERLACE_QPU);
+ filter_sys_t *const filter_sys = p_filter->p_sys;
+ picture_t * const pic = filter_NewPicture(p_filter);
-
+
- MMAL_PARAMETER_IMAGEFX_PARAMETERS_T imfx_param = {
- { MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS, sizeof(imfx_param) },
- MMAL_PARAM_IMAGEFX_DEINTERLACE_ADV,
@@ -3984,7 +3987,7 @@ Upstream-status: Pending
- };
+ if (pic == NULL)
+ goto fail1;
-
+
- int ret = VLC_SUCCESS;
- MMAL_STATUS_T status;
- filter_sys_t *sys;
@@ -3992,28 +3995,28 @@ Upstream-status: Pending
+ msg_Err(p_filter, "%s: Empty buffer", __func__);
+ goto fail2;
+ }
-
+
- msg_Dbg(filter, "Try to open mmal_deinterlace filter. frame_duration: %d, QPU %s!",
- frame_duration, use_qpu ? "used" : "unused");
+ if ((pic->context = hw_mmal_gen_context(buf, filter_sys->out_ppr)) == NULL)
+ goto fail2;
-
+
- if (filter->fmt_in.video.i_chroma != VLC_CODEC_MMAL_OPAQUE)
- return VLC_EGENERIC;
+ buf_to_pic_copy_props(pic, buf);
-
+
- if (filter->fmt_out.video.i_chroma != VLC_CODEC_MMAL_OPAQUE)
- return VLC_EGENERIC;
+#if TRACE_ALL
+ msg_Dbg(p_filter, "pic: prog=%d, tff=%d, date=%lld", pic->b_progressive, pic->b_top_field_first, (long long)pic->date);
+#endif
-
+
- sys = calloc(1, sizeof(filter_sys_t));
- if (!sys)
- return VLC_ENOMEM;
- filter->p_sys = sys;
+ return pic;
-
+
- bcm_host_init();
+fail2:
+ picture_Release(pic);
@@ -4021,7 +4024,7 @@ Upstream-status: Pending
+// mmal_buffer_header_release(buf);
+ return NULL;
+}
-
+
- status = mmal_component_create(MMAL_COMPONENT_DEFAULT_DEINTERLACE, &sys->component);
- if (status != MMAL_SUCCESS) {
- msg_Err(filter, "Failed to create MMAL component %s (status=%"PRIx32" %s)",
@@ -4040,7 +4043,7 @@ Upstream-status: Pending
+#else
+ VLC_UNUSED(port);
+#endif
-
+
- status = mmal_port_parameter_set(sys->component->output[0], &imfx_param.hdr);
- if (status != MMAL_SUCCESS) {
- msg_Err(filter, "Failed to configure MMAL component %s (status=%"PRIx32" %s)",
@@ -4049,7 +4052,7 @@ Upstream-status: Pending
- goto out;
- }
+ mmal_buffer_header_release(buffer);
-
+
- sys->component->control->userdata = (struct MMAL_PORT_USERDATA_T *)filter;
- status = mmal_port_enable(sys->component->control, control_port_cb);
- if (status != MMAL_SUCCESS) {
@@ -4080,7 +4083,7 @@ Upstream-status: Pending
+#endif
+ return;
}
-
+
- sys->input = sys->component->input[0];
- sys->input->userdata = (struct MMAL_PORT_USERDATA_T *)filter;
- if (filter->fmt_in.i_codec == VLC_CODEC_MMAL_OPAQUE)
@@ -4096,10 +4099,10 @@ Upstream-status: Pending
+ mmal_buffer_header_reset(buf); // User data stays intact so release will kill pic
+ mmal_buffer_header_release(buf);
+}
-
+
- es_format_Copy(&filter->fmt_out, &filter->fmt_in);
- filter->fmt_out.video.i_frame_rate *= 2;
-
+
- status = mmal_port_format_commit(sys->input);
- if (status != MMAL_SUCCESS) {
- msg_Err(filter, "Failed to commit format for input port %s (status=%"PRIx32" %s)",
@@ -4109,7 +4112,7 @@ Upstream-status: Pending
- }
- sys->input->buffer_size = sys->input->buffer_size_recommended;
- sys->input->buffer_num = sys->input->buffer_num_recommended;
-
+
- if (filter->fmt_in.i_codec == VLC_CODEC_MMAL_OPAQUE) {
- MMAL_PARAMETER_BOOLEAN_T zero_copy = {
- { MMAL_PARAMETER_ZERO_COPY, sizeof(MMAL_PARAMETER_BOOLEAN_T) },
@@ -4118,7 +4121,7 @@ Upstream-status: Pending
+static MMAL_STATUS_T fill_output_from_q(filter_t * const p_filter, filter_sys_t * const sys, MMAL_QUEUE_T * const q)
+{
+ MMAL_BUFFER_HEADER_T * out_buf;
-
+
- status = mmal_port_parameter_set(sys->input, &zero_copy.hdr);
- if (status != MMAL_SUCCESS) {
- msg_Err(filter, "Failed to set zero copy on port %s (status=%"PRIx32" %s)",
@@ -4136,7 +4139,7 @@ Upstream-status: Pending
}
+ return MMAL_SUCCESS;
+}
-
+
- status = mmal_port_enable(sys->input, input_port_cb);
- if (status != MMAL_SUCCESS) {
- msg_Err(filter, "Failed to enable input port %s (status=%"PRIx32" %s)",
@@ -4149,14 +4152,14 @@ Upstream-status: Pending
+static MMAL_BOOL_T out_buffer_pre_release_cb(MMAL_BUFFER_HEADER_T *header, void *userdata)
+{
+ VLC_UNUSED(userdata);
-
+
- sys->output = sys->component->output[0];
- sys->output->userdata = (struct MMAL_PORT_USERDATA_T *)filter;
- mmal_format_full_copy(sys->output->format, sys->input->format);
+ cma_buf_t * const cb = header->user_data;
+ header->user_data = NULL;
+ cma_buf_unref(cb); // Copes fine with NULL
-
+
- status = mmal_port_format_commit(sys->output);
- if (status != MMAL_SUCCESS) {
- msg_Err(filter, "Failed to commit format for output port %s (status=%"PRIx32" %s)",
@@ -4240,7 +4243,7 @@ Upstream-status: Pending
+ goto fail;
+ }
+ mmal_buffer_header_reset(out_buf);
-
+
- sys->output->buffer_num = 3;
+ // Attach cma_buf to the buffer & ensure it is freed when the buffer is released
+ // On a good send callback the pic will be extracted to avoid this
@@ -4264,7 +4267,7 @@ Upstream-status: Pending
+ p_pic, out_buf->data, out_buf->user_data, out_buf->flags,
+ out_buf->length, out_buf->alloc_size, (long long)out_buf->pts);
+#endif
-
+
- if (filter->fmt_in.i_codec == VLC_CODEC_MMAL_OPAQUE) {
- MMAL_PARAMETER_UINT32_T extra_buffers = {
- { MMAL_PARAMETER_EXTRA_BUFFERS, sizeof(MMAL_PARAMETER_UINT32_T) },
@@ -4282,7 +4285,7 @@ Upstream-status: Pending
}
+ out_buf = NULL;
+ }
-
+
- MMAL_PARAMETER_BOOLEAN_T zero_copy = {
- { MMAL_PARAMETER_ZERO_COPY, sizeof(MMAL_PARAMETER_BOOLEAN_T) },
- 1
@@ -4297,7 +4300,7 @@ Upstream-status: Pending
+ msg_Err(p_filter, "Pic has not attached buffer");
+ goto fail;
+ }
-
+
- status = mmal_port_parameter_set(sys->output, &zero_copy.hdr);
- if (status != MMAL_SUCCESS) {
- msg_Err(filter, "Failed to set zero copy on port %s (status=%"PRIx32" %s)",
@@ -4317,7 +4320,7 @@ Upstream-status: Pending
+ goto fail;
}
}
-
+
- status = mmal_port_enable(sys->output, output_port_cb);
- if (status != MMAL_SUCCESS) {
- msg_Err(filter, "Failed to enable output port %s (status=%"PRIx32" %s)",
@@ -4410,7 +4413,7 @@ Upstream-status: Pending
+ // Crash on lockup
+ assert(ret_pics != NULL || seq_delta(sys->seq_in, sys->seq_out) < 5);
}
-
+
- status = mmal_component_enable(sys->component);
- if (status != MMAL_SUCCESS) {
- msg_Err(filter, "Failed to enable component %s (status=%"PRIx32" %s)",
@@ -4471,20 +4474,20 @@ Upstream-status: Pending
+ // Leaving the input disabled is fine - but we want to leave the output enabled
+ // so we can retrieve buffers that are still bound to pictures
}
-
+
- sys->filtered_pictures = mmal_queue_create();
+ sys->seq_in = 1;
+ sys->seq_out = 15;
-
+
- filter->pf_video_filter = deinterlace;
- filter->pf_flush = flush;
+#if TRACE_ALL
+ msg_Dbg(p_filter, ">>> %s", __func__);
+#endif
+}
-
+
- vlc_sem_init(&sys->sem, 0);
-
+
-out:
- if (ret != VLC_SUCCESS)
- Close(filter);
@@ -4493,7 +4496,7 @@ Upstream-status: Pending
+ // Nothing to do
+ VLC_UNUSED(p_filter);
+}
-
+
- return ret;
+static picture_t * pass_deinterlace(filter_t * p_filter, picture_t * p_pic)
+{
@@ -4502,7 +4505,7 @@ Upstream-status: Pending
+ p_pic->b_progressive = true;
+ return p_pic;
}
-
+
-static void Close(filter_t *filter)
+
+static void control_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
@@ -4511,7 +4514,7 @@ Upstream-status: Pending
- MMAL_BUFFER_HEADER_T *buffer;
+ filter_t *filter = (filter_t *)port->userdata;
+ MMAL_STATUS_T status;
-
+
- if (!sys)
+ if (buffer->cmd == MMAL_EVENT_ERROR) {
+ status = *(uint32_t *)buffer->data;
@@ -4533,7 +4536,7 @@ Upstream-status: Pending
+
+ if (sys == NULL)
return;
-
+
- if (sys->component && sys->component->control->is_enabled)
- mmal_port_disable(sys->component->control);
+ if (sys->use_passthrough)
@@ -4541,19 +4544,19 @@ Upstream-status: Pending
+ free(sys);
+ return;
+ }
-
+
- if (sys->input && sys->input->is_enabled)
- mmal_port_disable(sys->input);
+ di_flush(filter);
-
+
- if (sys->output && sys->output->is_enabled)
- mmal_port_disable(sys->output);
+ if (sys->component && sys->component->control->is_enabled)
+ mmal_port_disable(sys->component->control);
-
+
if (sys->component && sys->component->is_enabled)
mmal_component_disable(sys->component);
-
+
- while ((buffer = mmal_queue_get(sys->filtered_pictures))) {
- picture_t *pic = (picture_t *)buffer->user_data;
- picture_Release(pic);
@@ -4575,22 +4578,22 @@ Upstream-status: Pending
+ if (sys->out_pool != NULL)
+ mmal_pool_destroy(sys->out_pool);
}
-
+
- if (sys->filtered_pictures)
- mmal_queue_destroy(sys->filtered_pictures);
+ if (sys->out_q != NULL)
+ mmal_queue_destroy(sys->out_q);
-
+
if (sys->component)
mmal_component_release(sys->component);
-
+
- vlc_sem_destroy(&sys->sem);
+ cma_vcsm_exit(sys->vcsm_init_type);
+
free(sys);
+}
+
-
+
- bcm_host_deinit();
+static bool is_fmt_valid_in(const vlc_fourcc_t fmt)
+{
@@ -4598,7 +4601,7 @@ Upstream-status: Pending
+ fmt == VLC_CODEC_MMAL_ZC_I420 ||
+ fmt == VLC_CODEC_MMAL_ZC_SAND8;
}
-
+
-static int send_output_buffer(filter_t *filter)
+static int OpenMmalDeinterlace(filter_t *filter)
{
@@ -4619,7 +4622,7 @@ Upstream-status: Pending
+ if (!is_fmt_valid_in(filter->fmt_in.video.i_chroma) ||
+ filter->fmt_out.video.i_chroma != filter->fmt_in.video.i_chroma)
+ return VLC_EGENERIC;
-
+
- if (!sys->output->is_enabled) {
- ret = VLC_EGENERIC;
- goto out;
@@ -4665,7 +4668,7 @@ Upstream-status: Pending
+ msg_Warn(filter, "Deinterlace bypassed due to lack of GPU memory");
+ }
}
-
+
- picture = filter_NewPicture(filter);
- if (!picture) {
- msg_Warn(filter, "Failed to get new picture");
@@ -4717,7 +4720,7 @@ Upstream-status: Pending
}
- picture->format.i_frame_rate = filter->fmt_out.video.i_frame_rate;
- picture->format.i_frame_rate_base = filter->fmt_out.video.i_frame_rate_base;
-
+
- buffer = picture->p_sys->buffer;
- buffer->user_data = picture;
- buffer->cmd = 0;
@@ -4727,7 +4730,7 @@ Upstream-status: Pending
+ MMAL_COMPONENT_DEFAULT_DEINTERLACE, status, mmal_status_to_string(status));
+ goto fail;
+ }
-
+
- mmal_picture_lock(picture);
+ {
+ const MMAL_PARAMETER_IMAGEFX_PARAMETERS_T imfx_param = {
@@ -4738,7 +4741,7 @@ Upstream-status: Pending
+ 4,
+ { 5 /* Frame type: mixed */, frame_duration, sys->half_rate, sys->use_qpu }
+ };
-
+
- status = mmal_port_send_buffer(sys->output, buffer);
+ status = mmal_port_parameter_set(sys->component->output[0], &imfx_param.hdr);
+ if (status != MMAL_SUCCESS) {
@@ -4763,7 +4766,7 @@ Upstream-status: Pending
+ sys->component->control->name, status, mmal_status_to_string(status));
+ goto fail;
}
-
+
-out:
- return ret;
-}
@@ -4771,7 +4774,7 @@ Upstream-status: Pending
+ sys->input->userdata = (struct MMAL_PORT_USERDATA_T *)filter;
+ sys->input->format->encoding = vlc_to_mmal_video_fourcc(&filter->fmt_in.video);
+ hw_mmal_vlc_fmt_to_mmal_fmt(sys->input->format, &filter->fmt_in.video);
-
+
-static void fill_output_port(filter_t *filter)
-{
- filter_sys_t *sys = filter->p_sys;
@@ -4785,7 +4788,7 @@ Upstream-status: Pending
+ es_format_Copy(&filter->fmt_out, &filter->fmt_in);
+ if (!sys->half_rate)
+ filter->fmt_out.video.i_frame_rate *= 2;
-
+
- if (buffers_to_send > buffers_available)
- buffers_to_send = buffers_available;
+ status = mmal_port_format_commit(sys->input);
@@ -4797,7 +4800,7 @@ Upstream-status: Pending
+ sys->input->buffer_size = sys->input->buffer_size_recommended;
+ sys->input->buffer_num = 30;
+// sys->input->buffer_num = sys->input->buffer_num_recommended;
-
+
-#ifndef NDEBUG
- msg_Dbg(filter, "Send %d buffers to output port (available: %d, in_transit: %d, buffer_num: %d)",
- buffers_to_send, buffers_available, sys->output_in_transit,
@@ -4812,7 +4815,7 @@ Upstream-status: Pending
+ goto fail;
}
-}
-
+
-static picture_t *deinterlace(filter_t *filter, picture_t *picture)
-{
- filter_sys_t *sys = filter->p_sys;
@@ -4827,7 +4830,7 @@ Upstream-status: Pending
+ sys->input->name, status, mmal_status_to_string(status));
+ goto fail;
+ }
-
+
- fill_output_port(filter);
+ status = mmal_port_enable(sys->input, di_input_port_cb);
+ if (status != MMAL_SUCCESS) {
@@ -4835,12 +4838,12 @@ Upstream-status: Pending
+ sys->input->name, status, mmal_status_to_string(status));
+ goto fail;
+ }
-
+
- buffer = picture->p_sys->buffer;
- buffer->user_data = picture;
- buffer->pts = picture->date;
- buffer->cmd = 0;
-
+
- if (!picture->p_sys->displayed) {
- status = mmal_port_send_buffer(sys->input, buffer);
- if (status != MMAL_SUCCESS) {
@@ -4881,7 +4884,7 @@ Upstream-status: Pending
}
- if (out_picture)
- out_picture->p_next = NULL;
-
+
- return ret;
-}
-
@@ -4891,7 +4894,7 @@ Upstream-status: Pending
- MMAL_BUFFER_HEADER_T *buffer;
+ sys->output = sys->component->output[0];
+ mmal_format_full_copy(sys->output->format, sys->input->format);
-
+
- msg_Dbg(filter, "flush deinterlace filter");
+ if (!sys->is_cma)
+ {
@@ -4908,7 +4911,7 @@ Upstream-status: Pending
+ msg_Err(filter, "Failed to alloc cma buf pool");
+ goto fail;
+ }
-
+
- msg_Dbg(filter, "flush: flush ports (input: %d, output: %d in transit)",
- sys->input_in_transit, sys->output_in_transit);
- mmal_port_flush(sys->output);
@@ -4934,13 +4937,13 @@ Upstream-status: Pending
+ msg_Err(filter, "Failed to alloc out pool");
+ goto fail;
+ }
-
+
-static void control_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
-{
- filter_t *filter = (filter_t *)port->userdata;
- MMAL_STATUS_T status;
+ port_parameter_set_bool(sys->output, MMAL_PARAMETER_ZERO_COPY, true);
-
+
- if (buffer->cmd == MMAL_EVENT_ERROR) {
- status = *(uint32_t *)buffer->data;
- msg_Err(filter, "MMAL error %"PRIx32" \"%s\"", status,
@@ -4951,12 +4954,12 @@ Upstream-status: Pending
+ msg_Err(filter, "Output port format commit failed");
+ goto fail;
+ }
-
+
- mmal_buffer_header_release(buffer);
-}
+ sys->output->buffer_num = 30;
+ sys->output->buffer_size = sys->output->buffer_size_recommended;
-
+
-static void input_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
-{
- picture_t *picture = (picture_t *)buffer->user_data;
@@ -4970,7 +4973,7 @@ Upstream-status: Pending
+ goto fail;
+ }
+ }
-
+
- if (picture) {
- picture_Release(picture);
- } else {
@@ -4982,7 +4985,7 @@ Upstream-status: Pending
+ sys->component->name, status, mmal_status_to_string(status));
+ goto fail;
}
-
+
- atomic_fetch_sub(&sys->input_in_transit, 1);
- vlc_sem_post(&sys->sem);
+ filter->pf_video_filter = deinterlace;
@@ -4993,7 +4996,7 @@ Upstream-status: Pending
+ CloseMmalDeinterlace(filter);
+ return ret;
}
-
+
-static void output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
-{
- filter_t *filter = (filter_t *)port->userdata;
@@ -5022,7 +5025,7 @@ Upstream-status: Pending
+
+vlc_module_end()
+
-
+
- if (buffer->cmd == 0) {
- if (buffer->length > 0) {
- atomic_store(&sys->started, true);
@@ -8126,7 +8129,7 @@ Upstream-status: Pending
@@ -21,25 +21,1542 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
-
+
+// We would really like to use vlc_thread.h but the detach thread stuff can't be
+// used here :-(
+#include <pthread.h>
@@ -8148,7 +8151,7 @@ Upstream-status: Pending
+#include <interface/mmal/util/mmal_default_components.h>
+#include <interface/vmcs_host/vcgencmd.h>
+#include <interface/vcsm/user-vcsm.h>
-
+
+#include "mmal_cma.h"
#include "mmal_picture.h"
+#include "transform_ops.h"
@@ -9291,7 +9294,7 @@ Upstream-status: Pending
+ ent = ent_list_extract_pic_ent(&pc->ents_cur, pic);
+
+// printf("ent_found: %p\n", ent);
-
+
-int mmal_picture_lock(picture_t *picture)
+ if (ent == NULL)
+ {
@@ -9523,7 +9526,7 @@ Upstream-status: Pending
+ case MMAL_ENCODING_RGB16:
+ pb = 2;
+ break;
-
+
- int offset = 0;
- picture->p[0].p_pixels = buffer->data;
- for (int i = 1; i < picture->i_planes; i++) {
@@ -9544,14 +9547,14 @@ Upstream-status: Pending
+// msg_Err(p_filter, "%s: Unexpected format", __func__);
+ return VLC_EGENERIC;
}
-
+
- pic_sys->displayed = false;
+ // Fix up SAR if unset
+ if (pic->format.i_sar_den == 0 || pic->format.i_sar_num == 0) {
+ pic->format.i_sar_den = mm_fmt->par.den;
+ pic->format.i_sar_num = mm_fmt->par.num;
+ }
-
+
+ pic->i_planes = planes;
+ unsigned int offset = 0;
+ for (unsigned int i = 0; i != planes; ++i) {
@@ -9680,17 +9683,17 @@ Upstream-status: Pending
@@ -24,19 +24,298 @@
#ifndef VLC_MMAL_MMAL_PICTURE_H_
#define VLC_MMAL_MMAL_PICTURE_H_
-
+
+#include <stdatomic.h>
+
#include <vlc_common.h>
#include <interface/mmal/mmal.h>
-
+
+#include "mmal_cma.h"
+
/* Think twice before changing this. Incorrect values cause havoc. */
#define NUM_ACTUAL_OPAQUE_BUFFERS 30
-
+
-struct picture_sys_t {
- vlc_object_t *owner;
+#ifndef VLC_TICK_INVALID
@@ -9969,18 +9972,18 @@ Upstream-status: Pending
+vcsm_init_type_t cma_vcsm_type(void);
+const char * cma_vcsm_init_str(const vcsm_init_type_t init_mode);
+
-
+
- MMAL_BUFFER_HEADER_T *buffer;
- bool displayed;
-};
+#define VOUT_DISPLAY_CHANGE_MMAL_BASE 1024
+#define VOUT_DISPLAY_CHANGE_MMAL_HIDE (VOUT_DISPLAY_CHANGE_MMAL_BASE + 0)
-
+
-int mmal_picture_lock(picture_t *picture);
+#define MMAL_COMPONENT_DEFAULT_RESIZER "vc.ril.resize"
+#define MMAL_COMPONENT_ISP_RESIZER "vc.ril.isp"
+#define MMAL_COMPONENT_HVS "vc.ril.hvs"
-
+
#endif
--- /dev/null
+++ b/modules/hw/mmal/rpi_prof.h
@@ -10879,17 +10882,17 @@ Upstream-status: Pending
+++ b/modules/hw/mmal/vout.c
@@ -27,21 +27,28 @@
#endif
-
+
#include <math.h>
+#include <stdatomic.h>
-
+
#include <vlc_common.h>
-#include <vlc_atomic.h>
#include <vlc_plugin.h>
#include <vlc_threads.h>
#include <vlc_vout_display.h>
+#include <vlc_modules.h>
-
+
-#include "mmal_picture.h"
-
+#pragma GCC diagnostic push
@@ -10907,13 +10910,13 @@ Upstream-status: Pending
+#include "transform_ops.h"
+
+#define TRACE_ALL 0
-
+
#define MAX_BUFFERS_IN_TRANSIT 1
#define VC_TV_MAX_MODE_IDS 127
@@ -50,10 +57,28 @@
#define MMAL_LAYER_TEXT N_("VideoCore layer where the video is displayed.")
#define MMAL_LAYER_LONGTEXT N_("VideoCore layer where the video is displayed. Subpictures are displayed directly above and a black background directly below.")
-
+
-#define MMAL_BLANK_BACKGROUND_NAME "mmal-blank-background"
-#define MMAL_BLANK_BACKGROUND_TEXT N_("Blank screen below video.")
-#define MMAL_BLANK_BACKGROUND_LONGTEXT N_("Render blank screen below video. " \
@@ -10940,13 +10943,13 @@ Upstream-status: Pending
+#define MMAL_VOUT_TRANSPARENT_LONGTEXT N_("Enable layers beneath the video layer."\
+" By default these are disabled."\
+" Having the lower layers enabled can impact video performance")
-
+
#define MMAL_ADJUST_REFRESHRATE_NAME "mmal-adjust-refreshrate"
#define MMAL_ADJUST_REFRESHRATE_TEXT N_("Adjust HDMI refresh rate to the video.")
@@ -68,332 +93,628 @@
#define PHASE_OFFSET_TARGET ((double)0.25)
#define PHASE_CHECK_INTERVAL 100
-
+
-static int Open(vlc_object_t *);
-static void Close(vlc_object_t *);
-
@@ -10965,7 +10968,7 @@ Upstream-status: Pending
- set_callbacks(Open, Close)
-vlc_module_end()
+#define SUBS_MAX 4
-
+
-struct dmx_region_t {
- struct dmx_region_t *next;
- picture_t *picture;
@@ -10982,12 +10985,12 @@ Upstream-status: Pending
+ MMAL_COMPONENT_T *component;
+ subpic_reg_stash_t sub;
+} vout_subpic_t;
-
+
struct vout_display_sys_t {
- vlc_cond_t buffer_cond;
- vlc_mutex_t buffer_mutex;
vlc_mutex_t manage_mutex;
-
+
- plane_t planes[3]; /* Depending on video format up to 3 planes are used */
- picture_t **pictures; /* Actual list of alloced pictures passed into picture_pool */
- picture_pool_t *picture_pool;
@@ -10998,11 +11001,11 @@ Upstream-status: Pending
MMAL_POOL_T *pool; /* mmal buffer headers, used for pushing pictures to component*/
- struct dmx_region_t *dmx_region;
int i_planes; /* Number of actually used planes, 1 for opaque, 3 for i420 */
-
+
- uint32_t buffer_size; /* size of actual mmal buffers */
int buffers_in_transit; /* number of buffers currently pushed to mmal component */
unsigned num_buffers; /* number of buffers allocated at mmal port */
-
+
- DISPMANX_DISPLAY_HANDLE_T dmx_handle;
- DISPMANX_ELEMENT_HANDLE_T bkg_element;
- DISPMANX_RESOURCE_HANDLE_T bkg_resource;
@@ -11018,17 +11021,17 @@ Upstream-status: Pending
+ MMAL_DISPLAYTRANSFORM_T dest_transform; // Dest window coord transform
+ MMAL_DISPLAYTRANSFORM_T display_transform; // "Native" display transform
+ MMAL_DISPLAYTRANSFORM_T video_transform; // Combined config+native transform
-
+
- int i_frame_rate_base; /* cached framerate to detect changes for rate adjustment */
- int i_frame_rate;
+ unsigned int i_frame_rate_base; /* cached framerate to detect changes for rate adjustment */
+ unsigned int i_frame_rate;
-
+
int next_phase_check; /* lowpass for phase check frequency */
int phase_offset; /* currently applied offset to presentation time in ns */
int layer; /* the dispman layer (z-index) used for video rendering */
+ bool transparent; // Do not disable layers beneath ours
-
+
bool need_configure_display; /* indicates a required display reconfigure to main thread */
bool adjust_refresh_rate;
bool native_interlaced;
@@ -11037,7 +11040,7 @@ Upstream-status: Pending
- bool opaque; /* indicated use of opaque picture format (zerocopy) */
-};
+ bool force_config;
-
+
-static const vlc_fourcc_t subpicture_chromas[] = {
- VLC_CODEC_RGBA,
- 0
@@ -11058,14 +11061,14 @@ Upstream-status: Pending
+ MMAL_POOL_T * out_pool;
+ bool pending;
+ } isp;
-
+
-/* Utility functions */
-static inline uint32_t align(uint32_t x, uint32_t y);
-static int configure_display(vout_display_t *vd, const vout_display_cfg_t *cfg,
- const video_format_t *fmt);
+ MMAL_POOL_T * copy_pool;
+ MMAL_BUFFER_HEADER_T * copy_buf;
-
+
-/* VLC vout display callbacks */
-static picture_pool_t *vd_pool(vout_display_t *vd, unsigned count);
-static void vd_prepare(vout_display_t *vd, picture_t *picture,
@@ -11081,14 +11084,14 @@ Upstream-status: Pending
+ // Subpic blend if we have to do it here
+ vzc_pool_ctl_t * vzc;
+};
-
+
-/* TV service */
-static int query_resolution(vout_display_t *vd, unsigned *width, unsigned *height);
-static void tvservice_cb(void *callback_data, uint32_t reason, uint32_t param1,
- uint32_t param2);
-static void adjust_refresh_rate(vout_display_t *vd, const video_format_t *fmt);
-static int set_latency_target(vout_display_t *vd, bool enable);
-
+
-/* DispManX */
-static void display_subpicture(vout_display_t *vd, subpicture_t *subpicture);
-static void close_dmx(vout_display_t *vd);
@@ -11101,7 +11104,7 @@ Upstream-status: Pending
-static void show_background(vout_display_t *vd, bool enable);
-static void maintain_phase_sync(vout_display_t *vd);
+// ISP setup
-
+
-static int Open(vlc_object_t *object)
+static inline bool want_isp(const vout_display_t * const vd)
{
@@ -11115,14 +11118,14 @@ Upstream-status: Pending
- unsigned i;
+ return (vd->fmt.i_chroma == VLC_CODEC_MMAL_ZC_SAND10);
+}
-
+
- if (vout_display_IsWindowed(vd))
- return VLC_EGENERIC;
+static inline bool want_copy(const vout_display_t * const vd)
+{
+ return (vd->fmt.i_chroma == VLC_CODEC_I420 || vd->fmt.i_chroma == VLC_CODEC_I420_10L);
+}
-
+
- sys = calloc(1, sizeof(struct vout_display_sys_t));
- if (!sys)
- return VLC_ENOMEM;
@@ -11133,7 +11136,7 @@ Upstream-status: Pending
+ VLC_CODEC_I420 :
+ vd->fmt.i_chroma;
+}
-
+
- sys->layer = var_InheritInteger(vd, MMAL_LAYER_NAME);
- bcm_host_init();
+static MMAL_FOURCC_T vout_vlc_to_mmal_pic_fourcc(const unsigned int fcc)
@@ -11155,14 +11158,14 @@ Upstream-status: Pending
+ }
+ return MMAL_ENCODING_I420;
+}
-
+
- sys->opaque = vd->fmt.i_chroma == VLC_CODEC_MMAL_OPAQUE;
+static void display_set_format(const vout_display_t * const vd, MMAL_ES_FORMAT_T *const es_fmt, const bool is_intermediate)
+{
+ const unsigned int w = is_intermediate ? vd->fmt.i_visible_width : vd->fmt.i_width ;
+ const unsigned int h = is_intermediate ? vd->fmt.i_visible_height : vd->fmt.i_height;
+ MMAL_VIDEO_FORMAT_T * const v_fmt = &es_fmt->es->video;
-
+
- status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_RENDERER, &sys->component);
- if (status != MMAL_SUCCESS) {
- msg_Err(vd, "Failed to create MMAL component %s (status=%"PRIx32" %s)",
@@ -11189,7 +11192,7 @@ Upstream-status: Pending
+ v_fmt->frame_rate.num = vd->fmt.i_frame_rate;
+ v_fmt->frame_rate.den = vd->fmt.i_frame_rate_base;
+ v_fmt->color_space = vlc_to_mmal_color_space(vd->fmt.space);
-
+
- sys->component->control->userdata = (struct MMAL_PORT_USERDATA_T *)vd;
- status = mmal_port_enable(sys->component->control, control_port_cb);
- if (status != MMAL_SUCCESS) {
@@ -11241,12 +11244,12 @@ Upstream-status: Pending
+ status = *(uint32_t *)buffer->data;
+ msg_Err(vd, "MMAL error %"PRIx32" \"%s\"", status, mmal_status_to_string(status));
}
-
+
- sys->input = sys->component->input[0];
- sys->input->userdata = (struct MMAL_PORT_USERDATA_T *)vd;
+ mmal_buffer_header_release(buffer);
+}
-
+
- if (sys->opaque) {
- sys->input->format->encoding = MMAL_ENCODING_OPAQUE;
- sys->i_planes = 1;
@@ -11276,7 +11279,7 @@ Upstream-status: Pending
+ // but might not on later flushes as we shut down
+ vout_display_t * const vd = (vout_display_t *)port->userdata;
+ struct vout_isp_conf_s *const isp = &vd->sys->isp;
-
+
- status = mmal_port_format_commit(sys->input);
- if (status != MMAL_SUCCESS) {
- msg_Err(vd, "Failed to commit format for input port %s (status=%"PRIx32" %s)",
@@ -11298,7 +11301,7 @@ Upstream-status: Pending
+ mmal_buffer_header_release(buf);
+ }
+}
-
+
- vout_display_PlacePicture(&place, &vd->source, vd->cfg, false);
- display_region.hdr.id = MMAL_PARAMETER_DISPLAYREGION;
- display_region.hdr.size = sizeof(MMAL_DISPLAYREGION_T);
@@ -11355,7 +11358,7 @@ Upstream-status: Pending
+ return err;
+ }
}
-
+
- for (i = 0; i < sys->i_planes; ++i) {
- sys->planes[i].i_lines = buffer_height;
- sys->planes[i].i_pitch = buffer_pitch;
@@ -11368,7 +11371,7 @@ Upstream-status: Pending
+ return err;
+ }
+ }
-
+
- if (i > 0) {
- sys->planes[i].i_lines /= 2;
- sys->planes[i].i_pitch /= 2;
@@ -11383,7 +11386,7 @@ Upstream-status: Pending
}
+ return MMAL_SUCCESS;
+}
-
+
- vlc_mutex_init(&sys->buffer_mutex);
- vlc_cond_init(&sys->buffer_cond);
- vlc_mutex_init(&sys->manage_mutex);
@@ -11391,7 +11394,7 @@ Upstream-status: Pending
+{
+ struct vout_isp_conf_s * const isp = &vd_sys->isp;
+ VLC_UNUSED(vd);
-
+
- vd->pool = vd_pool;
- vd->prepare = vd_prepare;
- vd->display = vd_display;
@@ -11399,10 +11402,10 @@ Upstream-status: Pending
- vd->manage = vd_manage;
+ if (isp->component == NULL)
+ return;
-
+
- vc_tv_register_callback(tvservice_cb, vd);
+ isp_flush(isp);
-
+
- if (query_resolution(vd, &sys->display_width, &sys->display_height) >= 0) {
- vout_display_SendEventDisplaySize(vd, sys->display_width, sys->display_height);
- } else {
@@ -11418,28 +11421,28 @@ Upstream-status: Pending
+ mmal_queue_destroy(isp->out_q);
+ isp->out_q = NULL;
}
-
+
- sys->dmx_handle = vc_dispmanx_display_open(0);
- vd->info.subpicture_chromas = subpicture_chromas;
+ if (isp->out_pool != NULL) {
+ mmal_port_pool_destroy(isp->output, isp->out_pool);
+ isp->out_pool = NULL;
+ }
-
+
- vout_display_DeleteWindow(vd, NULL);
+ isp->input = NULL;
+ isp->output = NULL;
-
+
-out:
- if (ret != VLC_SUCCESS)
- Close(object);
+ mmal_component_release(isp->component);
+ isp->component = NULL;
-
+
- return ret;
+ return;
}
-
+
-static void Close(vlc_object_t *object)
+// Restuff into output rather than return to pool is we can
+static MMAL_BOOL_T isp_out_pool_cb(MMAL_POOL_T *pool, MMAL_BUFFER_HEADER_T *buffer, void *userdata)
@@ -11457,13 +11460,13 @@ Upstream-status: Pending
+ }
+ return MMAL_TRUE;
+}
-
+
- vc_tv_unregister_callback_full(tvservice_cb, vd);
+static MMAL_STATUS_T isp_setup(vout_display_t * const vd, vout_display_sys_t * const vd_sys)
+{
+ struct vout_isp_conf_s * const isp = &vd_sys->isp;
+ MMAL_STATUS_T err;
-
+
- if (sys->dmx_handle)
- close_dmx(vd);
+ if ((err = mmal_component_create(MMAL_COMPONENT_ISP_RESIZER, &isp->component)) != MMAL_SUCCESS) {
@@ -11472,7 +11475,7 @@ Upstream-status: Pending
+ }
+ isp->input = isp->component->input[0];
+ isp->output = isp->component->output[0];
-
+
- if (sys->component && sys->component->control->is_enabled)
- mmal_port_disable(sys->component->control);
+ isp->component->control->userdata = (void *)vd;
@@ -11480,29 +11483,29 @@ Upstream-status: Pending
+ msg_Err(vd, "Failed to enable ISP control port");
+ goto fail;
+ }
-
+
- if (sys->input && sys->input->is_enabled)
- mmal_port_disable(sys->input);
+ isp->input->userdata = (void *)vd;
+ display_set_format(vd, isp->input->format, false);
-
+
- if (sys->component && sys->component->is_enabled)
- mmal_component_disable(sys->component);
+ if ((err = port_parameter_set_bool(isp->input, MMAL_PARAMETER_ZERO_COPY, true)) != MMAL_SUCCESS)
+ goto fail;
-
+
- if (sys->pool)
- mmal_port_pool_destroy(sys->input, sys->pool);
+ if ((err = mmal_port_format_commit(isp->input)) != MMAL_SUCCESS) {
+ msg_Err(vd, "Failed to set ISP input format");
+ goto fail;
+ }
-
+
- if (sys->component)
- mmal_component_release(sys->component);
+ isp->input->buffer_size = isp->input->buffer_size_recommended;
+ isp->input->buffer_num = 30;
-
+
- if (sys->picture_pool)
- picture_pool_Release(sys->picture_pool);
- else
@@ -11516,7 +11519,7 @@ Upstream-status: Pending
+ msg_Err(vd, "Failed to create input pool");
+ goto fail;
+ }
-
+
- vlc_mutex_destroy(&sys->buffer_mutex);
- vlc_cond_destroy(&sys->buffer_cond);
- vlc_mutex_destroy(&sys->manage_mutex);
@@ -11525,7 +11528,7 @@ Upstream-status: Pending
+ err = MMAL_ENOMEM;
+ goto fail;
+ }
-
+
- if (sys->native_interlaced) {
- if (vc_gencmd(response, sizeof(response), "hvs_update_fields 0") < 0 ||
- response[18] != '0')
@@ -11539,7 +11542,7 @@ Upstream-status: Pending
+ msg_Err(vd, "Failed to set ISP input format");
+ goto fail;
}
-
+
- free(sys->pictures);
- free(sys);
+ isp->output->buffer_size = isp->output->buffer_size_recommended;
@@ -11558,13 +11561,13 @@ Upstream-status: Pending
+ goto fail;
+
+ return MMAL_SUCCESS;
-
+
- bcm_host_deinit();
+fail:
+ isp_close(vd, vd_sys);
+ return err;
}
-
+
-static inline uint32_t align(uint32_t x, uint32_t y) {
- uint32_t mod = x % y;
- if (mod == 0)
@@ -11792,7 +11795,7 @@ Upstream-status: Pending
+ }
+ return 0;
}
-
+
static int configure_display(vout_display_t *vd, const vout_display_cfg_t *cfg,
const video_format_t *fmt)
{
@@ -11801,7 +11804,7 @@ Upstream-status: Pending
- MMAL_DISPLAYREGION_T display_region;
+ vout_display_sys_t * const sys = vd->sys;
MMAL_STATUS_T status;
-
+
if (!cfg && !fmt)
+ {
+ msg_Err(vd, "%s: Missing cfg & fmt", __func__);
@@ -11809,17 +11812,17 @@ Upstream-status: Pending
+ }
+
+ isp_check(vd, sys);
-
+
if (fmt) {
sys->input->format->es->video.par.num = fmt->i_sar_num;
@@ -412,30 +733,14 @@ static int configure_display(vout_displa
if (!cfg)
cfg = vd->cfg;
-
+
- vout_display_PlacePicture(&place, fmt, cfg, false);
+ sys->video_transform = combine_transform(
+ vlc_to_mmal_transform(fmt->orientation), sys->display_transform);
-
+
- display_region.hdr.id = MMAL_PARAMETER_DISPLAYREGION;
- display_region.hdr.size = sizeof(MMAL_DISPLAYREGION_T);
- display_region.fullscreen = MMAL_FALSE;
@@ -11843,7 +11846,7 @@ Upstream-status: Pending
+ if (set_input_region(vd, fmt) != 0)
return -EINVAL;
- }
-
+
- show_background(vd, var_InheritBool(vd, MMAL_BLANK_BACKGROUND_NAME));
sys->adjust_refresh_rate = var_InheritBool(vd, MMAL_ADJUST_REFRESHRATE_NAME);
sys->native_interlaced = var_InheritBool(vd, MMAL_NATIVE_INTERLACED);
@@ -11851,7 +11854,7 @@ Upstream-status: Pending
@@ -446,204 +751,217 @@ static int configure_display(vout_displa
return 0;
}
-
+
+static void kill_pool(vout_display_sys_t * const sys)
+{
+ if (sys->pic_pool != NULL) {
@@ -11870,21 +11873,21 @@ Upstream-status: Pending
- MMAL_STATUS_T status;
- unsigned i;
+ vout_display_sys_t * const sys = vd->sys;
-
+
- if (sys->picture_pool) {
- if (sys->num_buffers < count)
- msg_Warn(vd, "Picture pool with %u pictures requested, but we already have one with %u pictures",
- count, sys->num_buffers);
+ msg_Dbg(vd, "%s: fmt:%dx%d,sar:%d/%d; source:%dx%d", __func__,
+ vd->fmt.i_width, vd->fmt.i_height, vd->fmt.i_sar_num, vd->fmt.i_sar_den, vd->source.i_width, vd->source.i_height);
-
+
- goto out;
+ if (sys->pic_pool == NULL) {
+ sys->pic_pool = picture_pool_NewFromFormat(&vd->fmt, count);
}
+ return sys->pic_pool;
+}
-
+
- if (sys->opaque) {
- if (count <= NUM_ACTUAL_OPAQUE_BUFFERS)
- count = NUM_ACTUAL_OPAQUE_BUFFERS;
@@ -11896,7 +11899,7 @@ Upstream-status: Pending
+ return true;
+ return false;
+}
-
+
- MMAL_PARAMETER_BOOLEAN_T zero_copy = {
- { MMAL_PARAMETER_ZERO_COPY, sizeof(MMAL_PARAMETER_BOOLEAN_T) },
- 1
@@ -11906,7 +11909,7 @@ Upstream-status: Pending
+{
+ vout_display_sys_t * const sys = vd->sys;
+ MMAL_STATUS_T err;
-
+
- status = mmal_port_parameter_set(sys->input, &zero_copy.hdr);
- if (status != MMAL_SUCCESS) {
- msg_Err(vd, "Failed to set zero copy on port %s (status=%"PRIx32" %s)",
@@ -11930,7 +11933,7 @@ Upstream-status: Pending
-#ifndef NDEBUG
- msg_Dbg(vd, "Creating picture pool with %u pictures", count);
#endif
-
+
- sys->input->buffer_num = count;
- status = mmal_port_enable(sys->input, input_port_cb);
- if (status != MMAL_SUCCESS) {
@@ -11942,7 +11945,7 @@ Upstream-status: Pending
+ if (subpicture != NULL) {
+ subpicture_Delete(subpicture);
}
-
+
- status = mmal_component_enable(sys->component);
- if (status != MMAL_SUCCESS) {
- msg_Err(vd, "Failed to enable component %s (status=%"PRIx32" %s)",
@@ -12017,11 +12020,11 @@ Upstream-status: Pending
+ msg_Err(vd, "Replicated buffer get fail");
+ goto fail;
}
-
+
- sys->pictures[i]->i_planes = sys->i_planes;
- memcpy(sys->pictures[i]->p, sys->planes, sys->i_planes * sizeof(plane_t));
- }
-
+
- memset(&picture_pool_cfg, 0, sizeof(picture_pool_configuration_t));
- picture_pool_cfg.picture_count = sys->num_buffers;
- picture_pool_cfg.picture = sys->pictures;
@@ -12035,7 +12038,7 @@ Upstream-status: Pending
+ if (mmal_port_format_commit(sys->input) != MMAL_SUCCESS)
+ msg_Warn(vd, "Input format commit failed");
+ }
-
+
- sys->picture_pool = picture_pool_NewExtended(&picture_pool_cfg);
- if (!sys->picture_pool) {
- msg_Err(vd, "Failed to create picture pool");
@@ -12047,7 +12050,7 @@ Upstream-status: Pending
+ goto fail;
+ }
}
-
+
-out:
- return sys->picture_pool;
-}
@@ -12123,18 +12126,18 @@ Upstream-status: Pending
- } else {
- picture_Release(picture);
}
-
+
- display_subpicture(vd, subpicture);
+fail:
+ for (unsigned int i = 0; i != SUBS_MAX && sys->subpic_bufs[i] != NULL; ++i) {
+ mmal_buffer_header_release(sys->subpic_bufs[i]);
+ sys->subpic_bufs[i] = NULL;
+ }
-
+
- if (subpicture)
- subpicture_Delete(subpicture);
+ picture_Release(p_pic);
-
+
if (sys->next_phase_check == 0 && sys->adjust_refresh_rate)
maintain_phase_sync(vd);
sys->next_phase_check = (sys->next_phase_check + 1) % PHASE_CHECK_INTERVAL;
@@ -12146,7 +12149,7 @@ Upstream-status: Pending
- vlc_mutex_unlock(&sys->buffer_mutex);
- }
}
-
+
static int vd_control(vout_display_t *vd, int query, va_list args)
{
- vout_display_sys_t *sys = vd->sys;
@@ -12155,7 +12158,7 @@ Upstream-status: Pending
+ vout_display_sys_t * const sys = vd->sys;
int ret = VLC_EGENERIC;
+ VLC_UNUSED(args);
-
+
switch (query) {
- case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE:
- tmp_cfg = va_arg(args, const vout_display_cfg_t *);
@@ -12175,7 +12178,7 @@ Upstream-status: Pending
+ if (configure_display(vd, vd->cfg, &vd->source) >= 0)
ret = VLC_SUCCESS;
break;
-
+
- case VOUT_DISPLAY_RESET_PICTURES:
- vlc_assert_unreachable();
case VOUT_DISPLAY_CHANGE_ZOOM:
@@ -12218,13 +12221,13 @@ Upstream-status: Pending
+ ret = VLC_SUCCESS;
break;
+ }
-
+
default:
msg_Warn(vd, "Unknown control query %d", query);
@@ -653,79 +971,207 @@ static int vd_control(vout_display_t *vd
return ret;
}
-
+
+static void set_display_windows(vout_display_t *const vd, vout_display_sys_t *const sys)
+{
+ unsigned int width, height;
@@ -12245,9 +12248,9 @@ Upstream-status: Pending
- vout_display_sys_t *sys = vd->sys;
- unsigned width, height;
+ vout_display_sys_t *const sys = vd->sys;
-
+
vlc_mutex_lock(&sys->manage_mutex);
-
+
if (sys->need_configure_display) {
- close_dmx(vd);
- sys->dmx_handle = vc_dispmanx_display_open(0);
@@ -12261,10 +12264,10 @@ Upstream-status: Pending
sys->need_configure_display = false;
+ set_display_windows(vd, sys);
}
-
+
vlc_mutex_unlock(&sys->manage_mutex);
}
-
+
-static void control_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
+
+static int attach_subpics(vout_display_t * const vd, vout_display_sys_t * const sys,
@@ -12273,7 +12276,7 @@ Upstream-status: Pending
- vout_display_t *vd = (vout_display_t *)port->userdata;
- MMAL_STATUS_T status;
+ unsigned int n = 0;
-
+
- if (buffer->cmd == MMAL_EVENT_ERROR) {
- status = *(uint32_t *)buffer->data;
- msg_Err(vd, "MMAL error %"PRIx32" \"%s\"", status, mmal_status_to_string(status));
@@ -12284,7 +12287,7 @@ Upstream-status: Pending
+ return VLC_ENOMEM;
+ }
}
-
+
- mmal_buffer_header_release(buffer);
+ // Attempt to import the subpics
+ for (subpicture_t * spic = subpicture; spic != NULL; spic = spic->p_next)
@@ -12330,7 +12333,7 @@ Upstream-status: Pending
+ }
+ return VLC_SUCCESS;
}
-
+
-static void input_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
+
+static void vd_prepare(vout_display_t *vd, picture_t *p_pic,
@@ -12425,12 +12428,12 @@ Upstream-status: Pending
vout_display_sys_t *sys = vd->sys;
- picture_t *picture = (picture_t *)buffer->user_data;
+ picture_sys_t *pic_sys = picture->p_sys;
-
+
- if (picture)
- picture_Release(picture);
+ if (!sys->adjust_refresh_rate || pic_sys->displayed)
+ return;
-
+
- vlc_mutex_lock(&sys->buffer_mutex);
- atomic_fetch_sub(&sys->buffers_in_transit, 1);
- vlc_cond_signal(&sys->buffer_cond);
@@ -12440,7 +12443,7 @@ Upstream-status: Pending
+ picture->date += sys->phase_offset;
+#endif
}
-
+
-static int query_resolution(vout_display_t *vd, unsigned *width, unsigned *height)
+
+static void vd_control_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
@@ -12449,7 +12452,7 @@ Upstream-status: Pending
- int ret = 0;
+ vout_display_t *vd = (vout_display_t *)port->userdata;
+ MMAL_STATUS_T status;
-
+
- if (vc_tv_get_display_state(&display_state) == 0) {
- if (display_state.state & 0xFF) {
- *width = display_state.display.hdmi.width;
@@ -12468,23 +12471,23 @@ Upstream-status: Pending
+ status = *(uint32_t *)buffer->data;
+ msg_Err(vd, "MMAL error %"PRIx32" \"%s\"", status, mmal_status_to_string(status));
}
-
+
- return ret;
+ mmal_buffer_header_release(buffer);
}
-
+
static void tvservice_cb(void *callback_data, uint32_t reason, uint32_t param1, uint32_t param2)
@@ -780,9 +1226,9 @@ static void adjust_refresh_rate(vout_dis
double best_score, score;
int i;
-
+
- vc_tv_get_display_state(&display_state);
+ vc_tv_get_display_state_id(sys->display_id, &display_state);
if(display_state.display.hdmi.mode != HDMI_MODE_OFF) {
- num_modes = vc_tv_hdmi_get_supported_modes_new(display_state.display.hdmi.group,
+ num_modes = vc_tv_hdmi_get_supported_modes_new_id(sys->display_id, display_state.display.hdmi.group,
supported_modes, VC_TV_MAX_MODE_IDS, NULL, NULL);
-
+
for (i = 0; i < num_modes; ++i) {
@@ -810,7 +1256,7 @@ static void adjust_refresh_rate(vout_dis
if((best_id >= 0) && (display_state.display.hdmi.mode != supported_modes[best_id].code)) {
@@ -12498,7 +12501,7 @@ Upstream-status: Pending
@@ -828,148 +1274,12 @@ static void adjust_refresh_rate(vout_dis
}
}
-
+
-static void display_subpicture(vout_display_t *vd, subpicture_t *subpicture)
-{
- vout_display_sys_t *sys = vd->sys;
@@ -12648,7 +12651,7 @@ Upstream-status: Pending
@@ -1012,32 +1322,436 @@ static void maintain_phase_sync(vout_dis
}
}
-
+
-static void show_background(vout_display_t *vd, bool enable)
+static void CloseMmalVout(vlc_object_t *object)
{
@@ -13700,7 +13703,7 @@ Upstream-status: Pending
@@ -43,6 +43,8 @@
# include "../android/utils.h"
#endif
-
+
+#define REQUIRE_DMA_BUF_IMPORT 1
+
typedef struct vlc_gl_sys_t
@@ -13709,7 +13712,7 @@ Upstream-status: Pending
@@ -355,6 +357,14 @@ static int Open (vlc_object_t *obj, cons
goto error;
}
-
+
+#if REQUIRE_DMA_BUF_IMPORT
+ if (!CheckToken(ext, "EGL_EXT_image_dma_buf_import"))
+ {
@@ -13728,7 +13731,7 @@ Upstream-status: Pending
p_owner->b_waiting = false;
vlc_cond_signal( &p_owner->wait_request );
+ vlc_mutex_unlock( &p_owner->lock );
-
+
/* If the video output is paused or slow, or if the picture pool size was
* under-estimated (e.g. greedy video filter, buggy decoder...), the
@@ -2005,7 +2006,6 @@ void input_DecoderDelete( decoder_t *p_d
@@ -13736,9 +13739,9 @@ Upstream-status: Pending
if( p_owner->p_vout != NULL )
vout_Cancel( p_owner->p_vout, true );
- vlc_mutex_unlock( &p_owner->lock );
-
+
vlc_join( p_owner->thread, NULL );
-
+
--- a/src/misc/fourcc.c
+++ b/src/misc/fourcc.c
@@ -755,8 +755,13 @@ static const struct
@@ -13762,7 +13765,7 @@ Upstream-status: Pending
@@ -365,10 +365,30 @@ void picture_CopyProperties( picture_t *
p_dst->b_top_field_first = p_src->b_top_field_first;
}
-
+
+static inline bool is_zc_chroma(const vlc_fourcc_t i_chroma)
+{
+ return i_chroma == VLC_CODEC_MMAL_OPAQUE ||
@@ -13789,15 +13792,15 @@ Upstream-status: Pending
+ for( int i = 0; i < p_src->i_planes; i++ )
+ plane_CopyPixels( p_dst->p+i, p_src->p+i );
+ }
-
+
assert( p_dst->context == NULL );
-
+
--- a/src/video_output/video_output.c
+++ b/src/video_output/video_output.c
@@ -964,6 +964,17 @@ static picture_t *ConvertRGB32AndBlend(v
return NULL;
}
-
+
+
+static inline bool is_zc_chroma(const vlc_fourcc_t i_chroma)
+{
@@ -13814,7 +13817,7 @@ Upstream-status: Pending
vout_thread_sys_t *sys = vout->p;
@@ -1098,7 +1109,7 @@ static int ThreadDisplayRenderPicture(vo
}
-
+
assert(vout_IsDisplayFiltered(vd) == !sys->display.use_dr);
- if (sys->display.use_dr && !is_direct) {
+ if (sys->display.use_dr && !is_direct && !is_zc_chroma(todisplay->format.i_chroma)) {
diff --git a/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0004-mmal_exit_fix.patch b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0005-mmal_exit_fix.patch
index b8ac0a0ba3..d8fc7fbfe2 100644
--- a/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0004-mmal_exit_fix.patch
+++ b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0005-mmal_exit_fix.patch
@@ -1,4 +1,7 @@
-Upstream-status: Pending
+Upstream-Status: Inappropriate
+
+RPI-Distro repo forks original vlc and applies patches
+to enable raspiberry pi support.
--- a/bin/vlc.c
+++ b/bin/vlc.c
@@ -12,5 +15,5 @@ Upstream-status: Pending
+// signal (SIGINT, SIG_DFL);
+ _exit(0);
}
-
+
/*****************************************************************************
diff --git a/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0006-Use-packageconfig-to-detect-mmal-support.patch b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0006-Use-packageconfig-to-detect-mmal-support.patch
deleted file mode 100644
index 3a2ac236c0..0000000000
--- a/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0006-Use-packageconfig-to-detect-mmal-support.patch
+++ /dev/null
@@ -1,56 +0,0 @@
-From: Vincent Davis Jr <vince@underview.tech>
-Date: Fri, 07 Jan 2022 07:10:47 PM CST
-Subject: [PATCH] Use packageconfig to acquire mmal flags
-
-Need to use userland graphics libraries package files as it's best to not assume /opt/vc is where
-all libs and headers are installed per distro. Also, needed to include $BCMHOST_MMAL_LIBS variable as
-AC_CHECK_LIB(bcm_host) fails to find `vc_tv_unregister_callback_full`. Adding $BCMHOST_MMAL_LIBS uses all
-libs inside bcm_host,mmal,vcsm,openmaxil .pc files when checking for `vc_tv_unregister_callback_full`
-function.
-
-Upstream-status: Pending
-
-Signed-off-by: Vincent Davis Jr <vince@underview.tech>
-diff --git a/configure.ac b/configure.ac
-index bff220510..4d487409d 100644
---- a/configure.ac
-+++ b/configure.ac
-@@ -3483,23 +3483,25 @@ AC_ARG_ENABLE(mmal_avcodec,
- [Use MMAL enabled avcodec libs (default disable)]))
- if test "${enable_mmal}" != "no"; then
- VLC_SAVE_FLAGS
-- LDFLAGS="${LDFLAGS} -L/opt/vc/lib -lvchostif"
-- CPPFLAGS="${CPPFLAGS} -isystem /opt/vc/include -isystem /opt/vc/include/interface/vcos/pthreads -isystem /opt/vc/include/interface/vmcs_host/linux"
-- AC_CHECK_HEADERS(interface/mmal/mmal.h,
-- [ AC_CHECK_LIB(bcm_host, vc_tv_unregister_callback_full, [
-+ PKG_CHECK_MODULES(BCMHOST_MMAL, [bcm_host mmal vcsm openmaxil egl], [
-+ HAVE_MMAL=yes
-+ AC_CHECK_HEADERS(interface/mmal/mmal.h,
-+ [ AC_CHECK_LIB(bcm_host $BCMHOST_MMAL_LIBS, vc_tv_unregister_callback_full, [
- have_mmal="yes"
-- VLC_ADD_PLUGIN([mmal])
-- VLC_ADD_LDFLAGS([mmal],[ -L/opt/vc/lib ])
-- VLC_ADD_CFLAGS([mmal],[ -isystem /opt/vc/include -isystem /opt/vc/include/interface/vcos/pthreads -isystem /opt/vc/include/interface/vmcs_host/linux ])
-- VLC_ADD_LIBS([mmal],[ -lbcm_host -lmmal -lmmal_core -lmmal_components -lmmal_util -lvchostif -lvchiq_arm -lvcsm ]) ], [
-+ VLC_ADD_PLUGIN([bcm_host mmal vcsm openmaxil egl])
-+ VLC_ADD_CFLAGS([bcm_host mmal vcsm openmaxil egl],[$BCMHOST_MMAL_CFLAGS])
-+ VLC_ADD_LIBS([bcm_host mmal vcsm openmaxil egl],[$BCMHOST_MMAL_LIBS]) ], [
- AS_IF([test "${enable_mmal}" = "yes"],
- [ AC_MSG_ERROR([Cannot find bcm library...]) ],
- [ AC_MSG_WARN([Cannot find bcm library...]) ])
-- ],
-- [])
-- ] , [ AS_IF([test "${enable_mmal}" = "yes"],
-- [ AC_MSG_ERROR([Cannot find development headers for mmal...]) ],
-- [ AC_MSG_WARN([Cannot find development headers for mmal...]) ]) ])
-+ ],[])
-+ ],[ AS_IF([test "${enable_mmal}" = "yes"],
-+ [ AC_MSG_ERROR([Cannot find development headers for mmal...]) ],
-+ [ AC_MSG_WARN([Cannot find development headers for mmal...]) ]) ])
-+ ],:[
-+ AC_MSG_WARN([${BCMHOST_PKG_ERRORS}: userland graphics not available.])
-+ HAVE_MMAL=no
-+ ])
- VLC_RESTORE_FLAGS
- fi
- AM_CONDITIONAL([HAVE_MMAL], [test "${have_mmal}" = "yes"])
diff --git a/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0005-mmal_chain.patch b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0006-mmal_chain.patch
index abd31df562..99fd03e101 100644
--- a/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0005-mmal_chain.patch
+++ b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0006-mmal_chain.patch
@@ -1,10 +1,13 @@
-Upstream-status: Pending
+Upstream-Status: Inappropriate
+
+RPI-Distro repo forks original vlc and applies patches
+to enable raspiberry pi support.
--- a/modules/video_chroma/chain.c
+++ b/modules/video_chroma/chain.c
@@ -280,8 +280,9 @@ static int BuildTransformChain( filter_t
return VLC_SUCCESS;
-
+
/* Lets try resize+chroma first, then transform */
- msg_Dbg( p_filter, "Trying to build chroma+resize" );
- EsFormatMergeSize( &fmt_mid, &p_filter->fmt_out, &p_filter->fmt_in );
diff --git a/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0007-armv6.patch b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0007-armv6.patch
new file mode 100644
index 0000000000..64a24268cf
--- /dev/null
+++ b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0007-armv6.patch
@@ -0,0 +1,53 @@
+Upstream-Status: Inappropriate
+
+RPI-Distro repo forks original vlc and applies patches
+to enable raspiberry pi support.
+
+--- a/modules/hw/mmal/blend_rgba_neon.S
++++ b/modules/hw/mmal/blend_rgba_neon.S
+@@ -1,10 +1,10 @@
+- .syntax unified
+- .arm
+-// .thumb
+- .text
++#include "../../arm_neon/asm.S"
+ .align 16
+ .arch armv7-a
+- .fpu neon-vfpv4
++ .syntax unified
++#if HAVE_AS_FPU_DIRECTIVE
++ .fpu neon-vfpv4
++#endif
+
+ @ blend_rgbx_rgba_neon
+
+--- a/modules/hw/mmal/codec.c
++++ b/modules/hw/mmal/codec.c
+@@ -29,6 +29,7 @@
+ #include <stdatomic.h>
+
+ #include <vlc_common.h>
++#include <vlc_cpu.h>
+ #include <vlc_plugin.h>
+ #include <vlc_codec.h>
+ #include <vlc_filter.h>
+@@ -2311,6 +2312,9 @@ static int OpenBlendMmal(vlc_object_t *o
+ filter_t * const p_filter = (filter_t *)object;
+ const vlc_fourcc_t vfcc_dst = p_filter->fmt_out.video.i_chroma;
+
++ if (!vlc_CPU_ARM_NEON())
++ return VLC_EGENERIC;
++
+ if (!hw_mmal_chroma_is_mmal(vfcc_dst) ||
+ !hw_mmal_vzc_subpic_fmt_valid(&p_filter->fmt_in.video))
+ {
+@@ -2421,6 +2425,9 @@ static int OpenBlendNeon(vlc_object_t *o
+ MMAL_FOURCC_T mfcc_dst = vlc_to_mmal_video_fourcc(&p_filter->fmt_out.video);
+ blend_neon_fn * blend_fn = (blend_neon_fn *)0;
+
++ if (!vlc_CPU_ARM_NEON())
++ return VLC_EGENERIC;
++
+ // Non-alpha RGB only for dest
+ if (vfcc_dst != VLC_CODEC_RGB32)
+ return VLC_EGENERIC;
diff --git a/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0007-use-vorbisidec.patch b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0007-use-vorbisidec.patch
deleted file mode 100644
index 18bdc4ddd1..0000000000
--- a/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0007-use-vorbisidec.patch
+++ /dev/null
@@ -1,18 +0,0 @@
-* tremor provides libvorbisidec, use it instead of libvorbisdec
-
-Upstream-status: Pending
-
-Signed-off-by: Tim Orling <TicoTimo@gmail.com>
-
-Index: vlc-2.2.1/modules/codec/Makefile.am
-===================================================================
---- vlc-2.2.1.orig/modules/codec/Makefile.am
-+++ vlc-2.2.1/modules/codec/Makefile.am
-@@ -234,7 +234,7 @@ codec_LTLIBRARIES += $(LTLIBtheora)
- libtremor_plugin_la_SOURCES = codec/vorbis.c
- libtremor_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) -DMODULE_NAME_IS_tremor
- libtremor_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(codecdir)'
--libtremor_plugin_la_LIBADD = -lvorbisdec -logg
-+libtremor_plugin_la_LIBADD = -lvorbisidec -logg
- EXTRA_LTLIBRARIES += libtremor_plugin.la
- codec_LTLIBRARIES += $(LTLIBtremor)
diff --git a/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0010-fix-numeric_limits-is-not-a-member-of-std.patch b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0010-fix-numeric_limits-is-not-a-member-of-std.patch
deleted file mode 100644
index a13b337fe2..0000000000
--- a/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0010-fix-numeric_limits-is-not-a-member-of-std.patch
+++ /dev/null
@@ -1,35 +0,0 @@
-From: Vincent Davis Jr <vince@underview.tech>
-Date: Fri, 07 Jan 2022 07:10:47 PM CST
-Subject: [PATCH] Fix numeric limits not a member
-
-* Fixes bellow compiler issue:
- ../../git/modules/demux/adaptive/playlist/SegmentInformation.cpp:397:23: error: 'numeric_limits' is not a member of 'std'
- 397 | if(number == std::numeric_limits<uint64_t>::max())
-
-Upstream-status: Pending
-
-Signed-off-by: Vincent Davis Jr <vince@underview.tech>
-diff --git a/modules/demux/adaptive/playlist/SegmentInformation.cpp b/modules/demux/adaptive/playlist/SegmentInformation.cpp
-index 344e155c7..8eeb05439 100644
---- a/modules/demux/adaptive/playlist/SegmentInformation.cpp
-+++ b/modules/demux/adaptive/playlist/SegmentInformation.cpp
-@@ -34,6 +34,7 @@
-
- #include <algorithm>
- #include <cassert>
-+#include <limits>
-
- using namespace adaptive::playlist;
-
-diff --git a/modules/demux/hls/playlist/Parser.cpp b/modules/demux/hls/playlist/Parser.cpp
-index 67110e4cd..743969922 100644
---- a/modules/demux/hls/playlist/Parser.cpp
-+++ b/modules/demux/hls/playlist/Parser.cpp
-@@ -42,6 +42,7 @@
- #include <map>
- #include <cctype>
- #include <algorithm>
-+#include <limits>
-
- using namespace adaptive;
- using namespace adaptive::playlist;
diff --git a/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0008-fix-luaL-checkint.patch b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/2001-fix-luaL-checkint.patch
index 96b5d2d246..e8990fca60 100644
--- a/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0008-fix-luaL-checkint.patch
+++ b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/2001-fix-luaL-checkint.patch
@@ -1,7 +1,10 @@
* luaL_checkint and luaL_optint were deprecated in lua 5.3
* replacement functions are luaL_checkinteger and luaL_optinteger
-Upstream-status: Pending
+Upstream-Status: Inappropriate
+
+RPI-Distro repo forks original vlc and applies patches to enable
+raspiberry pi support.
Signed-off-by: Tim Orling <TicoTimo@gmail.com>
diff --git a/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/2002-use-vorbisidec.patch b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/2002-use-vorbisidec.patch
new file mode 100644
index 0000000000..bfabf21fa4
--- /dev/null
+++ b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/2002-use-vorbisidec.patch
@@ -0,0 +1,33 @@
+From d0a7ba506fd302ad195f79f287b5a5a154ac02a3 Mon Sep 17 00:00:00 2001
+From: Vincent Davis Jr <vince@underview.tech>
+Date: Sun, 4 Dec 2022 16:09:51 -0600
+Subject: [PATCH] tremor provides libvorbisidec, use it instead of libvorbisdec
+
+Upstream-Status: Inappropriate
+
+RPI-Distro repo forks original vlc and applies patches to enable
+raspiberry pi support.
+
+THIS PATCHES HAS BEEN REIMPLEMENTED INORDER TO APPLY PROPERLY.
+
+Signed-off-by: Tim Orling <TicoTimo@gmail.com>
+---
+ modules/codec/Makefile.am | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/modules/codec/Makefile.am b/modules/codec/Makefile.am
+index 3dadf1119..8b6189e92 100644
+--- a/modules/codec/Makefile.am
++++ b/modules/codec/Makefile.am
+@@ -324,7 +324,7 @@ codec_LTLIBRARIES += $(LTLIBdaala)
+ libtremor_plugin_la_SOURCES = codec/vorbis.c
+ libtremor_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) -DMODULE_NAME_IS_tremor
+ libtremor_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(codecdir)'
+-libtremor_plugin_la_LIBADD = -lvorbisdec -logg
++libtremor_plugin_la_LIBADD = -lvorbisidec -logg
+ EXTRA_LTLIBRARIES += libtremor_plugin.la
+ codec_LTLIBRARIES += $(LTLIBtremor)
+
+--
+2.38.1
+
diff --git a/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/3001-configure.ac-setup-for-OE-usage.patch b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/3001-configure.ac-setup-for-OE-usage.patch
new file mode 100644
index 0000000000..d676be39bf
--- /dev/null
+++ b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/3001-configure.ac-setup-for-OE-usage.patch
@@ -0,0 +1,124 @@
+From ddc2ea76058466b45a1acf37bed0d794cd3112a3 Mon Sep 17 00:00:00 2001
+From: Vincent Davis Jr <vince@underview.tech>
+Date: Fri, 9 Dec 2022 19:04:42 -0600
+Subject: [PATCH] configure.ac: setup for OE usage
+
+Upstream-Status: Inappropriate
+
+RPI-Distro repo forks original vlc and applies patches to enable
+raspiberry pi support.
+
+Need to use userland graphics libraries package files as it's best
+to not assume /opt/vc is where all libs and headers are installed per
+distro. Also, needed to include $BCMHOST_MMAL_LIBS variable as
+AC_CHECK_LIB(bcm_host) fails to find `vc_tv_unregister_callback_full`.
+Adding $BCMHOST_MMAL_LIBS uses all libs inside
+bcm_host.pc, mmal.pc, vcsm.pc, openmaxil.pc files when checking
+for `vc_tv_unregister_callback_full` function.
+
+Supposed to change linked version to opengl to GLESv2
+
+Ensure correct package config file is used for:
+* opencv
+* freerdp
+
+Adds Workaround for modules/codec/omxil/omxil_core.h
+ multiple definition of `pf_enable_graphic_buffers'
+ multiple definition of `pf_get_graphic_buffer_usage'
+ multiple definition of `pf_get_hal_format'
+
+Signed-off-by: Vincent Davis Jr <vince@underview.tech>
+---
+ configure.ac | 34 ++++++++++++++++++++++------------
+ 1 file changed, 22 insertions(+), 12 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index a72dca0b6..5b8585a26 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -95,6 +95,13 @@ AS_IF([test -n "${with_binary_version}"],[
+ [Binary specific version])
+ ])
+
++# Workaround for modules/codec/omxil/omxil_core.h
++# multiple definition of `pf_enable_graphic_buffers'
++# multiple definition of `pf_get_graphic_buffer_usage'
++# multiple definition of `pf_get_hal_format'
++AC_SUBST([AM_CXXFLAGS], [-fcommon])
++AC_SUBST([AM_CFLAGS], [-fcommon])
++
+ dnl Prevent clang from accepting unknown flags with a mere warning
+ AX_APPEND_COMPILE_FLAGS([-Werror=unknown-warning-option -Werror=invalid-command-line-argument], [CFLAGS])
+ AX_APPEND_COMPILE_FLAGS([-Werror=unknown-warning-option -Werror=invalid-command-line-argument], [CXXFLAGS])
+@@ -1900,7 +1907,7 @@ PKG_ENABLE_MODULES_VLC([BLURAY], [libbluray], [libbluray >= 0.6.2], (libbluray f
+ dnl
+ dnl OpenCV wrapper and example filters
+ dnl
+-PKG_ENABLE_MODULES_VLC([OPENCV], [opencv_example opencv_wrapper], [opencv > 2.0], (OpenCV (computer vision) filter), [auto])
++PKG_ENABLE_MODULES_VLC([OPENCV], [opencv_example opencv_wrapper], [opencv4 >= 2.0], (OpenCV (computer vision) filter), [auto])
+
+
+ dnl
+@@ -2077,7 +2084,7 @@ PKG_ENABLE_MODULES_VLC([VNC], [vnc], [libvncclient >= 0.9.9], (VNC/rfb client su
+
+ dnl RDP/Remote Desktop access module
+ dnl
+-PKG_ENABLE_MODULES_VLC([FREERDP], [rdp], [freerdp >= 1.0.1], (RDP/Remote Desktop client support) )
++PKG_ENABLE_MODULES_VLC([FREERDP], [rdp], [freerdp2 >= 1.0.1], (RDP/Remote Desktop client support) )
+
+ dnl
+ dnl Real RTSP plugin
+@@ -3089,14 +3096,14 @@ PKG_CHECK_MODULES([GL], [gl], [
+ #ifdef _WIN32
+ # include <GL/glew.h>
+ #endif
+-#include <GL/gl.h>
++#include <GLES2/gl2.h>
+ ]], [
+ [int t0 = GL_TEXTURE0;]])
+ ], [
+ GL_CFLAGS=""
+ have_gl="yes"
+ AS_IF([test "${SYS}" != "mingw32"], [
+- GL_LIBS="-lGL"
++ GL_LIBS="-lGLESv2"
+ ], [
+ GL_LIBS="-lopengl32"
+ ])
+@@ -3483,15 +3490,14 @@ AC_ARG_ENABLE(mmal_avcodec,
+ [Use MMAL enabled avcodec libs (default disable)]))
+ if test "${enable_mmal}" != "no"; then
+ VLC_SAVE_FLAGS
+- LDFLAGS="${LDFLAGS} -L/opt/vc/lib -lvchostif"
+- CPPFLAGS="${CPPFLAGS} -isystem /opt/vc/include -isystem /opt/vc/include/interface/vcos/pthreads -isystem /opt/vc/include/interface/vmcs_host/linux"
+- AC_CHECK_HEADERS(interface/mmal/mmal.h,
+- [ AC_CHECK_LIB(bcm_host, vc_tv_unregister_callback_full, [
++ PKG_CHECK_MODULES(BCMHOST_MMAL, [bcm_host mmal vcsm openmaxil egl], [
++ HAVE_MMAL=yes
++ AC_CHECK_HEADERS(interface/mmal/mmal.h,
++ [ AC_CHECK_LIB(bcm_host $BCMHOST_MMAL_LIBS, vc_tv_unregister_callback_full, [
+ have_mmal="yes"
+- VLC_ADD_PLUGIN([mmal])
+- VLC_ADD_LDFLAGS([mmal],[ -L/opt/vc/lib ])
+- VLC_ADD_CFLAGS([mmal],[ -isystem /opt/vc/include -isystem /opt/vc/include/interface/vcos/pthreads -isystem /opt/vc/include/interface/vmcs_host/linux ])
+- VLC_ADD_LIBS([mmal],[ -lbcm_host -lmmal -lmmal_core -lmmal_components -lmmal_util -lvchostif -lvchiq_arm -lvcsm ]) ], [
++ VLC_ADD_PLUGIN([bcm_host mmal vcsm openmaxil egl])
++ VLC_ADD_CFLAGS([bcm_host mmal vcsm openmaxil egl],[$BCMHOST_MMAL_CFLAGS])
++ VLC_ADD_LIBS([bcm_host mmal vcsm openmaxil egl],[$BCMHOST_MMAL_LIBS -lmmal_components]) ], [
+ AS_IF([test "${enable_mmal}" = "yes"],
+ [ AC_MSG_ERROR([Cannot find bcm library...]) ],
+ [ AC_MSG_WARN([Cannot find bcm library...]) ])
+@@ -3500,6 +3506,10 @@ if test "${enable_mmal}" != "no"; then
+ ] , [ AS_IF([test "${enable_mmal}" = "yes"],
+ [ AC_MSG_ERROR([Cannot find development headers for mmal...]) ],
+ [ AC_MSG_WARN([Cannot find development headers for mmal...]) ]) ])
++ ],:[
++ AC_MSG_WARN([${BCMHOST_PKG_ERRORS}: userland graphics not available.])
++ HAVE_MMAL=NO
++ ])
+ VLC_RESTORE_FLAGS
+ fi
+ AM_CONDITIONAL([HAVE_MMAL], [test "${have_mmal}" = "yes"])
+--
+2.38.1
+
diff --git a/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0009-fix-EGL-macro-undeclared-and-EGLImageKHR.patch b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/3002-fix-EGL-macro-undeclared-and-EGLImageKHR.patch
index 9bd6b41469..ab72b4f3c9 100644
--- a/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/0009-fix-EGL-macro-undeclared-and-EGLImageKHR.patch
+++ b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/3002-fix-EGL-macro-undeclared-and-EGLImageKHR.patch
@@ -2,11 +2,14 @@ From: Vincent Davis Jr <vince@underview.tech>
Date: Fri, 07 Jan 2022 07:01:47 PM CST
Subject: [PATCH] Fix EGL macro undeclared and EGLImageKHR
+Upstream-Status: Inappropriate
+
+RPI-Distro repo forks original vlc and applies patches to enable
+raspiberry pi support.
+
* Fixes compiler issues related to EGL macro constant/enum value type not being defined
* Updates EGLImage to EGLImageKHR
-Upstream-status: Pending
-
Signed-off-by: Vincent Davis Jr <vince@underview.tech>
diff --git a/modules/hw/mmal/converter_mmal.c b/modules/hw/mmal/converter_mmal.c
index f31cb81d8..426af668b 100644
diff --git a/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/3003-codec-omxil_core-replace-opt-vc-path-with-usr-lib.patch b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/3003-codec-omxil_core-replace-opt-vc-path-with-usr-lib.patch
new file mode 100644
index 0000000000..a2dba50b2f
--- /dev/null
+++ b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/3003-codec-omxil_core-replace-opt-vc-path-with-usr-lib.patch
@@ -0,0 +1,43 @@
+From 85f6603aca1d174848b42e696a4cff8af57613d6 Mon Sep 17 00:00:00 2001
+From: Vincent Davis Jr <vince@underview.tech>
+Date: Thu, 8 Dec 2022 23:38:36 -0600
+Subject: [PATCH] codec: omxil_core replace /opt/vc path with /usr/lib
+
+Upstream-Status: Inappropriate
+
+RPI-Distro repo clones original VLC and applies patches to enable
+raspiberry pi support.
+
+Configures omxil_core.c for OE usages as libbcm_host.so
+and libopenmaxil.so are located in a different location.
+
+Signed-off-by: Vincent Davis Jr <vince@underview.tech>
+---
+ modules/codec/omxil/omxil_core.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/modules/codec/omxil/omxil_core.c b/modules/codec/omxil/omxil_core.c
+index 5098f517a..5922d9034 100644
+--- a/modules/codec/omxil/omxil_core.c
++++ b/modules/codec/omxil/omxil_core.c
+@@ -56,7 +56,7 @@ static const char *ppsz_dll_list[] =
+ #if defined(USE_IOMX)
+ "libiomx.so", /* Not used when using IOMX, the lib should already be loaded */
+ #elif defined(RPI_OMX)
+- "/opt/vc/lib/libopenmaxil.so", /* Broadcom IL core */
++ "/usr/lib/libopenmaxil.so", /* Broadcom IL core */
+ #elif 1
+ "libOMX_Core.so", /* TI OMAP IL core */
+ "libOmxCore.so", /* Qualcomm IL core */
+@@ -70,7 +70,7 @@ static const char *ppsz_dll_list[] =
+ #ifdef RPI_OMX
+ static const char *ppsz_extra_dll_list[] =
+ {
+- "/opt/vc/lib/libbcm_host.so", /* Broadcom host library */
++ "/usr/lib/libbcm_host.so", /* Broadcom host library */
+ 0
+ };
+ #endif
+--
+2.38.1
+
diff --git a/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/3004-use-GLESv2-headers-over-GL-headers.patch b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/3004-use-GLESv2-headers-over-GL-headers.patch
new file mode 100644
index 0000000000..8016ab3795
--- /dev/null
+++ b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/3004-use-GLESv2-headers-over-GL-headers.patch
@@ -0,0 +1,60 @@
+From 377a67af6c3f7c38f6f7ba24f042ba1a6cfd3f24 Mon Sep 17 00:00:00 2001
+From: Vincent Davis Jr <vince@underview.tech>
+Date: Fri, 9 Dec 2022 00:21:43 -0600
+Subject: [PATCH] use GLESv2 headers over GL headers
+
+Upstream-Status: Inappropriate
+
+RPI-Distro repo forks original vlc and applies patches to enable
+raspiberry pi support.
+
+We utilize GLESv2 during compilation. Patches ensures
+we utilize headers for it.
+
+Signed-off-by: Vincent Davis Jr <vince@underview.tech>
+---
+ modules/video_output/opengl/converter.h | 12 +++---------
+ modules/visualization/glspectrum.c | 4 +++-
+ 2 files changed, 6 insertions(+), 10 deletions(-)
+
+diff --git a/modules/video_output/opengl/converter.h b/modules/video_output/opengl/converter.h
+index 7000e1f38..a3fe32671 100644
+--- a/modules/video_output/opengl/converter.h
++++ b/modules/video_output/opengl/converter.h
+@@ -41,15 +41,9 @@
+ # include <OpenGLES/ES2/glext.h>
+ # endif
+ #else /* !defined (__APPLE__) */
+-# if defined (USE_OPENGL_ES2)
+-# include <GLES2/gl2.h>
+-# include <GLES2/gl2ext.h>
+-# else
+-# ifdef _WIN32
+-# include <GL/glew.h>
+-# endif
+-# include <GL/gl.h>
+-# endif
++#define USE_OPENGL_ES2
++#include <GLES2/gl2.h>
++#include <GLES2/gl2ext.h>
+ #endif
+
+ #define VLCGL_PICTURE_MAX 128
+diff --git a/modules/visualization/glspectrum.c b/modules/visualization/glspectrum.c
+index 06f8d1bdf..470080b1a 100644
+--- a/modules/visualization/glspectrum.c
++++ b/modules/visualization/glspectrum.c
+@@ -37,7 +37,9 @@
+ #ifdef __APPLE__
+ # include <OpenGL/gl.h>
+ #else
+-# include <GL/gl.h>
++#define USE_OPENGL_ES2
++#include <GLES2/gl2.h>
++#include <GLES2/gl2ext.h>
+ #endif
+
+ #include <math.h>
+--
+2.38.1
+
diff --git a/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/3005-modules-remove-glspectrum-usage.patch b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/3005-modules-remove-glspectrum-usage.patch
new file mode 100644
index 0000000000..7cf210be27
--- /dev/null
+++ b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/3005-modules-remove-glspectrum-usage.patch
@@ -0,0 +1,149 @@
+From 5f1bb5889d838719e381350b25c00ef3a75d0e02 Mon Sep 17 00:00:00 2001
+From: Vincent Davis Jr <vince@underview.tech>
+Date: Fri, 9 Dec 2022 01:07:55 -0600
+Subject: [PATCH] modules: remove glspectrum usage
+
+Upstream-Status: Inappropriate
+
+RPI-Distro repo forks original vlc and applies patches to enable
+raspiberry pi support.
+
+The glspectrum modules requries OpenGL
+while we only want to utilize GLESv2.
+
+Signed-off-by: Vincent Davis Jr <vince@underview.tech>
+---
+ modules/Makefile.in | 24 ------------------------
+ modules/visualization/Makefile.am | 10 ----------
+ 2 files changed, 34 deletions(-)
+
+diff --git a/modules/Makefile.in b/modules/Makefile.in
+index bde45db53..c9c4342ad 100644
+--- a/modules/Makefile.in
++++ b/modules/Makefile.in
+@@ -481,7 +481,6 @@ TESTS = hpack_test$(EXEEXT) hpackenc_test$(EXEEXT) \
+ @HAVE_WIN32_FALSE@am__append_247 = $(X_LIBS) $(X_PRE_LIBS) -lX11
+ @HAVE_DARWIN_FALSE@@HAVE_WIN32_FALSE@am__append_248 = $(X_LIBS) $(X_PRE_LIBS) -lX11
+ @HAVE_EVAS_TRUE@am__append_249 = libevas_plugin.la
+-@HAVE_GL_TRUE@am__append_250 = libglspectrum_plugin.la
+ @ENABLE_SOUT_TRUE@@HAVE_GCRYPT_TRUE@am__append_251 = libaccess_output_livehttp_plugin.la
+ @ENABLE_SOUT_TRUE@am__append_252 = libaccess_output_shout_plugin.la \
+ @ENABLE_SOUT_TRUE@ libaccess_output_srt_plugin.la \
+@@ -2028,13 +2027,7 @@ libgles2_plugin_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(libgles2_plugin_la_CFLAGS) $(CFLAGS) \
+ $(libgles2_plugin_la_LDFLAGS) $(LDFLAGS) -o $@
+-libglspectrum_plugin_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
+-am_libglspectrum_plugin_la_OBJECTS = visualization/glspectrum.lo \
+- visualization/visual/fft.lo visualization/visual/window.lo
+-libglspectrum_plugin_la_OBJECTS = \
+- $(am_libglspectrum_plugin_la_OBJECTS)
+-@HAVE_GL_TRUE@am_libglspectrum_plugin_la_rpath = -rpath $(visudir)
+ libglwin32_plugin_la_DEPENDENCIES = libchroma_copy.la \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_5)
+ am__objects_23 = \
+@@ -6507,7 +6500,6 @@ am__depfiles_remade = \
+ video_splitter/$(DEPDIR)/clone.Plo \
+ video_splitter/$(DEPDIR)/libpanoramix_plugin_la-panoramix.Plo \
+ video_splitter/$(DEPDIR)/wall.Plo \
+- visualization/$(DEPDIR)/glspectrum.Plo \
+ visualization/$(DEPDIR)/libgoom_plugin_la-goom.Plo \
+ visualization/$(DEPDIR)/libprojectm_plugin_la-projectm.Plo \
+ visualization/$(DEPDIR)/libvsxu_plugin_la-vsxu.Plo \
+@@ -6731,7 +6723,6 @@ SOURCES = $(liba52_plugin_la_SOURCES) $(libaa_plugin_la_SOURCES) \
+ $(libglconv_vaapi_x11_plugin_la_SOURCES) \
+ $(libglconv_vdpau_plugin_la_SOURCES) \
+ $(libgles2_plugin_la_SOURCES) \
+- $(libglspectrum_plugin_la_SOURCES) \
+ $(libglwin32_plugin_la_SOURCES) $(libglx_plugin_la_SOURCES) \
+ $(libgme_plugin_la_SOURCES) $(libgnutls_plugin_la_SOURCES) \
+ $(libgoom_plugin_la_SOURCES) $(libgradfun_plugin_la_SOURCES) \
+@@ -7130,7 +7121,6 @@ DIST_SOURCES = $(liba52_plugin_la_SOURCES) $(libaa_plugin_la_SOURCES) \
+ $(libglconv_vaapi_x11_plugin_la_SOURCES) \
+ $(libglconv_vdpau_plugin_la_SOURCES) \
+ $(libgles2_plugin_la_SOURCES) \
+- $(libglspectrum_plugin_la_SOURCES) \
+ $(libglwin32_plugin_la_SOURCES) $(libglx_plugin_la_SOURCES) \
+ $(libgme_plugin_la_SOURCES) $(libgnutls_plugin_la_SOURCES) \
+ $(libgoom_plugin_la_SOURCES) $(libgradfun_plugin_la_SOURCES) \
+@@ -12696,13 +12686,6 @@ libevent_thread_la_LDFLAGS = -static
+ visudir = $(pluginsdir)/visualization
+ visu_LTLIBRARIES = $(am__append_250) $(LTLIBgoom) $(LTLIBprojectm) \
+ libvisual_plugin.la $(LTLIBvsxu)
+-libglspectrum_plugin_la_SOURCES = \
+- visualization/glspectrum.c \
+- visualization/visual/fft.c visualization/visual/fft.h \
+- visualization/visual/window.c visualization/visual/window.h \
+- visualization/visual/window_presets.h
+-
+-libglspectrum_plugin_la_LIBADD = $(GL_LIBS) $(LIBM)
+ libgoom_plugin_la_SOURCES = visualization/goom.c
+ libgoom_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) $(GOOM_CFLAGS)
+ libgoom_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(visudir)'
+@@ -15715,8 +15698,6 @@ visualization/$(am__dirstamp):
+ visualization/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) visualization/$(DEPDIR)
+ @: > visualization/$(DEPDIR)/$(am__dirstamp)
+-visualization/glspectrum.lo: visualization/$(am__dirstamp) \
+- visualization/$(DEPDIR)/$(am__dirstamp)
+ visualization/visual/$(am__dirstamp):
+ @$(MKDIR_P) visualization/visual
+ @: > visualization/visual/$(am__dirstamp)
+@@ -15728,8 +15709,6 @@ visualization/visual/fft.lo: visualization/visual/$(am__dirstamp) \
+ visualization/visual/window.lo: visualization/visual/$(am__dirstamp) \
+ visualization/visual/$(DEPDIR)/$(am__dirstamp)
+
+-libglspectrum_plugin.la: $(libglspectrum_plugin_la_OBJECTS) $(libglspectrum_plugin_la_DEPENDENCIES) $(EXTRA_libglspectrum_plugin_la_DEPENDENCIES)
+- $(AM_V_CCLD)$(LINK) $(am_libglspectrum_plugin_la_rpath) $(libglspectrum_plugin_la_OBJECTS) $(libglspectrum_plugin_la_LIBADD) $(LIBS)
+ video_output/opengl/libglwin32_plugin_la-vout_helper.lo: \
+ video_output/opengl/$(am__dirstamp) \
+ video_output/opengl/$(DEPDIR)/$(am__dirstamp)
+@@ -21420,7 +21399,6 @@ distclean-compile:
+ @AMDEP_TRUE@@am__include@ @am__quote@video_splitter/$(DEPDIR)/clone.Plo@am__quote@ # am--include-marker
+ @AMDEP_TRUE@@am__include@ @am__quote@video_splitter/$(DEPDIR)/libpanoramix_plugin_la-panoramix.Plo@am__quote@ # am--include-marker
+ @AMDEP_TRUE@@am__include@ @am__quote@video_splitter/$(DEPDIR)/wall.Plo@am__quote@ # am--include-marker
+-@AMDEP_TRUE@@am__include@ @am__quote@visualization/$(DEPDIR)/glspectrum.Plo@am__quote@ # am--include-marker
+ @AMDEP_TRUE@@am__include@ @am__quote@visualization/$(DEPDIR)/libgoom_plugin_la-goom.Plo@am__quote@ # am--include-marker
+ @AMDEP_TRUE@@am__include@ @am__quote@visualization/$(DEPDIR)/libprojectm_plugin_la-projectm.Plo@am__quote@ # am--include-marker
+ @AMDEP_TRUE@@am__include@ @am__quote@visualization/$(DEPDIR)/libvsxu_plugin_la-vsxu.Plo@am__quote@ # am--include-marker
+@@ -30324,7 +30302,6 @@ distclean: distclean-recursive
+ -rm -f video_splitter/$(DEPDIR)/clone.Plo
+ -rm -f video_splitter/$(DEPDIR)/libpanoramix_plugin_la-panoramix.Plo
+ -rm -f video_splitter/$(DEPDIR)/wall.Plo
+- -rm -f visualization/$(DEPDIR)/glspectrum.Plo
+ -rm -f visualization/$(DEPDIR)/libgoom_plugin_la-goom.Plo
+ -rm -f visualization/$(DEPDIR)/libprojectm_plugin_la-projectm.Plo
+ -rm -f visualization/$(DEPDIR)/libvsxu_plugin_la-vsxu.Plo
+@@ -31722,7 +31699,6 @@ maintainer-clean: maintainer-clean-recursive
+ -rm -f video_splitter/$(DEPDIR)/clone.Plo
+ -rm -f video_splitter/$(DEPDIR)/libpanoramix_plugin_la-panoramix.Plo
+ -rm -f video_splitter/$(DEPDIR)/wall.Plo
+- -rm -f visualization/$(DEPDIR)/glspectrum.Plo
+ -rm -f visualization/$(DEPDIR)/libgoom_plugin_la-goom.Plo
+ -rm -f visualization/$(DEPDIR)/libprojectm_plugin_la-projectm.Plo
+ -rm -f visualization/$(DEPDIR)/libvsxu_plugin_la-vsxu.Plo
+diff --git a/modules/visualization/Makefile.am b/modules/visualization/Makefile.am
+index 10619e030..aafc97f87 100644
+--- a/modules/visualization/Makefile.am
++++ b/modules/visualization/Makefile.am
+@@ -1,16 +1,6 @@
+ visudir = $(pluginsdir)/visualization
+ visu_LTLIBRARIES =
+
+-libglspectrum_plugin_la_SOURCES = \
+- visualization/glspectrum.c \
+- visualization/visual/fft.c visualization/visual/fft.h \
+- visualization/visual/window.c visualization/visual/window.h \
+- visualization/visual/window_presets.h
+-libglspectrum_plugin_la_LIBADD = $(GL_LIBS) $(LIBM)
+-if HAVE_GL
+-visu_LTLIBRARIES += libglspectrum_plugin.la
+-endif
+-
+ libgoom_plugin_la_SOURCES = visualization/goom.c
+ libgoom_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) $(GOOM_CFLAGS)
+ libgoom_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(visudir)'
+--
+2.38.1
+
diff --git a/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/3006-codec-omxil_core.h-fix-multiple-definition-of.patch b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/3006-codec-omxil_core.h-fix-multiple-definition-of.patch
new file mode 100644
index 0000000000..e680c88bca
--- /dev/null
+++ b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/3006-codec-omxil_core.h-fix-multiple-definition-of.patch
@@ -0,0 +1,43 @@
+From fd4d233757cc46cd89f68b45ec4b059940dd84ae Mon Sep 17 00:00:00 2001
+From: Vincent Davis Jr <vince@underview.tech>
+Date: Fri, 9 Dec 2022 19:58:11 -0600
+Subject: [PATCH] codec: omxil_core.h fix multiple definition of
+
+Upstream-Status: Inappropriate
+
+RPI-Distro repo forks original vlc and applies patches
+to enable raspiberry pi support.
+
+Issue occurs during compilation as
+* pf_enable_graphic_buffers
+* pf_get_graphic_buffer_usage
+* pf_get_hal_format
+
+Apears to be defined multiple times as the omxil_core.h
+is included in multiple files.
+
+Signed-off-by: Vincent Davis Jr <vince@underview.tech>
+---
+ modules/codec/omxil/omxil_core.h | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/modules/codec/omxil/omxil_core.h b/modules/codec/omxil/omxil_core.h
+index ac3db510b..f6e42f5ed 100644
+--- a/modules/codec/omxil/omxil_core.h
++++ b/modules/codec/omxil/omxil_core.h
+@@ -34,9 +34,9 @@ extern OMX_ERRORTYPE (*pf_component_enum)(OMX_STRING, OMX_U32, OMX_U32);
+ extern OMX_ERRORTYPE (*pf_get_roles_of_component)(OMX_STRING, OMX_U32 *, OMX_U8 **);
+
+ /* Extra IOMX android functions. Can be NULL if we don't link with libiomx */
+-OMX_ERRORTYPE (*pf_enable_graphic_buffers)(OMX_HANDLETYPE, OMX_U32, OMX_BOOL);
+-OMX_ERRORTYPE (*pf_get_graphic_buffer_usage)(OMX_HANDLETYPE, OMX_U32, OMX_U32*);
+-OMX_ERRORTYPE (*pf_get_hal_format) (const char *, int *);
++extern OMX_ERRORTYPE (*pf_enable_graphic_buffers)(OMX_HANDLETYPE, OMX_U32, OMX_BOOL);
++extern OMX_ERRORTYPE (*pf_get_graphic_buffer_usage)(OMX_HANDLETYPE, OMX_U32, OMX_U32*);
++extern OMX_ERRORTYPE (*pf_get_hal_format) (const char *, int *);
+
+ int InitOmxCore(vlc_object_t *p_this);
+ void DeinitOmxCore(void);
+--
+2.38.1
+
diff --git a/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/3007-remove-xorg-related-link-libs.patch b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/3007-remove-xorg-related-link-libs.patch
new file mode 100644
index 0000000000..a0487fa2e4
--- /dev/null
+++ b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/3007-remove-xorg-related-link-libs.patch
@@ -0,0 +1,36 @@
+From 34e4f4dad923095989ccb0ab8efb883c592bdbfd Mon Sep 17 00:00:00 2001
+From: Vincent Davis Jr <vince@underview.tech>
+Date: Fri, 9 Dec 2022 20:04:27 -0600
+Subject: [PATCH] remove xorg related link libs
+
+Upstream-Status: Inappropriate
+
+RPI-Distro repo forks original vlc and applies patches
+to enable raspiberry pi support.
+
+If x11 isn't defined in DISTRO_FEATURES
+required xorg related libs are not included
+in recipe-sysroot resulting in compilation
+failure.
+
+Signed-off-by: Vincent Davis Jr <vince@underview.tech>
+---
+ modules/hw/mmal/Makefile.am | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/modules/hw/mmal/Makefile.am b/modules/hw/mmal/Makefile.am
+index 4abe68e2e..86dad2c2d 100644
+--- a/modules/hw/mmal/Makefile.am
++++ b/modules/hw/mmal/Makefile.am
+@@ -8,7 +8,7 @@ libmmal_vout_plugin_la_SOURCES = vout.c mmal_cma.c mmal_picture.c subpic.c\
+ mmal_cma.h mmal_picture.h subpic.h transform_ops.h\
+ mmal_piccpy_neon.S
+ libmmal_vout_plugin_la_CFLAGS = $(AM_CFLAGS)
+-libmmal_vout_plugin_la_LDFLAGS = $(AM_LDFLAGS) -lm -lX11 -lXrandr
++libmmal_vout_plugin_la_LDFLAGS = $(AM_LDFLAGS) -lm
+ libmmal_vout_plugin_la_LIBADD = $(LIBS_mmal)
+ mmal_LTLIBRARIES = libmmal_vout_plugin.la
+
+--
+2.38.1
+
diff --git a/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/3008-vo-Makefile.am-exclude-libgl_plugin.patch b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/3008-vo-Makefile.am-exclude-libgl_plugin.patch
new file mode 100644
index 0000000000..8806c80a60
--- /dev/null
+++ b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/3008-vo-Makefile.am-exclude-libgl_plugin.patch
@@ -0,0 +1,97 @@
+From 28917a258a4173af0abda0eef7faef5cbf95f123 Mon Sep 17 00:00:00 2001
+From: Vincent Davis Jr <vince@underview.tech>
+Date: Fri, 9 Dec 2022 21:28:48 -0600
+Subject: [PATCH] vo: Makefile.am exclude libgl_plugin
+
+Upstream-Status: Inappropriate
+
+RPI-Distro repo forks original vlc and applies patches
+to enable raspiberry pi support.
+
+In the situation where opengl isn't included in
+DISTRO_FEATURES. We need to exclude the opengl
+vout plugin from being built.
+
+Signed-off-by: Vincent Davis Jr <vince@underview.tech>
+---
+ modules/video_output/Makefile.am | 64 --------------------------------
+ 1 file changed, 64 deletions(-)
+
+diff --git a/modules/video_output/Makefile.am b/modules/video_output/Makefile.am
+index 78c06cfc4..14a330e68 100644
+--- a/modules/video_output/Makefile.am
++++ b/modules/video_output/Makefile.am
+@@ -57,70 +57,6 @@ if HAVE_TVOS
+ vout_LTLIBRARIES += libvout_ios_plugin.la libglconv_cvpx_plugin.la
+ endif
+
+-### OpenGL ###
+-libgles2_plugin_la_SOURCES = $(OPENGL_COMMONSOURCES) video_output/opengl/display.c
+-libgles2_plugin_la_CFLAGS = $(AM_CFLAGS) $(GLES2_CFLAGS) -DUSE_OPENGL_ES2 $(OPENGL_COMMONCLFAGS)
+-libgles2_plugin_la_LIBADD = $(GLES2_LIBS) $(LIBM) $(OPENGL_COMMONLIBS)
+-libgles2_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(voutdir)'
+-
+-EXTRA_LTLIBRARIES += libgles2_plugin.la
+-vout_LTLIBRARIES += $(LTLIBgles2)
+-
+-libgl_plugin_la_SOURCES = $(OPENGL_COMMONSOURCES) video_output/opengl/display.c
+-libgl_plugin_la_CFLAGS = $(AM_CFLAGS) $(GL_CFLAGS) $(OPENGL_COMMONCLFAGS)
+-libgl_plugin_la_LIBADD = $(LIBM) $(OPENGL_COMMONLIBS)
+-if HAVE_WIN32
+-libgl_plugin_la_CFLAGS += -DHAVE_GL_CORE_SYMBOLS
+-libgl_plugin_la_LIBADD += $(GL_LIBS)
+-endif
+-
+-libglconv_vaapi_wl_plugin_la_SOURCES = video_output/opengl/converter_vaapi.c \
+- video_output/opengl/converter.h \
+- hw/vaapi/vlc_vaapi.c hw/vaapi/vlc_vaapi.h
+-libglconv_vaapi_wl_plugin_la_CFLAGS = $(AM_CFLAGS) $(GL_CFLAGS) -DHAVE_VA_WL $(LIBVA_WL_CFLAGS)
+-libglconv_vaapi_wl_plugin_la_LIBADD = $(LIBVA_LIBS) $(LIBVA_EGL_LIBS) \
+- $(LIBVA_WL_LIBS)
+-
+-libglconv_vaapi_x11_plugin_la_SOURCES = $(libglconv_vaapi_wl_plugin_la_SOURCES)
+-libglconv_vaapi_x11_plugin_la_CFLAGS = $(AM_CFLAGS) -DHAVE_VA_X11
+-libglconv_vaapi_x11_plugin_la_LIBADD = $(LIBVA_LIBS) $(LIBVA_EGL_LIBS) \
+- $(LIBVA_X11_LIBS) $(X_LIBS) $(X_PRE_LIBS) -lX11
+-
+-libglconv_vaapi_drm_plugin_la_SOURCES = $(libglconv_vaapi_wl_plugin_la_SOURCES)
+-libglconv_vaapi_drm_plugin_la_CFLAGS = $(AM_CFLAGS) -DHAVE_VA_DRM
+-libglconv_vaapi_drm_plugin_la_LIBADD = $(LIBVA_LIBS) $(LIBVA_EGL_LIBS) \
+- $(LIBVA_DRM_LIBS)
+-
+-libglconv_vdpau_plugin_la_SOURCES = video_output/opengl/converter_vdpau.c \
+- video_output/opengl/converter.h hw/vdpau/vlc_vdpau.h
+-libglconv_vdpau_plugin_la_CFLAGS = $(AM_CFLAGS) $(VDPAU_CFLAGS)
+-libglconv_vdpau_plugin_la_LIBADD = $(LIBDL) libvlc_vdpau.la $(X_LIBS) $(X_PRE_LIBS) -lX11
+-
+-if HAVE_GL
+-vout_LTLIBRARIES += libgl_plugin.la
+-if HAVE_EGL
+-if HAVE_VAAPI
+-if HAVE_WAYLAND_EGL
+-if HAVE_VAAPI_WL
+-vout_LTLIBRARIES += libglconv_vaapi_wl_plugin.la
+-endif
+-endif
+-if HAVE_XCB
+-if HAVE_VAAPI_X11
+-vout_LTLIBRARIES += libglconv_vaapi_x11_plugin.la
+-endif
+-endif
+-if HAVE_VAAPI_DRM
+-vout_LTLIBRARIES += libglconv_vaapi_drm_plugin.la
+-endif
+-endif
+-endif # HAVE_EGL
+-
+-if HAVE_VDPAU
+-vout_LTLIBRARIES += libglconv_vdpau_plugin.la
+-endif
+-endif # HAVE_GL
+-
+ ### XCB ###
+ libvlc_xcb_events_la_SOURCES = \
+ video_output/xcb/events.c video_output/xcb/events.h
+--
+2.38.1
+
diff --git a/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/3009-vo-converter_vaapi-Fix-EGL-macro-undeclared.patch b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/3009-vo-converter_vaapi-Fix-EGL-macro-undeclared.patch
new file mode 100644
index 0000000000..0f28199511
--- /dev/null
+++ b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/files/3009-vo-converter_vaapi-Fix-EGL-macro-undeclared.patch
@@ -0,0 +1,59 @@
+From 35276c4b02b9114436108e74727d192f1e21f239 Mon Sep 17 00:00:00 2001
+From: Vincent Davis Jr <vince@underview.tech>
+Date: Fri, 9 Dec 2022 23:31:33 -0600
+Subject: [PATCH] vo: converter_vaapi Fix EGL macro undeclared
+
+Upstream-Status: Inappropriate
+
+RPI-Distro repo forks original vlc and applies patches to enable
+raspiberry pi support.
+
+Fixes compiler issues related to EGL macro constant/enum value type
+not being defined
+
+Signed-off-by: Vincent Davis Jr <vince@underview.tech>
+---
+ modules/video_output/opengl/converter_vaapi.c | 27 +++++++++++++++++++
+ 1 file changed, 27 insertions(+)
+
+diff --git a/modules/video_output/opengl/converter_vaapi.c b/modules/video_output/opengl/converter_vaapi.c
+index cd842f711..59245fe4c 100644
+--- a/modules/video_output/opengl/converter_vaapi.c
++++ b/modules/video_output/opengl/converter_vaapi.c
+@@ -55,6 +55,33 @@
+
+ #define DRM_FORMAT_MOD_INVALID fourcc_mod_code(NONE, DRM_FORMAT_RESERVED)
+
++#define EGL_LINUX_DMA_BUF_EXT 0x3270
++#define EGL_LINUX_DRM_FOURCC_EXT 0x3271
++#define EGL_DMA_BUF_PLANE0_FD_EXT 0x3272
++#define EGL_DMA_BUF_PLANE0_OFFSET_EXT 0x3273
++#define EGL_DMA_BUF_PLANE0_PITCH_EXT 0x3274
++#define EGL_DMA_BUF_PLANE1_FD_EXT 0x3275
++#define EGL_DMA_BUF_PLANE1_OFFSET_EXT 0x3276
++#define EGL_DMA_BUF_PLANE1_PITCH_EXT 0x3277
++#define EGL_DMA_BUF_PLANE2_FD_EXT 0x3278
++#define EGL_DMA_BUF_PLANE2_OFFSET_EXT 0x3279
++#define EGL_DMA_BUF_PLANE2_PITCH_EXT 0x327A
++#define EGL_YUV_COLOR_SPACE_HINT_EXT 0x327B
++#define EGL_SAMPLE_RANGE_HINT_EXT 0x327C
++#define EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT 0x327D
++#define EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT 0x327E
++#define EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT 0x3443
++#define EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT 0x3444
++#define EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT 0x3445
++#define EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT 0x3446
++#define EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT 0x3447
++#define EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT 0x3448
++#define EGL_DMA_BUF_PLANE3_FD_EXT 0x3440
++#define EGL_DMA_BUF_PLANE3_OFFSET_EXT 0x3441
++#define EGL_DMA_BUF_PLANE3_PITCH_EXT 0x3442
++#define EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT 0x3449
++#define EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT 0x344A
++
+ struct priv
+ {
+ struct vlc_vaapi_instance *vainst;
+--
+2.38.1
+
diff --git a/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/rpidistro-vlc_3.0.12.bb b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/rpidistro-vlc_3.0.17.bb
index b244dde88e..2653b28f90 100644
--- a/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/rpidistro-vlc_3.0.12.bb
+++ b/meta-raspberrypi/dynamic-layers/multimedia-layer/recipes-multimedia/rpidistro-vlc/rpidistro-vlc_3.0.17.bb
@@ -9,17 +9,25 @@ SRC_URI = "\
git://git@github.com/RPi-Distro/vlc;protocol=https;branch=buster-rpt \
file://0001-configure-fix-linking-on-RISC-V-ISA.patch \
file://0002-Revert-configure-Require-libmodplug-0.8.9.patch \
- file://0003-mmal_20.patch \
- file://0004-mmal_exit_fix.patch \
- file://0005-mmal_chain.patch \
- file://0006-Use-packageconfig-to-detect-mmal-support.patch \
- file://0007-use-vorbisidec.patch \
- file://0008-fix-luaL-checkint.patch \
- file://0009-fix-EGL-macro-undeclared-and-EGLImageKHR.patch \
- file://0010-fix-numeric_limits-is-not-a-member-of-std.patch \
-"
-
-SRCREV = "f7fd69f12a3b89d03768fa3bd468e8f33cd1dc7c"
+ file://0003-CVE-2022-41325.patch \
+ file://0004-mmal_20.patch \
+ file://0005-mmal_exit_fix.patch \
+ file://0006-mmal_chain.patch \
+ file://0007-armv6.patch \
+ file://2001-fix-luaL-checkint.patch \
+ file://2002-use-vorbisidec.patch \
+ file://3001-configure.ac-setup-for-OE-usage.patch \
+ file://3002-fix-EGL-macro-undeclared-and-EGLImageKHR.patch \
+ file://3003-codec-omxil_core-replace-opt-vc-path-with-usr-lib.patch \
+ file://3004-use-GLESv2-headers-over-GL-headers.patch \
+ file://3005-modules-remove-glspectrum-usage.patch \
+ file://3006-codec-omxil_core.h-fix-multiple-definition-of.patch \
+ ${@bb.utils.contains('DISTRO_FEATURES', 'x11', '', 'file://3007-remove-xorg-related-link-libs.patch', d)} \
+ ${@bb.utils.contains('DISTRO_FEATURES', 'opengl', '', 'file://3008-vo-Makefile.am-exclude-libgl_plugin.patch', d)} \
+ file://3009-vo-converter_vaapi-Fix-EGL-macro-undeclared.patch \
+ "
+
+SRCREV = "b276eb0d7bc3213363e97dbb681ef7c927be6c73"
S = "${WORKDIR}/git"
@@ -37,24 +45,29 @@ EXTRA_OECONF = "\
--enable-run-as-root \
--enable-xvideo \
--disable-lua \
- --disable-screen --disable-caca \
+ --disable-screen \
+ --disable-caca \
--enable-vlm \
--enable-tremor \
- --disable-aa --disable-faad \
+ --disable-aa \
+ --disable-faad \
--enable-dbus \
--without-contrib \
--without-kde-solid \
--enable-realrtsp \
--disable-libtar \
--enable-avcodec \
-"
+ --disable-css \
+ "
PACKAGECONFIG ?= "\
${@bb.utils.contains('DISTRO_FEATURES', 'x11', 'x11', '', d)} \
${@bb.utils.contains('MACHINE_FEATURES', 'vc4graphics', '', 'mmal', d)} \
- live555 dv1394 notify fontconfig fluidsynth freetype dvdread png udev \
- x264 alsa harfbuzz jack neon fribidi dvbpsi a52 v4l2 gles2 \
-"
+ ${@bb.utils.contains('DISTRO_FEATURES', 'opengl', 'gles2', '', d)} \
+ ${@bb.utils.contains_any('DISTRO_FEATURES', 'x11', 'notify', '', d)} \
+ live555 dv1394 fontconfig fluidsynth freetype png udev \
+ x264 alsa harfbuzz jack neon fribidi dvbpsi a52 v4l2 \
+ "
PACKAGECONFIG[mmal] = "--enable-omxil --enable-omxil-vout --enable-rpi-omxil --enable-mmal --enable-mmal-avcodec,,userland"
PACKAGECONFIG[x264] = "--enable-x264,--disable-x264,x264"
@@ -65,13 +78,13 @@ PACKAGECONFIG[live555] = "--enable-live555 LIVE555_PREFIX=${STAGING_DIR_HOST}${p
PACKAGECONFIG[libass] = "--enable-libass,--disable-libass,libass"
PACKAGECONFIG[postproc] = "--enable-postproc,--disable-postproc,libpostproc"
PACKAGECONFIG[libva] = "--enable-libva,--disable-libva,libva"
-PACKAGECONFIG[opencv] = "--enable-opencv,--disable-opencv,opencv"
+#PACKAGECONFIG[opencv] = "--enable-opencv,--disable-opencv,opencv"
PACKAGECONFIG[speex] = "--enable-speex,--disable-speex,speex"
PACKAGECONFIG[gstreamer] = "--enable-gst-decode,--disable-gst-decode,gstreamer1.0 gstreamer1.0-plugins-base gstreamer1.0-plugins-bad"
PACKAGECONFIG[vpx] = "--enable-vpx,--disable-vpx, libvpx"
-PACKAGECONFIG[freerdp] = "--enable-freerdp,--disable-freerdp, freerdp"
+#PACKAGECONFIG[freerdp] = "--enable-freerdp,--disable-freerdp, freerdp"
PACKAGECONFIG[dvbpsi] = "--enable-dvbpsi,--disable-dvbpsi, libdvbpsi"
-PACKAGECONFIG[samba] = "--enable-smbclient,--disable-smbclient, samba"
+#PACKAGECONFIG[samba] = "--enable-smbclient,--disable-smbclient, samba"
PACKAGECONFIG[upnp] = "--enable-upnp,--disable-upnp,libupnp"
PACKAGECONFIG[dvdnav] = "--enable-dvdnav,--disable-dvdnav,libdvdnav libdvdcss"
PACKAGECONFIG[sftp] = "--enable-sftp,--disable-sftp,libssh2"
@@ -84,14 +97,14 @@ PACKAGECONFIG[svgdec] = "--enable-svgdec,--disable-svgdec,librsvg cairo"
PACKAGECONFIG[notify] = "--enable-notify,--disable-notify, libnotify gtk+3"
PACKAGECONFIG[fontconfig] = "--enable-fontconfig,--disable-fontconfig, fontconfig"
PACKAGECONFIG[freetype] = "--enable-freetype,--disable-freetype, freetype"
-PACKAGECONFIG[dvdread] = "--enable-dvdread,--disable-dvdread, libdvdread libdvdcss"
+#PACKAGECONFIG[dvdread] = "--enable-dvdread,--disable-dvdread, libdvdread libdvdcss"
PACKAGECONFIG[vnc] = "--enable-vnc,--disable-vnc, libvncserver"
-PACKAGECONFIG[x11] = "--with-x --enable-xcb,--without-x --disable-xcb, xcb-util-keysyms libxpm libxinerama"
+PACKAGECONFIG[x11] = "--with-x --enable-xcb,--without-x --disable-xcb, xcb-util-keysyms libxpm libxinerama"
PACKAGECONFIG[png] = "--enable-png,--disable-png,libpng"
-PACKAGECONFIG[vdpau] = "--enable-vdpau,--disable-vdpau,libvdpau"
-PACKAGECONFIG[wayland] = "--enable-wayland,--disable-wayland,wayland wayland-native"
+#PACKAGECONFIG[vdpau] = "--enable-vdpau,--disable-vdpau,libvdpau"
+#PACKAGECONFIG[wayland] = "--enable-wayland,--disable-wayland,wayland wayland-native"
PACKAGECONFIG[gles2] = "--enable-gles2,--disable-gles2,virtual/libgles2"
-PACKAGECONFIG[dca] = "--enable-dca,,"
+#PACKAGECONFIG[dca] = "--enable-dca,--disable-dca,libdca"
PACKAGECONFIG[fribidi] = "--enable-fribidi,,fribidi"
PACKAGECONFIG[gnutls] = "--enable-gnutls,,gnutls"
PACKAGECONFIG[fluidsynth] = "--enable-fluidsynth,,fluidsynth"
@@ -105,25 +118,15 @@ PACKAGECONFIG[pulseaudio] = "--enable-pulse,--disable-pulse,pulseaudio"
PACKAGECONFIG[sdl-image] = "--enable-sdl-image,,libsdl-image"
PACKAGECONFIG[v4l2] = "--enable-v4l2,,v4l-utils"
-# Workaround for modules/codec/omxil/omxil_core.h
-# multiple definition of `pf_enable_graphic_buffers'
-# multiple definition of `pf_get_graphic_buffer_usage'
-# multiple definition of `pf_get_hal_format'
-TARGET_CFLAGS:append = " -fcommon"
-TARGET_CXXFLAGS:append = " -fcommon"
+TARGET_CFLAGS:append = " -I${STAGING_INCDIR}/drm"
+TARGET_LDFLAGS:append = " ${@bb.utils.contains('DISTRO_FEATURES', 'opengl', '-lGLESv2', '', d)}"
# Ensures the --enable-mmal-avcodec flag is available for usage
do_configure:prepend() {
olddir=`pwd`
cd ${S}
./bootstrap
- cd $olddir
-}
-
-do_configure:append() {
- # https://forums.raspberrypi.com/viewtopic.php?p=1601535
- sed -i "/GLAPI void APIENTRY glShaderSource (/d" ${STAGING_INCDIR}/GL/glext.h
- #sed -i -e s:'${top_builddir_slash}libtool':'${top_builddir_slash}'${TARGET_SYS}-libtool:g ${B}/doltlibtool
+ cd $olddir
}
# This recipe packages vlc as a library as well, so qt4 dependencies
@@ -140,20 +143,20 @@ FILES:${PN} += "\
${datadir}/vlc \
${datadir}/icons \
${datadir}/metainfo/vlc.appdata.xml \
-"
+ "
FILES:${PN}-dbg += "\
${libdir}/vlc/*/.debug \
${libdir}/vlc/plugins/*/.debug \
-"
+ "
FILES:${PN}-staticdev += "\
${libdir}/vlc/plugins/*/*.a \
${libdir}/vlc/libcompat.a \
-"
+ "
# Only enable it for rpi class of machines
COMPATIBLE_HOST = "null"
-COMPATIBLE_HOST:rpi = "'(.*)'"
+COMPATIBLE_HOST:rpi = "(.*)"
INSANE_SKIP:${PN} = "dev-so"
diff --git a/meta-raspberrypi/recipes-connectivity/bluez5/bluez5/0001-bcm43xx-Add-bcm43xx-3wire-variant.patch b/meta-raspberrypi/recipes-connectivity/bluez5/bluez5/0001-bcm43xx-Add-bcm43xx-3wire-variant.patch
index 3bc02c49e2..1843b038e5 100644
--- a/meta-raspberrypi/recipes-connectivity/bluez5/bluez5/0001-bcm43xx-Add-bcm43xx-3wire-variant.patch
+++ b/meta-raspberrypi/recipes-connectivity/bluez5/bluez5/0001-bcm43xx-Add-bcm43xx-3wire-variant.patch
@@ -1,17 +1,17 @@
-From b4f2b77472aeb967d3a7595e8a965785c7a37c87 Mon Sep 17 00:00:00 2001
+From 8e8321cd597d3d9d342a8a3533ad10751dde5885 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Tue, 16 Feb 2016 16:40:46 +0000
-Subject: [PATCH 1/4] bcm43xx: Add bcm43xx-3wire variant
+Subject: [PATCH] bcm43xx: Add bcm43xx-3wire variant
---
tools/hciattach.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/tools/hciattach.c b/tools/hciattach.c
-index 59a76a7..5861d33 100644
+index 276a4e56e..7d01d8b74 100644
--- a/tools/hciattach.c
+++ b/tools/hciattach.c
-@@ -1144,6 +1144,9 @@ struct uart_t uart[] = {
+@@ -1078,6 +1078,9 @@ struct uart_t uart[] = {
{ "bcm43xx", 0x0000, 0x0000, HCI_UART_H4, 115200, 3000000,
FLOW_CTL, DISABLE_PM, NULL, bcm43xx, NULL },
@@ -21,6 +21,3 @@ index 59a76a7..5861d33 100644
{ "ath3k", 0x0000, 0x0000, HCI_UART_ATH3K, 115200, 115200,
FLOW_CTL, DISABLE_PM, NULL, ath3k_ps, ath3k_pm },
---
-1.9.1
-
diff --git a/meta-raspberrypi/recipes-connectivity/bluez5/bluez5/0002-bcm43xx-The-UART-speed-must-be-reset-after-the-firmw.patch b/meta-raspberrypi/recipes-connectivity/bluez5/bluez5/0002-bcm43xx-The-UART-speed-must-be-reset-after-the-firmw.patch
index 5a0a434a30..1dd89a1e23 100644
--- a/meta-raspberrypi/recipes-connectivity/bluez5/bluez5/0002-bcm43xx-The-UART-speed-must-be-reset-after-the-firmw.patch
+++ b/meta-raspberrypi/recipes-connectivity/bluez5/bluez5/0002-bcm43xx-The-UART-speed-must-be-reset-after-the-firmw.patch
@@ -1,17 +1,18 @@
-From e145c9621f976063e5c573db1f2053d906f63427 Mon Sep 17 00:00:00 2001
+From 96e5e5eef04c6c4ae83d4d822a536cfa87605ae2 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Tue, 16 Feb 2016 16:39:09 +0000
-Subject: [PATCH 2/4] bcm43xx: The UART speed must be reset after the firmware download
+Subject: [PATCH] bcm43xx: The UART speed must be reset after the firmware
+ download
---
tools/hciattach_bcm43xx.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/tools/hciattach_bcm43xx.c b/tools/hciattach_bcm43xx.c
-index 81f38cb..0b792e0 100644
+index b89fc1b50..de01a6aea 100644
--- a/tools/hciattach_bcm43xx.c
+++ b/tools/hciattach_bcm43xx.c
-@@ -366,11 +366,8 @@ int bcm43xx_init(int fd, int def_speed, int speed, struct termios *ti,
+@@ -350,11 +350,8 @@ int bcm43xx_init(int fd, int def_speed, int speed, struct termios *ti,
return -1;
if (bcm43xx_locate_patch(FIRMWARE_DIR, chip_name, fw_path)) {
@@ -24,7 +25,7 @@ index 81f38cb..0b792e0 100644
if (bcm43xx_load_firmware(fd, fw_path))
return -1;
-@@ -380,6 +377,7 @@ int bcm43xx_init(int fd, int def_speed, int speed, struct termios *ti,
+@@ -364,6 +361,7 @@ int bcm43xx_init(int fd, int def_speed, int speed, struct termios *ti,
return -1;
}
@@ -32,6 +33,3 @@ index 81f38cb..0b792e0 100644
if (bcm43xx_reset(fd))
return -1;
}
---
-1.9.1
-
diff --git a/meta-raspberrypi/recipes-connectivity/bluez5/bluez5/0003-Increase-firmware-load-timeout-to-30s.patch b/meta-raspberrypi/recipes-connectivity/bluez5/bluez5/0003-Increase-firmware-load-timeout-to-30s.patch
index f9f09ebb09..d1c586c7a7 100644
--- a/meta-raspberrypi/recipes-connectivity/bluez5/bluez5/0003-Increase-firmware-load-timeout-to-30s.patch
+++ b/meta-raspberrypi/recipes-connectivity/bluez5/bluez5/0003-Increase-firmware-load-timeout-to-30s.patch
@@ -1,17 +1,17 @@
-From d41dc2046dd08d8c95197f677e224506f5b39bdd Mon Sep 17 00:00:00 2001
+From 05c3e145b5aa62e7e759932ea99f94d495b651c3 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Wed, 20 Jan 2016 16:00:37 +0000
-Subject: [PATCH 3/4] Increase firmware load timeout to 30s
+Subject: [PATCH] Increase firmware load timeout to 30s
---
tools/hciattach.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/hciattach.c b/tools/hciattach.c
-index 5861d33..4141796 100644
+index 7d01d8b74..465bb17dd 100644
--- a/tools/hciattach.c
+++ b/tools/hciattach.c
-@@ -1293,7 +1293,7 @@ int main(int argc, char *argv[])
+@@ -1227,7 +1227,7 @@ int main(int argc, char *argv[])
{
struct uart_t *u = NULL;
int detach, printpid, raw, opt, i, n, ld, err;
@@ -20,6 +20,3 @@ index 5861d33..4141796 100644
int init_speed = 0;
int send_break = 0;
pid_t pid;
---
-1.9.1
-
diff --git a/meta-raspberrypi/recipes-connectivity/bluez5/bluez5/0004-Move-the-43xx-firmware-into-lib-firmware.patch b/meta-raspberrypi/recipes-connectivity/bluez5/bluez5/0004-Move-the-43xx-firmware-into-lib-firmware.patch
deleted file mode 100644
index dadce354e9..0000000000
--- a/meta-raspberrypi/recipes-connectivity/bluez5/bluez5/0004-Move-the-43xx-firmware-into-lib-firmware.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 76681284b0ea49852041fdb97a35175089a08781 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 23 Feb 2016 17:52:29 +0000
-Subject: [PATCH 4/4] Move the 43xx firmware into /lib/firmware
-
----
- tools/hciattach_bcm43xx.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/tools/hciattach_bcm43xx.c b/tools/hciattach_bcm43xx.c
-index 0b792e0..207f668 100644
---- a/tools/hciattach_bcm43xx.c
-+++ b/tools/hciattach_bcm43xx.c
-@@ -43,7 +43,7 @@
- #include "hciattach.h"
-
- #ifndef FIRMWARE_DIR
--#define FIRMWARE_DIR "/etc/firmware"
-+#define FIRMWARE_DIR "/lib/firmware"
- #endif
-
- #define FW_EXT ".hcd"
---
-1.9.1
-
diff --git a/meta-raspberrypi/recipes-connectivity/bluez5/bluez5/0004-Move-the-hciattach-firmware-into-lib-firmware.patch b/meta-raspberrypi/recipes-connectivity/bluez5/bluez5/0004-Move-the-hciattach-firmware-into-lib-firmware.patch
new file mode 100644
index 0000000000..dde7b38499
--- /dev/null
+++ b/meta-raspberrypi/recipes-connectivity/bluez5/bluez5/0004-Move-the-hciattach-firmware-into-lib-firmware.patch
@@ -0,0 +1,29 @@
+From 744f894e42d05b1dee917cc221ed3c1815990459 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 23 Feb 2016 17:52:29 +0000
+Subject: [PATCH] Move the hciattach firmware into /lib/firmware
+
+* FIRMWARE_DIR is now used by all hciattach firmware (not just bcm43xx) since 5.66 with:
+ commit d9253248363b995e44c1f5e393ed1c7aa4ec81ce
+ Author: Marek Vasut <marex@denx.de>
+ Date: Tue Nov 1 12:53:33 2022 +0100
+ Subject: tools: Make hciattach_* firmware path build-time configurable
+
+Signed-off-by: Martin Jansa <Martin.Jansa@gmail.com>
+---
+ tools/hciattach.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/hciattach.h b/tools/hciattach.h
+index dfa4c1e7a..e88484766 100644
+--- a/tools/hciattach.h
++++ b/tools/hciattach.h
+@@ -41,7 +41,7 @@
+ #define HCI_UART_VND_DETECT 5
+
+ #ifndef FIRMWARE_DIR
+-#define FIRMWARE_DIR "/etc/firmware"
++#define FIRMWARE_DIR "/lib/firmware"
+ #endif
+
+ int read_hci_event(int fd, unsigned char *buf, int size);
diff --git a/meta-raspberrypi/recipes-connectivity/bluez5/bluez5_%.bbappend b/meta-raspberrypi/recipes-connectivity/bluez5/bluez5_%.bbappend
index 09d410350b..c5d905b295 100644
--- a/meta-raspberrypi/recipes-connectivity/bluez5/bluez5_%.bbappend
+++ b/meta-raspberrypi/recipes-connectivity/bluez5/bluez5_%.bbappend
@@ -4,7 +4,7 @@ SRC_URI:append:rpi = "\
file://0001-bcm43xx-Add-bcm43xx-3wire-variant.patch \
file://0002-bcm43xx-The-UART-speed-must-be-reset-after-the-firmw.patch \
file://0003-Increase-firmware-load-timeout-to-30s.patch \
- file://0004-Move-the-43xx-firmware-into-lib-firmware.patch \
+ file://0004-Move-the-hciattach-firmware-into-lib-firmware.patch \
"
RDEPENDS:${PN}:append:rpi = " pi-bluetooth"
diff --git a/meta-raspberrypi/recipes-graphics/wayland/weston_%.bbappend b/meta-raspberrypi/recipes-graphics/wayland/weston_%.bbappend
index 89917f0498..f9ed06a8f2 100644
--- a/meta-raspberrypi/recipes-graphics/wayland/weston_%.bbappend
+++ b/meta-raspberrypi/recipes-graphics/wayland/weston_%.bbappend
@@ -1,4 +1,4 @@
-PACKAGECONFIG:remove:rpi = "${@bb.utils.contains('MACHINE_FEATURES', 'vc4graphics', 'fbdev', '', d)}"
+PACKAGECONFIG:remove:rpi = "${@bb.utils.contains('MACHINE_FEATURES', 'vc4graphics', 'fbdev', 'egl clients', d)}"
EXTRA_OECONF:append:rpi = " \
--disable-xwayland-test \
diff --git a/meta-raspberrypi/recipes-kernel/linux/linux-raspberrypi.inc b/meta-raspberrypi/recipes-kernel/linux/linux-raspberrypi.inc
index be1883c2bb..4f67d298fd 100644
--- a/meta-raspberrypi/recipes-kernel/linux/linux-raspberrypi.inc
+++ b/meta-raspberrypi/recipes-kernel/linux/linux-raspberrypi.inc
@@ -3,7 +3,7 @@ SECTION = "kernel"
LICENSE = "GPL-2.0-only"
LIC_FILES_CHKSUM = "file://COPYING;md5=6bc538ed5bd9a7fc9398086aedcd7e46"
-COMPATIBLE_MACHINE = "^rpi$"
+COMPATIBLE_MACHINE ?= "^rpi$"
PE = "1"
PV = "${LINUX_VERSION}+git${SRCPV}"
diff --git a/meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/0001-avcodec-arm-sbcenc-avoid-callee-preserved-vfp-regist.patch b/meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/0001-avcodec-arm-sbcenc-avoid-callee-preserved-vfp-regist.patch
index e9c9eb7de7..d9c07dd77e 100644
--- a/meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/0001-avcodec-arm-sbcenc-avoid-callee-preserved-vfp-regist.patch
+++ b/meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/0001-avcodec-arm-sbcenc-avoid-callee-preserved-vfp-regist.patch
@@ -2,6 +2,11 @@ From: James Cowgill <jcowgill@debian.org>
Date: Sun, 11 Aug 2019 16:50:56 +0100
Subject: avcodec/arm/sbcenc: avoid callee preserved vfp registers
+Upstream-Status: Inappropriate
+
+RPI-Distro repo clones original ffmpeg and applies patches to enable
+raspiberry pi support.
+
When compiling FFmpeg with GCC-9, some very random segfaults were
observed in code which had previously called down into the SBC encoder
NEON assembly routines. This was caused by these functions clobbering
@@ -19,8 +24,6 @@ sets of registers consecutively numbered which hopefully makes the
code more easy to follow. Since this commit only reallocates
registers, it should have no performance impact.
-Upstream-status: Pending
-
Signed-off-by: James Cowgill <jcowgill@debian.org>
---
libavcodec/arm/sbcdsp_neon.S | 220 +++++++++++++++++++++----------------------
@@ -38,7 +41,7 @@ index d83d21d..914abfb 100644
- vld1.16 {d8, d9}, [r2, :128]!
+ vld1.16 {d16, d17}, [r0, :64]!
+ vld1.16 {d20, d21}, [r2, :128]!
-
+
- vmull.s16 q0, d4, d8
- vld1.16 {d6, d7}, [r0, :64]!
- vmull.s16 q1, d5, d9
@@ -47,7 +50,7 @@ index d83d21d..914abfb 100644
+ vld1.16 {d18, d19}, [r0, :64]!
+ vmull.s16 q1, d17, d21
+ vld1.16 {d22, d23}, [r2, :128]!
-
+
- vmlal.s16 q0, d6, d10
- vld1.16 {d4, d5}, [r0, :64]!
- vmlal.s16 q1, d7, d11
@@ -56,7 +59,7 @@ index d83d21d..914abfb 100644
+ vld1.16 {d16, d17}, [r0, :64]!
+ vmlal.s16 q1, d19, d23
+ vld1.16 {d20, d21}, [r2, :128]!
-
+
- vmlal.s16 q0, d4, d8
- vld1.16 {d6, d7}, [r0, :64]!
- vmlal.s16 q1, d5, d9
@@ -65,7 +68,7 @@ index d83d21d..914abfb 100644
+ vld1.16 {d18, d19}, [r0, :64]!
+ vmlal.s16 q1, d17, d21
+ vld1.16 {d22, d23}, [r2, :128]!
-
+
- vmlal.s16 q0, d6, d10
- vld1.16 {d4, d5}, [r0, :64]!
- vmlal.s16 q1, d7, d11
@@ -74,23 +77,23 @@ index d83d21d..914abfb 100644
+ vld1.16 {d16, d17}, [r0, :64]!
+ vmlal.s16 q1, d19, d23
+ vld1.16 {d20, d21}, [r2, :128]!
-
+
- vmlal.s16 q0, d4, d8
- vmlal.s16 q1, d5, d9
+ vmlal.s16 q0, d16, d20
+ vmlal.s16 q1, d17, d21
-
+
vpadd.s32 d0, d0, d1
vpadd.s32 d1, d2, d3
-
+
vrshrn.s32 d0, q0, SBC_PROTO_FIXED_SCALE
-
+
- vld1.16 {d2, d3, d4, d5}, [r2, :128]!
+ vld1.16 {d16, d17, d18, d19}, [r2, :128]!
-
+
vdup.i32 d1, d0[1] /* TODO: can be eliminated */
vdup.i32 d0, d0[0] /* TODO: can be eliminated */
-
+
- vmull.s16 q3, d2, d0
- vmull.s16 q4, d3, d0
- vmlal.s16 q3, d4, d1
@@ -99,14 +102,14 @@ index d83d21d..914abfb 100644
+ vmull.s16 q11, d17, d0
+ vmlal.s16 q10, d18, d1
+ vmlal.s16 q11, d19, d1
-
+
- vpadd.s32 d0, d6, d7 /* TODO: can be eliminated */
- vpadd.s32 d1, d8, d9 /* TODO: can be eliminated */
+ vpadd.s32 d0, d20, d21 /* TODO: can be eliminated */
+ vpadd.s32 d1, d22, d23 /* TODO: can be eliminated */
-
+
vst1.32 {d0, d1}, [r1, :128]
-
+
@@ -91,57 +91,57 @@ function ff_sbc_analyze_8_neon, export=1
/* TODO: merge even and odd cases (or even merge all four calls to this
* function) in order to have only aligned reads from 'in' array
@@ -213,13 +216,13 @@ index d83d21d..914abfb 100644
+ vpadd.s32 d1, d26, d27
+ vpadd.s32 d2, d28, d29
+ vpadd.s32 d3, d30, d31
-
+
vrshr.s32 q0, q0, SBC_PROTO_FIXED_SCALE
vrshr.s32 q1, q1, SBC_PROTO_FIXED_SCALE
@@ -153,38 +153,38 @@ function ff_sbc_analyze_8_neon, export=1
vdup.i32 d1, d0[1] /* TODO: can be eliminated */
vdup.i32 d0, d0[0] /* TODO: can be eliminated */
-
+
- vld1.16 {d4, d5}, [r2, :128]!
- vmull.s16 q6, d4, d0
- vld1.16 {d6, d7}, [r2, :128]!
@@ -284,5 +287,6 @@ index d83d21d..914abfb 100644
+ vpadd.s32 d1, d26, d27 /* TODO: can be eliminated */
+ vpadd.s32 d2, d28, d29 /* TODO: can be eliminated */
+ vpadd.s32 d3, d30, d31 /* TODO: can be eliminated */
-
+
vst1.32 {d0, d1, d2, d3}, [r1, :128]
+
diff --git a/meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/0002-Fix-build-on-powerpc-and-ppc64.patch b/meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/0002-Fix-build-on-powerpc-and-ppc64.patch
index 4d9c1b9f58..f398791679 100644
--- a/meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/0002-Fix-build-on-powerpc-and-ppc64.patch
+++ b/meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/0002-Fix-build-on-powerpc-and-ppc64.patch
@@ -2,7 +2,10 @@ From: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
Date: Tue, 19 Jan 2021 20:35:29 +0100
Subject: Fix build on powerpc and ppc64
-Upstream-status: Pending
+Upstream-Status: Inappropriate
+
+RPI-Distro repo clones original ffmpeg and applies patches to enable
+raspiberry pi support.
---
libswscale/ppc/yuv2rgb_altivec.c | 10 ++++++++++
@@ -15,7 +18,7 @@ index 5365452..930ef6b 100644
@@ -283,6 +283,16 @@ static inline void cvtyuvtoRGB(SwsContext *c, vector signed short Y,
* ------------------------------------------------------------------------------
*/
-
+
+#if !HAVE_VSX
+static inline vector unsigned char vec_xl(signed long long offset, const ubyte *addr)
+{
diff --git a/meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/0003-avcodec-pngenc-remove-monowhite-from-apng-formats.patch b/meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/0003-avcodec-pngenc-remove-monowhite-from-apng-formats.patch
index 38f3fd4dab..11e3383aab 100644
--- a/meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/0003-avcodec-pngenc-remove-monowhite-from-apng-formats.patch
+++ b/meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/0003-avcodec-pngenc-remove-monowhite-from-apng-formats.patch
@@ -2,13 +2,15 @@ From: Paul B Mahol <onemda@gmail.com>
Date: Sun, 14 Feb 2021 17:20:03 +0100
Subject: avcodec/pngenc: remove monowhite from apng formats
+Upstream-Status: Inappropriate
+
+RPI-Distro repo clones original ffmpeg and applies patches to enable
+raspiberry pi support.
+
Monowhite pixel format is not supported, and it does not make sense
to add support for it.
Fixes #7989
-
-Upstream-status: Pending
-
---
libavcodec/pngenc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/0004-ffmpeg-4.3.2-rpi_10.patch b/meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/0004-ffmpeg-4.3.4-rpi_14.patch
index 6bab0d05b5..740ac0eab9 100644
--- a/meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/0004-ffmpeg-4.3.2-rpi_10.patch
+++ b/meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/0004-ffmpeg-4.3.4-rpi_14.patch
@@ -1,16 +1,27 @@
-Upstream-status: Pending
+Upstream-Status: Inappropriate
+
+RPI-Distro repo clones original ffmpeg and applies patches to enable
+raspiberry pi support.
--- a/configure
+++ b/configure
-@@ -274,6 +274,7 @@ External library support:
+@@ -207,6 +207,7 @@ External library support:
+ --disable-bzlib disable bzlib [autodetect]
+ --disable-coreimage disable Apple CoreImage framework [autodetect]
+ --enable-chromaprint enable audio fingerprinting with chromaprint [no]
++ --disable-epoxy disable epoxy [autodetect]
+ --enable-frei0r enable frei0r video filtering [no]
+ --enable-gcrypt enable gcrypt, needed for rtmp(t)e support
+ if openssl, librtmp or gmp is not used [no]
+@@ -274,6 +275,7 @@ External library support:
--enable-libtls enable LibreSSL (via libtls), needed for https support
if openssl, gnutls or mbedtls is not used [no]
--enable-libtwolame enable MP2 encoding via libtwolame [no]
-+ --enable-libudev enable libudev [no]
++ --disable-libudev disable libudev [autodetect]
--enable-libv4l2 enable libv4l2/v4l-utils [no]
--enable-libvidstab enable video stabilization using vid.stab [no]
--enable-libvmaf enable vmaf filter via libvmaf [no]
-@@ -336,12 +337,17 @@ External library support:
+@@ -336,12 +338,17 @@ External library support:
--enable-libmfx enable Intel MediaSDK (AKA Quick Sync Video) code via libmfx [no]
--enable-libnpp enable Nvidia Performance Primitives-based code [no]
--enable-mmal enable Broadcom Multi-Media Abstraction Layer (Raspberry Pi) via MMAL [no]
@@ -28,23 +39,17 @@ Upstream-status: Pending
--disable-vaapi disable Video Acceleration API (mainly Unix/Intel) code [autodetect]
--disable-vdpau disable Nvidia Video Decode and Presentation API for Unix code [autodetect]
--disable-videotoolbox disable VideoToolbox code [autodetect]
-@@ -1771,6 +1777,7 @@ EXTERNAL_LIBRARY_LIST="
- libdav1d
- libdc1394
- libdrm
+@@ -1699,7 +1706,9 @@ EXTERNAL_AUTODETECT_LIBRARY_LIST="
+ avfoundation
+ bzlib
+ coreimage
+ epoxy
- libflite
- libfontconfig
- libfreetype
-@@ -1807,6 +1814,7 @@ EXTERNAL_LIBRARY_LIST="
- libtesseract
- libtheora
- libtwolame
+ iconv
+ libudev
- libv4l2
- libvorbis
- libvpx
-@@ -1861,7 +1869,10 @@ HWACCEL_LIBRARY_LIST="
+ libxcb
+ libxcb_shm
+ libxcb_shape
+@@ -1861,7 +1870,10 @@ HWACCEL_LIBRARY_LIST="
mmal
omx
opencl
@@ -53,9 +58,9 @@ Upstream-status: Pending
+ rpi4_8
+ rpi4_10
"
-
+
DOCUMENT_LIST="
-@@ -1877,12 +1888,16 @@ FEATURE_LIST="
+@@ -1877,12 +1889,16 @@ FEATURE_LIST="
gray
hardcoded_tables
omx_rpi
@@ -70,17 +75,17 @@ Upstream-status: Pending
+ vout_drm
+ vout_egl
"
-
+
# this list should be kept in linking order
-@@ -1923,6 +1938,7 @@ SUBSYSTEM_LIST="
+@@ -1923,6 +1939,7 @@ SUBSYSTEM_LIST="
pixelutils
network
rdft
+ rpi
"
-
+
# COMPONENT_LIST needs to come last to ensure correct dependency checking
-@@ -2405,9 +2421,11 @@ CONFIG_EXTRA="
+@@ -2405,9 +2422,11 @@ CONFIG_EXTRA="
rangecoder
riffdec
riffenc
@@ -92,7 +97,7 @@ Upstream-status: Pending
scene_sad
sinewin
snappy
-@@ -2737,6 +2755,8 @@ hap_decoder_select="snappy texturedsp"
+@@ -2737,6 +2756,8 @@ hap_decoder_select="snappy texturedsp"
hap_encoder_deps="libsnappy"
hap_encoder_select="texturedspenc"
hevc_decoder_select="bswapdsp cabac golomb hevcparse videodsp"
@@ -101,7 +106,7 @@ Upstream-status: Pending
huffyuv_decoder_select="bswapdsp huffyuvdsp llviddsp"
huffyuv_encoder_select="bswapdsp huffman huffyuvencdsp llvidencdsp"
hymt_decoder_select="huffyuv_decoder"
-@@ -2903,6 +2923,7 @@ d3d11va_deps="dxva_h ID3D11VideoDecoder
+@@ -2903,6 +2924,7 @@ d3d11va_deps="dxva_h ID3D11VideoDecoder
dxva2_deps="dxva2api_h DXVA2_ConfigPictureDecode ole32 user32"
ffnvcodec_deps_any="libdl LoadLibrary"
nvdec_deps="ffnvcodec"
@@ -109,7 +114,7 @@ Upstream-status: Pending
vaapi_x11_deps="xlib"
videotoolbox_hwaccel_deps="videotoolbox pthreads"
videotoolbox_hwaccel_extralibs="-framework QuartzCore"
-@@ -2934,6 +2955,12 @@ hevc_dxva2_hwaccel_deps="dxva2 DXVA_PicP
+@@ -2934,6 +2956,12 @@ hevc_dxva2_hwaccel_deps="dxva2 DXVA_PicP
hevc_dxva2_hwaccel_select="hevc_decoder"
hevc_nvdec_hwaccel_deps="nvdec"
hevc_nvdec_hwaccel_select="hevc_decoder"
@@ -122,16 +127,15 @@ Upstream-status: Pending
hevc_vaapi_hwaccel_deps="vaapi VAPictureParameterBufferHEVC"
hevc_vaapi_hwaccel_select="hevc_decoder"
hevc_vdpau_hwaccel_deps="vdpau VdpPictureInfoHEVC"
-@@ -3401,8 +3428,14 @@ sndio_indev_deps="sndio"
+@@ -3401,8 +3429,13 @@ sndio_indev_deps="sndio"
sndio_outdev_deps="sndio"
v4l2_indev_deps_any="linux_videodev2_h sys_videoio_h"
v4l2_indev_suggest="libv4l2"
+v4l2_outdev_deps="libdrm"
v4l2_outdev_deps_any="linux_videodev2_h sys_videoio_h"
v4l2_outdev_suggest="libv4l2"
-+vout_drm_outdev_deps="libdrm vout_drm"
-+vout_egl_outdev_deps="xlib"
-+vout_egl_outdev_select="epoxy"
++vout_drm_outdev_deps="libdrm"
++vout_egl_outdev_deps="xlib epoxy"
+vout_rpi_outdev_deps="rpi"
+vout_rpi_outdev_select="sand"
vfwcap_indev_deps="vfw32 vfwcap_defines"
@@ -145,23 +149,20 @@ Upstream-status: Pending
unsharp_opencl_filter_deps="opencl"
uspp_filter_deps="gpl avcodec"
vaguedenoiser_filter_deps="gpl"
-@@ -6299,6 +6333,7 @@ enabled libdav1d && require_pkg
- enabled libdavs2 && require_pkg_config libdavs2 "davs2 >= 1.6.0" davs2.h davs2_decoder_open
- enabled libdc1394 && require_pkg_config libdc1394 libdc1394-2 dc1394/dc1394.h dc1394_new
- enabled libdrm && require_pkg_config libdrm libdrm xf86drm.h drmGetVersion
-+enabled epoxy && require_pkg_config epoxy epoxy epoxy/egl.h epoxy_egl_version
- enabled libfdk_aac && { check_pkg_config libfdk_aac fdk-aac "fdk-aac/aacenc_lib.h" aacEncOpen ||
- { require libfdk_aac fdk-aac/aacenc_lib.h aacEncOpen -lfdk-aac &&
- warn "using libfdk without pkg-config"; } }
-@@ -6376,6 +6411,7 @@ enabled libtls && require_pkg
- enabled libtwolame && require libtwolame twolame.h twolame_init -ltwolame &&
- { check_lib libtwolame twolame.h twolame_encode_buffer_float32_interleaved -ltwolame ||
- die "ERROR: libtwolame must be installed and version must be >= 0.3.10"; }
-+enabled libudev && require_pkg_config libudev libudev libudev.h udev_new
- enabled libv4l2 && require_pkg_config libv4l2 libv4l2 libv4l2.h v4l2_ioctl
- enabled libvidstab && require_pkg_config libvidstab "vidstab >= 0.98" vid.stab/libvidstab.h vsMotionDetectInit
- enabled libvmaf && require_pkg_config libvmaf "libvmaf >= 1.3.9" libvmaf.h compute_vmaf
-@@ -6430,11 +6466,12 @@ enabled mbedtls && { check_pkg
+@@ -6102,6 +6136,12 @@ check_func_headers glob.h glob
+ enabled xlib &&
+ check_lib xlib "X11/Xlib.h X11/extensions/Xvlib.h" XvGetPortAttribute -lXv -lX11 -lXext
+
++enabled libudev &&
++ check_pkg_config libudev libudev libudev.h udev_new
++
++enabled epoxy &&
++ check_pkg_config epoxy epoxy epoxy/egl.h epoxy_egl_version
++
+ check_headers direct.h
+ check_headers dirent.h
+ check_headers dxgidebug.h
+@@ -6430,11 +6470,12 @@ enabled mbedtls && { check_pkg
check_lib mbedtls mbedtls/ssl.h mbedtls_ssl_init -lmbedtls -lmbedx509 -lmbedcrypto ||
die "ERROR: mbedTLS not found"; }
enabled mediacodec && { enabled jni || die "ERROR: mediacodec requires --enable-jni"; }
@@ -176,26 +177,32 @@ Upstream-status: Pending
die "ERROR: mmal not found" &&
check_func_headers interface/mmal/mmal.h "MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS"; }
enabled openal && { { for al_extralibs in "${OPENAL_LIBS}" "-lopenal" "-lOpenAL32"; do
-@@ -6475,6 +6512,10 @@ enabled rkmpp && { require_p
+@@ -6475,8 +6516,16 @@ enabled rkmpp && { require_p
{ enabled libdrm ||
die "ERROR: rkmpp requires --enable-libdrm"; }
}
+enabled v4l2_request && { enabled libdrm ||
+ die "ERROR: v4l2-request requires --enable-libdrm"; } &&
+ { enabled libudev ||
-+ die "ERROR: v4l2-request requires --enable-libudev"; }
++ die "ERROR: v4l2-request requires libudev"; }
enabled vapoursynth && require_pkg_config vapoursynth "vapoursynth-script >= 42" VSScript.h vsscript_init
-
-
-@@ -6556,6 +6597,8 @@ if enabled v4l2_m2m; then
+
++enabled vout_drm && { enabled libdrm || die "ERROR: vout_drm requires --enable-libdrm"; }
++
++enabled vout_egl && { enabled epoxy || die "ERROR: vout_egl requires epoxy"; } &&
++ { enabled xlib || die "ERROR: vout_egl requires xlib"; }
+
+ if enabled gcrypt; then
+ GCRYPT_CONFIG="${cross_prefix}libgcrypt-config"
+@@ -6556,6 +6605,8 @@ if enabled v4l2_m2m; then
check_cc vp9_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_VP9;"
fi
-
+
+check_func_headers "linux/media.h linux/videodev2.h" v4l2_timeval_to_ns
+check_cc hevc_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_HEVC_SLICE;"
check_headers sys/videoio.h
test_code cc sys/videoio.h "struct v4l2_frmsizeenum vfse; vfse.discrete.width = 0;" && enable_sanitized struct_v4l2_frmivalenum_discrete
-
+
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -2119,8 +2119,8 @@ static int ifilter_send_frame(InputFilte
@@ -208,11 +215,11 @@ Upstream-status: Pending
+ ifilter->height != av_frame_cropped_height(frame);
break;
}
-
+
@@ -2131,6 +2131,9 @@ static int ifilter_send_frame(InputFilte
(ifilter->hw_frames_ctx && ifilter->hw_frames_ctx->data != frame->hw_frames_ctx->data))
need_reinit = 1;
-
+
+ if (no_cvt_hw && fg->graph)
+ need_reinit = 0;
+
@@ -221,7 +228,7 @@ Upstream-status: Pending
if (ret < 0)
@@ -2401,8 +2404,7 @@ static int decode_video(InputStream *ist
decoded_frame->top_field_first = ist->top_field_first;
-
+
ist->frames_decoded++;
-
- if (ist->hwaccel_retrieve_data && decoded_frame->format == ist->hwaccel_pix_fmt) {
@@ -229,7 +236,21 @@ Upstream-status: Pending
err = ist->hwaccel_retrieve_data(ist->dec_ctx, decoded_frame);
if (err < 0)
goto fail;
-@@ -2820,6 +2822,16 @@ static enum AVPixelFormat get_format(AVC
+@@ -2600,7 +2602,12 @@ static int process_input_packet(InputStr
+ case AVMEDIA_TYPE_VIDEO:
+ ret = decode_video (ist, repeating ? NULL : &avpkt, &got_output, &duration_pts, !pkt,
+ &decode_failed);
+- if (!repeating || !pkt || got_output) {
++ // Pi: Do not inc dts if no_cvt_hw set
++ // V4L2 H264 decode has long latency and sometimes spits out a long
++ // stream of output without input. In this case incrementing DTS is wrong.
++ // There may be cases where the condition as written is correct so only
++ // "fix" in the cases which cause problems
++ if (!repeating || !pkt || (got_output && !no_cvt_hw)) {
+ if (pkt && pkt->duration) {
+ duration_dts = av_rescale_q(pkt->duration, ist->st->time_base, AV_TIME_BASE_Q);
+ } else if(ist->dec_ctx->framerate.num != 0 && ist->dec_ctx->framerate.den != 0) {
+@@ -2820,6 +2827,16 @@ static enum AVPixelFormat get_format(AVC
} else {
const HWAccel *hwaccel = NULL;
int i;
@@ -246,10 +267,10 @@ Upstream-status: Pending
for (i = 0; hwaccels[i].name; i++) {
if (hwaccels[i].pix_fmt == *p) {
hwaccel = &hwaccels[i];
-@@ -2914,6 +2926,15 @@ static int init_input_stream(int ist_ind
+@@ -2914,6 +2931,15 @@ static int init_input_stream(int ist_ind
return ret;
}
-
+
+#if CONFIG_HEVC_RPI_DECODER
+ ret = -1;
+ if (strcmp(codec->name, "hevc_rpi") == 0 &&
@@ -270,7 +291,7 @@ Upstream-status: Pending
HWACCEL_QSV,
+ HWACCEL_RPI,
};
-
+
typedef struct HWAccel {
@@ -590,6 +591,7 @@ extern int video_sync_method;
extern float frame_drop_threshold;
@@ -283,15 +304,15 @@ Upstream-status: Pending
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -1186,8 +1186,8 @@ int ifilter_parameters_from_frame(InputF
-
+
ifilter->format = frame->format;
-
+
- ifilter->width = frame->width;
- ifilter->height = frame->height;
+ ifilter->width = av_frame_cropped_width(frame);
+ ifilter->height = av_frame_cropped_height(frame);
ifilter->sample_aspect_ratio = frame->sample_aspect_ratio;
-
+
ifilter->sample_rate = frame->sample_rate;
--- a/fftools/ffmpeg_hw.c
+++ b/fftools/ffmpeg_hw.c
@@ -309,7 +330,7 @@ Upstream-status: Pending
@@ -130,6 +130,12 @@ static const char *opt_name_enc_time_bas
}\
}
-
+
+#if CONFIG_RPI
+static int rpi_init(AVCodecContext *avctx) {
+ return 0;
@@ -376,7 +397,7 @@ Upstream-status: Pending
+ v4l2_req_devscan.o weak_link.o
OBJS-$(CONFIG_WMA_FREQS) += wma_freqs.o
OBJS-$(CONFIG_WMV2DSP) += wmv2dsp.o
-
+
@@ -391,6 +396,14 @@ OBJS-$(CONFIG_HEVC_QSV_DECODER) +
OBJS-$(CONFIG_HEVC_QSV_ENCODER) += qsvenc_hevc.o hevc_ps_enc.o \
hevc_data.o
@@ -399,7 +420,7 @@ Upstream-status: Pending
+OBJS-$(CONFIG_HEVC_RPI4_8_HWACCEL) += rpivid_hevc.o
+OBJS-$(CONFIG_HEVC_RPI4_10_HWACCEL) += rpivid_hevc.o
+OBJS-$(CONFIG_HEVC_V4L2REQUEST_HWACCEL) += v4l2_request_hevc.o v4l2_req_decode_q.o\
-+ v4l2_req_hevc_v1.o v4l2_req_hevc_v2.o
++ v4l2_req_hevc_v1.o v4l2_req_hevc_v2.o v4l2_req_hevc_v3.o v4l2_req_hevc_v4.o
OBJS-$(CONFIG_HEVC_VAAPI_HWACCEL) += vaapi_hevc.o h265_profile_level.o
OBJS-$(CONFIG_HEVC_VDPAU_HWACCEL) += vdpau_hevc.o
OBJS-$(CONFIG_MJPEG_NVDEC_HWACCEL) += nvdec_mjpeg.o
@@ -435,6 +456,1866 @@ Upstream-status: Pending
+$(SUBDIR)rpi_qpu.o: $(SUBDIR)rpi_hevc_transform8.h $(SUBDIR)rpi_hevc_transform10.h
+$(SUBDIR)rpi_hevcdec.o $(SUBDIR)rpi_shader_template.o $(SUBDIR)rpi_qpu.o: $(SUBDIR)rpi_hevc_shader.h
+endif
+--- a/libavcodec/aarch64/Makefile
++++ b/libavcodec/aarch64/Makefile
+@@ -44,10 +44,12 @@ NEON-OBJS-$(CONFIG_H264PRED)
+ NEON-OBJS-$(CONFIG_H264QPEL) += aarch64/h264qpel_neon.o \
+ aarch64/hpeldsp_neon.o
+ NEON-OBJS-$(CONFIG_HPELDSP) += aarch64/hpeldsp_neon.o
+-NEON-OBJS-$(CONFIG_IDCTDSP) += aarch64/simple_idct_neon.o
++NEON-OBJS-$(CONFIG_IDCTDSP) += aarch64/idctdsp_neon.o \
++ aarch64/simple_idct_neon.o
+ NEON-OBJS-$(CONFIG_MDCT) += aarch64/mdct_neon.o
+ NEON-OBJS-$(CONFIG_MPEGAUDIODSP) += aarch64/mpegaudiodsp_neon.o
+ NEON-OBJS-$(CONFIG_PIXBLOCKDSP) += aarch64/pixblockdsp_neon.o
++NEON-OBJS-$(CONFIG_VC1DSP) += aarch64/vc1dsp_neon.o
+ NEON-OBJS-$(CONFIG_VP8DSP) += aarch64/vp8dsp_neon.o
+
+ # decoders/encoders
+--- a/libavcodec/aarch64/idctdsp_init_aarch64.c
++++ b/libavcodec/aarch64/idctdsp_init_aarch64.c
+@@ -27,19 +27,29 @@
+ #include "libavcodec/idctdsp.h"
+ #include "idct.h"
+
++void ff_put_pixels_clamped_neon(const int16_t *, uint8_t *, ptrdiff_t);
++void ff_put_signed_pixels_clamped_neon(const int16_t *, uint8_t *, ptrdiff_t);
++void ff_add_pixels_clamped_neon(const int16_t *, uint8_t *, ptrdiff_t);
++
+ av_cold void ff_idctdsp_init_aarch64(IDCTDSPContext *c, AVCodecContext *avctx,
+ unsigned high_bit_depth)
+ {
+ int cpu_flags = av_get_cpu_flags();
+
+- if (have_neon(cpu_flags) && !avctx->lowres && !high_bit_depth) {
+- if (avctx->idct_algo == FF_IDCT_AUTO ||
+- avctx->idct_algo == FF_IDCT_SIMPLEAUTO ||
+- avctx->idct_algo == FF_IDCT_SIMPLENEON) {
+- c->idct_put = ff_simple_idct_put_neon;
+- c->idct_add = ff_simple_idct_add_neon;
+- c->idct = ff_simple_idct_neon;
+- c->perm_type = FF_IDCT_PERM_PARTTRANS;
++ if (have_neon(cpu_flags)) {
++ if (!avctx->lowres && !high_bit_depth) {
++ if (avctx->idct_algo == FF_IDCT_AUTO ||
++ avctx->idct_algo == FF_IDCT_SIMPLEAUTO ||
++ avctx->idct_algo == FF_IDCT_SIMPLENEON) {
++ c->idct_put = ff_simple_idct_put_neon;
++ c->idct_add = ff_simple_idct_add_neon;
++ c->idct = ff_simple_idct_neon;
++ c->perm_type = FF_IDCT_PERM_PARTTRANS;
++ }
+ }
++
++ c->add_pixels_clamped = ff_add_pixels_clamped_neon;
++ c->put_pixels_clamped = ff_put_pixels_clamped_neon;
++ c->put_signed_pixels_clamped = ff_put_signed_pixels_clamped_neon;
+ }
+ }
+--- /dev/null
++++ b/libavcodec/aarch64/idctdsp_neon.S
+@@ -0,0 +1,130 @@
++/*
++ * IDCT AArch64 NEON optimisations
++ *
++ * Copyright (c) 2022 Ben Avison <bavison@riscosopen.org>
++ *
++ * This file is part of FFmpeg.
++ *
++ * FFmpeg is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * FFmpeg is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#include "libavutil/aarch64/asm.S"
++
++// Clamp 16-bit signed block coefficients to unsigned 8-bit
++// On entry:
++// x0 -> array of 64x 16-bit coefficients
++// x1 -> 8-bit results
++// x2 = row stride for results, bytes
++function ff_put_pixels_clamped_neon, export=1
++ ld1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x0], #64
++ ld1 {v4.16b, v5.16b, v6.16b, v7.16b}, [x0]
++ sqxtun v0.8b, v0.8h
++ sqxtun v1.8b, v1.8h
++ sqxtun v2.8b, v2.8h
++ sqxtun v3.8b, v3.8h
++ sqxtun v4.8b, v4.8h
++ st1 {v0.8b}, [x1], x2
++ sqxtun v0.8b, v5.8h
++ st1 {v1.8b}, [x1], x2
++ sqxtun v1.8b, v6.8h
++ st1 {v2.8b}, [x1], x2
++ sqxtun v2.8b, v7.8h
++ st1 {v3.8b}, [x1], x2
++ st1 {v4.8b}, [x1], x2
++ st1 {v0.8b}, [x1], x2
++ st1 {v1.8b}, [x1], x2
++ st1 {v2.8b}, [x1]
++ ret
++endfunc
++
++// Clamp 16-bit signed block coefficients to signed 8-bit (biased by 128)
++// On entry:
++// x0 -> array of 64x 16-bit coefficients
++// x1 -> 8-bit results
++// x2 = row stride for results, bytes
++function ff_put_signed_pixels_clamped_neon, export=1
++ ld1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x0], #64
++ movi v4.8b, #128
++ ld1 {v16.16b, v17.16b, v18.16b, v19.16b}, [x0]
++ sqxtn v0.8b, v0.8h
++ sqxtn v1.8b, v1.8h
++ sqxtn v2.8b, v2.8h
++ sqxtn v3.8b, v3.8h
++ sqxtn v5.8b, v16.8h
++ add v0.8b, v0.8b, v4.8b
++ sqxtn v6.8b, v17.8h
++ add v1.8b, v1.8b, v4.8b
++ sqxtn v7.8b, v18.8h
++ add v2.8b, v2.8b, v4.8b
++ sqxtn v16.8b, v19.8h
++ add v3.8b, v3.8b, v4.8b
++ st1 {v0.8b}, [x1], x2
++ add v0.8b, v5.8b, v4.8b
++ st1 {v1.8b}, [x1], x2
++ add v1.8b, v6.8b, v4.8b
++ st1 {v2.8b}, [x1], x2
++ add v2.8b, v7.8b, v4.8b
++ st1 {v3.8b}, [x1], x2
++ add v3.8b, v16.8b, v4.8b
++ st1 {v0.8b}, [x1], x2
++ st1 {v1.8b}, [x1], x2
++ st1 {v2.8b}, [x1], x2
++ st1 {v3.8b}, [x1]
++ ret
++endfunc
++
++// Add 16-bit signed block coefficients to unsigned 8-bit
++// On entry:
++// x0 -> array of 64x 16-bit coefficients
++// x1 -> 8-bit input and results
++// x2 = row stride for 8-bit input and results, bytes
++function ff_add_pixels_clamped_neon, export=1
++ ld1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x0], #64
++ mov x3, x1
++ ld1 {v4.8b}, [x1], x2
++ ld1 {v5.8b}, [x1], x2
++ ld1 {v6.8b}, [x1], x2
++ ld1 {v7.8b}, [x1], x2
++ ld1 {v16.16b, v17.16b, v18.16b, v19.16b}, [x0]
++ uaddw v0.8h, v0.8h, v4.8b
++ uaddw v1.8h, v1.8h, v5.8b
++ uaddw v2.8h, v2.8h, v6.8b
++ ld1 {v4.8b}, [x1], x2
++ uaddw v3.8h, v3.8h, v7.8b
++ ld1 {v5.8b}, [x1], x2
++ sqxtun v0.8b, v0.8h
++ ld1 {v6.8b}, [x1], x2
++ sqxtun v1.8b, v1.8h
++ ld1 {v7.8b}, [x1]
++ sqxtun v2.8b, v2.8h
++ sqxtun v3.8b, v3.8h
++ uaddw v4.8h, v16.8h, v4.8b
++ st1 {v0.8b}, [x3], x2
++ uaddw v0.8h, v17.8h, v5.8b
++ st1 {v1.8b}, [x3], x2
++ uaddw v1.8h, v18.8h, v6.8b
++ st1 {v2.8b}, [x3], x2
++ uaddw v2.8h, v19.8h, v7.8b
++ sqxtun v4.8b, v4.8h
++ sqxtun v0.8b, v0.8h
++ st1 {v3.8b}, [x3], x2
++ sqxtun v1.8b, v1.8h
++ sqxtun v2.8b, v2.8h
++ st1 {v4.8b}, [x3], x2
++ st1 {v0.8b}, [x3], x2
++ st1 {v1.8b}, [x3], x2
++ st1 {v2.8b}, [x3]
++ ret
++endfunc
+--- a/libavcodec/aarch64/vc1dsp_init_aarch64.c
++++ b/libavcodec/aarch64/vc1dsp_init_aarch64.c
+@@ -21,10 +21,28 @@
+ #include "libavutil/attributes.h"
+ #include "libavutil/cpu.h"
+ #include "libavutil/aarch64/cpu.h"
++#include "libavutil/intreadwrite.h"
+ #include "libavcodec/vc1dsp.h"
+
+ #include "config.h"
+
++void ff_vc1_inv_trans_8x8_neon(int16_t *block);
++void ff_vc1_inv_trans_8x4_neon(uint8_t *dest, ptrdiff_t stride, int16_t *block);
++void ff_vc1_inv_trans_4x8_neon(uint8_t *dest, ptrdiff_t stride, int16_t *block);
++void ff_vc1_inv_trans_4x4_neon(uint8_t *dest, ptrdiff_t stride, int16_t *block);
++
++void ff_vc1_inv_trans_8x8_dc_neon(uint8_t *dest, ptrdiff_t stride, int16_t *block);
++void ff_vc1_inv_trans_8x4_dc_neon(uint8_t *dest, ptrdiff_t stride, int16_t *block);
++void ff_vc1_inv_trans_4x8_dc_neon(uint8_t *dest, ptrdiff_t stride, int16_t *block);
++void ff_vc1_inv_trans_4x4_dc_neon(uint8_t *dest, ptrdiff_t stride, int16_t *block);
++
++void ff_vc1_v_loop_filter4_neon(uint8_t *src, ptrdiff_t stride, int pq);
++void ff_vc1_h_loop_filter4_neon(uint8_t *src, ptrdiff_t stride, int pq);
++void ff_vc1_v_loop_filter8_neon(uint8_t *src, ptrdiff_t stride, int pq);
++void ff_vc1_h_loop_filter8_neon(uint8_t *src, ptrdiff_t stride, int pq);
++void ff_vc1_v_loop_filter16_neon(uint8_t *src, ptrdiff_t stride, int pq);
++void ff_vc1_h_loop_filter16_neon(uint8_t *src, ptrdiff_t stride, int pq);
++
+ void ff_put_vc1_chroma_mc8_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride,
+ int h, int x, int y);
+ void ff_avg_vc1_chroma_mc8_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride,
+@@ -34,14 +52,90 @@ void ff_put_vc1_chroma_mc4_neon(uint8_t
+ void ff_avg_vc1_chroma_mc4_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride,
+ int h, int x, int y);
+
++int ff_vc1_unescape_buffer_helper_neon(const uint8_t *src, int size, uint8_t *dst);
++
++static int vc1_unescape_buffer_neon(const uint8_t *src, int size, uint8_t *dst)
++{
++ /* Dealing with starting and stopping, and removing escape bytes, are
++ * comparatively less time-sensitive, so are more clearly expressed using
++ * a C wrapper around the assembly inner loop. Note that we assume a
++ * little-endian machine that supports unaligned loads. */
++ int dsize = 0;
++ while (size >= 4)
++ {
++ int found = 0;
++ while (!found && (((uintptr_t) dst) & 7) && size >= 4)
++ {
++ found = (AV_RL32(src) &~ 0x03000000) == 0x00030000;
++ if (!found)
++ {
++ *dst++ = *src++;
++ --size;
++ ++dsize;
++ }
++ }
++ if (!found)
++ {
++ int skip = size - ff_vc1_unescape_buffer_helper_neon(src, size, dst);
++ dst += skip;
++ src += skip;
++ size -= skip;
++ dsize += skip;
++ while (!found && size >= 4)
++ {
++ found = (AV_RL32(src) &~ 0x03000000) == 0x00030000;
++ if (!found)
++ {
++ *dst++ = *src++;
++ --size;
++ ++dsize;
++ }
++ }
++ }
++ if (found)
++ {
++ *dst++ = *src++;
++ *dst++ = *src++;
++ ++src;
++ size -= 3;
++ dsize += 2;
++ }
++ }
++ while (size > 0)
++ {
++ *dst++ = *src++;
++ --size;
++ ++dsize;
++ }
++ return dsize;
++}
++
+ av_cold void ff_vc1dsp_init_aarch64(VC1DSPContext *dsp)
+ {
+ int cpu_flags = av_get_cpu_flags();
+
+ if (have_neon(cpu_flags)) {
++ dsp->vc1_inv_trans_8x8 = ff_vc1_inv_trans_8x8_neon;
++ dsp->vc1_inv_trans_8x4 = ff_vc1_inv_trans_8x4_neon;
++ dsp->vc1_inv_trans_4x8 = ff_vc1_inv_trans_4x8_neon;
++ dsp->vc1_inv_trans_4x4 = ff_vc1_inv_trans_4x4_neon;
++ dsp->vc1_inv_trans_8x8_dc = ff_vc1_inv_trans_8x8_dc_neon;
++ dsp->vc1_inv_trans_8x4_dc = ff_vc1_inv_trans_8x4_dc_neon;
++ dsp->vc1_inv_trans_4x8_dc = ff_vc1_inv_trans_4x8_dc_neon;
++ dsp->vc1_inv_trans_4x4_dc = ff_vc1_inv_trans_4x4_dc_neon;
++
++ dsp->vc1_v_loop_filter4 = ff_vc1_v_loop_filter4_neon;
++ dsp->vc1_h_loop_filter4 = ff_vc1_h_loop_filter4_neon;
++ dsp->vc1_v_loop_filter8 = ff_vc1_v_loop_filter8_neon;
++ dsp->vc1_h_loop_filter8 = ff_vc1_h_loop_filter8_neon;
++ dsp->vc1_v_loop_filter16 = ff_vc1_v_loop_filter16_neon;
++ dsp->vc1_h_loop_filter16 = ff_vc1_h_loop_filter16_neon;
++
+ dsp->put_no_rnd_vc1_chroma_pixels_tab[0] = ff_put_vc1_chroma_mc8_neon;
+ dsp->avg_no_rnd_vc1_chroma_pixels_tab[0] = ff_avg_vc1_chroma_mc8_neon;
+ dsp->put_no_rnd_vc1_chroma_pixels_tab[1] = ff_put_vc1_chroma_mc4_neon;
+ dsp->avg_no_rnd_vc1_chroma_pixels_tab[1] = ff_avg_vc1_chroma_mc4_neon;
++
++ dsp->vc1_unescape_buffer = vc1_unescape_buffer_neon;
+ }
+ }
+--- /dev/null
++++ b/libavcodec/aarch64/vc1dsp_neon.S
+@@ -0,0 +1,1546 @@
++/*
++ * VC1 AArch64 NEON optimisations
++ *
++ * Copyright (c) 2022 Ben Avison <bavison@riscosopen.org>
++ *
++ * This file is part of FFmpeg.
++ *
++ * FFmpeg is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * FFmpeg is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#include "libavutil/aarch64/asm.S"
++
++// VC-1 8x8 inverse transform
++// On entry:
++// x0 -> array of 16-bit inverse transform coefficients, in column-major order
++// On exit:
++// array at x0 updated to hold transformed block; also now held in row-major order
++function ff_vc1_inv_trans_8x8_neon, export=1
++ ld1 {v1.16b, v2.16b}, [x0], #32
++ ld1 {v3.16b, v4.16b}, [x0], #32
++ ld1 {v5.16b, v6.16b}, [x0], #32
++ shl v1.8h, v1.8h, #2 // 8/2 * src[0]
++ sub x1, x0, #3*32
++ ld1 {v16.16b, v17.16b}, [x0]
++ shl v7.8h, v2.8h, #4 // 16 * src[8]
++ shl v18.8h, v2.8h, #2 // 4 * src[8]
++ shl v19.8h, v4.8h, #4 // 16 * src[24]
++ ldr d0, .Lcoeffs_it8
++ shl v5.8h, v5.8h, #2 // 8/2 * src[32]
++ shl v20.8h, v6.8h, #4 // 16 * src[40]
++ shl v21.8h, v6.8h, #2 // 4 * src[40]
++ shl v22.8h, v17.8h, #4 // 16 * src[56]
++ ssra v20.8h, v19.8h, #2 // 4 * src[24] + 16 * src[40]
++ mul v23.8h, v3.8h, v0.h[0] // 6/2 * src[16]
++ sub v19.8h, v19.8h, v21.8h // 16 * src[24] - 4 * src[40]
++ ssra v7.8h, v22.8h, #2 // 16 * src[8] + 4 * src[56]
++ sub v18.8h, v22.8h, v18.8h // - 4 * src[8] + 16 * src[56]
++ shl v3.8h, v3.8h, #3 // 16/2 * src[16]
++ mls v20.8h, v2.8h, v0.h[2] // - 15 * src[8] + 4 * src[24] + 16 * src[40]
++ ssra v1.8h, v1.8h, #1 // 12/2 * src[0]
++ ssra v5.8h, v5.8h, #1 // 12/2 * src[32]
++ mla v7.8h, v4.8h, v0.h[2] // 16 * src[8] + 15 * src[24] + 4 * src[56]
++ shl v21.8h, v16.8h, #3 // 16/2 * src[48]
++ mls v19.8h, v2.8h, v0.h[1] // - 9 * src[8] + 16 * src[24] - 4 * src[40]
++ sub v2.8h, v23.8h, v21.8h // t4/2 = 6/2 * src[16] - 16/2 * src[48]
++ mla v18.8h, v4.8h, v0.h[1] // - 4 * src[8] + 9 * src[24] + 16 * src[56]
++ add v4.8h, v1.8h, v5.8h // t1/2 = 12/2 * src[0] + 12/2 * src[32]
++ sub v1.8h, v1.8h, v5.8h // t2/2 = 12/2 * src[0] - 12/2 * src[32]
++ mla v3.8h, v16.8h, v0.h[0] // t3/2 = 16/2 * src[16] + 6/2 * src[48]
++ mla v7.8h, v6.8h, v0.h[1] // t1 = 16 * src[8] + 15 * src[24] + 9 * src[40] + 4 * src[56]
++ add v5.8h, v1.8h, v2.8h // t6/2 = t2/2 + t4/2
++ sub v16.8h, v1.8h, v2.8h // t7/2 = t2/2 - t4/2
++ mla v20.8h, v17.8h, v0.h[1] // -t2 = - 15 * src[8] + 4 * src[24] + 16 * src[40] + 9 * src[56]
++ add v21.8h, v1.8h, v2.8h // t6/2 = t2/2 + t4/2
++ add v22.8h, v4.8h, v3.8h // t5/2 = t1/2 + t3/2
++ mls v19.8h, v17.8h, v0.h[2] // -t3 = - 9 * src[8] + 16 * src[24] - 4 * src[40] - 15 * src[56]
++ sub v17.8h, v4.8h, v3.8h // t8/2 = t1/2 - t3/2
++ add v23.8h, v4.8h, v3.8h // t5/2 = t1/2 + t3/2
++ mls v18.8h, v6.8h, v0.h[2] // -t4 = - 4 * src[8] + 9 * src[24] - 15 * src[40] + 16 * src[56]
++ sub v1.8h, v1.8h, v2.8h // t7/2 = t2/2 - t4/2
++ sub v2.8h, v4.8h, v3.8h // t8/2 = t1/2 - t3/2
++ neg v3.8h, v7.8h // -t1
++ neg v4.8h, v20.8h // +t2
++ neg v6.8h, v19.8h // +t3
++ ssra v22.8h, v7.8h, #1 // (t5 + t1) >> 1
++ ssra v1.8h, v19.8h, #1 // (t7 - t3) >> 1
++ neg v7.8h, v18.8h // +t4
++ ssra v5.8h, v4.8h, #1 // (t6 + t2) >> 1
++ ssra v16.8h, v6.8h, #1 // (t7 + t3) >> 1
++ ssra v2.8h, v18.8h, #1 // (t8 - t4) >> 1
++ ssra v17.8h, v7.8h, #1 // (t8 + t4) >> 1
++ ssra v21.8h, v20.8h, #1 // (t6 - t2) >> 1
++ ssra v23.8h, v3.8h, #1 // (t5 - t1) >> 1
++ srshr v3.8h, v22.8h, #2 // (t5 + t1 + 4) >> 3
++ srshr v4.8h, v5.8h, #2 // (t6 + t2 + 4) >> 3
++ srshr v5.8h, v16.8h, #2 // (t7 + t3 + 4) >> 3
++ srshr v6.8h, v17.8h, #2 // (t8 + t4 + 4) >> 3
++ srshr v2.8h, v2.8h, #2 // (t8 - t4 + 4) >> 3
++ srshr v1.8h, v1.8h, #2 // (t7 - t3 + 4) >> 3
++ srshr v7.8h, v21.8h, #2 // (t6 - t2 + 4) >> 3
++ srshr v16.8h, v23.8h, #2 // (t5 - t1 + 4) >> 3
++ trn2 v17.8h, v3.8h, v4.8h
++ trn2 v18.8h, v5.8h, v6.8h
++ trn2 v19.8h, v2.8h, v1.8h
++ trn2 v20.8h, v7.8h, v16.8h
++ trn1 v21.4s, v17.4s, v18.4s
++ trn2 v17.4s, v17.4s, v18.4s
++ trn1 v18.4s, v19.4s, v20.4s
++ trn2 v19.4s, v19.4s, v20.4s
++ trn1 v3.8h, v3.8h, v4.8h
++ trn2 v4.2d, v21.2d, v18.2d
++ trn1 v20.2d, v17.2d, v19.2d
++ trn1 v5.8h, v5.8h, v6.8h
++ trn1 v1.8h, v2.8h, v1.8h
++ trn1 v2.8h, v7.8h, v16.8h
++ trn1 v6.2d, v21.2d, v18.2d
++ trn2 v7.2d, v17.2d, v19.2d
++ shl v16.8h, v20.8h, #4 // 16 * src[24]
++ shl v17.8h, v4.8h, #4 // 16 * src[40]
++ trn1 v18.4s, v3.4s, v5.4s
++ trn1 v19.4s, v1.4s, v2.4s
++ shl v21.8h, v7.8h, #4 // 16 * src[56]
++ shl v22.8h, v6.8h, #2 // 4 * src[8]
++ shl v23.8h, v4.8h, #2 // 4 * src[40]
++ trn2 v3.4s, v3.4s, v5.4s
++ trn2 v1.4s, v1.4s, v2.4s
++ shl v2.8h, v6.8h, #4 // 16 * src[8]
++ sub v5.8h, v16.8h, v23.8h // 16 * src[24] - 4 * src[40]
++ ssra v17.8h, v16.8h, #2 // 4 * src[24] + 16 * src[40]
++ sub v16.8h, v21.8h, v22.8h // - 4 * src[8] + 16 * src[56]
++ trn1 v22.2d, v18.2d, v19.2d
++ trn2 v18.2d, v18.2d, v19.2d
++ trn1 v19.2d, v3.2d, v1.2d
++ ssra v2.8h, v21.8h, #2 // 16 * src[8] + 4 * src[56]
++ mls v17.8h, v6.8h, v0.h[2] // - 15 * src[8] + 4 * src[24] + 16 * src[40]
++ shl v21.8h, v22.8h, #2 // 8/2 * src[0]
++ shl v18.8h, v18.8h, #2 // 8/2 * src[32]
++ mls v5.8h, v6.8h, v0.h[1] // - 9 * src[8] + 16 * src[24] - 4 * src[40]
++ shl v6.8h, v19.8h, #3 // 16/2 * src[16]
++ trn2 v1.2d, v3.2d, v1.2d
++ mla v16.8h, v20.8h, v0.h[1] // - 4 * src[8] + 9 * src[24] + 16 * src[56]
++ ssra v21.8h, v21.8h, #1 // 12/2 * src[0]
++ ssra v18.8h, v18.8h, #1 // 12/2 * src[32]
++ mul v3.8h, v19.8h, v0.h[0] // 6/2 * src[16]
++ shl v19.8h, v1.8h, #3 // 16/2 * src[48]
++ mla v2.8h, v20.8h, v0.h[2] // 16 * src[8] + 15 * src[24] + 4 * src[56]
++ add v20.8h, v21.8h, v18.8h // t1/2 = 12/2 * src[0] + 12/2 * src[32]
++ mla v6.8h, v1.8h, v0.h[0] // t3/2 = 16/2 * src[16] + 6/2 * src[48]
++ sub v1.8h, v21.8h, v18.8h // t2/2 = 12/2 * src[0] - 12/2 * src[32]
++ sub v3.8h, v3.8h, v19.8h // t4/2 = 6/2 * src[16] - 16/2 * src[48]
++ mla v17.8h, v7.8h, v0.h[1] // -t2 = - 15 * src[8] + 4 * src[24] + 16 * src[40] + 9 * src[56]
++ mls v5.8h, v7.8h, v0.h[2] // -t3 = - 9 * src[8] + 16 * src[24] - 4 * src[40] - 15 * src[56]
++ add v7.8h, v1.8h, v3.8h // t6/2 = t2/2 + t4/2
++ add v18.8h, v20.8h, v6.8h // t5/2 = t1/2 + t3/2
++ mls v16.8h, v4.8h, v0.h[2] // -t4 = - 4 * src[8] + 9 * src[24] - 15 * src[40] + 16 * src[56]
++ sub v19.8h, v1.8h, v3.8h // t7/2 = t2/2 - t4/2
++ neg v21.8h, v17.8h // +t2
++ mla v2.8h, v4.8h, v0.h[1] // t1 = 16 * src[8] + 15 * src[24] + 9 * src[40] + 4 * src[56]
++ sub v0.8h, v20.8h, v6.8h // t8/2 = t1/2 - t3/2
++ neg v4.8h, v5.8h // +t3
++ sub v22.8h, v1.8h, v3.8h // t7/2 = t2/2 - t4/2
++ sub v23.8h, v20.8h, v6.8h // t8/2 = t1/2 - t3/2
++ neg v24.8h, v16.8h // +t4
++ add v6.8h, v20.8h, v6.8h // t5/2 = t1/2 + t3/2
++ add v1.8h, v1.8h, v3.8h // t6/2 = t2/2 + t4/2
++ ssra v7.8h, v21.8h, #1 // (t6 + t2) >> 1
++ neg v3.8h, v2.8h // -t1
++ ssra v18.8h, v2.8h, #1 // (t5 + t1) >> 1
++ ssra v19.8h, v4.8h, #1 // (t7 + t3) >> 1
++ ssra v0.8h, v24.8h, #1 // (t8 + t4) >> 1
++ srsra v23.8h, v16.8h, #1 // (t8 - t4 + 1) >> 1
++ srsra v22.8h, v5.8h, #1 // (t7 - t3 + 1) >> 1
++ srsra v1.8h, v17.8h, #1 // (t6 - t2 + 1) >> 1
++ srsra v6.8h, v3.8h, #1 // (t5 - t1 + 1) >> 1
++ srshr v2.8h, v18.8h, #6 // (t5 + t1 + 64) >> 7
++ srshr v3.8h, v7.8h, #6 // (t6 + t2 + 64) >> 7
++ srshr v4.8h, v19.8h, #6 // (t7 + t3 + 64) >> 7
++ srshr v5.8h, v0.8h, #6 // (t8 + t4 + 64) >> 7
++ srshr v16.8h, v23.8h, #6 // (t8 - t4 + 65) >> 7
++ srshr v17.8h, v22.8h, #6 // (t7 - t3 + 65) >> 7
++ st1 {v2.16b, v3.16b}, [x1], #32
++ srshr v0.8h, v1.8h, #6 // (t6 - t2 + 65) >> 7
++ srshr v1.8h, v6.8h, #6 // (t5 - t1 + 65) >> 7
++ st1 {v4.16b, v5.16b}, [x1], #32
++ st1 {v16.16b, v17.16b}, [x1], #32
++ st1 {v0.16b, v1.16b}, [x1]
++ ret
++endfunc
++
++// VC-1 8x4 inverse transform
++// On entry:
++// x0 -> array of 8-bit samples, in row-major order
++// x1 = row stride for 8-bit sample array
++// x2 -> array of 16-bit inverse transform coefficients, in row-major order
++// On exit:
++// array at x0 updated by saturated addition of (narrowed) transformed block
++function ff_vc1_inv_trans_8x4_neon, export=1
++ ld1 {v1.8b, v2.8b, v3.8b, v4.8b}, [x2], #32
++ mov x3, x0
++ ld1 {v16.8b, v17.8b, v18.8b, v19.8b}, [x2]
++ ldr q0, .Lcoeffs_it8 // includes 4-point coefficients in upper half of vector
++ ld1 {v5.8b}, [x0], x1
++ trn2 v6.4h, v1.4h, v3.4h
++ trn2 v7.4h, v2.4h, v4.4h
++ trn1 v1.4h, v1.4h, v3.4h
++ trn1 v2.4h, v2.4h, v4.4h
++ trn2 v3.4h, v16.4h, v18.4h
++ trn2 v4.4h, v17.4h, v19.4h
++ trn1 v16.4h, v16.4h, v18.4h
++ trn1 v17.4h, v17.4h, v19.4h
++ ld1 {v18.8b}, [x0], x1
++ trn1 v19.2s, v6.2s, v3.2s
++ trn2 v3.2s, v6.2s, v3.2s
++ trn1 v6.2s, v7.2s, v4.2s
++ trn2 v4.2s, v7.2s, v4.2s
++ trn1 v7.2s, v1.2s, v16.2s
++ trn1 v20.2s, v2.2s, v17.2s
++ shl v21.4h, v19.4h, #4 // 16 * src[1]
++ trn2 v1.2s, v1.2s, v16.2s
++ shl v16.4h, v3.4h, #4 // 16 * src[3]
++ trn2 v2.2s, v2.2s, v17.2s
++ shl v17.4h, v6.4h, #4 // 16 * src[5]
++ ld1 {v22.8b}, [x0], x1
++ shl v23.4h, v4.4h, #4 // 16 * src[7]
++ mul v24.4h, v1.4h, v0.h[0] // 6/2 * src[2]
++ ld1 {v25.8b}, [x0]
++ shl v26.4h, v19.4h, #2 // 4 * src[1]
++ shl v27.4h, v6.4h, #2 // 4 * src[5]
++ ssra v21.4h, v23.4h, #2 // 16 * src[1] + 4 * src[7]
++ ssra v17.4h, v16.4h, #2 // 4 * src[3] + 16 * src[5]
++ sub v23.4h, v23.4h, v26.4h // - 4 * src[1] + 16 * src[7]
++ sub v16.4h, v16.4h, v27.4h // 16 * src[3] - 4 * src[5]
++ shl v7.4h, v7.4h, #2 // 8/2 * src[0]
++ shl v20.4h, v20.4h, #2 // 8/2 * src[4]
++ mla v21.4h, v3.4h, v0.h[2] // 16 * src[1] + 15 * src[3] + 4 * src[7]
++ shl v1.4h, v1.4h, #3 // 16/2 * src[2]
++ mls v17.4h, v19.4h, v0.h[2] // - 15 * src[1] + 4 * src[3] + 16 * src[5]
++ ssra v7.4h, v7.4h, #1 // 12/2 * src[0]
++ mls v16.4h, v19.4h, v0.h[1] // - 9 * src[1] + 16 * src[3] - 4 * src[5]
++ ssra v20.4h, v20.4h, #1 // 12/2 * src[4]
++ mla v23.4h, v3.4h, v0.h[1] // - 4 * src[1] + 9 * src[3] + 16 * src[7]
++ shl v3.4h, v2.4h, #3 // 16/2 * src[6]
++ mla v1.4h, v2.4h, v0.h[0] // t3/2 = 16/2 * src[2] + 6/2 * src[6]
++ mla v21.4h, v6.4h, v0.h[1] // t1 = 16 * src[1] + 15 * src[3] + 9 * src[5] + 4 * src[7]
++ mla v17.4h, v4.4h, v0.h[1] // -t2 = - 15 * src[1] + 4 * src[3] + 16 * src[5] + 9 * src[7]
++ sub v2.4h, v24.4h, v3.4h // t4/2 = 6/2 * src[2] - 16/2 * src[6]
++ mls v16.4h, v4.4h, v0.h[2] // -t3 = - 9 * src[1] + 16 * src[3] - 4 * src[5] - 15 * src[7]
++ add v3.4h, v7.4h, v20.4h // t1/2 = 12/2 * src[0] + 12/2 * src[4]
++ mls v23.4h, v6.4h, v0.h[2] // -t4 = - 4 * src[1] + 9 * src[3] - 15 * src[5] + 16 * src[7]
++ sub v4.4h, v7.4h, v20.4h // t2/2 = 12/2 * src[0] - 12/2 * src[4]
++ neg v6.4h, v21.4h // -t1
++ add v7.4h, v3.4h, v1.4h // t5/2 = t1/2 + t3/2
++ sub v19.4h, v3.4h, v1.4h // t8/2 = t1/2 - t3/2
++ add v20.4h, v4.4h, v2.4h // t6/2 = t2/2 + t4/2
++ sub v24.4h, v4.4h, v2.4h // t7/2 = t2/2 - t4/2
++ add v26.4h, v3.4h, v1.4h // t5/2 = t1/2 + t3/2
++ add v27.4h, v4.4h, v2.4h // t6/2 = t2/2 + t4/2
++ sub v2.4h, v4.4h, v2.4h // t7/2 = t2/2 - t4/2
++ sub v1.4h, v3.4h, v1.4h // t8/2 = t1/2 - t3/2
++ neg v3.4h, v17.4h // +t2
++ neg v4.4h, v16.4h // +t3
++ neg v28.4h, v23.4h // +t4
++ ssra v7.4h, v21.4h, #1 // (t5 + t1) >> 1
++ ssra v1.4h, v23.4h, #1 // (t8 - t4) >> 1
++ ssra v20.4h, v3.4h, #1 // (t6 + t2) >> 1
++ ssra v24.4h, v4.4h, #1 // (t7 + t3) >> 1
++ ssra v19.4h, v28.4h, #1 // (t8 + t4) >> 1
++ ssra v2.4h, v16.4h, #1 // (t7 - t3) >> 1
++ ssra v27.4h, v17.4h, #1 // (t6 - t2) >> 1
++ ssra v26.4h, v6.4h, #1 // (t5 - t1) >> 1
++ trn1 v1.2d, v7.2d, v1.2d
++ trn1 v2.2d, v20.2d, v2.2d
++ trn1 v3.2d, v24.2d, v27.2d
++ trn1 v4.2d, v19.2d, v26.2d
++ srshr v1.8h, v1.8h, #2 // (t5 + t1 + 4) >> 3, (t8 - t4 + 4) >> 3
++ srshr v2.8h, v2.8h, #2 // (t6 + t2 + 4) >> 3, (t7 - t3 + 4) >> 3
++ srshr v3.8h, v3.8h, #2 // (t7 + t3 + 4) >> 3, (t6 - t2 + 4) >> 3
++ srshr v4.8h, v4.8h, #2 // (t8 + t4 + 4) >> 3, (t5 - t1 + 4) >> 3
++ trn2 v6.8h, v1.8h, v2.8h
++ trn1 v1.8h, v1.8h, v2.8h
++ trn2 v2.8h, v3.8h, v4.8h
++ trn1 v3.8h, v3.8h, v4.8h
++ trn2 v4.4s, v6.4s, v2.4s
++ trn1 v7.4s, v1.4s, v3.4s
++ trn2 v1.4s, v1.4s, v3.4s
++ mul v3.8h, v4.8h, v0.h[5] // 22/2 * src[24]
++ trn1 v2.4s, v6.4s, v2.4s
++ mul v4.8h, v4.8h, v0.h[4] // 10/2 * src[24]
++ mul v6.8h, v7.8h, v0.h[6] // 17 * src[0]
++ mul v1.8h, v1.8h, v0.h[6] // 17 * src[16]
++ mls v3.8h, v2.8h, v0.h[4] // t4/2 = - 10/2 * src[8] + 22/2 * src[24]
++ mla v4.8h, v2.8h, v0.h[5] // t3/2 = 22/2 * src[8] + 10/2 * src[24]
++ add v0.8h, v6.8h, v1.8h // t1 = 17 * src[0] + 17 * src[16]
++ sub v1.8h, v6.8h, v1.8h // t2 = 17 * src[0] - 17 * src[16]
++ neg v2.8h, v3.8h // -t4/2
++ neg v6.8h, v4.8h // -t3/2
++ ssra v4.8h, v0.8h, #1 // (t1 + t3) >> 1
++ ssra v2.8h, v1.8h, #1 // (t2 - t4) >> 1
++ ssra v3.8h, v1.8h, #1 // (t2 + t4) >> 1
++ ssra v6.8h, v0.8h, #1 // (t1 - t3) >> 1
++ srshr v0.8h, v4.8h, #6 // (t1 + t3 + 64) >> 7
++ srshr v1.8h, v2.8h, #6 // (t2 - t4 + 64) >> 7
++ srshr v2.8h, v3.8h, #6 // (t2 + t4 + 64) >> 7
++ srshr v3.8h, v6.8h, #6 // (t1 - t3 + 64) >> 7
++ uaddw v0.8h, v0.8h, v5.8b
++ uaddw v1.8h, v1.8h, v18.8b
++ uaddw v2.8h, v2.8h, v22.8b
++ uaddw v3.8h, v3.8h, v25.8b
++ sqxtun v0.8b, v0.8h
++ sqxtun v1.8b, v1.8h
++ sqxtun v2.8b, v2.8h
++ sqxtun v3.8b, v3.8h
++ st1 {v0.8b}, [x3], x1
++ st1 {v1.8b}, [x3], x1
++ st1 {v2.8b}, [x3], x1
++ st1 {v3.8b}, [x3]
++ ret
++endfunc
++
++// VC-1 4x8 inverse transform
++// On entry:
++// x0 -> array of 8-bit samples, in row-major order
++// x1 = row stride for 8-bit sample array
++// x2 -> array of 16-bit inverse transform coefficients, in row-major order (row stride is 8 coefficients)
++// On exit:
++// array at x0 updated by saturated addition of (narrowed) transformed block
++function ff_vc1_inv_trans_4x8_neon, export=1
++ mov x3, #16
++ ldr q0, .Lcoeffs_it8 // includes 4-point coefficients in upper half of vector
++ mov x4, x0
++ ld1 {v1.d}[0], [x2], x3 // 00 01 02 03
++ ld1 {v2.d}[0], [x2], x3 // 10 11 12 13
++ ld1 {v3.d}[0], [x2], x3 // 20 21 22 23
++ ld1 {v4.d}[0], [x2], x3 // 30 31 32 33
++ ld1 {v1.d}[1], [x2], x3 // 40 41 42 43
++ ld1 {v2.d}[1], [x2], x3 // 50 51 52 53
++ ld1 {v3.d}[1], [x2], x3 // 60 61 62 63
++ ld1 {v4.d}[1], [x2] // 70 71 72 73
++ ld1 {v5.s}[0], [x0], x1
++ ld1 {v6.s}[0], [x0], x1
++ ld1 {v7.s}[0], [x0], x1
++ trn2 v16.8h, v1.8h, v2.8h // 01 11 03 13 41 51 43 53
++ trn1 v1.8h, v1.8h, v2.8h // 00 10 02 12 40 50 42 52
++ trn2 v2.8h, v3.8h, v4.8h // 21 31 23 33 61 71 63 73
++ trn1 v3.8h, v3.8h, v4.8h // 20 30 22 32 60 70 62 72
++ ld1 {v4.s}[0], [x0], x1
++ trn2 v17.4s, v16.4s, v2.4s // 03 13 23 33 43 53 63 73
++ trn1 v18.4s, v1.4s, v3.4s // 00 10 20 30 40 50 60 70
++ trn1 v2.4s, v16.4s, v2.4s // 01 11 21 31 41 51 61 71
++ mul v16.8h, v17.8h, v0.h[4] // 10/2 * src[3]
++ ld1 {v5.s}[1], [x0], x1
++ mul v17.8h, v17.8h, v0.h[5] // 22/2 * src[3]
++ ld1 {v6.s}[1], [x0], x1
++ trn2 v1.4s, v1.4s, v3.4s // 02 12 22 32 42 52 62 72
++ mul v3.8h, v18.8h, v0.h[6] // 17 * src[0]
++ ld1 {v7.s}[1], [x0], x1
++ mul v1.8h, v1.8h, v0.h[6] // 17 * src[2]
++ ld1 {v4.s}[1], [x0]
++ mla v16.8h, v2.8h, v0.h[5] // t3/2 = 22/2 * src[1] + 10/2 * src[3]
++ mls v17.8h, v2.8h, v0.h[4] // t4/2 = - 10/2 * src[1] + 22/2 * src[3]
++ add v2.8h, v3.8h, v1.8h // t1 = 17 * src[0] + 17 * src[2]
++ sub v1.8h, v3.8h, v1.8h // t2 = 17 * src[0] - 17 * src[2]
++ neg v3.8h, v16.8h // -t3/2
++ ssra v16.8h, v2.8h, #1 // (t1 + t3) >> 1
++ neg v18.8h, v17.8h // -t4/2
++ ssra v17.8h, v1.8h, #1 // (t2 + t4) >> 1
++ ssra v3.8h, v2.8h, #1 // (t1 - t3) >> 1
++ ssra v18.8h, v1.8h, #1 // (t2 - t4) >> 1
++ srshr v1.8h, v16.8h, #2 // (t1 + t3 + 64) >> 3
++ srshr v2.8h, v17.8h, #2 // (t2 + t4 + 64) >> 3
++ srshr v3.8h, v3.8h, #2 // (t1 - t3 + 64) >> 3
++ srshr v16.8h, v18.8h, #2 // (t2 - t4 + 64) >> 3
++ trn2 v17.8h, v2.8h, v3.8h // 12 13 32 33 52 53 72 73
++ trn2 v18.8h, v1.8h, v16.8h // 10 11 30 31 50 51 70 71
++ trn1 v1.8h, v1.8h, v16.8h // 00 01 20 21 40 41 60 61
++ trn1 v2.8h, v2.8h, v3.8h // 02 03 22 23 42 43 62 63
++ trn1 v3.4s, v18.4s, v17.4s // 10 11 12 13 50 51 52 53
++ trn2 v16.4s, v18.4s, v17.4s // 30 31 32 33 70 71 72 73
++ trn1 v17.4s, v1.4s, v2.4s // 00 01 02 03 40 41 42 43
++ mov d18, v3.d[1] // 50 51 52 53
++ shl v19.4h, v3.4h, #4 // 16 * src[8]
++ mov d20, v16.d[1] // 70 71 72 73
++ shl v21.4h, v16.4h, #4 // 16 * src[24]
++ mov d22, v17.d[1] // 40 41 42 43
++ shl v23.4h, v3.4h, #2 // 4 * src[8]
++ shl v24.4h, v18.4h, #4 // 16 * src[40]
++ shl v25.4h, v20.4h, #4 // 16 * src[56]
++ shl v26.4h, v18.4h, #2 // 4 * src[40]
++ trn2 v1.4s, v1.4s, v2.4s // 20 21 22 23 60 61 62 63
++ ssra v24.4h, v21.4h, #2 // 4 * src[24] + 16 * src[40]
++ sub v2.4h, v25.4h, v23.4h // - 4 * src[8] + 16 * src[56]
++ shl v17.4h, v17.4h, #2 // 8/2 * src[0]
++ sub v21.4h, v21.4h, v26.4h // 16 * src[24] - 4 * src[40]
++ shl v22.4h, v22.4h, #2 // 8/2 * src[32]
++ mov d23, v1.d[1] // 60 61 62 63
++ ssra v19.4h, v25.4h, #2 // 16 * src[8] + 4 * src[56]
++ mul v25.4h, v1.4h, v0.h[0] // 6/2 * src[16]
++ shl v1.4h, v1.4h, #3 // 16/2 * src[16]
++ mls v24.4h, v3.4h, v0.h[2] // - 15 * src[8] + 4 * src[24] + 16 * src[40]
++ ssra v17.4h, v17.4h, #1 // 12/2 * src[0]
++ mls v21.4h, v3.4h, v0.h[1] // - 9 * src[8] + 16 * src[24] - 4 * src[40]
++ ssra v22.4h, v22.4h, #1 // 12/2 * src[32]
++ mla v2.4h, v16.4h, v0.h[1] // - 4 * src[8] + 9 * src[24] + 16 * src[56]
++ shl v3.4h, v23.4h, #3 // 16/2 * src[48]
++ mla v19.4h, v16.4h, v0.h[2] // 16 * src[8] + 15 * src[24] + 4 * src[56]
++ mla v1.4h, v23.4h, v0.h[0] // t3/2 = 16/2 * src[16] + 6/2 * src[48]
++ mla v24.4h, v20.4h, v0.h[1] // -t2 = - 15 * src[8] + 4 * src[24] + 16 * src[40] + 9 * src[56]
++ add v16.4h, v17.4h, v22.4h // t1/2 = 12/2 * src[0] + 12/2 * src[32]
++ sub v3.4h, v25.4h, v3.4h // t4/2 = 6/2 * src[16] - 16/2 * src[48]
++ sub v17.4h, v17.4h, v22.4h // t2/2 = 12/2 * src[0] - 12/2 * src[32]
++ mls v21.4h, v20.4h, v0.h[2] // -t3 = - 9 * src[8] + 16 * src[24] - 4 * src[40] - 15 * src[56]
++ mla v19.4h, v18.4h, v0.h[1] // t1 = 16 * src[8] + 15 * src[24] + 9 * src[40] + 4 * src[56]
++ add v20.4h, v16.4h, v1.4h // t5/2 = t1/2 + t3/2
++ mls v2.4h, v18.4h, v0.h[2] // -t4 = - 4 * src[8] + 9 * src[24] - 15 * src[40] + 16 * src[56]
++ sub v0.4h, v16.4h, v1.4h // t8/2 = t1/2 - t3/2
++ add v18.4h, v17.4h, v3.4h // t6/2 = t2/2 + t4/2
++ sub v22.4h, v17.4h, v3.4h // t7/2 = t2/2 - t4/2
++ neg v23.4h, v24.4h // +t2
++ sub v25.4h, v17.4h, v3.4h // t7/2 = t2/2 - t4/2
++ add v3.4h, v17.4h, v3.4h // t6/2 = t2/2 + t4/2
++ neg v17.4h, v21.4h // +t3
++ sub v26.4h, v16.4h, v1.4h // t8/2 = t1/2 - t3/2
++ add v1.4h, v16.4h, v1.4h // t5/2 = t1/2 + t3/2
++ neg v16.4h, v19.4h // -t1
++ neg v27.4h, v2.4h // +t4
++ ssra v20.4h, v19.4h, #1 // (t5 + t1) >> 1
++ srsra v0.4h, v2.4h, #1 // (t8 - t4 + 1) >> 1
++ ssra v18.4h, v23.4h, #1 // (t6 + t2) >> 1
++ srsra v22.4h, v21.4h, #1 // (t7 - t3 + 1) >> 1
++ ssra v25.4h, v17.4h, #1 // (t7 + t3) >> 1
++ srsra v3.4h, v24.4h, #1 // (t6 - t2 + 1) >> 1
++ ssra v26.4h, v27.4h, #1 // (t8 + t4) >> 1
++ srsra v1.4h, v16.4h, #1 // (t5 - t1 + 1) >> 1
++ trn1 v0.2d, v20.2d, v0.2d
++ trn1 v2.2d, v18.2d, v22.2d
++ trn1 v3.2d, v25.2d, v3.2d
++ trn1 v1.2d, v26.2d, v1.2d
++ srshr v0.8h, v0.8h, #6 // (t5 + t1 + 64) >> 7, (t8 - t4 + 65) >> 7
++ srshr v2.8h, v2.8h, #6 // (t6 + t2 + 64) >> 7, (t7 - t3 + 65) >> 7
++ srshr v3.8h, v3.8h, #6 // (t7 + t3 + 64) >> 7, (t6 - t2 + 65) >> 7
++ srshr v1.8h, v1.8h, #6 // (t8 + t4 + 64) >> 7, (t5 - t1 + 65) >> 7
++ uaddw v0.8h, v0.8h, v5.8b
++ uaddw v2.8h, v2.8h, v6.8b
++ uaddw v3.8h, v3.8h, v7.8b
++ uaddw v1.8h, v1.8h, v4.8b
++ sqxtun v0.8b, v0.8h
++ sqxtun v2.8b, v2.8h
++ sqxtun v3.8b, v3.8h
++ sqxtun v1.8b, v1.8h
++ st1 {v0.s}[0], [x4], x1
++ st1 {v2.s}[0], [x4], x1
++ st1 {v3.s}[0], [x4], x1
++ st1 {v1.s}[0], [x4], x1
++ st1 {v0.s}[1], [x4], x1
++ st1 {v2.s}[1], [x4], x1
++ st1 {v3.s}[1], [x4], x1
++ st1 {v1.s}[1], [x4]
++ ret
++endfunc
++
++// VC-1 4x4 inverse transform
++// On entry:
++// x0 -> array of 8-bit samples, in row-major order
++// x1 = row stride for 8-bit sample array
++// x2 -> array of 16-bit inverse transform coefficients, in row-major order (row stride is 8 coefficients)
++// On exit:
++// array at x0 updated by saturated addition of (narrowed) transformed block
++function ff_vc1_inv_trans_4x4_neon, export=1
++ mov x3, #16
++ ldr d0, .Lcoeffs_it4
++ mov x4, x0
++ ld1 {v1.d}[0], [x2], x3 // 00 01 02 03
++ ld1 {v2.d}[0], [x2], x3 // 10 11 12 13
++ ld1 {v3.d}[0], [x2], x3 // 20 21 22 23
++ ld1 {v4.d}[0], [x2] // 30 31 32 33
++ ld1 {v5.s}[0], [x0], x1
++ ld1 {v5.s}[1], [x0], x1
++ ld1 {v6.s}[0], [x0], x1
++ trn2 v7.4h, v1.4h, v2.4h // 01 11 03 13
++ trn1 v1.4h, v1.4h, v2.4h // 00 10 02 12
++ ld1 {v6.s}[1], [x0]
++ trn2 v2.4h, v3.4h, v4.4h // 21 31 23 33
++ trn1 v3.4h, v3.4h, v4.4h // 20 30 22 32
++ trn2 v4.2s, v7.2s, v2.2s // 03 13 23 33
++ trn1 v16.2s, v1.2s, v3.2s // 00 10 20 30
++ trn1 v2.2s, v7.2s, v2.2s // 01 11 21 31
++ trn2 v1.2s, v1.2s, v3.2s // 02 12 22 32
++ mul v3.4h, v4.4h, v0.h[0] // 10/2 * src[3]
++ mul v4.4h, v4.4h, v0.h[1] // 22/2 * src[3]
++ mul v7.4h, v16.4h, v0.h[2] // 17 * src[0]
++ mul v1.4h, v1.4h, v0.h[2] // 17 * src[2]
++ mla v3.4h, v2.4h, v0.h[1] // t3/2 = 22/2 * src[1] + 10/2 * src[3]
++ mls v4.4h, v2.4h, v0.h[0] // t4/2 = - 10/2 * src[1] + 22/2 * src[3]
++ add v2.4h, v7.4h, v1.4h // t1 = 17 * src[0] + 17 * src[2]
++ sub v1.4h, v7.4h, v1.4h // t2 = 17 * src[0] - 17 * src[2]
++ neg v7.4h, v3.4h // -t3/2
++ neg v16.4h, v4.4h // -t4/2
++ ssra v3.4h, v2.4h, #1 // (t1 + t3) >> 1
++ ssra v4.4h, v1.4h, #1 // (t2 + t4) >> 1
++ ssra v16.4h, v1.4h, #1 // (t2 - t4) >> 1
++ ssra v7.4h, v2.4h, #1 // (t1 - t3) >> 1
++ srshr v1.4h, v3.4h, #2 // (t1 + t3 + 64) >> 3
++ srshr v2.4h, v4.4h, #2 // (t2 + t4 + 64) >> 3
++ srshr v3.4h, v16.4h, #2 // (t2 - t4 + 64) >> 3
++ srshr v4.4h, v7.4h, #2 // (t1 - t3 + 64) >> 3
++ trn2 v7.4h, v1.4h, v3.4h // 10 11 30 31
++ trn1 v1.4h, v1.4h, v3.4h // 00 01 20 21
++ trn2 v3.4h, v2.4h, v4.4h // 12 13 32 33
++ trn1 v2.4h, v2.4h, v4.4h // 02 03 22 23
++ trn2 v4.2s, v7.2s, v3.2s // 30 31 32 33
++ trn1 v16.2s, v1.2s, v2.2s // 00 01 02 03
++ trn1 v3.2s, v7.2s, v3.2s // 10 11 12 13
++ trn2 v1.2s, v1.2s, v2.2s // 20 21 22 23
++ mul v2.4h, v4.4h, v0.h[1] // 22/2 * src[24]
++ mul v4.4h, v4.4h, v0.h[0] // 10/2 * src[24]
++ mul v7.4h, v16.4h, v0.h[2] // 17 * src[0]
++ mul v1.4h, v1.4h, v0.h[2] // 17 * src[16]
++ mls v2.4h, v3.4h, v0.h[0] // t4/2 = - 10/2 * src[8] + 22/2 * src[24]
++ mla v4.4h, v3.4h, v0.h[1] // t3/2 = 22/2 * src[8] + 10/2 * src[24]
++ add v0.4h, v7.4h, v1.4h // t1 = 17 * src[0] + 17 * src[16]
++ sub v1.4h, v7.4h, v1.4h // t2 = 17 * src[0] - 17 * src[16]
++ neg v3.4h, v2.4h // -t4/2
++ neg v7.4h, v4.4h // -t3/2
++ ssra v4.4h, v0.4h, #1 // (t1 + t3) >> 1
++ ssra v3.4h, v1.4h, #1 // (t2 - t4) >> 1
++ ssra v2.4h, v1.4h, #1 // (t2 + t4) >> 1
++ ssra v7.4h, v0.4h, #1 // (t1 - t3) >> 1
++ trn1 v0.2d, v4.2d, v3.2d
++ trn1 v1.2d, v2.2d, v7.2d
++ srshr v0.8h, v0.8h, #6 // (t1 + t3 + 64) >> 7, (t2 - t4 + 64) >> 7
++ srshr v1.8h, v1.8h, #6 // (t2 + t4 + 64) >> 7, (t1 - t3 + 64) >> 7
++ uaddw v0.8h, v0.8h, v5.8b
++ uaddw v1.8h, v1.8h, v6.8b
++ sqxtun v0.8b, v0.8h
++ sqxtun v1.8b, v1.8h
++ st1 {v0.s}[0], [x4], x1
++ st1 {v0.s}[1], [x4], x1
++ st1 {v1.s}[0], [x4], x1
++ st1 {v1.s}[1], [x4]
++ ret
++endfunc
++
++// VC-1 8x8 inverse transform, DC case
++// On entry:
++// x0 -> array of 8-bit samples, in row-major order
++// x1 = row stride for 8-bit sample array
++// x2 -> 16-bit inverse transform DC coefficient
++// On exit:
++// array at x0 updated by saturated addition of (narrowed) transformed block
++function ff_vc1_inv_trans_8x8_dc_neon, export=1
++ ldrsh w2, [x2]
++ mov x3, x0
++ ld1 {v0.8b}, [x0], x1
++ ld1 {v1.8b}, [x0], x1
++ ld1 {v2.8b}, [x0], x1
++ add w2, w2, w2, lsl #1
++ ld1 {v3.8b}, [x0], x1
++ ld1 {v4.8b}, [x0], x1
++ add w2, w2, #1
++ ld1 {v5.8b}, [x0], x1
++ asr w2, w2, #1
++ ld1 {v6.8b}, [x0], x1
++ add w2, w2, w2, lsl #1
++ ld1 {v7.8b}, [x0]
++ add w0, w2, #16
++ asr w0, w0, #5
++ dup v16.8h, w0
++ uaddw v0.8h, v16.8h, v0.8b
++ uaddw v1.8h, v16.8h, v1.8b
++ uaddw v2.8h, v16.8h, v2.8b
++ uaddw v3.8h, v16.8h, v3.8b
++ uaddw v4.8h, v16.8h, v4.8b
++ uaddw v5.8h, v16.8h, v5.8b
++ sqxtun v0.8b, v0.8h
++ uaddw v6.8h, v16.8h, v6.8b
++ sqxtun v1.8b, v1.8h
++ uaddw v7.8h, v16.8h, v7.8b
++ sqxtun v2.8b, v2.8h
++ sqxtun v3.8b, v3.8h
++ sqxtun v4.8b, v4.8h
++ st1 {v0.8b}, [x3], x1
++ sqxtun v0.8b, v5.8h
++ st1 {v1.8b}, [x3], x1
++ sqxtun v1.8b, v6.8h
++ st1 {v2.8b}, [x3], x1
++ sqxtun v2.8b, v7.8h
++ st1 {v3.8b}, [x3], x1
++ st1 {v4.8b}, [x3], x1
++ st1 {v0.8b}, [x3], x1
++ st1 {v1.8b}, [x3], x1
++ st1 {v2.8b}, [x3]
++ ret
++endfunc
++
++// VC-1 8x4 inverse transform, DC case
++// On entry:
++// x0 -> array of 8-bit samples, in row-major order
++// x1 = row stride for 8-bit sample array
++// x2 -> 16-bit inverse transform DC coefficient
++// On exit:
++// array at x0 updated by saturated addition of (narrowed) transformed block
++function ff_vc1_inv_trans_8x4_dc_neon, export=1
++ ldrsh w2, [x2]
++ mov x3, x0
++ ld1 {v0.8b}, [x0], x1
++ ld1 {v1.8b}, [x0], x1
++ ld1 {v2.8b}, [x0], x1
++ add w2, w2, w2, lsl #1
++ ld1 {v3.8b}, [x0]
++ add w0, w2, #1
++ asr w0, w0, #1
++ add w0, w0, w0, lsl #4
++ add w0, w0, #64
++ asr w0, w0, #7
++ dup v4.8h, w0
++ uaddw v0.8h, v4.8h, v0.8b
++ uaddw v1.8h, v4.8h, v1.8b
++ uaddw v2.8h, v4.8h, v2.8b
++ uaddw v3.8h, v4.8h, v3.8b
++ sqxtun v0.8b, v0.8h
++ sqxtun v1.8b, v1.8h
++ sqxtun v2.8b, v2.8h
++ sqxtun v3.8b, v3.8h
++ st1 {v0.8b}, [x3], x1
++ st1 {v1.8b}, [x3], x1
++ st1 {v2.8b}, [x3], x1
++ st1 {v3.8b}, [x3]
++ ret
++endfunc
++
++// VC-1 4x8 inverse transform, DC case
++// On entry:
++// x0 -> array of 8-bit samples, in row-major order
++// x1 = row stride for 8-bit sample array
++// x2 -> 16-bit inverse transform DC coefficient
++// On exit:
++// array at x0 updated by saturated addition of (narrowed) transformed block
++function ff_vc1_inv_trans_4x8_dc_neon, export=1
++ ldrsh w2, [x2]
++ mov x3, x0
++ ld1 {v0.s}[0], [x0], x1
++ ld1 {v1.s}[0], [x0], x1
++ ld1 {v2.s}[0], [x0], x1
++ add w2, w2, w2, lsl #4
++ ld1 {v3.s}[0], [x0], x1
++ add w2, w2, #4
++ asr w2, w2, #3
++ add w2, w2, w2, lsl #1
++ ld1 {v0.s}[1], [x0], x1
++ add w2, w2, #16
++ asr w2, w2, #5
++ dup v4.8h, w2
++ ld1 {v1.s}[1], [x0], x1
++ ld1 {v2.s}[1], [x0], x1
++ ld1 {v3.s}[1], [x0]
++ uaddw v0.8h, v4.8h, v0.8b
++ uaddw v1.8h, v4.8h, v1.8b
++ uaddw v2.8h, v4.8h, v2.8b
++ uaddw v3.8h, v4.8h, v3.8b
++ sqxtun v0.8b, v0.8h
++ sqxtun v1.8b, v1.8h
++ sqxtun v2.8b, v2.8h
++ sqxtun v3.8b, v3.8h
++ st1 {v0.s}[0], [x3], x1
++ st1 {v1.s}[0], [x3], x1
++ st1 {v2.s}[0], [x3], x1
++ st1 {v3.s}[0], [x3], x1
++ st1 {v0.s}[1], [x3], x1
++ st1 {v1.s}[1], [x3], x1
++ st1 {v2.s}[1], [x3], x1
++ st1 {v3.s}[1], [x3]
++ ret
++endfunc
++
++// VC-1 4x4 inverse transform, DC case
++// On entry:
++// x0 -> array of 8-bit samples, in row-major order
++// x1 = row stride for 8-bit sample array
++// x2 -> 16-bit inverse transform DC coefficient
++// On exit:
++// array at x0 updated by saturated addition of (narrowed) transformed block
++function ff_vc1_inv_trans_4x4_dc_neon, export=1
++ ldrsh w2, [x2]
++ mov x3, x0
++ ld1 {v0.s}[0], [x0], x1
++ ld1 {v1.s}[0], [x0], x1
++ ld1 {v0.s}[1], [x0], x1
++ add w2, w2, w2, lsl #4
++ ld1 {v1.s}[1], [x0]
++ add w0, w2, #4
++ asr w0, w0, #3
++ add w0, w0, w0, lsl #4
++ add w0, w0, #64
++ asr w0, w0, #7
++ dup v2.8h, w0
++ uaddw v0.8h, v2.8h, v0.8b
++ uaddw v1.8h, v2.8h, v1.8b
++ sqxtun v0.8b, v0.8h
++ sqxtun v1.8b, v1.8h
++ st1 {v0.s}[0], [x3], x1
++ st1 {v1.s}[0], [x3], x1
++ st1 {v0.s}[1], [x3], x1
++ st1 {v1.s}[1], [x3]
++ ret
++endfunc
++
++.align 5
++.Lcoeffs_it8:
++.quad 0x000F00090003
++.Lcoeffs_it4:
++.quad 0x0011000B0005
++.Lcoeffs:
++.quad 0x00050002
++
++// VC-1 in-loop deblocking filter for 4 pixel pairs at boundary of vertically-neighbouring blocks
++// On entry:
++// x0 -> top-left pel of lower block
++// x1 = row stride, bytes
++// w2 = PQUANT bitstream parameter
++function ff_vc1_v_loop_filter4_neon, export=1
++ sub x3, x0, w1, sxtw #2
++ ldr d0, .Lcoeffs
++ ld1 {v1.s}[0], [x0], x1 // P5
++ ld1 {v2.s}[0], [x3], x1 // P1
++ ld1 {v3.s}[0], [x3], x1 // P2
++ ld1 {v4.s}[0], [x0], x1 // P6
++ ld1 {v5.s}[0], [x3], x1 // P3
++ ld1 {v6.s}[0], [x0], x1 // P7
++ ld1 {v7.s}[0], [x3] // P4
++ ld1 {v16.s}[0], [x0] // P8
++ ushll v17.8h, v1.8b, #1 // 2*P5
++ dup v18.8h, w2 // pq
++ ushll v2.8h, v2.8b, #1 // 2*P1
++ uxtl v3.8h, v3.8b // P2
++ uxtl v4.8h, v4.8b // P6
++ uxtl v19.8h, v5.8b // P3
++ mls v2.4h, v3.4h, v0.h[1] // 2*P1-5*P2
++ uxtl v3.8h, v6.8b // P7
++ mls v17.4h, v4.4h, v0.h[1] // 2*P5-5*P6
++ ushll v5.8h, v5.8b, #1 // 2*P3
++ uxtl v6.8h, v7.8b // P4
++ mla v17.4h, v3.4h, v0.h[1] // 2*P5-5*P6+5*P7
++ uxtl v3.8h, v16.8b // P8
++ mla v2.4h, v19.4h, v0.h[1] // 2*P1-5*P2+5*P3
++ uxtl v1.8h, v1.8b // P5
++ mls v5.4h, v6.4h, v0.h[1] // 2*P3-5*P4
++ mls v17.4h, v3.4h, v0.h[0] // 2*P5-5*P6+5*P7-2*P8
++ sub v3.4h, v6.4h, v1.4h // P4-P5
++ mls v2.4h, v6.4h, v0.h[0] // 2*P1-5*P2+5*P3-2*P4
++ mla v5.4h, v1.4h, v0.h[1] // 2*P3-5*P4+5*P5
++ mls v5.4h, v4.4h, v0.h[0] // 2*P3-5*P4+5*P5-2*P6
++ abs v4.4h, v3.4h
++ srshr v7.4h, v17.4h, #3
++ srshr v2.4h, v2.4h, #3
++ sshr v4.4h, v4.4h, #1 // clip
++ srshr v5.4h, v5.4h, #3
++ abs v7.4h, v7.4h // a2
++ sshr v3.4h, v3.4h, #8 // clip_sign
++ abs v2.4h, v2.4h // a1
++ cmeq v16.4h, v4.4h, #0 // test clip == 0
++ abs v17.4h, v5.4h // a0
++ sshr v5.4h, v5.4h, #8 // a0_sign
++ cmhs v19.4h, v2.4h, v7.4h // test a1 >= a2
++ cmhs v18.4h, v17.4h, v18.4h // test a0 >= pq
++ sub v3.4h, v3.4h, v5.4h // clip_sign - a0_sign
++ bsl v19.8b, v7.8b, v2.8b // a3
++ orr v2.8b, v16.8b, v18.8b // test clip == 0 || a0 >= pq
++ uqsub v5.4h, v17.4h, v19.4h // a0 >= a3 ? a0-a3 : 0 (a0 > a3 in all cases where filtering is enabled, so makes more sense to subtract this way round than the opposite and then taking the abs)
++ cmhs v7.4h, v19.4h, v17.4h // test a3 >= a0
++ mul v0.4h, v5.4h, v0.h[1] // a0 >= a3 ? 5*(a0-a3) : 0
++ orr v5.8b, v2.8b, v7.8b // test clip == 0 || a0 >= pq || a3 >= a0
++ mov w0, v5.s[1] // move to gp reg
++ ushr v0.4h, v0.4h, #3 // a0 >= a3 ? (5*(a0-a3))>>3 : 0
++ cmhs v5.4h, v0.4h, v4.4h
++ tbnz w0, #0, 1f // none of the 4 pixel pairs should be updated if this one is not filtered
++ bsl v5.8b, v4.8b, v0.8b // FFMIN(d, clip)
++ bic v0.8b, v5.8b, v2.8b // set each d to zero if it should not be filtered because clip == 0 || a0 >= pq (a3 > a0 case already zeroed by saturating sub)
++ mls v6.4h, v0.4h, v3.4h // invert d depending on clip_sign & a0_sign, or zero it if they match, and accumulate into P4
++ mla v1.4h, v0.4h, v3.4h // invert d depending on clip_sign & a0_sign, or zero it if they match, and accumulate into P5
++ sqxtun v0.8b, v6.8h
++ sqxtun v1.8b, v1.8h
++ st1 {v0.s}[0], [x3], x1
++ st1 {v1.s}[0], [x3]
++1: ret
++endfunc
++
++// VC-1 in-loop deblocking filter for 4 pixel pairs at boundary of horizontally-neighbouring blocks
++// On entry:
++// x0 -> top-left pel of right block
++// x1 = row stride, bytes
++// w2 = PQUANT bitstream parameter
++function ff_vc1_h_loop_filter4_neon, export=1
++ sub x3, x0, #4 // where to start reading
++ ldr d0, .Lcoeffs
++ ld1 {v1.8b}, [x3], x1
++ sub x0, x0, #1 // where to start writing
++ ld1 {v2.8b}, [x3], x1
++ ld1 {v3.8b}, [x3], x1
++ ld1 {v4.8b}, [x3]
++ dup v5.8h, w2 // pq
++ trn1 v6.8b, v1.8b, v2.8b
++ trn2 v1.8b, v1.8b, v2.8b
++ trn1 v2.8b, v3.8b, v4.8b
++ trn2 v3.8b, v3.8b, v4.8b
++ trn1 v4.4h, v6.4h, v2.4h // P1, P5
++ trn1 v7.4h, v1.4h, v3.4h // P2, P6
++ trn2 v2.4h, v6.4h, v2.4h // P3, P7
++ trn2 v1.4h, v1.4h, v3.4h // P4, P8
++ ushll v3.8h, v4.8b, #1 // 2*P1, 2*P5
++ uxtl v6.8h, v7.8b // P2, P6
++ uxtl v7.8h, v2.8b // P3, P7
++ uxtl v1.8h, v1.8b // P4, P8
++ mls v3.8h, v6.8h, v0.h[1] // 2*P1-5*P2, 2*P5-5*P6
++ ushll v2.8h, v2.8b, #1 // 2*P3, 2*P7
++ uxtl v4.8h, v4.8b // P1, P5
++ mla v3.8h, v7.8h, v0.h[1] // 2*P1-5*P2+5*P3, 2*P5-5*P6+5*P7
++ mov d6, v6.d[1] // P6
++ mls v3.8h, v1.8h, v0.h[0] // 2*P1-5*P2+5*P3-2*P4, 2*P5-5*P6+5*P7-2*P8
++ mov d4, v4.d[1] // P5
++ mls v2.4h, v1.4h, v0.h[1] // 2*P3-5*P4
++ mla v2.4h, v4.4h, v0.h[1] // 2*P3-5*P4+5*P5
++ sub v7.4h, v1.4h, v4.4h // P4-P5
++ mls v2.4h, v6.4h, v0.h[0] // 2*P3-5*P4+5*P5-2*P6
++ srshr v3.8h, v3.8h, #3
++ abs v6.4h, v7.4h
++ sshr v7.4h, v7.4h, #8 // clip_sign
++ srshr v2.4h, v2.4h, #3
++ abs v3.8h, v3.8h // a1, a2
++ sshr v6.4h, v6.4h, #1 // clip
++ mov d16, v3.d[1] // a2
++ abs v17.4h, v2.4h // a0
++ cmeq v18.4h, v6.4h, #0 // test clip == 0
++ sshr v2.4h, v2.4h, #8 // a0_sign
++ cmhs v19.4h, v3.4h, v16.4h // test a1 >= a2
++ cmhs v5.4h, v17.4h, v5.4h // test a0 >= pq
++ sub v2.4h, v7.4h, v2.4h // clip_sign - a0_sign
++ bsl v19.8b, v16.8b, v3.8b // a3
++ orr v3.8b, v18.8b, v5.8b // test clip == 0 || a0 >= pq
++ uqsub v5.4h, v17.4h, v19.4h // a0 >= a3 ? a0-a3 : 0 (a0 > a3 in all cases where filtering is enabled, so makes more sense to subtract this way round than the opposite and then taking the abs)
++ cmhs v7.4h, v19.4h, v17.4h // test a3 >= a0
++ mul v0.4h, v5.4h, v0.h[1] // a0 >= a3 ? 5*(a0-a3) : 0
++ orr v5.8b, v3.8b, v7.8b // test clip == 0 || a0 >= pq || a3 >= a0
++ mov w2, v5.s[1] // move to gp reg
++ ushr v0.4h, v0.4h, #3 // a0 >= a3 ? (5*(a0-a3))>>3 : 0
++ cmhs v5.4h, v0.4h, v6.4h
++ tbnz w2, #0, 1f // none of the 4 pixel pairs should be updated if this one is not filtered
++ bsl v5.8b, v6.8b, v0.8b // FFMIN(d, clip)
++ bic v0.8b, v5.8b, v3.8b // set each d to zero if it should not be filtered because clip == 0 || a0 >= pq (a3 > a0 case already zeroed by saturating sub)
++ mla v4.4h, v0.4h, v2.4h // invert d depending on clip_sign & a0_sign, or zero it if they match, and accumulate into P5
++ mls v1.4h, v0.4h, v2.4h // invert d depending on clip_sign & a0_sign, or zero it if they match, and accumulate into P4
++ sqxtun v3.8b, v4.8h
++ sqxtun v2.8b, v1.8h
++ st2 {v2.b, v3.b}[0], [x0], x1
++ st2 {v2.b, v3.b}[1], [x0], x1
++ st2 {v2.b, v3.b}[2], [x0], x1
++ st2 {v2.b, v3.b}[3], [x0]
++1: ret
++endfunc
++
++// VC-1 in-loop deblocking filter for 8 pixel pairs at boundary of vertically-neighbouring blocks
++// On entry:
++// x0 -> top-left pel of lower block
++// x1 = row stride, bytes
++// w2 = PQUANT bitstream parameter
++function ff_vc1_v_loop_filter8_neon, export=1
++ sub x3, x0, w1, sxtw #2
++ ldr d0, .Lcoeffs
++ ld1 {v1.8b}, [x0], x1 // P5
++ movi v2.2d, #0x0000ffff00000000
++ ld1 {v3.8b}, [x3], x1 // P1
++ ld1 {v4.8b}, [x3], x1 // P2
++ ld1 {v5.8b}, [x0], x1 // P6
++ ld1 {v6.8b}, [x3], x1 // P3
++ ld1 {v7.8b}, [x0], x1 // P7
++ ushll v16.8h, v1.8b, #1 // 2*P5
++ ushll v3.8h, v3.8b, #1 // 2*P1
++ ld1 {v17.8b}, [x3] // P4
++ uxtl v4.8h, v4.8b // P2
++ ld1 {v18.8b}, [x0] // P8
++ uxtl v5.8h, v5.8b // P6
++ dup v19.8h, w2 // pq
++ uxtl v20.8h, v6.8b // P3
++ mls v3.8h, v4.8h, v0.h[1] // 2*P1-5*P2
++ uxtl v4.8h, v7.8b // P7
++ ushll v6.8h, v6.8b, #1 // 2*P3
++ mls v16.8h, v5.8h, v0.h[1] // 2*P5-5*P6
++ uxtl v7.8h, v17.8b // P4
++ uxtl v17.8h, v18.8b // P8
++ mla v16.8h, v4.8h, v0.h[1] // 2*P5-5*P6+5*P7
++ uxtl v1.8h, v1.8b // P5
++ mla v3.8h, v20.8h, v0.h[1] // 2*P1-5*P2+5*P3
++ sub v4.8h, v7.8h, v1.8h // P4-P5
++ mls v6.8h, v7.8h, v0.h[1] // 2*P3-5*P4
++ mls v16.8h, v17.8h, v0.h[0] // 2*P5-5*P6+5*P7-2*P8
++ abs v17.8h, v4.8h
++ sshr v4.8h, v4.8h, #8 // clip_sign
++ mls v3.8h, v7.8h, v0.h[0] // 2*P1-5*P2+5*P3-2*P4
++ sshr v17.8h, v17.8h, #1 // clip
++ mla v6.8h, v1.8h, v0.h[1] // 2*P3-5*P4+5*P5
++ srshr v16.8h, v16.8h, #3
++ mls v6.8h, v5.8h, v0.h[0] // 2*P3-5*P4+5*P5-2*P6
++ cmeq v5.8h, v17.8h, #0 // test clip == 0
++ srshr v3.8h, v3.8h, #3
++ abs v16.8h, v16.8h // a2
++ abs v3.8h, v3.8h // a1
++ srshr v6.8h, v6.8h, #3
++ cmhs v18.8h, v3.8h, v16.8h // test a1 >= a2
++ abs v20.8h, v6.8h // a0
++ sshr v6.8h, v6.8h, #8 // a0_sign
++ bsl v18.16b, v16.16b, v3.16b // a3
++ cmhs v3.8h, v20.8h, v19.8h // test a0 >= pq
++ sub v4.8h, v4.8h, v6.8h // clip_sign - a0_sign
++ uqsub v6.8h, v20.8h, v18.8h // a0 >= a3 ? a0-a3 : 0 (a0 > a3 in all cases where filtering is enabled, so makes more sense to subtract this way round than the opposite and then taking the abs)
++ cmhs v16.8h, v18.8h, v20.8h // test a3 >= a0
++ orr v3.16b, v5.16b, v3.16b // test clip == 0 || a0 >= pq
++ mul v0.8h, v6.8h, v0.h[1] // a0 >= a3 ? 5*(a0-a3) : 0
++ orr v5.16b, v3.16b, v16.16b // test clip == 0 || a0 >= pq || a3 >= a0
++ cmtst v2.2d, v5.2d, v2.2d // if 2nd of each group of is not filtered, then none of the others in the group should be either
++ mov w0, v5.s[1] // move to gp reg
++ ushr v0.8h, v0.8h, #3 // a0 >= a3 ? (5*(a0-a3))>>3 : 0
++ mov w2, v5.s[3]
++ orr v2.16b, v3.16b, v2.16b
++ cmhs v3.8h, v0.8h, v17.8h
++ and w0, w0, w2
++ bsl v3.16b, v17.16b, v0.16b // FFMIN(d, clip)
++ tbnz w0, #0, 1f // none of the 8 pixel pairs should be updated in this case
++ bic v0.16b, v3.16b, v2.16b // set each d to zero if it should not be filtered
++ mls v7.8h, v0.8h, v4.8h // invert d depending on clip_sign & a0_sign, or zero it if they match, and accumulate into P4
++ mla v1.8h, v0.8h, v4.8h // invert d depending on clip_sign & a0_sign, or zero it if they match, and accumulate into P5
++ sqxtun v0.8b, v7.8h
++ sqxtun v1.8b, v1.8h
++ st1 {v0.8b}, [x3], x1
++ st1 {v1.8b}, [x3]
++1: ret
++endfunc
++
++// VC-1 in-loop deblocking filter for 8 pixel pairs at boundary of horizontally-neighbouring blocks
++// On entry:
++// x0 -> top-left pel of right block
++// x1 = row stride, bytes
++// w2 = PQUANT bitstream parameter
++function ff_vc1_h_loop_filter8_neon, export=1
++ sub x3, x0, #4 // where to start reading
++ ldr d0, .Lcoeffs
++ ld1 {v1.8b}, [x3], x1 // P1[0], P2[0]...
++ sub x0, x0, #1 // where to start writing
++ ld1 {v2.8b}, [x3], x1
++ add x4, x0, x1, lsl #2
++ ld1 {v3.8b}, [x3], x1
++ ld1 {v4.8b}, [x3], x1
++ ld1 {v5.8b}, [x3], x1
++ ld1 {v6.8b}, [x3], x1
++ ld1 {v7.8b}, [x3], x1
++ trn1 v16.8b, v1.8b, v2.8b // P1[0], P1[1], P3[0]...
++ ld1 {v17.8b}, [x3]
++ trn2 v1.8b, v1.8b, v2.8b // P2[0], P2[1], P4[0]...
++ trn1 v2.8b, v3.8b, v4.8b // P1[2], P1[3], P3[2]...
++ trn2 v3.8b, v3.8b, v4.8b // P2[2], P2[3], P4[2]...
++ dup v4.8h, w2 // pq
++ trn1 v18.8b, v5.8b, v6.8b // P1[4], P1[5], P3[4]...
++ trn2 v5.8b, v5.8b, v6.8b // P2[4], P2[5], P4[4]...
++ trn1 v6.4h, v16.4h, v2.4h // P1[0], P1[1], P1[2], P1[3], P5[0]...
++ trn1 v19.4h, v1.4h, v3.4h // P2[0], P2[1], P2[2], P2[3], P6[0]...
++ trn1 v20.8b, v7.8b, v17.8b // P1[6], P1[7], P3[6]...
++ trn2 v7.8b, v7.8b, v17.8b // P2[6], P2[7], P4[6]...
++ trn2 v2.4h, v16.4h, v2.4h // P3[0], P3[1], P3[2], P3[3], P7[0]...
++ trn2 v1.4h, v1.4h, v3.4h // P4[0], P4[1], P4[2], P4[3], P8[0]...
++ trn1 v3.4h, v18.4h, v20.4h // P1[4], P1[5], P1[6], P1[7], P5[4]...
++ trn1 v16.4h, v5.4h, v7.4h // P2[4], P2[5], P2[6], P2[7], P6[4]...
++ trn2 v17.4h, v18.4h, v20.4h // P3[4], P3[5], P3[6], P3[7], P7[4]...
++ trn2 v5.4h, v5.4h, v7.4h // P4[4], P4[5], P4[6], P4[7], P8[4]...
++ trn1 v7.2s, v6.2s, v3.2s // P1
++ trn1 v18.2s, v19.2s, v16.2s // P2
++ trn2 v3.2s, v6.2s, v3.2s // P5
++ trn2 v6.2s, v19.2s, v16.2s // P6
++ trn1 v16.2s, v2.2s, v17.2s // P3
++ trn2 v2.2s, v2.2s, v17.2s // P7
++ ushll v7.8h, v7.8b, #1 // 2*P1
++ trn1 v17.2s, v1.2s, v5.2s // P4
++ ushll v19.8h, v3.8b, #1 // 2*P5
++ trn2 v1.2s, v1.2s, v5.2s // P8
++ uxtl v5.8h, v18.8b // P2
++ uxtl v6.8h, v6.8b // P6
++ uxtl v18.8h, v16.8b // P3
++ mls v7.8h, v5.8h, v0.h[1] // 2*P1-5*P2
++ uxtl v2.8h, v2.8b // P7
++ ushll v5.8h, v16.8b, #1 // 2*P3
++ mls v19.8h, v6.8h, v0.h[1] // 2*P5-5*P6
++ uxtl v16.8h, v17.8b // P4
++ uxtl v1.8h, v1.8b // P8
++ mla v19.8h, v2.8h, v0.h[1] // 2*P5-5*P6+5*P7
++ uxtl v2.8h, v3.8b // P5
++ mla v7.8h, v18.8h, v0.h[1] // 2*P1-5*P2+5*P3
++ sub v3.8h, v16.8h, v2.8h // P4-P5
++ mls v5.8h, v16.8h, v0.h[1] // 2*P3-5*P4
++ mls v19.8h, v1.8h, v0.h[0] // 2*P5-5*P6+5*P7-2*P8
++ abs v1.8h, v3.8h
++ sshr v3.8h, v3.8h, #8 // clip_sign
++ mls v7.8h, v16.8h, v0.h[0] // 2*P1-5*P2+5*P3-2*P4
++ sshr v1.8h, v1.8h, #1 // clip
++ mla v5.8h, v2.8h, v0.h[1] // 2*P3-5*P4+5*P5
++ srshr v17.8h, v19.8h, #3
++ mls v5.8h, v6.8h, v0.h[0] // 2*P3-5*P4+5*P5-2*P6
++ cmeq v6.8h, v1.8h, #0 // test clip == 0
++ srshr v7.8h, v7.8h, #3
++ abs v17.8h, v17.8h // a2
++ abs v7.8h, v7.8h // a1
++ srshr v5.8h, v5.8h, #3
++ cmhs v18.8h, v7.8h, v17.8h // test a1 >= a2
++ abs v19.8h, v5.8h // a0
++ sshr v5.8h, v5.8h, #8 // a0_sign
++ bsl v18.16b, v17.16b, v7.16b // a3
++ cmhs v4.8h, v19.8h, v4.8h // test a0 >= pq
++ sub v3.8h, v3.8h, v5.8h // clip_sign - a0_sign
++ uqsub v5.8h, v19.8h, v18.8h // a0 >= a3 ? a0-a3 : 0 (a0 > a3 in all cases where filtering is enabled, so makes more sense to subtract this way round than the opposite and then taking the abs)
++ cmhs v7.8h, v18.8h, v19.8h // test a3 >= a0
++ orr v4.16b, v6.16b, v4.16b // test clip == 0 || a0 >= pq
++ mul v0.8h, v5.8h, v0.h[1] // a0 >= a3 ? 5*(a0-a3) : 0
++ orr v5.16b, v4.16b, v7.16b // test clip == 0 || a0 >= pq || a3 >= a0
++ mov w2, v5.s[1] // move to gp reg
++ ushr v0.8h, v0.8h, #3 // a0 >= a3 ? (5*(a0-a3))>>3 : 0
++ mov w3, v5.s[3]
++ cmhs v5.8h, v0.8h, v1.8h
++ and w5, w2, w3
++ bsl v5.16b, v1.16b, v0.16b // FFMIN(d, clip)
++ tbnz w5, #0, 2f // none of the 8 pixel pairs should be updated in this case
++ bic v0.16b, v5.16b, v4.16b // set each d to zero if it should not be filtered because clip == 0 || a0 >= pq (a3 > a0 case already zeroed by saturating sub)
++ mla v2.8h, v0.8h, v3.8h // invert d depending on clip_sign & a0_sign, or zero it if they match, and accumulate into P5
++ mls v16.8h, v0.8h, v3.8h // invert d depending on clip_sign & a0_sign, or zero it if they match, and accumulate into P4
++ sqxtun v1.8b, v2.8h
++ sqxtun v0.8b, v16.8h
++ tbnz w2, #0, 1f // none of the first 4 pixel pairs should be updated if so
++ st2 {v0.b, v1.b}[0], [x0], x1
++ st2 {v0.b, v1.b}[1], [x0], x1
++ st2 {v0.b, v1.b}[2], [x0], x1
++ st2 {v0.b, v1.b}[3], [x0]
++1: tbnz w3, #0, 2f // none of the second 4 pixel pairs should be updated if so
++ st2 {v0.b, v1.b}[4], [x4], x1
++ st2 {v0.b, v1.b}[5], [x4], x1
++ st2 {v0.b, v1.b}[6], [x4], x1
++ st2 {v0.b, v1.b}[7], [x4]
++2: ret
++endfunc
++
++// VC-1 in-loop deblocking filter for 16 pixel pairs at boundary of vertically-neighbouring blocks
++// On entry:
++// x0 -> top-left pel of lower block
++// x1 = row stride, bytes
++// w2 = PQUANT bitstream parameter
++function ff_vc1_v_loop_filter16_neon, export=1
++ sub x3, x0, w1, sxtw #2
++ ldr d0, .Lcoeffs
++ ld1 {v1.16b}, [x0], x1 // P5
++ movi v2.2d, #0x0000ffff00000000
++ ld1 {v3.16b}, [x3], x1 // P1
++ ld1 {v4.16b}, [x3], x1 // P2
++ ld1 {v5.16b}, [x0], x1 // P6
++ ld1 {v6.16b}, [x3], x1 // P3
++ ld1 {v7.16b}, [x0], x1 // P7
++ ushll v16.8h, v1.8b, #1 // 2*P5[0..7]
++ ushll v17.8h, v3.8b, #1 // 2*P1[0..7]
++ ld1 {v18.16b}, [x3] // P4
++ uxtl v19.8h, v4.8b // P2[0..7]
++ ld1 {v20.16b}, [x0] // P8
++ uxtl v21.8h, v5.8b // P6[0..7]
++ dup v22.8h, w2 // pq
++ ushll2 v3.8h, v3.16b, #1 // 2*P1[8..15]
++ mls v17.8h, v19.8h, v0.h[1] // 2*P1[0..7]-5*P2[0..7]
++ ushll2 v19.8h, v1.16b, #1 // 2*P5[8..15]
++ uxtl2 v4.8h, v4.16b // P2[8..15]
++ mls v16.8h, v21.8h, v0.h[1] // 2*P5[0..7]-5*P6[0..7]
++ uxtl2 v5.8h, v5.16b // P6[8..15]
++ uxtl v23.8h, v6.8b // P3[0..7]
++ uxtl v24.8h, v7.8b // P7[0..7]
++ mls v3.8h, v4.8h, v0.h[1] // 2*P1[8..15]-5*P2[8..15]
++ ushll v4.8h, v6.8b, #1 // 2*P3[0..7]
++ uxtl v25.8h, v18.8b // P4[0..7]
++ mls v19.8h, v5.8h, v0.h[1] // 2*P5[8..15]-5*P6[8..15]
++ uxtl2 v26.8h, v6.16b // P3[8..15]
++ mla v17.8h, v23.8h, v0.h[1] // 2*P1[0..7]-5*P2[0..7]+5*P3[0..7]
++ uxtl2 v7.8h, v7.16b // P7[8..15]
++ ushll2 v6.8h, v6.16b, #1 // 2*P3[8..15]
++ mla v16.8h, v24.8h, v0.h[1] // 2*P5[0..7]-5*P6[0..7]+5*P7[0..7]
++ uxtl2 v18.8h, v18.16b // P4[8..15]
++ uxtl v23.8h, v20.8b // P8[0..7]
++ mls v4.8h, v25.8h, v0.h[1] // 2*P3[0..7]-5*P4[0..7]
++ uxtl v24.8h, v1.8b // P5[0..7]
++ uxtl2 v20.8h, v20.16b // P8[8..15]
++ mla v3.8h, v26.8h, v0.h[1] // 2*P1[8..15]-5*P2[8..15]+5*P3[8..15]
++ uxtl2 v1.8h, v1.16b // P5[8..15]
++ sub v26.8h, v25.8h, v24.8h // P4[0..7]-P5[0..7]
++ mla v19.8h, v7.8h, v0.h[1] // 2*P5[8..15]-5*P6[8..15]+5*P7[8..15]
++ sub v7.8h, v18.8h, v1.8h // P4[8..15]-P5[8..15]
++ mls v6.8h, v18.8h, v0.h[1] // 2*P3[8..15]-5*P4[8..15]
++ abs v27.8h, v26.8h
++ sshr v26.8h, v26.8h, #8 // clip_sign[0..7]
++ mls v17.8h, v25.8h, v0.h[0] // 2*P1[0..7]-5*P2[0..7]+5*P3[0..7]-2*P4[0..7]
++ abs v28.8h, v7.8h
++ sshr v27.8h, v27.8h, #1 // clip[0..7]
++ mls v16.8h, v23.8h, v0.h[0] // 2*P5[0..7]-5*P6[0..7]+5*P7[0..7]-2*P8[0..7]
++ sshr v7.8h, v7.8h, #8 // clip_sign[8..15]
++ sshr v23.8h, v28.8h, #1 // clip[8..15]
++ mla v4.8h, v24.8h, v0.h[1] // 2*P3[0..7]-5*P4[0..7]+5*P5[0..7]
++ cmeq v28.8h, v27.8h, #0 // test clip[0..7] == 0
++ srshr v17.8h, v17.8h, #3
++ mls v3.8h, v18.8h, v0.h[0] // 2*P1[8..15]-5*P2[8..15]+5*P3[8..15]-2*P4[8..15]
++ cmeq v29.8h, v23.8h, #0 // test clip[8..15] == 0
++ srshr v16.8h, v16.8h, #3
++ mls v19.8h, v20.8h, v0.h[0] // 2*P5[8..15]-5*P6[8..15]+5*P7[8..15]-2*P8[8..15]
++ abs v17.8h, v17.8h // a1[0..7]
++ mla v6.8h, v1.8h, v0.h[1] // 2*P3[8..15]-5*P4[8..15]+5*P5[8..15]
++ srshr v3.8h, v3.8h, #3
++ mls v4.8h, v21.8h, v0.h[0] // 2*P3[0..7]-5*P4[0..7]+5*P5[0..7]-2*P6[0..7]
++ abs v16.8h, v16.8h // a2[0..7]
++ srshr v19.8h, v19.8h, #3
++ mls v6.8h, v5.8h, v0.h[0] // 2*P3[8..15]-5*P4[8..15]+5*P5[8..15]-2*P6[8..15]
++ cmhs v5.8h, v17.8h, v16.8h // test a1[0..7] >= a2[0..7]
++ abs v3.8h, v3.8h // a1[8..15]
++ srshr v4.8h, v4.8h, #3
++ abs v19.8h, v19.8h // a2[8..15]
++ bsl v5.16b, v16.16b, v17.16b // a3[0..7]
++ srshr v6.8h, v6.8h, #3
++ cmhs v16.8h, v3.8h, v19.8h // test a1[8..15] >= a2[8.15]
++ abs v17.8h, v4.8h // a0[0..7]
++ sshr v4.8h, v4.8h, #8 // a0_sign[0..7]
++ bsl v16.16b, v19.16b, v3.16b // a3[8..15]
++ uqsub v3.8h, v17.8h, v5.8h // a0[0..7] >= a3[0..7] ? a0[0..7]-a3[0..7] : 0 (a0 > a3 in all cases where filtering is enabled, so makes more sense to subtract this way round than the opposite and then taking the abs)
++ abs v19.8h, v6.8h // a0[8..15]
++ cmhs v20.8h, v17.8h, v22.8h // test a0[0..7] >= pq
++ cmhs v5.8h, v5.8h, v17.8h // test a3[0..7] >= a0[0..7]
++ sub v4.8h, v26.8h, v4.8h // clip_sign[0..7] - a0_sign[0..7]
++ sshr v6.8h, v6.8h, #8 // a0_sign[8..15]
++ mul v3.8h, v3.8h, v0.h[1] // a0[0..7] >= a3[0..7] ? 5*(a0[0..7]-a3[0..7]) : 0
++ uqsub v17.8h, v19.8h, v16.8h // a0[8..15] >= a3[8..15] ? a0[8..15]-a3[8..15] : 0 (a0 > a3 in all cases where filtering is enabled, so makes more sense to subtract this way round than the opposite and then taking the abs)
++ orr v20.16b, v28.16b, v20.16b // test clip[0..7] == 0 || a0[0..7] >= pq
++ cmhs v21.8h, v19.8h, v22.8h // test a0[8..15] >= pq
++ cmhs v16.8h, v16.8h, v19.8h // test a3[8..15] >= a0[8..15]
++ mul v0.8h, v17.8h, v0.h[1] // a0[8..15] >= a3[8..15] ? 5*(a0[8..15]-a3[8..15]) : 0
++ sub v6.8h, v7.8h, v6.8h // clip_sign[8..15] - a0_sign[8..15]
++ orr v5.16b, v20.16b, v5.16b // test clip[0..7] == 0 || a0[0..7] >= pq || a3[0..7] >= a0[0..7]
++ ushr v3.8h, v3.8h, #3 // a0[0..7] >= a3[0..7] ? (5*(a0[0..7]-a3[0..7]))>>3 : 0
++ orr v7.16b, v29.16b, v21.16b // test clip[8..15] == 0 || a0[8..15] >= pq
++ cmtst v17.2d, v5.2d, v2.2d // if 2nd of each group of is not filtered, then none of the others in the group should be either
++ mov w0, v5.s[1] // move to gp reg
++ cmhs v19.8h, v3.8h, v27.8h
++ ushr v0.8h, v0.8h, #3 // a0[8..15] >= a3[8..15] ? (5*(a0[8..15]-a3[8..15]))>>3 : 0
++ mov w2, v5.s[3]
++ orr v5.16b, v7.16b, v16.16b // test clip[8..15] == 0 || a0[8..15] >= pq || a3[8..15] >= a0[8..15]
++ orr v16.16b, v20.16b, v17.16b
++ bsl v19.16b, v27.16b, v3.16b // FFMIN(d[0..7], clip[0..7])
++ cmtst v2.2d, v5.2d, v2.2d
++ cmhs v3.8h, v0.8h, v23.8h
++ mov w4, v5.s[1]
++ mov w5, v5.s[3]
++ and w0, w0, w2
++ bic v5.16b, v19.16b, v16.16b // set each d[0..7] to zero if it should not be filtered because clip[0..7] == 0 || a0[0..7] >= pq (a3 > a0 case already zeroed by saturating sub)
++ orr v2.16b, v7.16b, v2.16b
++ bsl v3.16b, v23.16b, v0.16b // FFMIN(d[8..15], clip[8..15])
++ mls v25.8h, v5.8h, v4.8h // invert d[0..7] depending on clip_sign[0..7] & a0_sign[0..7], or zero it if they match, and accumulate into P4[0..7]
++ and w2, w4, w5
++ bic v0.16b, v3.16b, v2.16b // set each d[8..15] to zero if it should not be filtered because clip[8..15] == 0 || a0[8..15] >= pq (a3 > a0 case already zeroed by saturating sub)
++ mla v24.8h, v5.8h, v4.8h // invert d[0..7] depending on clip_sign[0..7] & a0_sign[0..7], or zero it if they match, and accumulate into P5[0..7]
++ and w0, w0, w2
++ mls v18.8h, v0.8h, v6.8h // invert d[8..15] depending on clip_sign[8..15] & a0_sign[8..15], or zero it if they match, and accumulate into P4[8..15]
++ sqxtun v2.8b, v25.8h
++ tbnz w0, #0, 1f // none of the 16 pixel pairs should be updated in this case
++ mla v1.8h, v0.8h, v6.8h // invert d[8..15] depending on clip_sign[8..15] & a0_sign[8..15], or zero it if they match, and accumulate into P5[8..15]
++ sqxtun v0.8b, v24.8h
++ sqxtun2 v2.16b, v18.8h
++ sqxtun2 v0.16b, v1.8h
++ st1 {v2.16b}, [x3], x1
++ st1 {v0.16b}, [x3]
++1: ret
++endfunc
++
++// VC-1 in-loop deblocking filter for 16 pixel pairs at boundary of horizontally-neighbouring blocks
++// On entry:
++// x0 -> top-left pel of right block
++// x1 = row stride, bytes
++// w2 = PQUANT bitstream parameter
++function ff_vc1_h_loop_filter16_neon, export=1
++ sub x3, x0, #4 // where to start reading
++ ldr d0, .Lcoeffs
++ ld1 {v1.8b}, [x3], x1 // P1[0], P2[0]...
++ sub x0, x0, #1 // where to start writing
++ ld1 {v2.8b}, [x3], x1
++ add x4, x0, x1, lsl #3
++ ld1 {v3.8b}, [x3], x1
++ add x5, x0, x1, lsl #2
++ ld1 {v4.8b}, [x3], x1
++ add x6, x4, x1, lsl #2
++ ld1 {v5.8b}, [x3], x1
++ ld1 {v6.8b}, [x3], x1
++ ld1 {v7.8b}, [x3], x1
++ trn1 v16.8b, v1.8b, v2.8b // P1[0], P1[1], P3[0]...
++ ld1 {v17.8b}, [x3], x1
++ trn2 v1.8b, v1.8b, v2.8b // P2[0], P2[1], P4[0]...
++ ld1 {v2.8b}, [x3], x1
++ trn1 v18.8b, v3.8b, v4.8b // P1[2], P1[3], P3[2]...
++ ld1 {v19.8b}, [x3], x1
++ trn2 v3.8b, v3.8b, v4.8b // P2[2], P2[3], P4[2]...
++ ld1 {v4.8b}, [x3], x1
++ trn1 v20.8b, v5.8b, v6.8b // P1[4], P1[5], P3[4]...
++ ld1 {v21.8b}, [x3], x1
++ trn2 v5.8b, v5.8b, v6.8b // P2[4], P2[5], P4[4]...
++ ld1 {v6.8b}, [x3], x1
++ trn1 v22.8b, v7.8b, v17.8b // P1[6], P1[7], P3[6]...
++ ld1 {v23.8b}, [x3], x1
++ trn2 v7.8b, v7.8b, v17.8b // P2[6], P2[7], P4[6]...
++ ld1 {v17.8b}, [x3], x1
++ trn1 v24.8b, v2.8b, v19.8b // P1[8], P1[9], P3[8]...
++ ld1 {v25.8b}, [x3]
++ trn2 v2.8b, v2.8b, v19.8b // P2[8], P2[9], P4[8]...
++ trn1 v19.4h, v16.4h, v18.4h // P1[0], P1[1], P1[2], P1[3], P5[0]...
++ trn1 v26.8b, v4.8b, v21.8b // P1[10], P1[11], P3[10]...
++ trn2 v4.8b, v4.8b, v21.8b // P2[10], P2[11], P4[10]...
++ trn1 v21.4h, v1.4h, v3.4h // P2[0], P2[1], P2[2], P2[3], P6[0]...
++ trn1 v27.4h, v20.4h, v22.4h // P1[4], P1[5], P1[6], P1[7], P5[4]...
++ trn1 v28.8b, v6.8b, v23.8b // P1[12], P1[13], P3[12]...
++ trn2 v6.8b, v6.8b, v23.8b // P2[12], P2[13], P4[12]...
++ trn1 v23.4h, v5.4h, v7.4h // P2[4], P2[5], P2[6], P2[7], P6[4]...
++ trn1 v29.4h, v24.4h, v26.4h // P1[8], P1[9], P1[10], P1[11], P5[8]...
++ trn1 v30.8b, v17.8b, v25.8b // P1[14], P1[15], P3[14]...
++ trn2 v17.8b, v17.8b, v25.8b // P2[14], P2[15], P4[14]...
++ trn1 v25.4h, v2.4h, v4.4h // P2[8], P2[9], P2[10], P2[11], P6[8]...
++ trn1 v31.2s, v19.2s, v27.2s // P1[0..7]
++ trn2 v19.2s, v19.2s, v27.2s // P5[0..7]
++ trn1 v27.2s, v21.2s, v23.2s // P2[0..7]
++ trn2 v21.2s, v21.2s, v23.2s // P6[0..7]
++ trn1 v23.4h, v28.4h, v30.4h // P1[12], P1[13], P1[14], P1[15], P5[12]...
++ trn2 v16.4h, v16.4h, v18.4h // P3[0], P3[1], P3[2], P3[3], P7[0]...
++ trn1 v18.4h, v6.4h, v17.4h // P2[12], P2[13], P2[14], P2[15], P6[12]...
++ trn2 v20.4h, v20.4h, v22.4h // P3[4], P3[5], P3[6], P3[7], P7[4]...
++ trn2 v22.4h, v24.4h, v26.4h // P3[8], P3[9], P3[10], P3[11], P7[8]...
++ trn1 v24.2s, v29.2s, v23.2s // P1[8..15]
++ trn2 v23.2s, v29.2s, v23.2s // P5[8..15]
++ trn1 v26.2s, v25.2s, v18.2s // P2[8..15]
++ trn2 v18.2s, v25.2s, v18.2s // P6[8..15]
++ trn2 v25.4h, v28.4h, v30.4h // P3[12], P3[13], P3[14], P3[15], P7[12]...
++ trn2 v1.4h, v1.4h, v3.4h // P4[0], P4[1], P4[2], P4[3], P8[0]...
++ trn2 v3.4h, v5.4h, v7.4h // P4[4], P4[5], P4[6], P4[7], P8[4]...
++ trn2 v2.4h, v2.4h, v4.4h // P4[8], P4[9], P4[10], P4[11], P8[8]...
++ trn2 v4.4h, v6.4h, v17.4h // P4[12], P4[13], P4[14], P4[15], P8[12]...
++ ushll v5.8h, v31.8b, #1 // 2*P1[0..7]
++ ushll v6.8h, v19.8b, #1 // 2*P5[0..7]
++ trn1 v7.2s, v16.2s, v20.2s // P3[0..7]
++ uxtl v17.8h, v27.8b // P2[0..7]
++ trn2 v16.2s, v16.2s, v20.2s // P7[0..7]
++ uxtl v20.8h, v21.8b // P6[0..7]
++ trn1 v21.2s, v22.2s, v25.2s // P3[8..15]
++ ushll v24.8h, v24.8b, #1 // 2*P1[8..15]
++ trn2 v22.2s, v22.2s, v25.2s // P7[8..15]
++ ushll v25.8h, v23.8b, #1 // 2*P5[8..15]
++ trn1 v27.2s, v1.2s, v3.2s // P4[0..7]
++ uxtl v26.8h, v26.8b // P2[8..15]
++ mls v5.8h, v17.8h, v0.h[1] // 2*P1[0..7]-5*P2[0..7]
++ uxtl v17.8h, v18.8b // P6[8..15]
++ mls v6.8h, v20.8h, v0.h[1] // 2*P5[0..7]-5*P6[0..7]
++ trn1 v18.2s, v2.2s, v4.2s // P4[8..15]
++ uxtl v28.8h, v7.8b // P3[0..7]
++ mls v24.8h, v26.8h, v0.h[1] // 2*P1[8..15]-5*P2[8..15]
++ uxtl v16.8h, v16.8b // P7[0..7]
++ uxtl v26.8h, v21.8b // P3[8..15]
++ mls v25.8h, v17.8h, v0.h[1] // 2*P5[8..15]-5*P6[8..15]
++ uxtl v22.8h, v22.8b // P7[8..15]
++ ushll v7.8h, v7.8b, #1 // 2*P3[0..7]
++ uxtl v27.8h, v27.8b // P4[0..7]
++ trn2 v1.2s, v1.2s, v3.2s // P8[0..7]
++ ushll v3.8h, v21.8b, #1 // 2*P3[8..15]
++ trn2 v2.2s, v2.2s, v4.2s // P8[8..15]
++ uxtl v4.8h, v18.8b // P4[8..15]
++ mla v5.8h, v28.8h, v0.h[1] // 2*P1[0..7]-5*P2[0..7]+5*P3[0..7]
++ uxtl v1.8h, v1.8b // P8[0..7]
++ mla v6.8h, v16.8h, v0.h[1] // 2*P5[0..7]-5*P6[0..7]+5*P7[0..7]
++ uxtl v2.8h, v2.8b // P8[8..15]
++ uxtl v16.8h, v19.8b // P5[0..7]
++ mla v24.8h, v26.8h, v0.h[1] // 2*P1[8..15]-5*P2[8..15]+5*P3[8..15]
++ uxtl v18.8h, v23.8b // P5[8..15]
++ dup v19.8h, w2 // pq
++ mla v25.8h, v22.8h, v0.h[1] // 2*P5[8..15]-5*P6[8..15]+5*P7[8..15]
++ sub v21.8h, v27.8h, v16.8h // P4[0..7]-P5[0..7]
++ sub v22.8h, v4.8h, v18.8h // P4[8..15]-P5[8..15]
++ mls v7.8h, v27.8h, v0.h[1] // 2*P3[0..7]-5*P4[0..7]
++ abs v23.8h, v21.8h
++ mls v3.8h, v4.8h, v0.h[1] // 2*P3[8..15]-5*P4[8..15]
++ abs v26.8h, v22.8h
++ sshr v21.8h, v21.8h, #8 // clip_sign[0..7]
++ mls v5.8h, v27.8h, v0.h[0] // 2*P1[0..7]-5*P2[0..7]+5*P3[0..7]-2*P4[0..7]
++ sshr v23.8h, v23.8h, #1 // clip[0..7]
++ sshr v26.8h, v26.8h, #1 // clip[8..15]
++ mls v6.8h, v1.8h, v0.h[0] // 2*P5[0..7]-5*P6[0..7]+5*P7[0..7]-2*P8[0..7]
++ sshr v1.8h, v22.8h, #8 // clip_sign[8..15]
++ cmeq v22.8h, v23.8h, #0 // test clip[0..7] == 0
++ mls v24.8h, v4.8h, v0.h[0] // 2*P1[8..15]-5*P2[8..15]+5*P3[8..15]-2*P4[8..15]
++ cmeq v28.8h, v26.8h, #0 // test clip[8..15] == 0
++ srshr v5.8h, v5.8h, #3
++ mls v25.8h, v2.8h, v0.h[0] // 2*P5[8..15]-5*P6[8..15]+5*P7[8..15]-2*P8[8..15]
++ srshr v2.8h, v6.8h, #3
++ mla v7.8h, v16.8h, v0.h[1] // 2*P3[0..7]-5*P4[0..7]+5*P5[0..7]
++ srshr v6.8h, v24.8h, #3
++ mla v3.8h, v18.8h, v0.h[1] // 2*P3[8..15]-5*P4[8..15]+5*P5[8..15]
++ abs v5.8h, v5.8h // a1[0..7]
++ srshr v24.8h, v25.8h, #3
++ mls v3.8h, v17.8h, v0.h[0] // 2*P3[8..15]-5*P4[8..15]+5*P5[8..15]-2*P6[8..15]
++ abs v2.8h, v2.8h // a2[0..7]
++ abs v6.8h, v6.8h // a1[8..15]
++ mls v7.8h, v20.8h, v0.h[0] // 2*P3[0..7]-5*P4[0..7]+5*P5[0..7]-2*P6[0..7]
++ abs v17.8h, v24.8h // a2[8..15]
++ cmhs v20.8h, v5.8h, v2.8h // test a1[0..7] >= a2[0..7]
++ srshr v3.8h, v3.8h, #3
++ cmhs v24.8h, v6.8h, v17.8h // test a1[8..15] >= a2[8.15]
++ srshr v7.8h, v7.8h, #3
++ bsl v20.16b, v2.16b, v5.16b // a3[0..7]
++ abs v2.8h, v3.8h // a0[8..15]
++ sshr v3.8h, v3.8h, #8 // a0_sign[8..15]
++ bsl v24.16b, v17.16b, v6.16b // a3[8..15]
++ abs v5.8h, v7.8h // a0[0..7]
++ sshr v6.8h, v7.8h, #8 // a0_sign[0..7]
++ cmhs v7.8h, v2.8h, v19.8h // test a0[8..15] >= pq
++ sub v1.8h, v1.8h, v3.8h // clip_sign[8..15] - a0_sign[8..15]
++ uqsub v3.8h, v2.8h, v24.8h // a0[8..15] >= a3[8..15] ? a0[8..15]-a3[8..15] : 0 (a0 > a3 in all cases where filtering is enabled, so makes more sense to subtract this way round than the opposite and then taking the abs)
++ cmhs v2.8h, v24.8h, v2.8h // test a3[8..15] >= a0[8..15]
++ uqsub v17.8h, v5.8h, v20.8h // a0[0..7] >= a3[0..7] ? a0[0..7]-a3[0..7] : 0 (a0 > a3 in all cases where filtering is enabled, so makes more sense to subtract this way round than the opposite and then taking the abs)
++ cmhs v19.8h, v5.8h, v19.8h // test a0[0..7] >= pq
++ orr v7.16b, v28.16b, v7.16b // test clip[8..15] == 0 || a0[8..15] >= pq
++ sub v6.8h, v21.8h, v6.8h // clip_sign[0..7] - a0_sign[0..7]
++ mul v3.8h, v3.8h, v0.h[1] // a0[8..15] >= a3[8..15] ? 5*(a0[8..15]-a3[8..15]) : 0
++ cmhs v5.8h, v20.8h, v5.8h // test a3[0..7] >= a0[0..7]
++ orr v19.16b, v22.16b, v19.16b // test clip[0..7] == 0 || a0[0..7] >= pq
++ mul v0.8h, v17.8h, v0.h[1] // a0[0..7] >= a3[0..7] ? 5*(a0[0..7]-a3[0..7]) : 0
++ orr v2.16b, v7.16b, v2.16b // test clip[8..15] == 0 || a0[8..15] >= pq || a3[8..15] >= a0[8..15]
++ orr v5.16b, v19.16b, v5.16b // test clip[0..7] == 0 || a0[0..7] >= pq || a3[0..7] >= a0[0..7]
++ ushr v3.8h, v3.8h, #3 // a0[8..15] >= a3[8..15] ? (5*(a0[8..15]-a3[8..15]))>>3 : 0
++ mov w7, v2.s[1]
++ mov w8, v2.s[3]
++ ushr v0.8h, v0.8h, #3 // a0[0..7] >= a3[0..7] ? (5*(a0[0..7]-a3[0..7]))>>3 : 0
++ mov w2, v5.s[1] // move to gp reg
++ cmhs v2.8h, v3.8h, v26.8h
++ mov w3, v5.s[3]
++ cmhs v5.8h, v0.8h, v23.8h
++ bsl v2.16b, v26.16b, v3.16b // FFMIN(d[8..15], clip[8..15])
++ and w9, w7, w8
++ bsl v5.16b, v23.16b, v0.16b // FFMIN(d[0..7], clip[0..7])
++ and w10, w2, w3
++ bic v0.16b, v2.16b, v7.16b // set each d[8..15] to zero if it should not be filtered because clip[8..15] == 0 || a0[8..15] >= pq (a3 > a0 case already zeroed by saturating sub)
++ and w9, w10, w9
++ bic v2.16b, v5.16b, v19.16b // set each d[0..7] to zero if it should not be filtered because clip[0..7] == 0 || a0[0..7] >= pq (a3 > a0 case already zeroed by saturating sub)
++ mls v4.8h, v0.8h, v1.8h // invert d[8..15] depending on clip_sign[8..15] & a0_sign[8..15], or zero it if they match, and accumulate into P4
++ tbnz w9, #0, 4f // none of the 16 pixel pairs should be updated in this case
++ mls v27.8h, v2.8h, v6.8h // invert d[0..7] depending on clip_sign[0..7] & a0_sign[0..7], or zero it if they match, and accumulate into P4
++ mla v16.8h, v2.8h, v6.8h // invert d[0..7] depending on clip_sign[0..7] & a0_sign[0..7], or zero it if they match, and accumulate into P5
++ sqxtun v2.8b, v4.8h
++ mla v18.8h, v0.8h, v1.8h // invert d[8..15] depending on clip_sign[8..15] & a0_sign[8..15], or zero it if they match, and accumulate into P5
++ sqxtun v0.8b, v27.8h
++ sqxtun v1.8b, v16.8h
++ sqxtun v3.8b, v18.8h
++ tbnz w2, #0, 1f
++ st2 {v0.b, v1.b}[0], [x0], x1
++ st2 {v0.b, v1.b}[1], [x0], x1
++ st2 {v0.b, v1.b}[2], [x0], x1
++ st2 {v0.b, v1.b}[3], [x0]
++1: tbnz w3, #0, 2f
++ st2 {v0.b, v1.b}[4], [x5], x1
++ st2 {v0.b, v1.b}[5], [x5], x1
++ st2 {v0.b, v1.b}[6], [x5], x1
++ st2 {v0.b, v1.b}[7], [x5]
++2: tbnz w7, #0, 3f
++ st2 {v2.b, v3.b}[0], [x4], x1
++ st2 {v2.b, v3.b}[1], [x4], x1
++ st2 {v2.b, v3.b}[2], [x4], x1
++ st2 {v2.b, v3.b}[3], [x4]
++3: tbnz w8, #0, 4f
++ st2 {v2.b, v3.b}[4], [x6], x1
++ st2 {v2.b, v3.b}[5], [x6], x1
++ st2 {v2.b, v3.b}[6], [x6], x1
++ st2 {v2.b, v3.b}[7], [x6]
++4: ret
++endfunc
++
++// Copy at most the specified number of bytes from source to destination buffer,
++// stopping at a multiple of 32 bytes, none of which are the start of an escape sequence
++// On entry:
++// x0 -> source buffer
++// w1 = max number of bytes to copy
++// x2 -> destination buffer, optimally 8-byte aligned
++// On exit:
++// w0 = number of bytes not copied
++function ff_vc1_unescape_buffer_helper_neon, export=1
++ // Offset by 80 to screen out cases that are too short for us to handle,
++ // and also make it easy to test for loop termination, or to determine
++ // whether we need an odd number of half-iterations of the loop.
++ subs w1, w1, #80
++ b.mi 90f
++
++ // Set up useful constants
++ movi v20.4s, #3, lsl #24
++ movi v21.4s, #3, lsl #16
++
++ tst w1, #32
++ b.ne 1f
++
++ ld1 {v0.16b, v1.16b, v2.16b}, [x0], #48
++ ext v25.16b, v0.16b, v1.16b, #1
++ ext v26.16b, v0.16b, v1.16b, #2
++ ext v27.16b, v0.16b, v1.16b, #3
++ ext v29.16b, v1.16b, v2.16b, #1
++ ext v30.16b, v1.16b, v2.16b, #2
++ ext v31.16b, v1.16b, v2.16b, #3
++ bic v24.16b, v0.16b, v20.16b
++ bic v25.16b, v25.16b, v20.16b
++ bic v26.16b, v26.16b, v20.16b
++ bic v27.16b, v27.16b, v20.16b
++ bic v28.16b, v1.16b, v20.16b
++ bic v29.16b, v29.16b, v20.16b
++ bic v30.16b, v30.16b, v20.16b
++ bic v31.16b, v31.16b, v20.16b
++ eor v24.16b, v24.16b, v21.16b
++ eor v25.16b, v25.16b, v21.16b
++ eor v26.16b, v26.16b, v21.16b
++ eor v27.16b, v27.16b, v21.16b
++ eor v28.16b, v28.16b, v21.16b
++ eor v29.16b, v29.16b, v21.16b
++ eor v30.16b, v30.16b, v21.16b
++ eor v31.16b, v31.16b, v21.16b
++ cmeq v24.4s, v24.4s, #0
++ cmeq v25.4s, v25.4s, #0
++ cmeq v26.4s, v26.4s, #0
++ cmeq v27.4s, v27.4s, #0
++ add w1, w1, #32
++ b 3f
++
++1: ld1 {v3.16b, v4.16b, v5.16b}, [x0], #48
++ ext v25.16b, v3.16b, v4.16b, #1
++ ext v26.16b, v3.16b, v4.16b, #2
++ ext v27.16b, v3.16b, v4.16b, #3
++ ext v29.16b, v4.16b, v5.16b, #1
++ ext v30.16b, v4.16b, v5.16b, #2
++ ext v31.16b, v4.16b, v5.16b, #3
++ bic v24.16b, v3.16b, v20.16b
++ bic v25.16b, v25.16b, v20.16b
++ bic v26.16b, v26.16b, v20.16b
++ bic v27.16b, v27.16b, v20.16b
++ bic v28.16b, v4.16b, v20.16b
++ bic v29.16b, v29.16b, v20.16b
++ bic v30.16b, v30.16b, v20.16b
++ bic v31.16b, v31.16b, v20.16b
++ eor v24.16b, v24.16b, v21.16b
++ eor v25.16b, v25.16b, v21.16b
++ eor v26.16b, v26.16b, v21.16b
++ eor v27.16b, v27.16b, v21.16b
++ eor v28.16b, v28.16b, v21.16b
++ eor v29.16b, v29.16b, v21.16b
++ eor v30.16b, v30.16b, v21.16b
++ eor v31.16b, v31.16b, v21.16b
++ cmeq v24.4s, v24.4s, #0
++ cmeq v25.4s, v25.4s, #0
++ cmeq v26.4s, v26.4s, #0
++ cmeq v27.4s, v27.4s, #0
++ // Drop through...
++2: mov v0.16b, v5.16b
++ ld1 {v1.16b, v2.16b}, [x0], #32
++ cmeq v28.4s, v28.4s, #0
++ cmeq v29.4s, v29.4s, #0
++ cmeq v30.4s, v30.4s, #0
++ cmeq v31.4s, v31.4s, #0
++ orr v24.16b, v24.16b, v25.16b
++ orr v26.16b, v26.16b, v27.16b
++ orr v28.16b, v28.16b, v29.16b
++ orr v30.16b, v30.16b, v31.16b
++ ext v25.16b, v0.16b, v1.16b, #1
++ orr v22.16b, v24.16b, v26.16b
++ ext v26.16b, v0.16b, v1.16b, #2
++ ext v27.16b, v0.16b, v1.16b, #3
++ ext v29.16b, v1.16b, v2.16b, #1
++ orr v23.16b, v28.16b, v30.16b
++ ext v30.16b, v1.16b, v2.16b, #2
++ ext v31.16b, v1.16b, v2.16b, #3
++ bic v24.16b, v0.16b, v20.16b
++ bic v25.16b, v25.16b, v20.16b
++ bic v26.16b, v26.16b, v20.16b
++ orr v22.16b, v22.16b, v23.16b
++ bic v27.16b, v27.16b, v20.16b
++ bic v28.16b, v1.16b, v20.16b
++ bic v29.16b, v29.16b, v20.16b
++ bic v30.16b, v30.16b, v20.16b
++ bic v31.16b, v31.16b, v20.16b
++ addv s22, v22.4s
++ eor v24.16b, v24.16b, v21.16b
++ eor v25.16b, v25.16b, v21.16b
++ eor v26.16b, v26.16b, v21.16b
++ eor v27.16b, v27.16b, v21.16b
++ eor v28.16b, v28.16b, v21.16b
++ mov w3, v22.s[0]
++ eor v29.16b, v29.16b, v21.16b
++ eor v30.16b, v30.16b, v21.16b
++ eor v31.16b, v31.16b, v21.16b
++ cmeq v24.4s, v24.4s, #0
++ cmeq v25.4s, v25.4s, #0
++ cmeq v26.4s, v26.4s, #0
++ cmeq v27.4s, v27.4s, #0
++ cbnz w3, 90f
++ st1 {v3.16b, v4.16b}, [x2], #32
++3: mov v3.16b, v2.16b
++ ld1 {v4.16b, v5.16b}, [x0], #32
++ cmeq v28.4s, v28.4s, #0
++ cmeq v29.4s, v29.4s, #0
++ cmeq v30.4s, v30.4s, #0
++ cmeq v31.4s, v31.4s, #0
++ orr v24.16b, v24.16b, v25.16b
++ orr v26.16b, v26.16b, v27.16b
++ orr v28.16b, v28.16b, v29.16b
++ orr v30.16b, v30.16b, v31.16b
++ ext v25.16b, v3.16b, v4.16b, #1
++ orr v22.16b, v24.16b, v26.16b
++ ext v26.16b, v3.16b, v4.16b, #2
++ ext v27.16b, v3.16b, v4.16b, #3
++ ext v29.16b, v4.16b, v5.16b, #1
++ orr v23.16b, v28.16b, v30.16b
++ ext v30.16b, v4.16b, v5.16b, #2
++ ext v31.16b, v4.16b, v5.16b, #3
++ bic v24.16b, v3.16b, v20.16b
++ bic v25.16b, v25.16b, v20.16b
++ bic v26.16b, v26.16b, v20.16b
++ orr v22.16b, v22.16b, v23.16b
++ bic v27.16b, v27.16b, v20.16b
++ bic v28.16b, v4.16b, v20.16b
++ bic v29.16b, v29.16b, v20.16b
++ bic v30.16b, v30.16b, v20.16b
++ bic v31.16b, v31.16b, v20.16b
++ addv s22, v22.4s
++ eor v24.16b, v24.16b, v21.16b
++ eor v25.16b, v25.16b, v21.16b
++ eor v26.16b, v26.16b, v21.16b
++ eor v27.16b, v27.16b, v21.16b
++ eor v28.16b, v28.16b, v21.16b
++ mov w3, v22.s[0]
++ eor v29.16b, v29.16b, v21.16b
++ eor v30.16b, v30.16b, v21.16b
++ eor v31.16b, v31.16b, v21.16b
++ cmeq v24.4s, v24.4s, #0
++ cmeq v25.4s, v25.4s, #0
++ cmeq v26.4s, v26.4s, #0
++ cmeq v27.4s, v27.4s, #0
++ cbnz w3, 91f
++ st1 {v0.16b, v1.16b}, [x2], #32
++ subs w1, w1, #64
++ b.pl 2b
++
++90: add w0, w1, #80
++ ret
++
++91: sub w1, w1, #32
++ b 90b
++endfunc
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -149,6 +149,7 @@ extern AVCodec ff_hap_decoder;
@@ -448,7 +2329,7 @@ Upstream-status: Pending
@@ -890,6 +891,41 @@ static enum AVCodecID remap_deprecated_c
}
}
-
+
+static int codec_supports_format(const AVCodec * const p, const enum AVPixelFormat fmt)
+{
+ const enum AVPixelFormat *pf = p->pix_fmts;
@@ -528,7 +2409,7 @@ Upstream-status: Pending
@@ -26,83 +26,209 @@
#include "libavutil/internal.h"
#include "libavcodec/cabac.h"
-
+
+
#define get_cabac_inline get_cabac_inline_arm
static av_always_inline int get_cabac_inline_arm(CABACContext *c,
@@ -622,7 +2503,7 @@ Upstream-status: Pending
+ );
+ return bit;
+}
-
+
- __asm__ volatile(
- "ldrb %[bit] , [%[state]] \n\t"
- "add %[r_b] , %[tables] , %[lps_off] \n\t"
@@ -719,7 +2600,7 @@ Upstream-status: Pending
+#endif
+ "lsls %[range] , %[low], #16 \n\t"
+ "bne 1f \n\t"
-
+
- return bit & 1;
+ "str %[ptr] , [%[c], %[ptr_off]] \n\t"
+ "rev %[tmp] , %[tmp] \n\t"
@@ -803,7 +2684,7 @@ Upstream-status: Pending
+}
+
#endif /* HAVE_ARMV6T2_INLINE */
-
+
#endif /* AVCODEC_ARM_CABAC_H */
--- /dev/null
+++ b/libavcodec/arm/rpi_hevc_cabac.h
@@ -15211,6 +17092,883 @@ Upstream-status: Pending
+ bx lr
+
+endfunc
+--- a/libavcodec/arm/vc1dsp_init_neon.c
++++ b/libavcodec/arm/vc1dsp_init_neon.c
+@@ -19,6 +19,7 @@
+ #include <stdint.h>
+
+ #include "libavutil/attributes.h"
++#include "libavutil/intreadwrite.h"
+ #include "libavcodec/vc1dsp.h"
+ #include "vc1dsp.h"
+
+@@ -32,6 +33,13 @@ void ff_vc1_inv_trans_4x8_dc_neon(uint8_
+ void ff_vc1_inv_trans_8x4_dc_neon(uint8_t *dest, ptrdiff_t stride, int16_t *block);
+ void ff_vc1_inv_trans_4x4_dc_neon(uint8_t *dest, ptrdiff_t stride, int16_t *block);
+
++void ff_vc1_v_loop_filter4_neon(uint8_t *src, int stride, int pq);
++void ff_vc1_h_loop_filter4_neon(uint8_t *src, int stride, int pq);
++void ff_vc1_v_loop_filter8_neon(uint8_t *src, int stride, int pq);
++void ff_vc1_h_loop_filter8_neon(uint8_t *src, int stride, int pq);
++void ff_vc1_v_loop_filter16_neon(uint8_t *src, int stride, int pq);
++void ff_vc1_h_loop_filter16_neon(uint8_t *src, int stride, int pq);
++
+ void ff_put_pixels8x8_neon(uint8_t *block, const uint8_t *pixels,
+ ptrdiff_t line_size, int rnd);
+
+@@ -77,6 +85,64 @@ void ff_put_vc1_chroma_mc4_neon(uint8_t
+ void ff_avg_vc1_chroma_mc4_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride,
+ int h, int x, int y);
+
++int ff_vc1_unescape_buffer_helper_neon(const uint8_t *src, int size, uint8_t *dst);
++
++static int vc1_unescape_buffer_neon(const uint8_t *src, int size, uint8_t *dst)
++{
++ /* Dealing with starting and stopping, and removing escape bytes, are
++ * comparatively less time-sensitive, so are more clearly expressed using
++ * a C wrapper around the assembly inner loop. Note that we assume a
++ * little-endian machine that supports unaligned loads. */
++ int dsize = 0;
++ while (size >= 4)
++ {
++ int found = 0;
++ while (!found && (((uintptr_t) dst) & 7) && size >= 4)
++ {
++ found = (AV_RL32(src) &~ 0x03000000) == 0x00030000;
++ if (!found)
++ {
++ *dst++ = *src++;
++ --size;
++ ++dsize;
++ }
++ }
++ if (!found)
++ {
++ int skip = size - ff_vc1_unescape_buffer_helper_neon(src, size, dst);
++ dst += skip;
++ src += skip;
++ size -= skip;
++ dsize += skip;
++ while (!found && size >= 4)
++ {
++ found = (AV_RL32(src) &~ 0x03000000) == 0x00030000;
++ if (!found)
++ {
++ *dst++ = *src++;
++ --size;
++ ++dsize;
++ }
++ }
++ }
++ if (found)
++ {
++ *dst++ = *src++;
++ *dst++ = *src++;
++ ++src;
++ size -= 3;
++ dsize += 2;
++ }
++ }
++ while (size > 0)
++ {
++ *dst++ = *src++;
++ --size;
++ ++dsize;
++ }
++ return dsize;
++}
++
+ #define FN_ASSIGN(X, Y) \
+ dsp->put_vc1_mspel_pixels_tab[0][X+4*Y] = ff_put_vc1_mspel_mc##X##Y##_16_neon; \
+ dsp->put_vc1_mspel_pixels_tab[1][X+4*Y] = ff_put_vc1_mspel_mc##X##Y##_neon
+@@ -92,6 +158,13 @@ av_cold void ff_vc1dsp_init_neon(VC1DSPC
+ dsp->vc1_inv_trans_8x4_dc = ff_vc1_inv_trans_8x4_dc_neon;
+ dsp->vc1_inv_trans_4x4_dc = ff_vc1_inv_trans_4x4_dc_neon;
+
++ dsp->vc1_v_loop_filter4 = ff_vc1_v_loop_filter4_neon;
++ dsp->vc1_h_loop_filter4 = ff_vc1_h_loop_filter4_neon;
++ dsp->vc1_v_loop_filter8 = ff_vc1_v_loop_filter8_neon;
++ dsp->vc1_h_loop_filter8 = ff_vc1_h_loop_filter8_neon;
++ dsp->vc1_v_loop_filter16 = ff_vc1_v_loop_filter16_neon;
++ dsp->vc1_h_loop_filter16 = ff_vc1_h_loop_filter16_neon;
++
+ dsp->put_vc1_mspel_pixels_tab[1][ 0] = ff_put_pixels8x8_neon;
+ FN_ASSIGN(1, 0);
+ FN_ASSIGN(2, 0);
+@@ -116,4 +189,6 @@ av_cold void ff_vc1dsp_init_neon(VC1DSPC
+ dsp->avg_no_rnd_vc1_chroma_pixels_tab[0] = ff_avg_vc1_chroma_mc8_neon;
+ dsp->put_no_rnd_vc1_chroma_pixels_tab[1] = ff_put_vc1_chroma_mc4_neon;
+ dsp->avg_no_rnd_vc1_chroma_pixels_tab[1] = ff_avg_vc1_chroma_mc4_neon;
++
++ dsp->vc1_unescape_buffer = vc1_unescape_buffer_neon;
+ }
+--- a/libavcodec/arm/vc1dsp_neon.S
++++ b/libavcodec/arm/vc1dsp_neon.S
+@@ -1161,3 +1161,764 @@ function ff_vc1_inv_trans_4x4_dc_neon, e
+ vst1.32 {d1[1]}, [r0,:32]
+ bx lr
+ endfunc
++
++@ VC-1 in-loop deblocking filter for 4 pixel pairs at boundary of vertically-neighbouring blocks
++@ On entry:
++@ r0 -> top-left pel of lower block
++@ r1 = row stride, bytes
++@ r2 = PQUANT bitstream parameter
++function ff_vc1_v_loop_filter4_neon, export=1
++ sub r3, r0, r1, lsl #2
++ vldr d0, .Lcoeffs
++ vld1.32 {d1[0]}, [r0], r1 @ P5
++ vld1.32 {d2[0]}, [r3], r1 @ P1
++ vld1.32 {d3[0]}, [r3], r1 @ P2
++ vld1.32 {d4[0]}, [r0], r1 @ P6
++ vld1.32 {d5[0]}, [r3], r1 @ P3
++ vld1.32 {d6[0]}, [r0], r1 @ P7
++ vld1.32 {d7[0]}, [r3] @ P4
++ vld1.32 {d16[0]}, [r0] @ P8
++ vshll.u8 q9, d1, #1 @ 2*P5
++ vdup.16 d17, r2 @ pq
++ vshll.u8 q10, d2, #1 @ 2*P1
++ vmovl.u8 q11, d3 @ P2
++ vmovl.u8 q1, d4 @ P6
++ vmovl.u8 q12, d5 @ P3
++ vmls.i16 d20, d22, d0[1] @ 2*P1-5*P2
++ vmovl.u8 q11, d6 @ P7
++ vmls.i16 d18, d2, d0[1] @ 2*P5-5*P6
++ vshll.u8 q2, d5, #1 @ 2*P3
++ vmovl.u8 q3, d7 @ P4
++ vmla.i16 d18, d22, d0[1] @ 2*P5-5*P6+5*P7
++ vmovl.u8 q11, d16 @ P8
++ vmla.u16 d20, d24, d0[1] @ 2*P1-5*P2+5*P3
++ vmovl.u8 q12, d1 @ P5
++ vmls.u16 d4, d6, d0[1] @ 2*P3-5*P4
++ vmls.u16 d18, d22, d0[0] @ 2*P5-5*P6+5*P7-2*P8
++ vsub.i16 d1, d6, d24 @ P4-P5
++ vmls.i16 d20, d6, d0[0] @ 2*P1-5*P2+5*P3-2*P4
++ vmla.i16 d4, d24, d0[1] @ 2*P3-5*P4+5*P5
++ vmls.i16 d4, d2, d0[0] @ 2*P3-5*P4+5*P5-2*P6
++ vabs.s16 d2, d1
++ vrshr.s16 d3, d18, #3
++ vrshr.s16 d5, d20, #3
++ vshr.s16 d2, d2, #1 @ clip
++ vrshr.s16 d4, d4, #3
++ vabs.s16 d3, d3 @ a2
++ vshr.s16 d1, d1, #8 @ clip_sign
++ vabs.s16 d5, d5 @ a1
++ vceq.i16 d7, d2, #0 @ test clip == 0
++ vabs.s16 d16, d4 @ a0
++ vshr.s16 d4, d4, #8 @ a0_sign
++ vcge.s16 d18, d5, d3 @ test a1 >= a2
++ vcge.s16 d17, d16, d17 @ test a0 >= pq
++ vbsl d18, d3, d5 @ a3
++ vsub.i16 d1, d1, d4 @ clip_sign - a0_sign
++ vorr d3, d7, d17 @ test clip == 0 || a0 >= pq
++ vqsub.u16 d4, d16, d18 @ a0 >= a3 ? a0-a3 : 0 (a0 > a3 in all cases where filtering is enabled, so makes more sense to subtract this way round than the opposite and then taking the abs)
++ vcge.s16 d5, d18, d16 @ test a3 >= a0
++ vmul.i16 d0, d4, d0[1] @ a0 >= a3 ? 5*(a0-a3) : 0
++ vorr d4, d3, d5 @ test clip == 0 || a0 >= pq || a3 >= a0
++ vmov.32 r0, d4[1] @ move to gp reg
++ vshr.u16 d0, d0, #3 @ a0 >= a3 ? (5*(a0-a3))>>3 : 0
++ vcge.s16 d4, d0, d2
++ tst r0, #1
++ bne 1f @ none of the 4 pixel pairs should be updated if this one is not filtered
++ vbsl d4, d2, d0 @ FFMIN(d, clip)
++ vbic d0, d4, d3 @ set each d to zero if it should not be filtered because clip == 0 || a0 >= pq (a3 > a0 case already zeroed by saturating sub)
++ vmls.i16 d6, d0, d1 @ invert d depending on clip_sign & a0_sign, or zero it if they match, and accumulate into P4
++ vmla.i16 d24, d0, d1 @ invert d depending on clip_sign & a0_sign, or zero it if they match, and accumulate into P5
++ vqmovun.s16 d0, q3
++ vqmovun.s16 d1, q12
++ vst1.32 {d0[0]}, [r3], r1
++ vst1.32 {d1[0]}, [r3]
++1: bx lr
++endfunc
++
++@ VC-1 in-loop deblocking filter for 4 pixel pairs at boundary of horizontally-neighbouring blocks
++@ On entry:
++@ r0 -> top-left pel of right block
++@ r1 = row stride, bytes
++@ r2 = PQUANT bitstream parameter
++function ff_vc1_h_loop_filter4_neon, export=1
++ sub r3, r0, #4 @ where to start reading
++ vldr d0, .Lcoeffs
++ vld1.32 {d2}, [r3], r1
++ sub r0, r0, #1 @ where to start writing
++ vld1.32 {d4}, [r3], r1
++ vld1.32 {d3}, [r3], r1
++ vld1.32 {d5}, [r3]
++ vdup.16 d1, r2 @ pq
++ vtrn.8 q1, q2
++ vtrn.16 d2, d3 @ P1, P5, P3, P7
++ vtrn.16 d4, d5 @ P2, P6, P4, P8
++ vshll.u8 q3, d2, #1 @ 2*P1, 2*P5
++ vmovl.u8 q8, d4 @ P2, P6
++ vmovl.u8 q9, d3 @ P3, P7
++ vmovl.u8 q2, d5 @ P4, P8
++ vmls.i16 q3, q8, d0[1] @ 2*P1-5*P2, 2*P5-5*P6
++ vshll.u8 q10, d3, #1 @ 2*P3, 2*P7
++ vmovl.u8 q1, d2 @ P1, P5
++ vmla.i16 q3, q9, d0[1] @ 2*P1-5*P2+5*P3, 2*P5-5*P6+5*P7
++ vmls.i16 q3, q2, d0[0] @ 2*P1-5*P2+5*P3-2*P4, 2*P5-5*P6+5*P7-2*P8
++ vmov d2, d3 @ needs to be in an even-numbered vector for when we come to narrow it later
++ vmls.i16 d20, d4, d0[1] @ 2*P3-5*P4
++ vmla.i16 d20, d3, d0[1] @ 2*P3-5*P4+5*P5
++ vsub.i16 d3, d4, d2 @ P4-P5
++ vmls.i16 d20, d17, d0[0] @ 2*P3-5*P4+5*P5-2*P6
++ vrshr.s16 q3, q3, #3
++ vabs.s16 d5, d3
++ vshr.s16 d3, d3, #8 @ clip_sign
++ vrshr.s16 d16, d20, #3
++ vabs.s16 q3, q3 @ a1, a2
++ vshr.s16 d5, d5, #1 @ clip
++ vabs.s16 d17, d16 @ a0
++ vceq.i16 d18, d5, #0 @ test clip == 0
++ vshr.s16 d16, d16, #8 @ a0_sign
++ vcge.s16 d19, d6, d7 @ test a1 >= a2
++ vcge.s16 d1, d17, d1 @ test a0 >= pq
++ vsub.i16 d16, d3, d16 @ clip_sign - a0_sign
++ vbsl d19, d7, d6 @ a3
++ vorr d1, d18, d1 @ test clip == 0 || a0 >= pq
++ vqsub.u16 d3, d17, d19 @ a0 >= a3 ? a0-a3 : 0 (a0 > a3 in all cases where filtering is enabled, so makes more sense to subtract this way round than the opposite and then taking the abs)
++ vcge.s16 d6, d19, d17 @ test a3 >= a0 @
++ vmul.i16 d0, d3, d0[1] @ a0 >= a3 ? 5*(a0-a3) : 0
++ vorr d3, d1, d6 @ test clip == 0 || a0 >= pq || a3 >= a0
++ vmov.32 r2, d3[1] @ move to gp reg
++ vshr.u16 d0, d0, #3 @ a0 >= a3 ? (5*(a0-a3))>>3 : 0
++ vcge.s16 d3, d0, d5
++ tst r2, #1
++ bne 1f @ none of the 4 pixel pairs should be updated if this one is not filtered
++ vbsl d3, d5, d0 @ FFMIN(d, clip)
++ vbic d0, d3, d1 @ set each d to zero if it should not be filtered because clip == 0 || a0 >= pq (a3 > a0 case already zeroed by saturating sub)
++ vmla.i16 d2, d0, d16 @ invert d depending on clip_sign & a0_sign, or zero it if they match, and accumulate into P5
++ vmls.i16 d4, d0, d16 @ invert d depending on clip_sign & a0_sign, or zero it if they match, and accumulate into P4
++ vqmovun.s16 d1, q1
++ vqmovun.s16 d0, q2
++ vst2.8 {d0[0], d1[0]}, [r0], r1
++ vst2.8 {d0[1], d1[1]}, [r0], r1
++ vst2.8 {d0[2], d1[2]}, [r0], r1
++ vst2.8 {d0[3], d1[3]}, [r0]
++1: bx lr
++endfunc
++
++@ VC-1 in-loop deblocking filter for 8 pixel pairs at boundary of vertically-neighbouring blocks
++@ On entry:
++@ r0 -> top-left pel of lower block
++@ r1 = row stride, bytes
++@ r2 = PQUANT bitstream parameter
++function ff_vc1_v_loop_filter8_neon, export=1
++ sub r3, r0, r1, lsl #2
++ vldr d0, .Lcoeffs
++ vld1.32 {d1}, [r0 :64], r1 @ P5
++ vld1.32 {d2}, [r3 :64], r1 @ P1
++ vld1.32 {d3}, [r3 :64], r1 @ P2
++ vld1.32 {d4}, [r0 :64], r1 @ P6
++ vld1.32 {d5}, [r3 :64], r1 @ P3
++ vld1.32 {d6}, [r0 :64], r1 @ P7
++ vshll.u8 q8, d1, #1 @ 2*P5
++ vshll.u8 q9, d2, #1 @ 2*P1
++ vld1.32 {d7}, [r3 :64] @ P4
++ vmovl.u8 q1, d3 @ P2
++ vld1.32 {d20}, [r0 :64] @ P8
++ vmovl.u8 q11, d4 @ P6
++ vdup.16 q12, r2 @ pq
++ vmovl.u8 q13, d5 @ P3
++ vmls.i16 q9, q1, d0[1] @ 2*P1-5*P2
++ vmovl.u8 q1, d6 @ P7
++ vshll.u8 q2, d5, #1 @ 2*P3
++ vmls.i16 q8, q11, d0[1] @ 2*P5-5*P6
++ vmovl.u8 q3, d7 @ P4
++ vmovl.u8 q10, d20 @ P8
++ vmla.i16 q8, q1, d0[1] @ 2*P5-5*P6+5*P7
++ vmovl.u8 q1, d1 @ P5
++ vmla.i16 q9, q13, d0[1] @ 2*P1-5*P2+5*P3
++ vsub.i16 q13, q3, q1 @ P4-P5
++ vmls.i16 q2, q3, d0[1] @ 2*P3-5*P4
++ vmls.i16 q8, q10, d0[0] @ 2*P5-5*P6+5*P7-2*P8
++ vabs.s16 q10, q13
++ vshr.s16 q13, q13, #8 @ clip_sign
++ vmls.i16 q9, q3, d0[0] @ 2*P1-5*P2+5*P3-2*P4
++ vshr.s16 q10, q10, #1 @ clip
++ vmla.i16 q2, q1, d0[1] @ 2*P3-5*P4+5*P5
++ vrshr.s16 q8, q8, #3
++ vmls.i16 q2, q11, d0[0] @ 2*P3-5*P4+5*P5-2*P6
++ vceq.i16 q11, q10, #0 @ test clip == 0
++ vrshr.s16 q9, q9, #3
++ vabs.s16 q8, q8 @ a2
++ vabs.s16 q9, q9 @ a1
++ vrshr.s16 q2, q2, #3
++ vcge.s16 q14, q9, q8 @ test a1 >= a2
++ vabs.s16 q15, q2 @ a0
++ vshr.s16 q2, q2, #8 @ a0_sign
++ vbsl q14, q8, q9 @ a3
++ vcge.s16 q8, q15, q12 @ test a0 >= pq
++ vsub.i16 q2, q13, q2 @ clip_sign - a0_sign
++ vqsub.u16 q9, q15, q14 @ a0 >= a3 ? a0-a3 : 0 (a0 > a3 in all cases where filtering is enabled, so makes more sense to subtract this way round than the opposite and then taking the abs)
++ vcge.s16 q12, q14, q15 @ test a3 >= a0
++ vorr q8, q11, q8 @ test clip == 0 || a0 >= pq
++ vmul.i16 q0, q9, d0[1] @ a0 >= a3 ? 5*(a0-a3) : 0
++ vorr q9, q8, q12 @ test clip == 0 || a0 >= pq || a3 >= a0
++ vshl.i64 q11, q9, #16
++ vmov.32 r0, d18[1] @ move to gp reg
++ vshr.u16 q0, q0, #3 @ a0 >= a3 ? (5*(a0-a3))>>3 : 0
++ vmov.32 r2, d19[1]
++ vshr.s64 q9, q11, #48
++ vcge.s16 q11, q0, q10
++ vorr q8, q8, q9
++ and r0, r0, r2
++ vbsl q11, q10, q0 @ FFMIN(d, clip)
++ tst r0, #1
++ bne 1f @ none of the 8 pixel pairs should be updated in this case
++ vbic q0, q11, q8 @ set each d to zero if it should not be filtered
++ vmls.i16 q3, q0, q2 @ invert d depending on clip_sign & a0_sign, or zero it if they match, and accumulate into P4
++ vmla.i16 q1, q0, q2 @ invert d depending on clip_sign & a0_sign, or zero it if they match, and accumulate into P5
++ vqmovun.s16 d0, q3
++ vqmovun.s16 d1, q1
++ vst1.32 {d0}, [r3 :64], r1
++ vst1.32 {d1}, [r3 :64]
++1: bx lr
++endfunc
++
++.align 5
++.Lcoeffs:
++.quad 0x00050002
++
++@ VC-1 in-loop deblocking filter for 8 pixel pairs at boundary of horizontally-neighbouring blocks
++@ On entry:
++@ r0 -> top-left pel of right block
++@ r1 = row stride, bytes
++@ r2 = PQUANT bitstream parameter
++function ff_vc1_h_loop_filter8_neon, export=1
++ push {lr}
++ sub r3, r0, #4 @ where to start reading
++ vldr d0, .Lcoeffs
++ vld1.32 {d2}, [r3], r1 @ P1[0], P2[0]...
++ sub r0, r0, #1 @ where to start writing
++ vld1.32 {d4}, [r3], r1
++ add r12, r0, r1, lsl #2
++ vld1.32 {d3}, [r3], r1
++ vld1.32 {d5}, [r3], r1
++ vld1.32 {d6}, [r3], r1
++ vld1.32 {d16}, [r3], r1
++ vld1.32 {d7}, [r3], r1
++ vld1.32 {d17}, [r3]
++ vtrn.8 q1, q2 @ P1[0], P1[1], P3[0]... P1[2], P1[3], P3[2]... P2[0], P2[1], P4[0]... P2[2], P2[3], P4[2]...
++ vdup.16 q9, r2 @ pq
++ vtrn.16 d2, d3 @ P1[0], P1[1], P1[2], P1[3], P5[0]... P3[0], P3[1], P3[2], P3[3], P7[0]...
++ vtrn.16 d4, d5 @ P2[0], P2[1], P2[2], P2[3], P6[0]... P4[0], P4[1], P4[2], P4[3], P8[0]...
++ vtrn.8 q3, q8 @ P1[4], P1[5], P3[4]... P1[6], P1[7], P3[6]... P2[4], P2[5], P4[4]... P2[6], P2[7], P4[6]...
++ vtrn.16 d6, d7 @ P1[4], P1[5], P1[6], P1[7], P5[4]... P3[4], P3[5], P3[5], P3[7], P7[4]...
++ vtrn.16 d16, d17 @ P2[4], P2[5], P2[6], P2[7], P6[4]... P4[4], P4[5], P4[6], P4[7], P8[4]...
++ vtrn.32 d2, d6 @ P1, P5
++ vtrn.32 d4, d16 @ P2, P6
++ vtrn.32 d3, d7 @ P3, P7
++ vtrn.32 d5, d17 @ P4, P8
++ vshll.u8 q10, d2, #1 @ 2*P1
++ vshll.u8 q11, d6, #1 @ 2*P5
++ vmovl.u8 q12, d4 @ P2
++ vmovl.u8 q13, d16 @ P6
++ vmovl.u8 q14, d3 @ P3
++ vmls.i16 q10, q12, d0[1] @ 2*P1-5*P2
++ vmovl.u8 q12, d7 @ P7
++ vshll.u8 q1, d3, #1 @ 2*P3
++ vmls.i16 q11, q13, d0[1] @ 2*P5-5*P6
++ vmovl.u8 q2, d5 @ P4
++ vmovl.u8 q8, d17 @ P8
++ vmla.i16 q11, q12, d0[1] @ 2*P5-5*P6+5*P7
++ vmovl.u8 q3, d6 @ P5
++ vmla.i16 q10, q14, d0[1] @ 2*P1-5*P2+5*P3
++ vsub.i16 q12, q2, q3 @ P4-P5
++ vmls.i16 q1, q2, d0[1] @ 2*P3-5*P4
++ vmls.i16 q11, q8, d0[0] @ 2*P5-5*P6+5*P7-2*P8
++ vabs.s16 q8, q12
++ vshr.s16 q12, q12, #8 @ clip_sign
++ vmls.i16 q10, q2, d0[0] @ 2*P1-5*P2+5*P3-2*P4
++ vshr.s16 q8, q8, #1 @ clip
++ vmla.i16 q1, q3, d0[1] @ 2*P3-5*P4+5*P5
++ vrshr.s16 q11, q11, #3
++ vmls.i16 q1, q13, d0[0] @ 2*P3-5*P4+5*P5-2*P6
++ vceq.i16 q13, q8, #0 @ test clip == 0
++ vrshr.s16 q10, q10, #3
++ vabs.s16 q11, q11 @ a2
++ vabs.s16 q10, q10 @ a1
++ vrshr.s16 q1, q1, #3
++ vcge.s16 q14, q10, q11 @ test a1 >= a2
++ vabs.s16 q15, q1 @ a0
++ vshr.s16 q1, q1, #8 @ a0_sign
++ vbsl q14, q11, q10 @ a3
++ vcge.s16 q9, q15, q9 @ test a0 >= pq
++ vsub.i16 q1, q12, q1 @ clip_sign - a0_sign
++ vqsub.u16 q10, q15, q14 @ a0 >= a3 ? a0-a3 : 0 (a0 > a3 in all cases where filtering is enabled, so makes more sense to subtract this way round than the opposite and then taking the abs)
++ vcge.s16 q11, q14, q15 @ test a3 >= a0
++ vorr q9, q13, q9 @ test clip == 0 || a0 >= pq
++ vmul.i16 q0, q10, d0[1] @ a0 >= a3 ? 5*(a0-a3) : 0
++ vorr q10, q9, q11 @ test clip == 0 || a0 >= pq || a3 >= a0
++ vmov.32 r2, d20[1] @ move to gp reg
++ vshr.u16 q0, q0, #3 @ a0 >= a3 ? (5*(a0-a3))>>3 : 0
++ vmov.32 r3, d21[1]
++ vcge.s16 q10, q0, q8
++ and r14, r2, r3
++ vbsl q10, q8, q0 @ FFMIN(d, clip)
++ tst r14, #1
++ bne 2f @ none of the 8 pixel pairs should be updated in this case
++ vbic q0, q10, q9 @ set each d to zero if it should not be filtered because clip == 0 || a0 >= pq (a3 > a0 case already zeroed by saturating sub)
++ vmla.i16 q3, q0, q1 @ invert d depending on clip_sign & a0_sign, or zero it if they match, and accumulate into P5
++ vmls.i16 q2, q0, q1 @ invert d depending on clip_sign & a0_sign, or zero it if they match, and accumulate into P4
++ vqmovun.s16 d1, q3
++ vqmovun.s16 d0, q2
++ tst r2, #1
++ bne 1f @ none of the first 4 pixel pairs should be updated if so
++ vst2.8 {d0[0], d1[0]}, [r0], r1
++ vst2.8 {d0[1], d1[1]}, [r0], r1
++ vst2.8 {d0[2], d1[2]}, [r0], r1
++ vst2.8 {d0[3], d1[3]}, [r0]
++1: tst r3, #1
++ bne 2f @ none of the second 4 pixel pairs should be updated if so
++ vst2.8 {d0[4], d1[4]}, [r12], r1
++ vst2.8 {d0[5], d1[5]}, [r12], r1
++ vst2.8 {d0[6], d1[6]}, [r12], r1
++ vst2.8 {d0[7], d1[7]}, [r12]
++2: pop {pc}
++endfunc
++
++@ VC-1 in-loop deblocking filter for 16 pixel pairs at boundary of vertically-neighbouring blocks
++@ On entry:
++@ r0 -> top-left pel of lower block
++@ r1 = row stride, bytes
++@ r2 = PQUANT bitstream parameter
++function ff_vc1_v_loop_filter16_neon, export=1
++ vpush {d8-d15}
++ sub r3, r0, r1, lsl #2
++ vldr d0, .Lcoeffs
++ vld1.64 {q1}, [r0 :128], r1 @ P5
++ vld1.64 {q2}, [r3 :128], r1 @ P1
++ vld1.64 {q3}, [r3 :128], r1 @ P2
++ vld1.64 {q4}, [r0 :128], r1 @ P6
++ vld1.64 {q5}, [r3 :128], r1 @ P3
++ vld1.64 {q6}, [r0 :128], r1 @ P7
++ vshll.u8 q7, d2, #1 @ 2*P5[0..7]
++ vshll.u8 q8, d4, #1 @ 2*P1[0..7]
++ vld1.64 {q9}, [r3 :128] @ P4
++ vmovl.u8 q10, d6 @ P2[0..7]
++ vld1.64 {q11}, [r0 :128] @ P8
++ vmovl.u8 q12, d8 @ P6[0..7]
++ vdup.16 q13, r2 @ pq
++ vshll.u8 q2, d5, #1 @ 2*P1[8..15]
++ vmls.i16 q8, q10, d0[1] @ 2*P1[0..7]-5*P2[0..7]
++ vshll.u8 q10, d3, #1 @ 2*P5[8..15]
++ vmovl.u8 q3, d7 @ P2[8..15]
++ vmls.i16 q7, q12, d0[1] @ 2*P5[0..7]-5*P6[0..7]
++ vmovl.u8 q4, d9 @ P6[8..15]
++ vmovl.u8 q14, d10 @ P3[0..7]
++ vmovl.u8 q15, d12 @ P7[0..7]
++ vmls.i16 q2, q3, d0[1] @ 2*P1[8..15]-5*P2[8..15]
++ vshll.u8 q3, d10, #1 @ 2*P3[0..7]
++ vmls.i16 q10, q4, d0[1] @ 2*P5[8..15]-5*P6[8..15]
++ vmovl.u8 q6, d13 @ P7[8..15]
++ vmla.i16 q8, q14, d0[1] @ 2*P1[0..7]-5*P2[0..7]+5*P3[0..7]
++ vmovl.u8 q14, d18 @ P4[0..7]
++ vmovl.u8 q9, d19 @ P4[8..15]
++ vmla.i16 q7, q15, d0[1] @ 2*P5[0..7]-5*P6[0..7]+5*P7[0..7]
++ vmovl.u8 q15, d11 @ P3[8..15]
++ vshll.u8 q5, d11, #1 @ 2*P3[8..15]
++ vmls.i16 q3, q14, d0[1] @ 2*P3[0..7]-5*P4[0..7]
++ vmla.i16 q2, q15, d0[1] @ 2*P1[8..15]-5*P2[8..15]+5*P3[8..15]
++ vmovl.u8 q15, d22 @ P8[0..7]
++ vmovl.u8 q11, d23 @ P8[8..15]
++ vmla.i16 q10, q6, d0[1] @ 2*P5[8..15]-5*P6[8..15]+5*P7[8..15]
++ vmovl.u8 q6, d2 @ P5[0..7]
++ vmovl.u8 q1, d3 @ P5[8..15]
++ vmls.i16 q5, q9, d0[1] @ 2*P3[8..15]-5*P4[8..15]
++ vmls.i16 q8, q14, d0[0] @ 2*P1[0..7]-5*P2[0..7]+5*P3[0..7]-2*P4[0..7]
++ vmls.i16 q7, q15, d0[0] @ 2*P5[0..7]-5*P6[0..7]+5*P7[0..7]-2*P8[0..7]
++ vsub.i16 q15, q14, q6 @ P4[0..7]-P5[0..7]
++ vmla.i16 q3, q6, d0[1] @ 2*P3[0..7]-5*P4[0..7]+5*P5[0..7]
++ vrshr.s16 q8, q8, #3
++ vmls.i16 q2, q9, d0[0] @ 2*P1[8..15]-5*P2[8..15]+5*P3[8..15]-2*P4[8..15]
++ vrshr.s16 q7, q7, #3
++ vmls.i16 q10, q11, d0[0] @ 2*P5[8..15]-5*P6[8..15]+5*P7[8..15]-2*P8[8..15]
++ vabs.s16 q11, q15
++ vabs.s16 q8, q8 @ a1[0..7]
++ vmla.i16 q5, q1, d0[1] @ 2*P3[8..15]-5*P4[8..15]+5*P5[8..15]
++ vshr.s16 q15, q15, #8 @ clip_sign[0..7]
++ vrshr.s16 q2, q2, #3
++ vmls.i16 q3, q12, d0[0] @ 2*P3[0..7]-5*P4[0..7]+5*P5[0..7]-2*P6[0..7]
++ vabs.s16 q7, q7 @ a2[0..7]
++ vrshr.s16 q10, q10, #3
++ vsub.i16 q12, q9, q1 @ P4[8..15]-P5[8..15]
++ vshr.s16 q11, q11, #1 @ clip[0..7]
++ vmls.i16 q5, q4, d0[0] @ 2*P3[8..15]-5*P4[8..15]+5*P5[8..15]-2*P6[8..15]
++ vcge.s16 q4, q8, q7 @ test a1[0..7] >= a2[0..7]
++ vabs.s16 q2, q2 @ a1[8..15]
++ vrshr.s16 q3, q3, #3
++ vabs.s16 q10, q10 @ a2[8..15]
++ vbsl q4, q7, q8 @ a3[0..7]
++ vabs.s16 q7, q12
++ vshr.s16 q8, q12, #8 @ clip_sign[8..15]
++ vrshr.s16 q5, q5, #3
++ vcge.s16 q12, q2, q10 @ test a1[8..15] >= a2[8.15]
++ vshr.s16 q7, q7, #1 @ clip[8..15]
++ vbsl q12, q10, q2 @ a3[8..15]
++ vabs.s16 q2, q3 @ a0[0..7]
++ vceq.i16 q10, q11, #0 @ test clip[0..7] == 0
++ vshr.s16 q3, q3, #8 @ a0_sign[0..7]
++ vsub.i16 q3, q15, q3 @ clip_sign[0..7] - a0_sign[0..7]
++ vcge.s16 q15, q2, q13 @ test a0[0..7] >= pq
++ vorr q10, q10, q15 @ test clip[0..7] == 0 || a0[0..7] >= pq
++ vqsub.u16 q15, q2, q4 @ a0[0..7] >= a3[0..7] ? a0[0..7]-a3[0..7] : 0 (a0 > a3 in all cases where filtering is enabled, so makes more sense to subtract this way round than the opposite and then taking the abs)
++ vcge.s16 q2, q4, q2 @ test a3[0..7] >= a0[0..7]
++ vabs.s16 q4, q5 @ a0[8..15]
++ vshr.s16 q5, q5, #8 @ a0_sign[8..15]
++ vmul.i16 q15, q15, d0[1] @ a0[0..7] >= a3[0..7] ? 5*(a0[0..7]-a3[0..7]) : 0
++ vcge.s16 q13, q4, q13 @ test a0[8..15] >= pq
++ vorr q2, q10, q2 @ test clip[0..7] == 0 || a0[0..7] >= pq || a3[0..7] >= a0[0..7]
++ vsub.i16 q5, q8, q5 @ clip_sign[8..15] - a0_sign[8..15]
++ vceq.i16 q8, q7, #0 @ test clip[8..15] == 0
++ vshr.u16 q15, q15, #3 @ a0[0..7] >= a3[0..7] ? (5*(a0[0..7]-a3[0..7]))>>3 : 0
++ vmov.32 r0, d4[1] @ move to gp reg
++ vorr q8, q8, q13 @ test clip[8..15] == 0 || a0[8..15] >= pq
++ vqsub.u16 q13, q4, q12 @ a0[8..15] >= a3[8..15] ? a0[8..15]-a3[8..15] : 0 (a0 > a3 in all cases where filtering is enabled, so makes more sense to subtract this way round than the opposite and then taking the abs)
++ vmov.32 r2, d5[1]
++ vcge.s16 q4, q12, q4 @ test a3[8..15] >= a0[8..15]
++ vshl.i64 q2, q2, #16
++ vcge.s16 q12, q15, q11
++ vmul.i16 q0, q13, d0[1] @ a0[8..15] >= a3[8..15] ? 5*(a0[8..15]-a3[8..15]) : 0
++ vorr q4, q8, q4 @ test clip[8..15] == 0 || a0[8..15] >= pq || a3[8..15] >= a0[8..15]
++ vshr.s64 q2, q2, #48
++ and r0, r0, r2
++ vbsl q12, q11, q15 @ FFMIN(d[0..7], clip[0..7])
++ vshl.i64 q11, q4, #16
++ vmov.32 r2, d8[1]
++ vshr.u16 q0, q0, #3 @ a0[8..15] >= a3[8..15] ? (5*(a0[8..15]-a3[8..15]))>>3 : 0
++ vorr q2, q10, q2
++ vmov.32 r12, d9[1]
++ vshr.s64 q4, q11, #48
++ vcge.s16 q10, q0, q7
++ vbic q2, q12, q2 @ set each d[0..7] to zero if it should not be filtered because clip[0..7] == 0 || a0[0..7] >= pq (a3 > a0 case already zeroed by saturating sub)
++ vorr q4, q8, q4
++ and r2, r2, r12
++ vbsl q10, q7, q0 @ FFMIN(d[8..15], clip[8..15])
++ vmls.i16 q14, q2, q3 @ invert d[0..7] depending on clip_sign[0..7] & a0_sign[0..7], or zero it if they match, and accumulate into P4[0..7]
++ and r0, r0, r2
++ vbic q0, q10, q4 @ set each d[8..15] to zero if it should not be filtered because clip[8..15] == 0 || a0[8..15] >= pq (a3 > a0 case already zeroed by saturating sub)
++ tst r0, #1
++ bne 1f @ none of the 16 pixel pairs should be updated in this case
++ vmla.i16 q6, q2, q3 @ invert d[0..7] depending on clip_sign[0..7] & a0_sign[0..7], or zero it if they match, and accumulate into P5[0..7]
++ vmls.i16 q9, q0, q5 @ invert d[8..15] depending on clip_sign[8..15] & a0_sign[8..15], or zero it if they match, and accumulate into P4[8..15]
++ vqmovun.s16 d4, q14
++ vmla.i16 q1, q0, q5 @ invert d[8..15] depending on clip_sign[8..15] & a0_sign[8..15], or zero it if they match, and accumulate into P5[8..15]
++ vqmovun.s16 d0, q6
++ vqmovun.s16 d5, q9
++ vqmovun.s16 d1, q1
++ vst1.64 {q2}, [r3 :128], r1
++ vst1.64 {q0}, [r3 :128]
++1: vpop {d8-d15}
++ bx lr
++endfunc
++
++@ VC-1 in-loop deblocking filter for 16 pixel pairs at boundary of horizontally-neighbouring blocks
++@ On entry:
++@ r0 -> top-left pel of right block
++@ r1 = row stride, bytes
++@ r2 = PQUANT bitstream parameter
++function ff_vc1_h_loop_filter16_neon, export=1
++ push {r4-r6,lr}
++ vpush {d8-d15}
++ sub r3, r0, #4 @ where to start reading
++ vldr d0, .Lcoeffs
++ vld1.32 {d2}, [r3], r1 @ P1[0], P2[0]...
++ sub r0, r0, #1 @ where to start writing
++ vld1.32 {d3}, [r3], r1
++ add r4, r0, r1, lsl #2
++ vld1.32 {d10}, [r3], r1
++ vld1.32 {d11}, [r3], r1
++ vld1.32 {d16}, [r3], r1
++ vld1.32 {d4}, [r3], r1
++ vld1.32 {d8}, [r3], r1
++ vtrn.8 d2, d3 @ P1[0], P1[1], P3[0]... P2[0], P2[1], P4[0]...
++ vld1.32 {d14}, [r3], r1
++ vld1.32 {d5}, [r3], r1
++ vtrn.8 d10, d11 @ P1[2], P1[3], P3[2]... P2[2], P2[3], P4[2]...
++ vld1.32 {d6}, [r3], r1
++ vld1.32 {d12}, [r3], r1
++ vtrn.8 d16, d4 @ P1[4], P1[5], P3[4]... P2[4], P2[5], P4[4]...
++ vld1.32 {d13}, [r3], r1
++ vtrn.16 d2, d10 @ P1[0], P1[1], P1[2], P1[3], P5[0]... P3[0], P3[1], P3[2], P3[3], P7[0]...
++ vld1.32 {d1}, [r3], r1
++ vtrn.8 d8, d14 @ P1[6], P1[7], P3[6]... P2[6], P2[7], P4[6]...
++ vld1.32 {d7}, [r3], r1
++ vtrn.16 d3, d11 @ P2[0], P2[1], P2[2], P2[3], P6[0]... P4[0], P4[1], P4[2], P4[3], P8[0]...
++ vld1.32 {d9}, [r3], r1
++ vtrn.8 d5, d6 @ P1[8], P1[9], P3[8]... P2[8], P2[9], P4[8]...
++ vld1.32 {d15}, [r3]
++ vtrn.16 d16, d8 @ P1[4], P1[5], P1[6], P1[7], P5[4]... P3[4], P3[5], P3[6], P3[7], P7[4]...
++ vtrn.16 d4, d14 @ P2[4], P2[5], P2[6], P2[7], P6[4]... P4[4], P4[5], P4[6], P4[7], P8[4]...
++ vtrn.8 d12, d13 @ P1[10], P1[11], P3[10]... P2[10], P2[11], P4[10]...
++ vdup.16 q9, r2 @ pq
++ vtrn.8 d1, d7 @ P1[12], P1[13], P3[12]... P2[12], P2[13], P4[12]...
++ vtrn.32 d2, d16 @ P1[0..7], P5[0..7]
++ vtrn.16 d5, d12 @ P1[8], P1[7], P1[10], P1[11], P5[8]... P3[8], P3[9], P3[10], P3[11], P7[8]...
++ vtrn.16 d6, d13 @ P2[8], P2[7], P2[10], P2[11], P6[8]... P4[8], P4[9], P4[10], P4[11], P8[8]...
++ vtrn.8 d9, d15 @ P1[14], P1[15], P3[14]... P2[14], P2[15], P4[14]...
++ vtrn.32 d3, d4 @ P2[0..7], P6[0..7]
++ vshll.u8 q10, d2, #1 @ 2*P1[0..7]
++ vtrn.32 d10, d8 @ P3[0..7], P7[0..7]
++ vshll.u8 q11, d16, #1 @ 2*P5[0..7]
++ vtrn.32 d11, d14 @ P4[0..7], P8[0..7]
++ vtrn.16 d1, d9 @ P1[12], P1[13], P1[14], P1[15], P5[12]... P3[12], P3[13], P3[14], P3[15], P7[12]...
++ vtrn.16 d7, d15 @ P2[12], P2[13], P2[14], P2[15], P6[12]... P4[12], P4[13], P4[14], P4[15], P8[12]...
++ vmovl.u8 q1, d3 @ P2[0..7]
++ vmovl.u8 q12, d4 @ P6[0..7]
++ vtrn.32 d5, d1 @ P1[8..15], P5[8..15]
++ vtrn.32 d6, d7 @ P2[8..15], P6[8..15]
++ vtrn.32 d12, d9 @ P3[8..15], P7[8..15]
++ vtrn.32 d13, d15 @ P4[8..15], P8[8..15]
++ vmls.i16 q10, q1, d0[1] @ 2*P1[0..7]-5*P2[0..7]
++ vmovl.u8 q1, d10 @ P3[0..7]
++ vshll.u8 q2, d5, #1 @ 2*P1[8..15]
++ vshll.u8 q13, d1, #1 @ 2*P5[8..15]
++ vmls.i16 q11, q12, d0[1] @ 2*P5[0..7]-5*P6[0..7]
++ vmovl.u8 q14, d6 @ P2[8..15]
++ vmovl.u8 q3, d7 @ P6[8..15]
++ vmovl.u8 q15, d8 @ P7[0..7]
++ vmla.i16 q10, q1, d0[1] @ 2*P1[0..7]-5*P2[0..7]+5*P3[0..7]
++ vmovl.u8 q1, d12 @ P3[8..15]
++ vmls.i16 q2, q14, d0[1] @ 2*P1[8..15]-5*P2[8..15]
++ vmovl.u8 q4, d9 @ P7[8..15]
++ vshll.u8 q14, d10, #1 @ 2*P3[0..7]
++ vmls.i16 q13, q3, d0[1] @ 2*P5[8..15]-5*P6[8..15]
++ vmovl.u8 q5, d11 @ P4[0..7]
++ vmla.i16 q11, q15, d0[1] @ 2*P5[0..7]-5*P6[0..7]+5*P7[0..7]
++ vshll.u8 q15, d12, #1 @ 2*P3[8..15]
++ vmovl.u8 q6, d13 @ P4[8..15]
++ vmla.i16 q2, q1, d0[1] @ 2*P1[8..15]-5*P2[8..15]+5*P3[8..15]
++ vmovl.u8 q1, d14 @ P8[0..7]
++ vmovl.u8 q7, d15 @ P8[8..15]
++ vmla.i16 q13, q4, d0[1] @ 2*P5[8..15]-5*P6[8..15]+5*P7[8..15]
++ vmovl.u8 q4, d16 @ P5[0..7]
++ vmovl.u8 q8, d1 @ P5[8..15]
++ vmls.i16 q14, q5, d0[1] @ 2*P3[0..7]-5*P4[0..7]
++ vmls.i16 q15, q6, d0[1] @ 2*P3[8..15]-5*P4[8..15]
++ vmls.i16 q10, q5, d0[0] @ 2*P1[0..7]-5*P2[0..7]+5*P3[0..7]-2*P4[0..7]
++ vmls.i16 q11, q1, d0[0] @ 2*P5[0..7]-5*P6[0..7]+5*P7[0..7]-2*P8[0..7]
++ vsub.i16 q1, q5, q4 @ P4[0..7]-P5[0..7]
++ vmls.i16 q2, q6, d0[0] @ 2*P1[8..15]-5*P2[8..15]+5*P3[8..15]-2*P4[8..15]
++ vrshr.s16 q10, q10, #3
++ vmls.i16 q13, q7, d0[0] @ 2*P5[8..15]-5*P6[8..15]+5*P7[8..15]-2*P8[8..15]
++ vsub.i16 q7, q6, q8 @ P4[8..15]-P5[8..15]
++ vrshr.s16 q11, q11, #3
++ vmla.s16 q14, q4, d0[1] @ 2*P3[0..7]-5*P4[0..7]+5*P5[0..7]
++ vrshr.s16 q2, q2, #3
++ vmla.i16 q15, q8, d0[1] @ 2*P3[8..15]-5*P4[8..15]+5*P5[8..15]
++ vabs.s16 q10, q10 @ a1[0..7]
++ vrshr.s16 q13, q13, #3
++ vmls.i16 q15, q3, d0[0] @ 2*P3[8..15]-5*P4[8..15]+5*P5[8..15]-2*P6[8..15]
++ vabs.s16 q3, q11 @ a2[0..7]
++ vabs.s16 q2, q2 @ a1[8..15]
++ vmls.i16 q14, q12, d0[0] @ 2*P3[0..7]-5*P4[0..7]+5*P5[0..7]-2*P6[0..7]
++ vabs.s16 q11, q1
++ vabs.s16 q12, q13 @ a2[8..15]
++ vcge.s16 q13, q10, q3 @ test a1[0..7] >= a2[0..7]
++ vshr.s16 q1, q1, #8 @ clip_sign[0..7]
++ vrshr.s16 q15, q15, #3
++ vshr.s16 q11, q11, #1 @ clip[0..7]
++ vrshr.s16 q14, q14, #3
++ vbsl q13, q3, q10 @ a3[0..7]
++ vcge.s16 q3, q2, q12 @ test a1[8..15] >= a2[8.15]
++ vabs.s16 q10, q15 @ a0[8..15]
++ vshr.s16 q15, q15, #8 @ a0_sign[8..15]
++ vbsl q3, q12, q2 @ a3[8..15]
++ vabs.s16 q2, q14 @ a0[0..7]
++ vabs.s16 q12, q7
++ vshr.s16 q7, q7, #8 @ clip_sign[8..15]
++ vshr.s16 q14, q14, #8 @ a0_sign[0..7]
++ vshr.s16 q12, q12, #1 @ clip[8..15]
++ vsub.i16 q7, q7, q15 @ clip_sign[8..15] - a0_sign[8..15]
++ vqsub.u16 q15, q10, q3 @ a0[8..15] >= a3[8..15] ? a0[8..15]-a3[8..15] : 0 (a0 > a3 in all cases where filtering is enabled, so makes more sense to subtract this way round than the opposite and then taking the abs)
++ vcge.s16 q3, q3, q10 @ test a3[8..15] >= a0[8..15]
++ vcge.s16 q10, q10, q9 @ test a0[8..15] >= pq
++ vcge.s16 q9, q2, q9 @ test a0[0..7] >= pq
++ vsub.i16 q1, q1, q14 @ clip_sign[0..7] - a0_sign[0..7]
++ vqsub.u16 q14, q2, q13 @ a0[0..7] >= a3[0..7] ? a0[0..7]-a3[0..7] : 0 (a0 > a3 in all cases where filtering is enabled, so makes more sense to subtract this way round than the opposite and then taking the abs)
++ vcge.s16 q2, q13, q2 @ test a3[0..7] >= a0[0..7]
++ vmul.i16 q13, q15, d0[1] @ a0[8..15] >= a3[8..15] ? 5*(a0[8..15]-a3[8..15]) : 0
++ vceq.i16 q15, q11, #0 @ test clip[0..7] == 0
++ vmul.i16 q0, q14, d0[1] @ a0[0..7] >= a3[0..7] ? 5*(a0[0..7]-a3[0..7]) : 0
++ vorr q9, q15, q9 @ test clip[0..7] == 0 || a0[0..7] >= pq
++ vceq.i16 q14, q12, #0 @ test clip[8..15] == 0
++ vshr.u16 q13, q13, #3 @ a0[8..15] >= a3[8..15] ? (5*(a0[8..15]-a3[8..15]))>>3 : 0
++ vorr q2, q9, q2 @ test clip[0..7] == 0 || a0[0..7] >= pq || a3[0..7] >= a0[0..7]
++ vshr.u16 q0, q0, #3 @ a0[0..7] >= a3[0..7] ? (5*(a0[0..7]-a3[0..7]))>>3 : 0
++ vorr q10, q14, q10 @ test clip[8..15] == 0 || a0[8..15] >= pq
++ vcge.s16 q14, q13, q12
++ vmov.32 r2, d4[1] @ move to gp reg
++ vorr q3, q10, q3 @ test clip[8..15] == 0 || a0[8..15] >= pq || a3[8..15] >= a0[8..15]
++ vmov.32 r3, d5[1]
++ vcge.s16 q2, q0, q11
++ vbsl q14, q12, q13 @ FFMIN(d[8..15], clip[8..15])
++ vbsl q2, q11, q0 @ FFMIN(d[0..7], clip[0..7])
++ vmov.32 r5, d6[1]
++ vbic q0, q14, q10 @ set each d[8..15] to zero if it should not be filtered because clip[8..15] == 0 || a0[8..15] >= pq (a3 > a0 case already zeroed by saturating sub)
++ vmov.32 r6, d7[1]
++ and r12, r2, r3
++ vbic q2, q2, q9 @ set each d[0..7] to zero if it should not be filtered because clip[0..7] == 0 || a0[0..7] >= pq (a3 > a0 case already zeroed by saturating sub)
++ vmls.i16 q6, q0, q7 @ invert d[8..15] depending on clip_sign[8..15] & a0_sign[8..15], or zero it if they match, and accumulate into P4
++ vmls.i16 q5, q2, q1 @ invert d[0..7] depending on clip_sign[0..7] & a0_sign[0..7], or zero it if they match, and accumulate into P4
++ and r14, r5, r6
++ vmla.i16 q4, q2, q1 @ invert d[0..7] depending on clip_sign[0..7] & a0_sign[0..7], or zero it if they match, and accumulate into P5
++ and r12, r12, r14
++ vqmovun.s16 d4, q6
++ vmla.i16 q8, q0, q7 @ invert d[8..15] depending on clip_sign[8..15] & a0_sign[8..15], or zero it if they match, and accumulate into P5
++ tst r12, #1
++ bne 4f @ none of the 16 pixel pairs should be updated in this case
++ vqmovun.s16 d2, q5
++ vqmovun.s16 d3, q4
++ vqmovun.s16 d5, q8
++ tst r2, #1
++ bne 1f
++ vst2.8 {d2[0], d3[0]}, [r0], r1
++ vst2.8 {d2[1], d3[1]}, [r0], r1
++ vst2.8 {d2[2], d3[2]}, [r0], r1
++ vst2.8 {d2[3], d3[3]}, [r0]
++1: add r0, r4, r1, lsl #2
++ tst r3, #1
++ bne 2f
++ vst2.8 {d2[4], d3[4]}, [r4], r1
++ vst2.8 {d2[5], d3[5]}, [r4], r1
++ vst2.8 {d2[6], d3[6]}, [r4], r1
++ vst2.8 {d2[7], d3[7]}, [r4]
++2: add r4, r0, r1, lsl #2
++ tst r5, #1
++ bne 3f
++ vst2.8 {d4[0], d5[0]}, [r0], r1
++ vst2.8 {d4[1], d5[1]}, [r0], r1
++ vst2.8 {d4[2], d5[2]}, [r0], r1
++ vst2.8 {d4[3], d5[3]}, [r0]
++3: tst r6, #1
++ bne 4f
++ vst2.8 {d4[4], d5[4]}, [r4], r1
++ vst2.8 {d4[5], d5[5]}, [r4], r1
++ vst2.8 {d4[6], d5[6]}, [r4], r1
++ vst2.8 {d4[7], d5[7]}, [r4]
++4: vpop {d8-d15}
++ pop {r4-r6,pc}
++endfunc
++
++@ Copy at most the specified number of bytes from source to destination buffer,
++@ stopping at a multiple of 16 bytes, none of which are the start of an escape sequence
++@ On entry:
++@ r0 -> source buffer
++@ r1 = max number of bytes to copy
++@ r2 -> destination buffer, optimally 8-byte aligned
++@ On exit:
++@ r0 = number of bytes not copied
++function ff_vc1_unescape_buffer_helper_neon, export=1
++ @ Offset by 48 to screen out cases that are too short for us to handle,
++ @ and also make it easy to test for loop termination, or to determine
++ @ whether we need an odd number of half-iterations of the loop.
++ subs r1, r1, #48
++ bmi 90f
++
++ @ Set up useful constants
++ vmov.i32 q0, #0x3000000
++ vmov.i32 q1, #0x30000
++
++ tst r1, #16
++ bne 1f
++
++ vld1.8 {q8, q9}, [r0]!
++ vbic q12, q8, q0
++ vext.8 q13, q8, q9, #1
++ vext.8 q14, q8, q9, #2
++ vext.8 q15, q8, q9, #3
++ veor q12, q12, q1
++ vbic q13, q13, q0
++ vbic q14, q14, q0
++ vbic q15, q15, q0
++ vceq.i32 q12, q12, #0
++ veor q13, q13, q1
++ veor q14, q14, q1
++ veor q15, q15, q1
++ vceq.i32 q13, q13, #0
++ vceq.i32 q14, q14, #0
++ vceq.i32 q15, q15, #0
++ add r1, r1, #16
++ b 3f
++
++1: vld1.8 {q10, q11}, [r0]!
++ vbic q12, q10, q0
++ vext.8 q13, q10, q11, #1
++ vext.8 q14, q10, q11, #2
++ vext.8 q15, q10, q11, #3
++ veor q12, q12, q1
++ vbic q13, q13, q0
++ vbic q14, q14, q0
++ vbic q15, q15, q0
++ vceq.i32 q12, q12, #0
++ veor q13, q13, q1
++ veor q14, q14, q1
++ veor q15, q15, q1
++ vceq.i32 q13, q13, #0
++ vceq.i32 q14, q14, #0
++ vceq.i32 q15, q15, #0
++ @ Drop through...
++2: vmov q8, q11
++ vld1.8 {q9}, [r0]!
++ vorr q13, q12, q13
++ vorr q15, q14, q15
++ vbic q12, q8, q0
++ vorr q3, q13, q15
++ vext.8 q13, q8, q9, #1
++ vext.8 q14, q8, q9, #2
++ vext.8 q15, q8, q9, #3
++ veor q12, q12, q1
++ vorr d6, d6, d7
++ vbic q13, q13, q0
++ vbic q14, q14, q0
++ vbic q15, q15, q0
++ vceq.i32 q12, q12, #0
++ vmov r3, r12, d6
++ veor q13, q13, q1
++ veor q14, q14, q1
++ veor q15, q15, q1
++ vceq.i32 q13, q13, #0
++ vceq.i32 q14, q14, #0
++ vceq.i32 q15, q15, #0
++ orrs r3, r3, r12
++ bne 90f
++ vst1.64 {q10}, [r2]!
++3: vmov q10, q9
++ vld1.8 {q11}, [r0]!
++ vorr q13, q12, q13
++ vorr q15, q14, q15
++ vbic q12, q10, q0
++ vorr q3, q13, q15
++ vext.8 q13, q10, q11, #1
++ vext.8 q14, q10, q11, #2
++ vext.8 q15, q10, q11, #3
++ veor q12, q12, q1
++ vorr d6, d6, d7
++ vbic q13, q13, q0
++ vbic q14, q14, q0
++ vbic q15, q15, q0
++ vceq.i32 q12, q12, #0
++ vmov r3, r12, d6
++ veor q13, q13, q1
++ veor q14, q14, q1
++ veor q15, q15, q1
++ vceq.i32 q13, q13, #0
++ vceq.i32 q14, q14, #0
++ vceq.i32 q15, q15, #0
++ orrs r3, r3, r12
++ bne 91f
++ vst1.64 {q8}, [r2]!
++ subs r1, r1, #32
++ bpl 2b
++
++90: add r0, r1, #48
++ bx lr
++
++91: sub r1, r1, #16
++ b 90b
++endfunc
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -2567,6 +2567,17 @@ typedef struct AVHWAccel {
@@ -15229,7 +17987,7 @@ Upstream-status: Pending
+ */
+ void (*abort_frame)(AVCodecContext *avctx);
} AVHWAccel;
-
+
/**
--- a/libavcodec/cabac.h
+++ b/libavcodec/cabac.h
@@ -15253,7 +18011,7 @@ Upstream-status: Pending
+++ b/libavcodec/codec.h
@@ -350,6 +350,17 @@ const AVCodec *av_codec_iterate(void **o
AVCodec *avcodec_find_decoder(enum AVCodecID id);
-
+
/**
+ * Find a registered decoder with a matching codec ID and pix_fmt.
+ * A decoder will pix_fmt set to NULL will match any fmt.
@@ -15761,12 +18519,788 @@ Upstream-status: Pending
+};
+
+#endif
+--- /dev/null
++++ b/libavcodec/hevc-ctrls-v3.h
+@@ -0,0 +1,255 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * These are the HEVC state controls for use with stateless HEVC
++ * codec drivers.
++ *
++ * It turns out that these structs are not stable yet and will undergo
++ * more changes. So keep them private until they are stable and ready to
++ * become part of the official public API.
++ */
++
++#ifndef _HEVC_CTRLS_H_
++#define _HEVC_CTRLS_H_
++
++#include <linux/videodev2.h>
++
++/* The pixel format isn't stable at the moment and will likely be renamed. */
++#define V4L2_PIX_FMT_HEVC_SLICE v4l2_fourcc('S', '2', '6', '5') /* HEVC parsed slices */
++
++#define V4L2_CID_MPEG_VIDEO_HEVC_SPS (V4L2_CID_CODEC_BASE + 1008)
++#define V4L2_CID_MPEG_VIDEO_HEVC_PPS (V4L2_CID_CODEC_BASE + 1009)
++#define V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS (V4L2_CID_CODEC_BASE + 1010)
++#define V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX (V4L2_CID_CODEC_BASE + 1011)
++#define V4L2_CID_MPEG_VIDEO_HEVC_DECODE_PARAMS (V4L2_CID_CODEC_BASE + 1012)
++#define V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE (V4L2_CID_CODEC_BASE + 1015)
++#define V4L2_CID_MPEG_VIDEO_HEVC_START_CODE (V4L2_CID_CODEC_BASE + 1016)
++
++/* enum v4l2_ctrl_type type values */
++#define V4L2_CTRL_TYPE_HEVC_SPS 0x0120
++#define V4L2_CTRL_TYPE_HEVC_PPS 0x0121
++#define V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS 0x0122
++#define V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX 0x0123
++#define V4L2_CTRL_TYPE_HEVC_DECODE_PARAMS 0x0124
++
++enum v4l2_mpeg_video_hevc_decode_mode {
++ V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED,
++ V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_FRAME_BASED,
++};
++
++enum v4l2_mpeg_video_hevc_start_code {
++ V4L2_MPEG_VIDEO_HEVC_START_CODE_NONE,
++ V4L2_MPEG_VIDEO_HEVC_START_CODE_ANNEX_B,
++};
++
++#define V4L2_HEVC_SLICE_TYPE_B 0
++#define V4L2_HEVC_SLICE_TYPE_P 1
++#define V4L2_HEVC_SLICE_TYPE_I 2
++
++#define V4L2_HEVC_SPS_FLAG_SEPARATE_COLOUR_PLANE (1ULL << 0)
++#define V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED (1ULL << 1)
++#define V4L2_HEVC_SPS_FLAG_AMP_ENABLED (1ULL << 2)
++#define V4L2_HEVC_SPS_FLAG_SAMPLE_ADAPTIVE_OFFSET (1ULL << 3)
++#define V4L2_HEVC_SPS_FLAG_PCM_ENABLED (1ULL << 4)
++#define V4L2_HEVC_SPS_FLAG_PCM_LOOP_FILTER_DISABLED (1ULL << 5)
++#define V4L2_HEVC_SPS_FLAG_LONG_TERM_REF_PICS_PRESENT (1ULL << 6)
++#define V4L2_HEVC_SPS_FLAG_SPS_TEMPORAL_MVP_ENABLED (1ULL << 7)
++#define V4L2_HEVC_SPS_FLAG_STRONG_INTRA_SMOOTHING_ENABLED (1ULL << 8)
++
++/* The controls are not stable at the moment and will likely be reworked. */
++struct v4l2_ctrl_hevc_sps {
++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Sequence parameter set */
++ __u16 pic_width_in_luma_samples;
++ __u16 pic_height_in_luma_samples;
++ __u8 bit_depth_luma_minus8;
++ __u8 bit_depth_chroma_minus8;
++ __u8 log2_max_pic_order_cnt_lsb_minus4;
++ __u8 sps_max_dec_pic_buffering_minus1;
++ __u8 sps_max_num_reorder_pics;
++ __u8 sps_max_latency_increase_plus1;
++ __u8 log2_min_luma_coding_block_size_minus3;
++ __u8 log2_diff_max_min_luma_coding_block_size;
++ __u8 log2_min_luma_transform_block_size_minus2;
++ __u8 log2_diff_max_min_luma_transform_block_size;
++ __u8 max_transform_hierarchy_depth_inter;
++ __u8 max_transform_hierarchy_depth_intra;
++ __u8 pcm_sample_bit_depth_luma_minus1;
++ __u8 pcm_sample_bit_depth_chroma_minus1;
++ __u8 log2_min_pcm_luma_coding_block_size_minus3;
++ __u8 log2_diff_max_min_pcm_luma_coding_block_size;
++ __u8 num_short_term_ref_pic_sets;
++ __u8 num_long_term_ref_pics_sps;
++ __u8 chroma_format_idc;
++ __u8 sps_max_sub_layers_minus1;
++
++ __u64 flags;
++};
++
++#define V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT_ENABLED (1ULL << 0)
++#define V4L2_HEVC_PPS_FLAG_OUTPUT_FLAG_PRESENT (1ULL << 1)
++#define V4L2_HEVC_PPS_FLAG_SIGN_DATA_HIDING_ENABLED (1ULL << 2)
++#define V4L2_HEVC_PPS_FLAG_CABAC_INIT_PRESENT (1ULL << 3)
++#define V4L2_HEVC_PPS_FLAG_CONSTRAINED_INTRA_PRED (1ULL << 4)
++#define V4L2_HEVC_PPS_FLAG_TRANSFORM_SKIP_ENABLED (1ULL << 5)
++#define V4L2_HEVC_PPS_FLAG_CU_QP_DELTA_ENABLED (1ULL << 6)
++#define V4L2_HEVC_PPS_FLAG_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT (1ULL << 7)
++#define V4L2_HEVC_PPS_FLAG_WEIGHTED_PRED (1ULL << 8)
++#define V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED (1ULL << 9)
++#define V4L2_HEVC_PPS_FLAG_TRANSQUANT_BYPASS_ENABLED (1ULL << 10)
++#define V4L2_HEVC_PPS_FLAG_TILES_ENABLED (1ULL << 11)
++#define V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED (1ULL << 12)
++#define V4L2_HEVC_PPS_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED (1ULL << 13)
++#define V4L2_HEVC_PPS_FLAG_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED (1ULL << 14)
++#define V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_OVERRIDE_ENABLED (1ULL << 15)
++#define V4L2_HEVC_PPS_FLAG_PPS_DISABLE_DEBLOCKING_FILTER (1ULL << 16)
++#define V4L2_HEVC_PPS_FLAG_LISTS_MODIFICATION_PRESENT (1ULL << 17)
++#define V4L2_HEVC_PPS_FLAG_SLICE_SEGMENT_HEADER_EXTENSION_PRESENT (1ULL << 18)
++#define V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT (1ULL << 19)
++#define V4L2_HEVC_PPS_FLAG_UNIFORM_SPACING (1ULL << 20)
++
++struct v4l2_ctrl_hevc_pps {
++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture parameter set */
++ __u8 num_extra_slice_header_bits;
++ __u8 num_ref_idx_l0_default_active_minus1;
++ __u8 num_ref_idx_l1_default_active_minus1;
++ __s8 init_qp_minus26;
++ __u8 diff_cu_qp_delta_depth;
++ __s8 pps_cb_qp_offset;
++ __s8 pps_cr_qp_offset;
++ __u8 num_tile_columns_minus1;
++ __u8 num_tile_rows_minus1;
++ __u8 column_width_minus1[20];
++ __u8 row_height_minus1[22];
++ __s8 pps_beta_offset_div2;
++ __s8 pps_tc_offset_div2;
++ __u8 log2_parallel_merge_level_minus2;
++
++ __u8 padding[4];
++ __u64 flags;
++};
++
++#define V4L2_HEVC_DPB_ENTRY_LONG_TERM_REFERENCE 0x01
++
++#define V4L2_HEVC_DPB_ENTRIES_NUM_MAX 16
++
++struct v4l2_hevc_dpb_entry {
++ __u64 timestamp;
++ __u8 flags;
++ __u8 field_pic;
++ __u16 pic_order_cnt[2];
++ __u8 padding[2];
++};
++
++struct v4l2_hevc_pred_weight_table {
++ __s8 delta_luma_weight_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
++ __s8 luma_offset_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
++ __s8 delta_chroma_weight_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2];
++ __s8 chroma_offset_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2];
++
++ __s8 delta_luma_weight_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
++ __s8 luma_offset_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
++ __s8 delta_chroma_weight_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2];
++ __s8 chroma_offset_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2];
++
++ __u8 padding[6];
++
++ __u8 luma_log2_weight_denom;
++ __s8 delta_chroma_log2_weight_denom;
++};
++
++#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_LUMA (1ULL << 0)
++#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_CHROMA (1ULL << 1)
++#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_TEMPORAL_MVP_ENABLED (1ULL << 2)
++#define V4L2_HEVC_SLICE_PARAMS_FLAG_MVD_L1_ZERO (1ULL << 3)
++#define V4L2_HEVC_SLICE_PARAMS_FLAG_CABAC_INIT (1ULL << 4)
++#define V4L2_HEVC_SLICE_PARAMS_FLAG_COLLOCATED_FROM_L0 (1ULL << 5)
++#define V4L2_HEVC_SLICE_PARAMS_FLAG_USE_INTEGER_MV (1ULL << 6)
++#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_DEBLOCKING_FILTER_DISABLED (1ULL << 7)
++#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED (1ULL << 8)
++#define V4L2_HEVC_SLICE_PARAMS_FLAG_DEPENDENT_SLICE_SEGMENT (1ULL << 9)
++
++struct v4l2_ctrl_hevc_slice_params {
++ __u32 bit_size;
++ __u32 data_bit_offset;
++
++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */
++ __u32 slice_segment_addr;
++ __u32 num_entry_point_offsets;
++
++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: NAL unit header */
++ __u8 nal_unit_type;
++ __u8 nuh_temporal_id_plus1;
++
++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */
++ __u8 slice_type;
++ __u8 colour_plane_id;
++ __u16 slice_pic_order_cnt;
++ __u8 num_ref_idx_l0_active_minus1;
++ __u8 num_ref_idx_l1_active_minus1;
++ __u8 collocated_ref_idx;
++ __u8 five_minus_max_num_merge_cand;
++ __s8 slice_qp_delta;
++ __s8 slice_cb_qp_offset;
++ __s8 slice_cr_qp_offset;
++ __s8 slice_act_y_qp_offset;
++ __s8 slice_act_cb_qp_offset;
++ __s8 slice_act_cr_qp_offset;
++ __s8 slice_beta_offset_div2;
++ __s8 slice_tc_offset_div2;
++
++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture timing SEI message */
++ __u8 pic_struct;
++
++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */
++ __u8 ref_idx_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
++ __u8 ref_idx_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
++
++ __u8 padding[5];
++
++ __u32 entry_point_offset_minus1[256];
++
++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Weighted prediction parameter */
++ struct v4l2_hevc_pred_weight_table pred_weight_table;
++
++ __u64 flags;
++};
++
++#define V4L2_HEVC_DECODE_PARAM_FLAG_IRAP_PIC 0x1
++#define V4L2_HEVC_DECODE_PARAM_FLAG_IDR_PIC 0x2
++#define V4L2_HEVC_DECODE_PARAM_FLAG_NO_OUTPUT_OF_PRIOR 0x4
++
++struct v4l2_ctrl_hevc_decode_params {
++ __s32 pic_order_cnt_val;
++ __u8 num_active_dpb_entries;
++ struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
++ __u8 num_poc_st_curr_before;
++ __u8 num_poc_st_curr_after;
++ __u8 num_poc_lt_curr;
++ __u8 poc_st_curr_before[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
++ __u8 poc_st_curr_after[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
++ __u8 poc_lt_curr[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
++ __u64 flags;
++};
++
++struct v4l2_ctrl_hevc_scaling_matrix {
++ __u8 scaling_list_4x4[6][16];
++ __u8 scaling_list_8x8[6][64];
++ __u8 scaling_list_16x16[6][64];
++ __u8 scaling_list_32x32[2][64];
++ __u8 scaling_list_dc_coef_16x16[6];
++ __u8 scaling_list_dc_coef_32x32[2];
++};
++
++/* MPEG-class control IDs specific to the Hantro driver as defined by V4L2 */
++#define V4L2_CID_CODEC_HANTRO_BASE (V4L2_CTRL_CLASS_CODEC | 0x1200)
++/*
++ * V4L2_CID_HANTRO_HEVC_SLICE_HEADER_SKIP -
++ * the number of data (in bits) to skip in the
++ * slice segment header.
++ * If non-IDR, the bits to be skipped go from syntax element "pic_output_flag"
++ * to before syntax element "slice_temporal_mvp_enabled_flag".
++ * If IDR, the skipped bits are just "pic_output_flag"
++ * (separate_colour_plane_flag is not supported).
++ */
++#define V4L2_CID_HANTRO_HEVC_SLICE_HEADER_SKIP (V4L2_CID_CODEC_HANTRO_BASE + 0)
++
++#endif
+--- /dev/null
++++ b/libavcodec/hevc-ctrls-v4.h
+@@ -0,0 +1,515 @@
++/* SPDX-License-Identifier: ((GPL-2.0+ WITH Linux-syscall-note) OR BSD-3-Clause) */
++/*
++ * Video for Linux Two controls header file
++ *
++ * Copyright (C) 1999-2012 the contributors
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * Alternatively you can redistribute this file under the terms of the
++ * BSD license as stated below:
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in
++ * the documentation and/or other materials provided with the
++ * distribution.
++ * 3. The names of its contributors may not be used to endorse or promote
++ * products derived from this software without specific prior written
++ * permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
++ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
++ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
++ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * The contents of this header was split off from videodev2.h. All control
++ * definitions should be added to this header, which is included by
++ * videodev2.h.
++ */
++
++#ifndef AVCODEC_HEVC_CTRLS_V4_H
++#define AVCODEC_HEVC_CTRLS_V4_H
++
++#include <linux/const.h>
++#include <linux/types.h>
++
++#define V4L2_CID_STATELESS_HEVC_SPS (V4L2_CID_CODEC_STATELESS_BASE + 400)
++#define V4L2_CID_STATELESS_HEVC_PPS (V4L2_CID_CODEC_STATELESS_BASE + 401)
++#define V4L2_CID_STATELESS_HEVC_SLICE_PARAMS (V4L2_CID_CODEC_STATELESS_BASE + 402)
++#define V4L2_CID_STATELESS_HEVC_SCALING_MATRIX (V4L2_CID_CODEC_STATELESS_BASE + 403)
++#define V4L2_CID_STATELESS_HEVC_DECODE_PARAMS (V4L2_CID_CODEC_STATELESS_BASE + 404)
++#define V4L2_CID_STATELESS_HEVC_DECODE_MODE (V4L2_CID_CODEC_STATELESS_BASE + 405)
++#define V4L2_CID_STATELESS_HEVC_START_CODE (V4L2_CID_CODEC_STATELESS_BASE + 406)
++#define V4L2_CID_STATELESS_HEVC_ENTRY_POINT_OFFSETS (V4L2_CID_CODEC_STATELESS_BASE + 407)
++
++enum v4l2_stateless_hevc_decode_mode {
++ V4L2_STATELESS_HEVC_DECODE_MODE_SLICE_BASED,
++ V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED,
++};
++
++enum v4l2_stateless_hevc_start_code {
++ V4L2_STATELESS_HEVC_START_CODE_NONE,
++ V4L2_STATELESS_HEVC_START_CODE_ANNEX_B,
++};
++
++#define V4L2_HEVC_SLICE_TYPE_B 0
++#define V4L2_HEVC_SLICE_TYPE_P 1
++#define V4L2_HEVC_SLICE_TYPE_I 2
++
++#define V4L2_HEVC_SPS_FLAG_SEPARATE_COLOUR_PLANE (1ULL << 0)
++#define V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED (1ULL << 1)
++#define V4L2_HEVC_SPS_FLAG_AMP_ENABLED (1ULL << 2)
++#define V4L2_HEVC_SPS_FLAG_SAMPLE_ADAPTIVE_OFFSET (1ULL << 3)
++#define V4L2_HEVC_SPS_FLAG_PCM_ENABLED (1ULL << 4)
++#define V4L2_HEVC_SPS_FLAG_PCM_LOOP_FILTER_DISABLED (1ULL << 5)
++#define V4L2_HEVC_SPS_FLAG_LONG_TERM_REF_PICS_PRESENT (1ULL << 6)
++#define V4L2_HEVC_SPS_FLAG_SPS_TEMPORAL_MVP_ENABLED (1ULL << 7)
++#define V4L2_HEVC_SPS_FLAG_STRONG_INTRA_SMOOTHING_ENABLED (1ULL << 8)
++
++/**
++ * struct v4l2_ctrl_hevc_sps - ITU-T Rec. H.265: Sequence parameter set
++ *
++ * @video_parameter_set_id: specifies the value of the
++ * vps_video_parameter_set_id of the active VPS
++ * @seq_parameter_set_id: provides an identifier for the SPS for
++ * reference by other syntax elements
++ * @pic_width_in_luma_samples: specifies the width of each decoded picture
++ * in units of luma samples
++ * @pic_height_in_luma_samples: specifies the height of each decoded picture
++ * in units of luma samples
++ * @bit_depth_luma_minus8: this value plus 8specifies the bit depth of the
++ * samples of the luma array
++ * @bit_depth_chroma_minus8: this value plus 8 specifies the bit depth of the
++ * samples of the chroma arrays
++ * @log2_max_pic_order_cnt_lsb_minus4: this value plus 4 specifies the value of
++ * the variable MaxPicOrderCntLsb
++ * @sps_max_dec_pic_buffering_minus1: this value plus 1 specifies the maximum
++ * required size of the decoded picture
++ * buffer for the codec video sequence
++ * @sps_max_num_reorder_pics: indicates the maximum allowed number of pictures
++ * @sps_max_latency_increase_plus1: not equal to 0 is used to compute the
++ * value of SpsMaxLatencyPictures array
++ * @log2_min_luma_coding_block_size_minus3: plus 3 specifies the minimum
++ * luma coding block size
++ * @log2_diff_max_min_luma_coding_block_size: specifies the difference between
++ * the maximum and minimum luma
++ * coding block size
++ * @log2_min_luma_transform_block_size_minus2: plus 2 specifies the minimum luma
++ * transform block size
++ * @log2_diff_max_min_luma_transform_block_size: specifies the difference between
++ * the maximum and minimum luma
++ * transform block size
++ * @max_transform_hierarchy_depth_inter: specifies the maximum hierarchy
++ * depth for transform units of
++ * coding units coded in inter
++ * prediction mode
++ * @max_transform_hierarchy_depth_intra: specifies the maximum hierarchy
++ * depth for transform units of
++ * coding units coded in intra
++ * prediction mode
++ * @pcm_sample_bit_depth_luma_minus1: this value plus 1 specifies the number of
++ * bits used to represent each of PCM sample
++ * values of the luma component
++ * @pcm_sample_bit_depth_chroma_minus1: this value plus 1 specifies the number
++ * of bits used to represent each of PCM
++ * sample values of the chroma components
++ * @log2_min_pcm_luma_coding_block_size_minus3: this value plus 3 specifies the
++ * minimum size of coding blocks
++ * @log2_diff_max_min_pcm_luma_coding_block_size: specifies the difference between
++ * the maximum and minimum size of
++ * coding blocks
++ * @num_short_term_ref_pic_sets: specifies the number of st_ref_pic_set()
++ * syntax structures included in the SPS
++ * @num_long_term_ref_pics_sps: specifies the number of candidate long-term
++ * reference pictures that are specified in the SPS
++ * @chroma_format_idc: specifies the chroma sampling
++ * @sps_max_sub_layers_minus1: this value plus 1 specifies the maximum number
++ * of temporal sub-layers
++ * @reserved: padding field. Should be zeroed by applications.
++ * @flags: see V4L2_HEVC_SPS_FLAG_{}
++ */
++struct v4l2_ctrl_hevc_sps {
++ __u8 video_parameter_set_id;
++ __u8 seq_parameter_set_id;
++ __u16 pic_width_in_luma_samples;
++ __u16 pic_height_in_luma_samples;
++ __u8 bit_depth_luma_minus8;
++ __u8 bit_depth_chroma_minus8;
++ __u8 log2_max_pic_order_cnt_lsb_minus4;
++ __u8 sps_max_dec_pic_buffering_minus1;
++ __u8 sps_max_num_reorder_pics;
++ __u8 sps_max_latency_increase_plus1;
++ __u8 log2_min_luma_coding_block_size_minus3;
++ __u8 log2_diff_max_min_luma_coding_block_size;
++ __u8 log2_min_luma_transform_block_size_minus2;
++ __u8 log2_diff_max_min_luma_transform_block_size;
++ __u8 max_transform_hierarchy_depth_inter;
++ __u8 max_transform_hierarchy_depth_intra;
++ __u8 pcm_sample_bit_depth_luma_minus1;
++ __u8 pcm_sample_bit_depth_chroma_minus1;
++ __u8 log2_min_pcm_luma_coding_block_size_minus3;
++ __u8 log2_diff_max_min_pcm_luma_coding_block_size;
++ __u8 num_short_term_ref_pic_sets;
++ __u8 num_long_term_ref_pics_sps;
++ __u8 chroma_format_idc;
++ __u8 sps_max_sub_layers_minus1;
++
++ __u8 reserved[6];
++ __u64 flags;
++};
++
++#define V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT_ENABLED (1ULL << 0)
++#define V4L2_HEVC_PPS_FLAG_OUTPUT_FLAG_PRESENT (1ULL << 1)
++#define V4L2_HEVC_PPS_FLAG_SIGN_DATA_HIDING_ENABLED (1ULL << 2)
++#define V4L2_HEVC_PPS_FLAG_CABAC_INIT_PRESENT (1ULL << 3)
++#define V4L2_HEVC_PPS_FLAG_CONSTRAINED_INTRA_PRED (1ULL << 4)
++#define V4L2_HEVC_PPS_FLAG_TRANSFORM_SKIP_ENABLED (1ULL << 5)
++#define V4L2_HEVC_PPS_FLAG_CU_QP_DELTA_ENABLED (1ULL << 6)
++#define V4L2_HEVC_PPS_FLAG_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT (1ULL << 7)
++#define V4L2_HEVC_PPS_FLAG_WEIGHTED_PRED (1ULL << 8)
++#define V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED (1ULL << 9)
++#define V4L2_HEVC_PPS_FLAG_TRANSQUANT_BYPASS_ENABLED (1ULL << 10)
++#define V4L2_HEVC_PPS_FLAG_TILES_ENABLED (1ULL << 11)
++#define V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED (1ULL << 12)
++#define V4L2_HEVC_PPS_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED (1ULL << 13)
++#define V4L2_HEVC_PPS_FLAG_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED (1ULL << 14)
++#define V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_OVERRIDE_ENABLED (1ULL << 15)
++#define V4L2_HEVC_PPS_FLAG_PPS_DISABLE_DEBLOCKING_FILTER (1ULL << 16)
++#define V4L2_HEVC_PPS_FLAG_LISTS_MODIFICATION_PRESENT (1ULL << 17)
++#define V4L2_HEVC_PPS_FLAG_SLICE_SEGMENT_HEADER_EXTENSION_PRESENT (1ULL << 18)
++#define V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT (1ULL << 19)
++#define V4L2_HEVC_PPS_FLAG_UNIFORM_SPACING (1ULL << 20)
++
++/**
++ * struct v4l2_ctrl_hevc_pps - ITU-T Rec. H.265: Picture parameter set
++ *
++ * @pic_parameter_set_id: identifies the PPS for reference by other
++ * syntax elements
++ * @num_extra_slice_header_bits: specifies the number of extra slice header
++ * bits that are present in the slice header RBSP
++ * for coded pictures referring to the PPS.
++ * @num_ref_idx_l0_default_active_minus1: this value plus 1 specifies the
++ * inferred value of num_ref_idx_l0_active_minus1
++ * @num_ref_idx_l1_default_active_minus1: this value plus 1 specifies the
++ * inferred value of num_ref_idx_l1_active_minus1
++ * @init_qp_minus26: this value plus 26 specifies the initial value of SliceQp Y for
++ * each slice referring to the PPS
++ * @diff_cu_qp_delta_depth: specifies the difference between the luma coding
++ * tree block size and the minimum luma coding block
++ * size of coding units that convey cu_qp_delta_abs
++ * and cu_qp_delta_sign_flag
++ * @pps_cb_qp_offset: specify the offsets to the luma quantization parameter Cb
++ * @pps_cr_qp_offset: specify the offsets to the luma quantization parameter Cr
++ * @num_tile_columns_minus1: this value plus 1 specifies the number of tile columns
++ * partitioning the picture
++ * @num_tile_rows_minus1: this value plus 1 specifies the number of tile rows partitioning
++ * the picture
++ * @column_width_minus1: this value plus 1 specifies the width of the each tile column in
++ * units of coding tree blocks
++ * @row_height_minus1: this value plus 1 specifies the height of the each tile row in
++ * units of coding tree blocks
++ * @pps_beta_offset_div2: specify the default deblocking parameter offsets for
++ * beta divided by 2
++ * @pps_tc_offset_div2: specify the default deblocking parameter offsets for tC
++ * divided by 2
++ * @log2_parallel_merge_level_minus2: this value plus 2 specifies the value of
++ * the variable Log2ParMrgLevel
++ * @reserved: padding field. Should be zeroed by applications.
++ * @flags: see V4L2_HEVC_PPS_FLAG_{}
++ */
++struct v4l2_ctrl_hevc_pps {
++ __u8 pic_parameter_set_id;
++ __u8 num_extra_slice_header_bits;
++ __u8 num_ref_idx_l0_default_active_minus1;
++ __u8 num_ref_idx_l1_default_active_minus1;
++ __s8 init_qp_minus26;
++ __u8 diff_cu_qp_delta_depth;
++ __s8 pps_cb_qp_offset;
++ __s8 pps_cr_qp_offset;
++ __u8 num_tile_columns_minus1;
++ __u8 num_tile_rows_minus1;
++ __u8 column_width_minus1[20];
++ __u8 row_height_minus1[22];
++ __s8 pps_beta_offset_div2;
++ __s8 pps_tc_offset_div2;
++ __u8 log2_parallel_merge_level_minus2;
++ __u8 reserved;
++ __u64 flags;
++};
++
++#define V4L2_HEVC_DPB_ENTRY_LONG_TERM_REFERENCE 0x01
++
++#define V4L2_HEVC_SEI_PIC_STRUCT_FRAME 0
++#define V4L2_HEVC_SEI_PIC_STRUCT_TOP_FIELD 1
++#define V4L2_HEVC_SEI_PIC_STRUCT_BOTTOM_FIELD 2
++#define V4L2_HEVC_SEI_PIC_STRUCT_TOP_BOTTOM 3
++#define V4L2_HEVC_SEI_PIC_STRUCT_BOTTOM_TOP 4
++#define V4L2_HEVC_SEI_PIC_STRUCT_TOP_BOTTOM_TOP 5
++#define V4L2_HEVC_SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM 6
++#define V4L2_HEVC_SEI_PIC_STRUCT_FRAME_DOUBLING 7
++#define V4L2_HEVC_SEI_PIC_STRUCT_FRAME_TRIPLING 8
++#define V4L2_HEVC_SEI_PIC_STRUCT_TOP_PAIRED_PREVIOUS_BOTTOM 9
++#define V4L2_HEVC_SEI_PIC_STRUCT_BOTTOM_PAIRED_PREVIOUS_TOP 10
++#define V4L2_HEVC_SEI_PIC_STRUCT_TOP_PAIRED_NEXT_BOTTOM 11
++#define V4L2_HEVC_SEI_PIC_STRUCT_BOTTOM_PAIRED_NEXT_TOP 12
++
++#define V4L2_HEVC_DPB_ENTRIES_NUM_MAX 16
++
++/**
++ * struct v4l2_hevc_dpb_entry - HEVC decoded picture buffer entry
++ *
++ * @timestamp: timestamp of the V4L2 capture buffer to use as reference.
++ * @flags: long term flag for the reference frame
++ * @field_pic: whether the reference is a field picture or a frame.
++ * @reserved: padding field. Should be zeroed by applications.
++ * @pic_order_cnt_val: the picture order count of the current picture.
++ */
++struct v4l2_hevc_dpb_entry {
++ __u64 timestamp;
++ __u8 flags;
++ __u8 field_pic;
++ __u16 reserved;
++ __s32 pic_order_cnt_val;
++};
++
++/**
++ * struct v4l2_hevc_pred_weight_table - HEVC weighted prediction parameters
++ *
++ * @delta_luma_weight_l0: the difference of the weighting factor applied
++ * to the luma prediction value for list 0
++ * @luma_offset_l0: the additive offset applied to the luma prediction value
++ * for list 0
++ * @delta_chroma_weight_l0: the difference of the weighting factor applied
++ * to the chroma prediction values for list 0
++ * @chroma_offset_l0: the difference of the additive offset applied to
++ * the chroma prediction values for list 0
++ * @delta_luma_weight_l1: the difference of the weighting factor applied
++ * to the luma prediction value for list 1
++ * @luma_offset_l1: the additive offset applied to the luma prediction value
++ * for list 1
++ * @delta_chroma_weight_l1: the difference of the weighting factor applied
++ * to the chroma prediction values for list 1
++ * @chroma_offset_l1: the difference of the additive offset applied to
++ * the chroma prediction values for list 1
++ * @luma_log2_weight_denom: the base 2 logarithm of the denominator for
++ * all luma weighting factors
++ * @delta_chroma_log2_weight_denom: the difference of the base 2 logarithm
++ * of the denominator for all chroma
++ * weighting factors
++ */
++struct v4l2_hevc_pred_weight_table {
++ __s8 delta_luma_weight_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
++ __s8 luma_offset_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
++ __s8 delta_chroma_weight_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2];
++ __s8 chroma_offset_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2];
++
++ __s8 delta_luma_weight_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
++ __s8 luma_offset_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
++ __s8 delta_chroma_weight_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2];
++ __s8 chroma_offset_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2];
++
++ __u8 luma_log2_weight_denom;
++ __s8 delta_chroma_log2_weight_denom;
++};
++
++#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_LUMA (1ULL << 0)
++#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_CHROMA (1ULL << 1)
++#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_TEMPORAL_MVP_ENABLED (1ULL << 2)
++#define V4L2_HEVC_SLICE_PARAMS_FLAG_MVD_L1_ZERO (1ULL << 3)
++#define V4L2_HEVC_SLICE_PARAMS_FLAG_CABAC_INIT (1ULL << 4)
++#define V4L2_HEVC_SLICE_PARAMS_FLAG_COLLOCATED_FROM_L0 (1ULL << 5)
++#define V4L2_HEVC_SLICE_PARAMS_FLAG_USE_INTEGER_MV (1ULL << 6)
++#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_DEBLOCKING_FILTER_DISABLED (1ULL << 7)
++#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED (1ULL << 8)
++#define V4L2_HEVC_SLICE_PARAMS_FLAG_DEPENDENT_SLICE_SEGMENT (1ULL << 9)
++
++/**
++ * struct v4l2_ctrl_hevc_slice_params - HEVC slice parameters
++ *
++ * This control is a dynamically sized 1-dimensional array,
++ * V4L2_CTRL_FLAG_DYNAMIC_ARRAY flag must be set when using it.
++ *
++ * @bit_size: size (in bits) of the current slice data
++ * @data_byte_offset: offset (in bytes) to the video data in the current slice data
++ * @num_entry_point_offsets: specifies the number of entry point offset syntax
++ * elements in the slice header.
++ * @nal_unit_type: specifies the coding type of the slice (B, P or I)
++ * @nuh_temporal_id_plus1: minus 1 specifies a temporal identifier for the NAL unit
++ * @slice_type: see V4L2_HEVC_SLICE_TYPE_{}
++ * @colour_plane_id: specifies the colour plane associated with the current slice
++ * @slice_pic_order_cnt: specifies the picture order count
++ * @num_ref_idx_l0_active_minus1: this value plus 1 specifies the maximum
++ * reference index for reference picture list 0
++ * that may be used to decode the slice
++ * @num_ref_idx_l1_active_minus1: this value plus 1 specifies the maximum
++ * reference index for reference picture list 1
++ * that may be used to decode the slice
++ * @collocated_ref_idx: specifies the reference index of the collocated picture used
++ * for temporal motion vector prediction
++ * @five_minus_max_num_merge_cand: specifies the maximum number of merging
++ * motion vector prediction candidates supported in
++ * the slice subtracted from 5
++ * @slice_qp_delta: specifies the initial value of QpY to be used for the coding
++ * blocks in the slice
++ * @slice_cb_qp_offset: specifies a difference to be added to the value of pps_cb_qp_offset
++ * @slice_cr_qp_offset: specifies a difference to be added to the value of pps_cr_qp_offset
++ * @slice_act_y_qp_offset: screen content extension parameters
++ * @slice_act_cb_qp_offset: screen content extension parameters
++ * @slice_act_cr_qp_offset: screen content extension parameters
++ * @slice_beta_offset_div2: specify the deblocking parameter offsets for beta divided by 2
++ * @slice_tc_offset_div2: specify the deblocking parameter offsets for tC divided by 2
++ * @pic_struct: indicates whether a picture should be displayed as a frame or as one or
++ * more fields
++ * @reserved0: padding field. Should be zeroed by applications.
++ * @slice_segment_addr: specifies the address of the first coding tree block in
++ * the slice segment
++ * @ref_idx_l0: the list of L0 reference elements as indices in the DPB
++ * @ref_idx_l1: the list of L1 reference elements as indices in the DPB
++ * @short_term_ref_pic_set_size: specifies the size of short-term reference
++ * pictures set included in the SPS
++ * @long_term_ref_pic_set_size: specifies the size of long-term reference
++ * pictures set include in the SPS
++ * @pred_weight_table: the prediction weight coefficients for inter-picture
++ * prediction
++ * @reserved1: padding field. Should be zeroed by applications.
++ * @flags: see V4L2_HEVC_SLICE_PARAMS_FLAG_{}
++ */
++struct v4l2_ctrl_hevc_slice_params {
++ __u32 bit_size;
++ __u32 data_byte_offset;
++ __u32 num_entry_point_offsets;
++
++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: NAL unit header */
++ __u8 nal_unit_type;
++ __u8 nuh_temporal_id_plus1;
++
++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */
++ __u8 slice_type;
++ __u8 colour_plane_id;
++ __s32 slice_pic_order_cnt;
++ __u8 num_ref_idx_l0_active_minus1;
++ __u8 num_ref_idx_l1_active_minus1;
++ __u8 collocated_ref_idx;
++ __u8 five_minus_max_num_merge_cand;
++ __s8 slice_qp_delta;
++ __s8 slice_cb_qp_offset;
++ __s8 slice_cr_qp_offset;
++ __s8 slice_act_y_qp_offset;
++ __s8 slice_act_cb_qp_offset;
++ __s8 slice_act_cr_qp_offset;
++ __s8 slice_beta_offset_div2;
++ __s8 slice_tc_offset_div2;
++
++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture timing SEI message */
++ __u8 pic_struct;
++
++ __u8 reserved0[3];
++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */
++ __u32 slice_segment_addr;
++ __u8 ref_idx_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
++ __u8 ref_idx_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
++ __u16 short_term_ref_pic_set_size;
++ __u16 long_term_ref_pic_set_size;
++
++ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Weighted prediction parameter */
++ struct v4l2_hevc_pred_weight_table pred_weight_table;
++
++ __u8 reserved1[2];
++ __u64 flags;
++};
++
++#define V4L2_HEVC_DECODE_PARAM_FLAG_IRAP_PIC 0x1
++#define V4L2_HEVC_DECODE_PARAM_FLAG_IDR_PIC 0x2
++#define V4L2_HEVC_DECODE_PARAM_FLAG_NO_OUTPUT_OF_PRIOR 0x4
++
++/**
++ * struct v4l2_ctrl_hevc_decode_params - HEVC decode parameters
++ *
++ * @pic_order_cnt_val: picture order count
++ * @short_term_ref_pic_set_size: specifies the size of short-term reference
++ * pictures set included in the SPS of the first slice
++ * @long_term_ref_pic_set_size: specifies the size of long-term reference
++ * pictures set include in the SPS of the first slice
++ * @num_active_dpb_entries: the number of entries in dpb
++ * @num_poc_st_curr_before: the number of reference pictures in the short-term
++ * set that come before the current frame
++ * @num_poc_st_curr_after: the number of reference pictures in the short-term
++ * set that come after the current frame
++ * @num_poc_lt_curr: the number of reference pictures in the long-term set
++ * @poc_st_curr_before: provides the index of the short term before references
++ * in DPB array
++ * @poc_st_curr_after: provides the index of the short term after references
++ * in DPB array
++ * @poc_lt_curr: provides the index of the long term references in DPB array
++ * @reserved: padding field. Should be zeroed by applications.
++ * @dpb: the decoded picture buffer, for meta-data about reference frames
++ * @flags: see V4L2_HEVC_DECODE_PARAM_FLAG_{}
++ */
++struct v4l2_ctrl_hevc_decode_params {
++ __s32 pic_order_cnt_val;
++ __u16 short_term_ref_pic_set_size;
++ __u16 long_term_ref_pic_set_size;
++ __u8 num_active_dpb_entries;
++ __u8 num_poc_st_curr_before;
++ __u8 num_poc_st_curr_after;
++ __u8 num_poc_lt_curr;
++ __u8 poc_st_curr_before[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
++ __u8 poc_st_curr_after[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
++ __u8 poc_lt_curr[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
++ __u8 reserved[4];
++ struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
++ __u64 flags;
++};
++
++/**
++ * struct v4l2_ctrl_hevc_scaling_matrix - HEVC scaling lists parameters
++ *
++ * @scaling_list_4x4: scaling list is used for the scaling process for
++ * transform coefficients. The values on each scaling
++ * list are expected in raster scan order
++ * @scaling_list_8x8: scaling list is used for the scaling process for
++ * transform coefficients. The values on each scaling
++ * list are expected in raster scan order
++ * @scaling_list_16x16: scaling list is used for the scaling process for
++ * transform coefficients. The values on each scaling
++ * list are expected in raster scan order
++ * @scaling_list_32x32: scaling list is used for the scaling process for
++ * transform coefficients. The values on each scaling
++ * list are expected in raster scan order
++ * @scaling_list_dc_coef_16x16: scaling list is used for the scaling process
++ * for transform coefficients. The values on each
++ * scaling list are expected in raster scan order.
++ * @scaling_list_dc_coef_32x32: scaling list is used for the scaling process
++ * for transform coefficients. The values on each
++ * scaling list are expected in raster scan order.
++ */
++struct v4l2_ctrl_hevc_scaling_matrix {
++ __u8 scaling_list_4x4[6][16];
++ __u8 scaling_list_8x8[6][64];
++ __u8 scaling_list_16x16[6][64];
++ __u8 scaling_list_32x32[2][64];
++ __u8 scaling_list_dc_coef_16x16[6];
++ __u8 scaling_list_dc_coef_32x32[2];
++};
++
++#endif
--- a/libavcodec/hevc_parser.c
+++ b/libavcodec/hevc_parser.c
@@ -98,6 +98,19 @@ static int hevc_parse_slice_header(AVCod
avctx->profile = ps->sps->ptl.general_ptl.profile_idc;
avctx->level = ps->sps->ptl.general_ptl.level_idc;
-
+
+ if (ps->sps->chroma_format_idc == 1) {
+ avctx->chroma_sample_location = ps->sps->vui.chroma_loc_info_present_flag ?
+ ps->sps->vui.chroma_sample_loc_type_top_field + 1 :
@@ -15783,12 +19317,69 @@ Upstream-status: Pending
if (ps->vps->vps_timing_info_present_flag) {
num = ps->vps->vps_num_units_in_tick;
den = ps->vps->vps_time_scale;
+--- a/libavcodec/hevc_refs.c
++++ b/libavcodec/hevc_refs.c
+@@ -96,18 +96,22 @@ static HEVCFrame *alloc_frame(HEVCContex
+ if (!frame->rpl_buf)
+ goto fail;
+
+- frame->tab_mvf_buf = av_buffer_pool_get(s->tab_mvf_pool);
+- if (!frame->tab_mvf_buf)
+- goto fail;
+- frame->tab_mvf = (MvField *)frame->tab_mvf_buf->data;
++ if (s->tab_mvf_pool) {
++ frame->tab_mvf_buf = av_buffer_pool_get(s->tab_mvf_pool);
++ if (!frame->tab_mvf_buf)
++ goto fail;
++ frame->tab_mvf = (MvField *)frame->tab_mvf_buf->data;
++ }
+
+- frame->rpl_tab_buf = av_buffer_pool_get(s->rpl_tab_pool);
+- if (!frame->rpl_tab_buf)
+- goto fail;
+- frame->rpl_tab = (RefPicListTab **)frame->rpl_tab_buf->data;
+- frame->ctb_count = s->ps.sps->ctb_width * s->ps.sps->ctb_height;
+- for (j = 0; j < frame->ctb_count; j++)
+- frame->rpl_tab[j] = (RefPicListTab *)frame->rpl_buf->data;
++ if (s->rpl_tab_pool) {
++ frame->rpl_tab_buf = av_buffer_pool_get(s->rpl_tab_pool);
++ if (!frame->rpl_tab_buf)
++ goto fail;
++ frame->rpl_tab = (RefPicListTab **)frame->rpl_tab_buf->data;
++ frame->ctb_count = s->ps.sps->ctb_width * s->ps.sps->ctb_height;
++ for (j = 0; j < frame->ctb_count; j++)
++ frame->rpl_tab[j] = (RefPicListTab *)frame->rpl_buf->data;
++ }
+
+ frame->frame->top_field_first = s->sei.picture_timing.picture_struct == AV_PICTURE_STRUCTURE_TOP_FIELD;
+ frame->frame->interlaced_frame = (s->sei.picture_timing.picture_struct == AV_PICTURE_STRUCTURE_TOP_FIELD) || (s->sei.picture_timing.picture_struct == AV_PICTURE_STRUCTURE_BOTTOM_FIELD);
+@@ -276,14 +280,17 @@ static int init_slice_rpl(HEVCContext *s
+ int ctb_count = frame->ctb_count;
+ int ctb_addr_ts = s->ps.pps->ctb_addr_rs_to_ts[s->sh.slice_segment_addr];
+ int i;
++ RefPicListTab * const tab = (RefPicListTab *)frame->rpl_buf->data + s->slice_idx;
+
+ if (s->slice_idx >= frame->rpl_buf->size / sizeof(RefPicListTab))
+ return AVERROR_INVALIDDATA;
+
+- for (i = ctb_addr_ts; i < ctb_count; i++)
+- frame->rpl_tab[i] = (RefPicListTab *)frame->rpl_buf->data + s->slice_idx;
++ if (frame->rpl_tab) {
++ for (i = ctb_addr_ts; i < ctb_count; i++)
++ frame->rpl_tab[i] = tab;
++ }
+
+- frame->refPicList = (RefPicList *)frame->rpl_tab[ctb_addr_ts];
++ frame->refPicList = tab->refPicList;
+
+ return 0;
+ }
--- a/libavcodec/hevcdec.c
+++ b/libavcodec/hevcdec.c
@@ -332,6 +332,19 @@ static void export_stream_params(HEVCCon
-
+
ff_set_sar(avctx, sps->vui.sar);
-
+
+ if (sps->chroma_format_idc == 1) {
+ avctx->chroma_sample_location = sps->vui.chroma_loc_info_present_flag ?
+ sps->vui.chroma_sample_loc_type_top_field + 1 :
@@ -15816,7 +19407,7 @@ Upstream-status: Pending
+ CONFIG_HEVC_RPI4_10_HWACCEL + \
CONFIG_HEVC_VDPAU_HWACCEL)
enum AVPixelFormat pix_fmts[HWACCEL_MAX + 2], *fmt = pix_fmts;
-
+
switch (sps->pix_fmt) {
case AV_PIX_FMT_YUV420P:
case AV_PIX_FMT_YUVJ420P:
@@ -15851,7 +19442,43 @@ Upstream-status: Pending
break;
case AV_PIX_FMT_YUV444P:
#if CONFIG_HEVC_VDPAU_HWACCEL
-@@ -3230,7 +3258,14 @@ static int hevc_decode_frame(AVCodecCont
+@@ -459,6 +487,16 @@ static int set_sps(HEVCContext *s, const
+ if (!sps)
+ return 0;
+
++ // If hwaccel then we don't need all the s/w decode helper arrays
++ if (s->avctx->hwaccel) {
++ export_stream_params(s, sps);
++
++ s->avctx->pix_fmt = pix_fmt;
++ s->ps.sps = sps;
++ s->ps.vps = (HEVCVPS*) s->ps.vps_list[s->ps.sps->vps_id]->data;
++ return 0;
++ }
++
+ ret = pic_arrays_init(s, sps);
+ if (ret < 0)
+ goto fail;
+@@ -2809,11 +2847,13 @@ static int hevc_frame_start(HEVCContext
+ ((s->ps.sps->height >> s->ps.sps->log2_min_cb_size) + 1);
+ int ret;
+
+- memset(s->horizontal_bs, 0, s->bs_width * s->bs_height);
+- memset(s->vertical_bs, 0, s->bs_width * s->bs_height);
+- memset(s->cbf_luma, 0, s->ps.sps->min_tb_width * s->ps.sps->min_tb_height);
+- memset(s->is_pcm, 0, (s->ps.sps->min_pu_width + 1) * (s->ps.sps->min_pu_height + 1));
+- memset(s->tab_slice_address, -1, pic_size_in_ctb * sizeof(*s->tab_slice_address));
++ if (s->horizontal_bs) {
++ memset(s->horizontal_bs, 0, s->bs_width * s->bs_height);
++ memset(s->vertical_bs, 0, s->bs_width * s->bs_height);
++ memset(s->cbf_luma, 0, s->ps.sps->min_tb_width * s->ps.sps->min_tb_height);
++ memset(s->is_pcm, 0, (s->ps.sps->min_pu_width + 1) * (s->ps.sps->min_pu_height + 1));
++ memset(s->tab_slice_address, -1, pic_size_in_ctb * sizeof(*s->tab_slice_address));
++ }
+
+ s->is_decoded = 0;
+ s->first_nal_type = s->nal_unit_type;
+@@ -3230,7 +3270,14 @@ static int hevc_decode_frame(AVCodecCont
s->ref = NULL;
ret = decode_nal_units(s, avpkt->data, avpkt->size);
if (ret < 0)
@@ -15863,10 +19490,38 @@ Upstream-status: Pending
+
return ret;
+ }
-
+
if (avctx->hwaccel) {
if (s->ref && (ret = avctx->hwaccel->end_frame(avctx)) < 0) {
-@@ -3585,6 +3620,15 @@ AVCodec ff_hevc_decoder = {
+@@ -3273,15 +3320,19 @@ static int hevc_ref_frame(HEVCContext *s
+ if (ret < 0)
+ return ret;
+
+- dst->tab_mvf_buf = av_buffer_ref(src->tab_mvf_buf);
+- if (!dst->tab_mvf_buf)
+- goto fail;
+- dst->tab_mvf = src->tab_mvf;
++ if (src->tab_mvf_buf) {
++ dst->tab_mvf_buf = av_buffer_ref(src->tab_mvf_buf);
++ if (!dst->tab_mvf_buf)
++ goto fail;
++ dst->tab_mvf = src->tab_mvf;
++ }
+
+- dst->rpl_tab_buf = av_buffer_ref(src->rpl_tab_buf);
+- if (!dst->rpl_tab_buf)
+- goto fail;
+- dst->rpl_tab = src->rpl_tab;
++ if (src->rpl_tab_buf) {
++ dst->rpl_tab_buf = av_buffer_ref(src->rpl_tab_buf);
++ if (!dst->rpl_tab_buf)
++ goto fail;
++ dst->rpl_tab = src->rpl_tab;
++ }
+
+ dst->rpl_buf = av_buffer_ref(src->rpl_buf);
+ if (!dst->rpl_buf)
+@@ -3585,6 +3636,15 @@ AVCodec ff_hevc_decoder = {
#if CONFIG_HEVC_NVDEC_HWACCEL
HWACCEL_NVDEC(hevc),
#endif
@@ -15897,12 +19552,12 @@ Upstream-status: Pending
--- a/libavcodec/hwconfig.h
+++ b/libavcodec/hwconfig.h
@@ -24,6 +24,7 @@
-
-
+
+
#define HWACCEL_CAP_ASYNC_SAFE (1 << 0)
+#define HWACCEL_CAP_MT_SAFE (1 << 1)
-
-
+
+
typedef struct AVCodecHWConfigInternal {
@@ -70,6 +71,12 @@ typedef struct AVCodecHWConfigInternal {
HW_CONFIG_HWACCEL(1, 1, 0, D3D11, D3D11VA, ff_ ## codec ## _d3d11va2_hwaccel)
@@ -15922,7 +19577,7 @@ Upstream-status: Pending
@@ -24,6 +24,9 @@
* MMAL Video Decoder
*/
-
+
+#pragma GCC diagnostic push
+// Many many redundant decls in the header files
+#pragma GCC diagnostic ignored "-Wredundant-decls"
@@ -15935,12 +19590,12 @@ Upstream-status: Pending
#include <interface/mmal/vc/mmal_vc_api.h>
+#pragma GCC diagnostic pop
#include <stdatomic.h>
-
+
#include "avcodec.h"
--- a/libavcodec/pthread_frame.c
+++ b/libavcodec/pthread_frame.c
@@ -191,7 +191,8 @@ static attribute_align_arg void *frame_w
-
+
/* if the previous thread uses hwaccel then we take the lock to ensure
* the threads don't run concurrently */
- if (avctx->hwaccel) {
@@ -15950,9 +19605,9 @@ Upstream-status: Pending
p->hwaccel_serializing = 1;
}
@@ -614,7 +615,9 @@ void ff_thread_finish_setup(AVCodecConte
-
+
if (!(avctx->active_thread_type&FF_THREAD_FRAME)) return;
-
+
- if (avctx->hwaccel && !p->hwaccel_serializing) {
+ if (avctx->hwaccel &&
+ !(avctx->hwaccel->caps_internal & HWACCEL_CAP_MT_SAFE) &&
@@ -15965,7 +19620,7 @@ Upstream-status: Pending
@@ -293,6 +293,12 @@ const PixelFormatTag ff_raw_pix_fmt_tags
{ AV_PIX_FMT_RGB565LE,MKTAG( 3 , 0 , 0 , 0 ) }, /* flipped RGB565LE */
{ AV_PIX_FMT_YUV444P, MKTAG('Y', 'V', '2', '4') }, /* YUV444P, swapped UV */
-
+
+ /* RPI (Might as well define for everything) */
+ { AV_PIX_FMT_SAND128, MKTAG('S', 'A', 'N', 'D') },
+ { AV_PIX_FMT_RPI4_8, MKTAG('S', 'A', 'N', 'D') },
@@ -15974,13 +19629,13 @@ Upstream-status: Pending
+
{ AV_PIX_FMT_NONE, 0 },
};
-
+
--- a/libavcodec/rawenc.c
+++ b/libavcodec/rawenc.c
@@ -24,6 +24,7 @@
* Raw Video Encoder
*/
-
+
+#include "config.h"
#include "avcodec.h"
#include "raw.h"
@@ -15993,13 +19648,13 @@ Upstream-status: Pending
+#if CONFIG_SAND
+#include "libavutil/rpi_sand_fns.h"
+#endif
-
+
static av_cold int raw_encode_init(AVCodecContext *avctx)
{
@@ -49,22 +54,114 @@ FF_ENABLE_DEPRECATION_WARNINGS
return 0;
}
-
+
+#if CONFIG_SAND
+static int raw_sand8_as_yuv420(AVCodecContext *avctx, AVPacket *pkt,
+ const AVFrame *frame)
@@ -16080,7 +19735,7 @@ Upstream-status: Pending
- frame->width, frame->height, 1);
+ int ret;
+ AVFrame * frame = NULL;
-
+
- if (ret < 0)
+#if CONFIG_SAND
+ if (av_rpi_is_sand_frame(src_frame)) {
@@ -16104,7 +19759,7 @@ Upstream-status: Pending
+ frame->width, frame->height, 1);
+ if (ret < 0)
+ goto fail;
-
+
if ((ret = ff_alloc_packet2(avctx, pkt, ret, ret)) < 0)
- return ret;
+ goto fail;
@@ -16114,7 +19769,7 @@ Upstream-status: Pending
frame->width, frame->height, 1)) < 0)
- return ret;
+ goto fail;
-
+
if(avctx->codec_tag == AV_RL32("yuv2") && ret > 0 &&
frame->format == AV_PIX_FMT_YUYV422) {
@@ -81,8 +178,14 @@ static int raw_encode(AVCodecContext *av
@@ -16130,7 +19785,7 @@ Upstream-status: Pending
+ *got_packet = 0;
+ return ret;
}
-
+
AVCodec ff_rawvideo_encoder = {
--- /dev/null
+++ b/libavcodec/rpi_hevc_cabac.c
@@ -17637,7 +21292,7 @@ Upstream-status: Pending
+ const xy_off_t * const scan_xy_off = off_xys[scan_idx][log2_trafo_size - 2];
+
+ int use_vpu;
-+#if RPI_COMPRESS_COEFFS
++#if RPI_COMPRESS_COEFFS
+ int num_nonzero = 0;
+ int use_compress = 0;
+ int *coeffs32;
@@ -17979,7 +21634,7 @@ Upstream-status: Pending
+ }
+ use_compress = 0;
+ }
-+#endif
++#endif
+
+ if (nb_significant_coeff_flag != 0) {
+ const unsigned int gt1_idx_delta = (c_idx_nz << 2) |
@@ -18055,7 +21710,7 @@ Upstream-status: Pending
+ scale,
+ i == 0 && xy_off->coeff == 0 ? dc_scale : scale_m,
+ shift);
-+#if RPI_COMPRESS_COEFFS
++#if RPI_COMPRESS_COEFFS
+ if (use_compress)
+ coeffs32[num_nonzero++] = (res<<16) + (&blk_coeffs[xy_off->coeff] - coeffs);
+ else
@@ -18247,11 +21902,11 @@ Upstream-status: Pending
+#endif
+
+ if (!use_dc) {
-+#if RPI_COMPRESS_COEFFS
++#if RPI_COMPRESS_COEFFS
+ if (use_compress) {
+ coeffs32[num_nonzero] = 0;
+ }
-+#endif
++#endif
+ rpi_add_residual(s, lc->jb0, log2_trafo_size, c_idx, x0, y0, coeffs);
+ }
+}
@@ -29840,7 +33495,7 @@ Upstream-status: Pending
+ unsigned int i;
+ for (i = 0; i != 4; ++i) {
+ cf->s[i].n = 0;
-+#if RPI_COMPRESS_COEFFS
++#if RPI_COMPRESS_COEFFS
+ cf->s[i].packed = 1;
+ cf->s[i].packed_n = 0;
+#endif
@@ -46104,76 +49759,104 @@ Upstream-status: Pending
@@ -21,6 +21,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-
+
+#include <drm_fourcc.h>
#include <linux/videodev2.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
-@@ -30,12 +31,14 @@
+@@ -29,57 +30,82 @@
+ #include <poll.h>
#include "libavcodec/avcodec.h"
#include "libavcodec/internal.h"
++#include "libavutil/avassert.h"
#include "libavutil/pixdesc.h"
+#include "libavutil/hwcontext.h"
#include "v4l2_context.h"
#include "v4l2_buffers.h"
#include "v4l2_m2m.h"
+#include "weak_link.h"
-
+
#define USEC_PER_SEC 1000000
-static AVRational v4l2_timebase = { 1, USEC_PER_SEC };
+static const AVRational v4l2_timebase = { 1, USEC_PER_SEC };
-
- static inline V4L2m2mContext *buf_to_m2mctx(V4L2Buffer *buf)
+
+-static inline V4L2m2mContext *buf_to_m2mctx(V4L2Buffer *buf)
++static inline V4L2m2mContext *buf_to_m2mctx(const V4L2Buffer * const buf)
{
-@@ -52,34 +55,44 @@ static inline AVCodecContext *logger(V4L
- static inline AVRational v4l2_get_timebase(V4L2Buffer *avbuf)
+ return V4L2_TYPE_IS_OUTPUT(buf->context->type) ?
+ container_of(buf->context, V4L2m2mContext, output) :
+ container_of(buf->context, V4L2m2mContext, capture);
+ }
+
+-static inline AVCodecContext *logger(V4L2Buffer *buf)
++static inline AVCodecContext *logger(const V4L2Buffer * const buf)
{
- V4L2m2mContext *s = buf_to_m2mctx(avbuf);
+ return buf_to_m2mctx(buf)->avctx;
+ }
+
+-static inline AVRational v4l2_get_timebase(V4L2Buffer *avbuf)
++static inline AVRational v4l2_get_timebase(const V4L2Buffer * const avbuf)
+ {
+- V4L2m2mContext *s = buf_to_m2mctx(avbuf);
-
- if (s->avctx->pkt_timebase.num)
- return s->avctx->pkt_timebase;
- return s->avctx->time_base;
++ const V4L2m2mContext *s = buf_to_m2mctx(avbuf);
+ const AVRational tb = s->avctx->pkt_timebase.num ?
+ s->avctx->pkt_timebase :
+ s->avctx->time_base;
+ return tb.num && tb.den ? tb : v4l2_timebase;
}
-
+
-static inline void v4l2_set_pts(V4L2Buffer *out, int64_t pts)
-+static inline void v4l2_set_pts(V4L2Buffer *out, int64_t pts, int no_rescale)
++static inline struct timeval tv_from_int(const int64_t t)
{
- int64_t v4l2_pts;
--
++ return (struct timeval){
++ .tv_usec = t % USEC_PER_SEC,
++ .tv_sec = t / USEC_PER_SEC
++ };
++}
+
- if (pts == AV_NOPTS_VALUE)
- pts = 0;
--
++static inline int64_t int_from_tv(const struct timeval t)
++{
++ return (int64_t)t.tv_sec * USEC_PER_SEC + t.tv_usec;
++}
+
++static inline void v4l2_set_pts(V4L2Buffer * const out, const int64_t pts)
++{
/* convert pts to v4l2 timebase */
- v4l2_pts = av_rescale_q(pts, v4l2_get_timebase(out), v4l2_timebase);
+- out->buf.timestamp.tv_usec = v4l2_pts % USEC_PER_SEC;
+- out->buf.timestamp.tv_sec = v4l2_pts / USEC_PER_SEC;
+ const int64_t v4l2_pts =
-+ no_rescale ? pts :
+ pts == AV_NOPTS_VALUE ? 0 :
+ av_rescale_q(pts, v4l2_get_timebase(out), v4l2_timebase);
- out->buf.timestamp.tv_usec = v4l2_pts % USEC_PER_SEC;
- out->buf.timestamp.tv_sec = v4l2_pts / USEC_PER_SEC;
++ out->buf.timestamp = tv_from_int(v4l2_pts);
}
-
+
-static inline int64_t v4l2_get_pts(V4L2Buffer *avbuf)
-+static inline int64_t v4l2_get_pts(V4L2Buffer *avbuf, int no_rescale)
++static inline int64_t v4l2_get_pts(const V4L2Buffer * const avbuf)
{
- int64_t v4l2_pts;
-
++ const int64_t v4l2_pts = int_from_tv(avbuf->buf.timestamp);
++ return v4l2_pts != 0 ? v4l2_pts : AV_NOPTS_VALUE;
++#if 0
/* convert pts back to encoder timebase */
- v4l2_pts = (int64_t)avbuf->buf.timestamp.tv_sec * USEC_PER_SEC +
-+ const int64_t v4l2_pts = (int64_t)avbuf->buf.timestamp.tv_sec * USEC_PER_SEC +
- avbuf->buf.timestamp.tv_usec;
-
-- return av_rescale_q(v4l2_pts, v4l2_timebase, v4l2_get_timebase(avbuf));
+- avbuf->buf.timestamp.tv_usec;
+ return
-+ no_rescale ? v4l2_pts :
++ avbuf->context->no_pts_rescale ? v4l2_pts :
+ v4l2_pts == 0 ? AV_NOPTS_VALUE :
+ av_rescale_q(v4l2_pts, v4l2_timebase, v4l2_get_timebase(avbuf));
++#endif
+}
-+
+
+- return av_rescale_q(v4l2_pts, v4l2_timebase, v4l2_get_timebase(avbuf));
+static void set_buf_length(V4L2Buffer *out, unsigned int plane, uint32_t bytesused, uint32_t length)
+{
+ if (V4L2_TYPE_IS_MULTIPLANAR(out->buf.type)) {
@@ -46184,12 +49867,15 @@ Upstream-status: Pending
+ out->buf.length = length;
+ }
}
-
+
static enum AVColorPrimaries v4l2_get_color_primaries(V4L2Buffer *buf)
-@@ -116,6 +129,105 @@ static enum AVColorPrimaries v4l2_get_co
+@@ -116,49 +142,176 @@ static enum AVColorPrimaries v4l2_get_co
return AVCOL_PRI_UNSPECIFIED;
}
-
+
+-static enum AVColorRange v4l2_get_color_range(V4L2Buffer *buf)
+-{
+- enum v4l2_quantization qt;
+static void v4l2_set_color(V4L2Buffer *buf,
+ const enum AVColorPrimaries avcp,
+ const enum AVColorSpace avcs,
@@ -46230,7 +49916,10 @@ Upstream-status: Pending
+ default:
+ break;
+ }
-+
+
+- qt = V4L2_TYPE_IS_MULTIPLANAR(buf->buf.type) ?
+- buf->context->format.fmt.pix_mp.quantization :
+- buf->context->format.fmt.pix.quantization;
+ switch (avcs) {
+ case AVCOL_SPC_RGB:
+ cs = V4L2_COLORSPACE_SRGB;
@@ -46260,7 +49949,10 @@ Upstream-status: Pending
+ default:
+ break;
+ }
-+
+
+- switch (qt) {
+- case V4L2_QUANTIZATION_LIM_RANGE: return AVCOL_RANGE_MPEG;
+- case V4L2_QUANTIZATION_FULL_RANGE: return AVCOL_RANGE_JPEG;
+ switch (xfer) {
+ case AVCOL_TRC_BT709:
+ xfer = V4L2_XFER_FUNC_709;
@@ -46274,10 +49966,11 @@ Upstream-status: Pending
+ case AVCOL_TRC_SMPTE2084:
+ xfer = V4L2_XFER_FUNC_SMPTE2084;
+ break;
-+ default:
-+ break;
-+ }
-+
+ default:
+ break;
+ }
+
+- return AVCOL_RANGE_UNSPECIFIED;
+ if (V4L2_TYPE_IS_MULTIPLANAR(buf->buf.type)) {
+ buf->context->format.fmt.pix_mp.colorspace = cs;
+ buf->context->format.fmt.pix_mp.ycbcr_enc = ycbcr;
@@ -46287,15 +49980,58 @@ Upstream-status: Pending
+ buf->context->format.fmt.pix.ycbcr_enc = ycbcr;
+ buf->context->format.fmt.pix.xfer_func = xfer;
+ }
+ }
+
+-static enum AVColorSpace v4l2_get_color_space(V4L2Buffer *buf)
++static inline enum v4l2_quantization
++buf_quantization(const V4L2Buffer * const buf)
+ {
+- enum v4l2_ycbcr_encoding ycbcr;
+- enum v4l2_colorspace cs;
++ return V4L2_TYPE_IS_MULTIPLANAR(buf->buf.type) ?
++ buf->context->format.fmt.pix_mp.quantization :
++ buf->context->format.fmt.pix.quantization;
++}
+
+- cs = V4L2_TYPE_IS_MULTIPLANAR(buf->buf.type) ?
++static inline enum v4l2_colorspace
++buf_colorspace(const V4L2Buffer * const buf)
++{
++ return V4L2_TYPE_IS_MULTIPLANAR(buf->buf.type) ?
+ buf->context->format.fmt.pix_mp.colorspace :
+ buf->context->format.fmt.pix.colorspace;
++}
+
+- ycbcr = V4L2_TYPE_IS_MULTIPLANAR(buf->buf.type) ?
++static inline enum v4l2_ycbcr_encoding
++buf_ycbcr_enc(const V4L2Buffer * const buf)
++{
++ return V4L2_TYPE_IS_MULTIPLANAR(buf->buf.type) ?
+ buf->context->format.fmt.pix_mp.ycbcr_enc:
+ buf->context->format.fmt.pix.ycbcr_enc;
++}
+
+- switch(cs) {
+- case V4L2_COLORSPACE_SRGB: return AVCOL_SPC_RGB;
++static enum AVColorRange v4l2_get_color_range(V4L2Buffer *buf)
++{
++ switch (buf_quantization(buf)) {
++ case V4L2_QUANTIZATION_LIM_RANGE:
++ return AVCOL_RANGE_MPEG;
++ case V4L2_QUANTIZATION_FULL_RANGE:
++ return AVCOL_RANGE_JPEG;
++ case V4L2_QUANTIZATION_DEFAULT:
++ // If YUV (which we assume for all video decode) then, from the header
++ // comments, range is limited unless CS is JPEG
++ return buf_colorspace(buf) == V4L2_COLORSPACE_JPEG ?
++ AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
++ default:
++ break;
++ }
++
++ return AVCOL_RANGE_UNSPECIFIED;
+}
+
- static enum AVColorRange v4l2_get_color_range(V4L2Buffer *buf)
- {
- enum v4l2_quantization qt;
-@@ -134,6 +246,20 @@ static enum AVColorRange v4l2_get_color_
- return AVCOL_RANGE_UNSPECIFIED;
- }
-
+static void v4l2_set_color_range(V4L2Buffer *buf, const enum AVColorRange avcr)
+{
+ const enum v4l2_quantization q =
@@ -46310,13 +50046,51 @@ Upstream-status: Pending
+ }
+}
+
- static enum AVColorSpace v4l2_get_color_space(V4L2Buffer *buf)
++static enum AVColorSpace v4l2_get_color_space(V4L2Buffer *buf)
++{
++ switch (buf_colorspace(buf)) {
++ case V4L2_COLORSPACE_JPEG: // JPEG -> SRGB
++ case V4L2_COLORSPACE_SRGB:
++ return AVCOL_SPC_RGB;
+ case V4L2_COLORSPACE_REC709: return AVCOL_SPC_BT709;
+ case V4L2_COLORSPACE_470_SYSTEM_M: return AVCOL_SPC_FCC;
+ case V4L2_COLORSPACE_470_SYSTEM_BG: return AVCOL_SPC_BT470BG;
+ case V4L2_COLORSPACE_SMPTE170M: return AVCOL_SPC_SMPTE170M;
+ case V4L2_COLORSPACE_SMPTE240M: return AVCOL_SPC_SMPTE240M;
+ case V4L2_COLORSPACE_BT2020:
+- if (ycbcr == V4L2_YCBCR_ENC_BT2020_CONST_LUM)
+- return AVCOL_SPC_BT2020_CL;
+- else
+- return AVCOL_SPC_BT2020_NCL;
++ return buf_ycbcr_enc(buf) == V4L2_YCBCR_ENC_BT2020_CONST_LUM ?
++ AVCOL_SPC_BT2020_CL : AVCOL_SPC_BT2020_NCL;
+ default:
+ break;
+ }
+@@ -168,17 +321,9 @@ static enum AVColorSpace v4l2_get_color_
+
+ static enum AVColorTransferCharacteristic v4l2_get_color_trc(V4L2Buffer *buf)
{
- enum v4l2_ycbcr_encoding ycbcr;
-@@ -210,73 +336,165 @@ static enum AVColorTransferCharacteristi
+- enum v4l2_ycbcr_encoding ycbcr;
++ const enum v4l2_ycbcr_encoding ycbcr = buf_ycbcr_enc(buf);
+ enum v4l2_xfer_func xfer;
+- enum v4l2_colorspace cs;
+-
+- cs = V4L2_TYPE_IS_MULTIPLANAR(buf->buf.type) ?
+- buf->context->format.fmt.pix_mp.colorspace :
+- buf->context->format.fmt.pix.colorspace;
+-
+- ycbcr = V4L2_TYPE_IS_MULTIPLANAR(buf->buf.type) ?
+- buf->context->format.fmt.pix_mp.ycbcr_enc:
+- buf->context->format.fmt.pix.ycbcr_enc;
++ const enum v4l2_colorspace cs = buf_colorspace(buf);
+
+ xfer = V4L2_TYPE_IS_MULTIPLANAR(buf->buf.type) ?
+ buf->context->format.fmt.pix_mp.xfer_func:
+@@ -210,73 +355,165 @@ static enum AVColorTransferCharacteristi
return AVCOL_TRC_UNSPECIFIED;
}
-
+
-static void v4l2_free_buffer(void *opaque, uint8_t *unused)
+static int v4l2_buf_is_interlaced(const V4L2Buffer * const buf)
{
@@ -46327,7 +50101,7 @@ Upstream-status: Pending
- atomic_fetch_sub_explicit(&s->refcount, 1, memory_order_acq_rel);
+ return V4L2_FIELD_IS_INTERLACED(buf->buf.field);
+}
-
+
- if (s->reinit) {
- if (!atomic_load(&s->refcount))
- sem_post(&s->refsync);
@@ -46343,7 +50117,7 @@ Upstream-status: Pending
+{
+ return buf->buf.field == V4L2_FIELD_INTERLACED_TB;
+}
-
+
- av_buffer_unref(&avbuf->context_ref);
- }
+static void v4l2_set_interlace(V4L2Buffer * const buf, const int is_interlaced, const int is_tff)
@@ -46351,14 +50125,14 @@ Upstream-status: Pending
+ buf->buf.field = !is_interlaced ? V4L2_FIELD_NONE :
+ is_tff ? V4L2_FIELD_INTERLACED_TB : V4L2_FIELD_INTERLACED_BT;
}
-
+
-static int v4l2_buf_increase_ref(V4L2Buffer *in)
+static uint8_t * v4l2_get_drm_frame(V4L2Buffer *avbuf)
{
- V4L2m2mContext *s = buf_to_m2mctx(in);
+ AVDRMFrameDescriptor *drm_desc = &avbuf->drm_frame;
+ AVDRMLayerDescriptor *layer;
-
+
- if (in->context_ref)
- atomic_fetch_add(&in->context_refcount, 1);
- else {
@@ -46368,7 +50142,7 @@ Upstream-status: Pending
+ /* fill the DRM frame descriptor */
+ drm_desc->nb_objects = avbuf->num_planes;
+ drm_desc->nb_layers = 1;
-
+
- in->context_refcount = 1;
+ layer = &drm_desc->layers[0];
+ layer->nb_planes = avbuf->num_planes;
@@ -46378,7 +50152,7 @@ Upstream-status: Pending
+ layer->planes[i].offset = 0;
+ layer->planes[i].pitch = avbuf->plane_info[i].bytesperline;
}
-
+
- in->status = V4L2BUF_RET_USER;
- atomic_fetch_add_explicit(&s->refcount, 1, memory_order_relaxed);
+ switch (avbuf->context->av_pix_fmt) {
@@ -46386,7 +50160,7 @@ Upstream-status: Pending
+
+ layer->format = DRM_FORMAT_YUYV;
+ layer->nb_planes = 1;
-
+
- return 0;
+ break;
+
@@ -46435,7 +50209,7 @@ Upstream-status: Pending
+
+ return (uint8_t *) drm_desc;
}
-
+
-static int v4l2_buf_to_bufref(V4L2Buffer *in, int plane, AVBufferRef **buf)
+static void v4l2_free_bufref(void *opaque, uint8_t *data)
{
@@ -46443,25 +50217,25 @@ Upstream-status: Pending
+ AVBufferRef * bufref = (AVBufferRef *)data;
+ V4L2Buffer *avbuf = (V4L2Buffer *)bufref->data;
+ struct V4L2Context *ctx = ff_weak_link_lock(&avbuf->context_wl);
-
+
- if (plane >= in->num_planes)
- return AVERROR(EINVAL);
+ if (ctx != NULL) {
+ // Buffer still attached to context
+ V4L2m2mContext *s = buf_to_m2mctx(avbuf);
-
+
- /* even though most encoders return 0 in data_offset encoding vp8 does require this value */
- *buf = av_buffer_create((char *)in->plane_info[plane].mm_addr + in->planes[plane].data_offset,
- in->plane_info[plane].length, v4l2_free_buffer, in, 0);
- if (!*buf)
- return AVERROR(ENOMEM);
+ ff_mutex_lock(&ctx->lock);
-
+
- ret = v4l2_buf_increase_ref(in);
- if (ret)
- av_buffer_unref(buf);
-+ avbuf->status = V4L2BUF_AVAILABLE;
-
++ ff_v4l2_buffer_set_avail(avbuf);
+
- return ret;
+ if (s->draining && V4L2_TYPE_IS_OUTPUT(ctx->type)) {
+ av_log(logger(avbuf), AV_LOG_DEBUG, "%s: Buffer avail\n", ctx->name);
@@ -46482,8 +50256,9 @@ Upstream-status: Pending
+
+ ff_weak_link_unlock(avbuf->context_wl);
+ av_buffer_unref(&bufref);
-+}
-+
+ }
+
+-static int v4l2_bufref_to_buf(V4L2Buffer *out, int plane, const uint8_t* data, int size, int offset, AVBufferRef* bref)
+static int v4l2_buffer_export_drm(V4L2Buffer* avbuf)
+{
+ struct v4l2_exportbuffer expbuf;
@@ -46514,20 +50289,19 @@ Upstream-status: Pending
+ }
+
+ return 0;
- }
-
--static int v4l2_bufref_to_buf(V4L2Buffer *out, int plane, const uint8_t* data, int size, int offset, AVBufferRef* bref)
++}
++
+static int v4l2_bufref_to_buf(V4L2Buffer *out, int plane, const uint8_t* data, int size, int offset)
{
unsigned int bytesused, length;
+ int rv = 0;
-
+
if (plane >= out->num_planes)
return AVERROR(EINVAL);
-@@ -284,32 +502,57 @@ static int v4l2_bufref_to_buf(V4L2Buffer
+@@ -284,32 +521,57 @@ static int v4l2_bufref_to_buf(V4L2Buffer
length = out->plane_info[plane].length;
bytesused = FFMIN(size+offset, length);
-
+
- memcpy((uint8_t*)out->plane_info[plane].mm_addr+offset, data, FFMIN(size, length-offset));
-
- if (V4L2_TYPE_IS_MULTIPLANAR(out->buf.type)) {
@@ -46540,7 +50314,7 @@ Upstream-status: Pending
+ size = length - offset;
+ rv = AVERROR(ENOMEM);
}
-
+
- return 0;
+ memcpy((uint8_t*)out->plane_info[plane].mm_addr+offset, data, size);
+
@@ -46564,14 +50338,14 @@ Upstream-status: Pending
+ avbuf->status = V4L2BUF_RET_USER;
+ return newbuf;
}
-
+
static int v4l2_buffer_buf_to_swframe(AVFrame *frame, V4L2Buffer *avbuf)
{
- int i, ret;
+ int i;
-
+
frame->format = avbuf->context->av_pix_fmt;
-
+
- for (i = 0; i < avbuf->num_planes; i++) {
- ret = v4l2_buf_to_bufref(avbuf, i, &frame->buf[i]);
- if (ret)
@@ -46579,7 +50353,7 @@ Upstream-status: Pending
+ frame->buf[0] = wrap_avbuf(avbuf);
+ if (frame->buf[0] == NULL)
+ return AVERROR(ENOMEM);
-
++
+ if (buf_to_m2mctx(avbuf)->output_drm) {
+ /* 1. get references to the actual data */
+ frame->data[0] = (uint8_t *) v4l2_get_drm_frame(avbuf);
@@ -46587,7 +50361,7 @@ Upstream-status: Pending
+ frame->hw_frames_ctx = av_buffer_ref(avbuf->context->frames_ref);
+ return 0;
+ }
-+
+
+
+ /* 1. get references to the actual data */
+ for (i = 0; i < avbuf->num_planes; i++) {
@@ -46595,9 +50369,9 @@ Upstream-status: Pending
frame->linesize[i] = avbuf->plane_info[i].bytesperline;
- frame->data[i] = frame->buf[i]->data;
}
-
+
/* fixup special cases */
-@@ -318,17 +561,17 @@ static int v4l2_buffer_buf_to_swframe(AV
+@@ -318,17 +580,17 @@ static int v4l2_buffer_buf_to_swframe(AV
case AV_PIX_FMT_NV21:
if (avbuf->num_planes > 1)
break;
@@ -46606,7 +50380,7 @@ Upstream-status: Pending
+ frame->linesize[1] = frame->linesize[0];
+ frame->data[1] = frame->data[0] + frame->linesize[0] * ff_v4l2_get_format_height(&avbuf->context->format);
break;
-
+
case AV_PIX_FMT_YUV420P:
if (avbuf->num_planes > 1)
break;
@@ -46619,12 +50393,12 @@ Upstream-status: Pending
+ frame->data[1] = frame->data[0] + frame->linesize[0] * ff_v4l2_get_format_height(&avbuf->context->format);
+ frame->data[2] = frame->data[1] + frame->linesize[1] * ff_v4l2_get_format_height(&avbuf->context->format) / 2;
break;
-
+
default:
-@@ -338,68 +581,95 @@ static int v4l2_buffer_buf_to_swframe(AV
+@@ -338,68 +600,127 @@ static int v4l2_buffer_buf_to_swframe(AV
return 0;
}
-
+
+static void cpy_2d(uint8_t * dst, int dst_stride, const uint8_t * src, int src_stride, int w, int h)
+{
+ if (dst_stride == src_stride && w + 32 >= dst_stride) {
@@ -46644,6 +50418,38 @@ Upstream-status: Pending
+ return i != 0 && !(i == num_planes - 1 && (desc->flags & AV_PIX_FMT_FLAG_ALPHA));
+}
+
++static int v4l2_buffer_primeframe_to_buf(const AVFrame *frame, V4L2Buffer *out)
++{
++ const AVDRMFrameDescriptor *const src = (const AVDRMFrameDescriptor *)frame->data[0];
++
++ if (frame->format != AV_PIX_FMT_DRM_PRIME || !src)
++ return AVERROR(EINVAL);
++
++ av_assert0(out->buf.memory == V4L2_MEMORY_DMABUF);
++
++ if (V4L2_TYPE_IS_MULTIPLANAR(out->buf.type)) {
++ // Only currently cope with single buffer types
++ if (out->buf.length != 1)
++ return AVERROR_PATCHWELCOME;
++ if (src->nb_objects != 1)
++ return AVERROR(EINVAL);
++
++ out->planes[0].m.fd = src->objects[0].fd;
++ }
++ else {
++ if (src->nb_objects != 1)
++ return AVERROR(EINVAL);
++
++ out->buf.m.fd = src->objects[0].fd;
++ }
++
++ // No need to copy src AVDescriptor and if we did then we may confuse
++ // fd close on free
++ out->ref_buf = av_buffer_ref(frame->buf[0]);
++
++ return 0;
++}
++
static int v4l2_buffer_swframe_to_buf(const AVFrame *frame, V4L2Buffer *out)
{
- int i, ret;
@@ -46756,7 +50562,7 @@ Upstream-status: Pending
+ av_log(NULL, AV_LOG_ERROR, "%s: Plane total %u > buffer size %zu\n", __func__, offset, out->plane_info[0].length);
+ return -1;
+ }
-
+
- for (i = 0; i < out->num_planes; i++) {
- ret = v4l2_bufref_to_buf(out, i, frame->buf[i]->data, frame->buf[i]->size, 0, frame->buf[i]);
- if (ret)
@@ -46770,42 +50576,60 @@ Upstream-status: Pending
-
return 0;
}
-
-@@ -411,14 +681,22 @@ static int v4l2_buffer_swframe_to_buf(co
-
- int ff_v4l2_buffer_avframe_to_buf(const AVFrame *frame, V4L2Buffer *out)
+
+@@ -409,16 +730,31 @@ static int v4l2_buffer_swframe_to_buf(co
+ *
+ ******************************************************************************/
+
+-int ff_v4l2_buffer_avframe_to_buf(const AVFrame *frame, V4L2Buffer *out)
++int ff_v4l2_buffer_avframe_to_buf(const AVFrame *frame, V4L2Buffer *out, const int64_t track_ts)
{
- v4l2_set_pts(out, frame->pts);
-+ out->buf.flags = frame->key_frame ? (out->buf.flags & ~V4L2_BUF_FLAG_KEYFRAME) : (out->buf.flags | V4L2_BUF_FLAG_KEYFRAME);
+-
+- return v4l2_buffer_swframe_to_buf(frame, out);
++ out->buf.flags = frame->key_frame ?
++ (out->buf.flags | V4L2_BUF_FLAG_KEYFRAME) :
++ (out->buf.flags & ~V4L2_BUF_FLAG_KEYFRAME);
+ // Beware that colour info is held in format rather than the actual
+ // v4l2 buffer struct so this may not be as useful as you might hope
+ v4l2_set_color(out, frame->color_primaries, frame->colorspace, frame->color_trc);
+ v4l2_set_color_range(out, frame->color_range);
+ // PTS & interlace are buffer vars
-+ v4l2_set_pts(out, frame->pts, 0);
++ if (track_ts)
++ out->buf.timestamp = tv_from_int(track_ts);
++ else
++ v4l2_set_pts(out, frame->pts);
+ v4l2_set_interlace(out, frame->interlaced_frame, frame->top_field_first);
-
- return v4l2_buffer_swframe_to_buf(frame, out);
++
++ return frame->format == AV_PIX_FMT_DRM_PRIME ?
++ v4l2_buffer_primeframe_to_buf(frame, out) :
++ v4l2_buffer_swframe_to_buf(frame, out);
}
-
--int ff_v4l2_buffer_buf_to_avframe(AVFrame *frame, V4L2Buffer *avbuf)
-+int ff_v4l2_buffer_buf_to_avframe(AVFrame *frame, V4L2Buffer *avbuf, int no_rescale_pts)
+
+ int ff_v4l2_buffer_buf_to_avframe(AVFrame *frame, V4L2Buffer *avbuf)
{
int ret;
+ V4L2Context * const ctx = avbuf->context;
-
+
av_frame_unref(frame);
-
-@@ -433,13 +711,24 @@ int ff_v4l2_buffer_buf_to_avframe(AVFram
+
+@@ -429,17 +765,32 @@ int ff_v4l2_buffer_buf_to_avframe(AVFram
+
+ /* 2. get frame information */
+ frame->key_frame = !!(avbuf->buf.flags & V4L2_BUF_FLAG_KEYFRAME);
++ frame->pict_type = frame->key_frame ? AV_PICTURE_TYPE_I :
++ (avbuf->buf.flags & V4L2_BUF_FLAG_PFRAME) != 0 ? AV_PICTURE_TYPE_P :
++ (avbuf->buf.flags & V4L2_BUF_FLAG_BFRAME) != 0 ? AV_PICTURE_TYPE_B :
++ AV_PICTURE_TYPE_NONE;
+ frame->color_primaries = v4l2_get_color_primaries(avbuf);
frame->colorspace = v4l2_get_color_space(avbuf);
frame->color_range = v4l2_get_color_range(avbuf);
frame->color_trc = v4l2_get_color_trc(avbuf);
-- frame->pts = v4l2_get_pts(avbuf);
-+ frame->pts = v4l2_get_pts(avbuf, no_rescale_pts);
+ frame->pts = v4l2_get_pts(avbuf);
frame->pkt_dts = AV_NOPTS_VALUE;
+ frame->interlaced_frame = v4l2_buf_is_interlaced(avbuf);
+ frame->top_field_first = v4l2_buf_is_top_first(avbuf);
-
+
/* these values are updated also during re-init in v4l2_process_driver_event */
- frame->height = avbuf->context->height;
- frame->width = avbuf->context->width;
@@ -46820,18 +50644,17 @@ Upstream-status: Pending
+ frame->crop_right = ctx->selection.left + ctx->selection.width < frame->width ?
+ frame->width - (ctx->selection.left + ctx->selection.width) : 0;
+ frame->crop_bottom = ctx->selection.top + ctx->selection.height < frame->height ?
-+ frame->width - (ctx->selection.top + ctx->selection.height) : 0;
++ frame->height - (ctx->selection.top + ctx->selection.height) : 0;
+ }
-
+
/* 3. report errors upstream */
if (avbuf->buf.flags & V4L2_BUF_FLAG_ERROR) {
-@@ -452,15 +741,16 @@ int ff_v4l2_buffer_buf_to_avframe(AVFram
-
+@@ -452,15 +803,15 @@ int ff_v4l2_buffer_buf_to_avframe(AVFram
+
int ff_v4l2_buffer_buf_to_avpkt(AVPacket *pkt, V4L2Buffer *avbuf)
{
- int ret;
-+ av_log(logger(avbuf), AV_LOG_INFO, "%s\n", __func__);
-
+-
av_packet_unref(pkt);
- ret = v4l2_buf_to_bufref(avbuf, 0, &pkt->buf);
- if (ret)
@@ -46840,29 +50663,25 @@ Upstream-status: Pending
+ pkt->buf = wrap_avbuf(avbuf);
+ if (pkt->buf == NULL)
+ return AVERROR(ENOMEM);
-
+
pkt->size = V4L2_TYPE_IS_MULTIPLANAR(avbuf->buf.type) ? avbuf->buf.m.planes[0].bytesused : avbuf->buf.bytesused;
- pkt->data = pkt->buf->data;
+ pkt->data = (uint8_t*)avbuf->plane_info[0].mm_addr + avbuf->planes[0].data_offset;
-
++ pkt->flags = 0;
+
if (avbuf->buf.flags & V4L2_BUF_FLAG_KEYFRAME)
pkt->flags |= AV_PKT_FLAG_KEY;
-@@ -470,36 +760,89 @@ int ff_v4l2_buffer_buf_to_avpkt(AVPacket
- pkt->flags |= AV_PKT_FLAG_CORRUPT;
- }
-
-- pkt->dts = pkt->pts = v4l2_get_pts(avbuf);
-+ pkt->dts = pkt->pts = v4l2_get_pts(avbuf, 0);
-
+@@ -475,31 +826,91 @@ int ff_v4l2_buffer_buf_to_avpkt(AVPacket
return 0;
}
-
+
-int ff_v4l2_buffer_avpkt_to_buf(const AVPacket *pkt, V4L2Buffer *out)
-+int ff_v4l2_buffer_avpkt_to_buf_ext(const AVPacket *pkt, V4L2Buffer *out,
-+ const void *extdata, size_t extlen, int no_rescale_pts)
++int ff_v4l2_buffer_avpkt_to_buf_ext(const AVPacket * const pkt, V4L2Buffer * const out,
++ const void *extdata, size_t extlen,
++ const int64_t timestamp)
{
int ret;
-
+
- ret = v4l2_bufref_to_buf(out, 0, pkt->data, pkt->size, 0, pkt->buf);
- if (ret)
+ if (extlen) {
@@ -46874,18 +50693,23 @@ Upstream-status: Pending
+ ret = v4l2_bufref_to_buf(out, 0, pkt->data, pkt->size, extlen);
+ if (ret && ret != AVERROR(ENOMEM))
return ret;
-
+
- v4l2_set_pts(out, pkt->pts);
-+ v4l2_set_pts(out, pkt->pts, no_rescale_pts);
-
- if (pkt->flags & AV_PKT_FLAG_KEY)
- out->flags = V4L2_BUF_FLAG_KEYFRAME;
-
-- return 0;
++ if (timestamp)
++ out->buf.timestamp = tv_from_int(timestamp);
++ else
++ v4l2_set_pts(out, pkt->pts);
++
++ out->buf.flags = (pkt->flags & AV_PKT_FLAG_KEY) != 0 ?
++ (out->buf.flags | V4L2_BUF_FLAG_KEYFRAME) :
++ (out->buf.flags & ~V4L2_BUF_FLAG_KEYFRAME);
+
+- if (pkt->flags & AV_PKT_FLAG_KEY)
+- out->flags = V4L2_BUF_FLAG_KEYFRAME;
+ return ret;
- }
-
--int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index)
++}
+
+- return 0;
+int ff_v4l2_buffer_avpkt_to_buf(const AVPacket *pkt, V4L2Buffer *out)
+{
+ return ff_v4l2_buffer_avpkt_to_buf_ext(pkt, out, NULL, 0, 0);
@@ -46908,23 +50732,27 @@ Upstream-status: Pending
+ close(avbuf->drm_frame.objects[i].fd);
+ }
+
++ av_buffer_unref(&avbuf->ref_buf);
++
+ ff_weak_link_unref(&avbuf->context_wl);
+
+ av_free(avbuf);
-+}
-+
+ }
+
+-int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index)
+
-+int ff_v4l2_buffer_initialize(AVBufferRef ** pbufref, int index, V4L2Context *ctx)
++int ff_v4l2_buffer_initialize(AVBufferRef ** pbufref, int index, V4L2Context *ctx, enum v4l2_memory mem)
{
- V4L2Context *ctx = avbuf->context;
int ret, i;
+ V4L2Buffer * const avbuf = av_mallocz(sizeof(*avbuf));
+ AVBufferRef * bufref;
-+
+
+- avbuf->buf.memory = V4L2_MEMORY_MMAP;
+ *pbufref = NULL;
+ if (avbuf == NULL)
+ return AVERROR(ENOMEM);
-
++
+ bufref = av_buffer_create((uint8_t*)avbuf, sizeof(*avbuf), v4l2_buffer_buffer_free, NULL, 0);
+ if (bufref == NULL) {
+ av_free(avbuf);
@@ -46932,10 +50760,10 @@ Upstream-status: Pending
+ }
+
+ avbuf->context = ctx;
- avbuf->buf.memory = V4L2_MEMORY_MMAP;
++ avbuf->buf.memory = mem;
avbuf->buf.type = ctx->type;
avbuf->buf.index = index;
-
+
+ for (i = 0; i != FF_ARRAY_ELEMS(avbuf->drm_frame.objects); ++i) {
+ avbuf->drm_frame.objects[i].fd = -1;
+ }
@@ -46945,43 +50773,48 @@ Upstream-status: Pending
if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type)) {
avbuf->buf.length = VIDEO_MAX_PLANES;
avbuf->buf.m.planes = avbuf->planes;
-@@ -507,7 +850,7 @@ int ff_v4l2_buffer_initialize(V4L2Buffer
-
+@@ -507,7 +918,7 @@ int ff_v4l2_buffer_initialize(V4L2Buffer
+
ret = ioctl(buf_to_m2mctx(avbuf)->fd, VIDIOC_QUERYBUF, &avbuf->buf);
if (ret < 0)
- return AVERROR(errno);
+ goto fail;
-
+
if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type)) {
avbuf->num_planes = 0;
-@@ -527,25 +870,33 @@ int ff_v4l2_buffer_initialize(V4L2Buffer
-
+@@ -520,6 +931,8 @@ int ff_v4l2_buffer_initialize(V4L2Buffer
+ avbuf->num_planes = 1;
+
+ for (i = 0; i < avbuf->num_planes; i++) {
++ const int want_mmap = avbuf->buf.memory == V4L2_MEMORY_MMAP &&
++ (V4L2_TYPE_IS_OUTPUT(ctx->type) || !buf_to_m2mctx(avbuf)->output_drm);
+
+ avbuf->plane_info[i].bytesperline = V4L2_TYPE_IS_MULTIPLANAR(ctx->type) ?
+ ctx->format.fmt.pix_mp.plane_fmt[i].bytesperline :
+@@ -527,25 +940,29 @@ int ff_v4l2_buffer_initialize(V4L2Buffer
+
if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type)) {
avbuf->plane_info[i].length = avbuf->buf.m.planes[i].length;
- avbuf->plane_info[i].mm_addr = mmap(NULL, avbuf->buf.m.planes[i].length,
- PROT_READ | PROT_WRITE, MAP_SHARED,
- buf_to_m2mctx(avbuf)->fd, avbuf->buf.m.planes[i].m.mem_offset);
+
-+ if ((V4L2_TYPE_IS_OUTPUT(ctx->type) && buf_to_m2mctx(avbuf)->output_drm) ||
-+ !buf_to_m2mctx(avbuf)->output_drm) {
++ if (want_mmap)
+ avbuf->plane_info[i].mm_addr = mmap(NULL, avbuf->buf.m.planes[i].length,
+ PROT_READ | PROT_WRITE, MAP_SHARED,
+ buf_to_m2mctx(avbuf)->fd, avbuf->buf.m.planes[i].m.mem_offset);
-+ }
} else {
avbuf->plane_info[i].length = avbuf->buf.length;
- avbuf->plane_info[i].mm_addr = mmap(NULL, avbuf->buf.length,
- PROT_READ | PROT_WRITE, MAP_SHARED,
- buf_to_m2mctx(avbuf)->fd, avbuf->buf.m.offset);
+
-+ if ((V4L2_TYPE_IS_OUTPUT(ctx->type) && buf_to_m2mctx(avbuf)->output_drm) ||
-+ !buf_to_m2mctx(avbuf)->output_drm) {
++ if (want_mmap)
+ avbuf->plane_info[i].mm_addr = mmap(NULL, avbuf->buf.length,
+ PROT_READ | PROT_WRITE, MAP_SHARED,
+ buf_to_m2mctx(avbuf)->fd, avbuf->buf.m.offset);
-+ }
}
-
+
- if (avbuf->plane_info[i].mm_addr == MAP_FAILED)
- return AVERROR(ENOMEM);
+ if (avbuf->plane_info[i].mm_addr == MAP_FAILED) {
@@ -46990,19 +50823,19 @@ Upstream-status: Pending
+ goto fail;
+ }
}
-
+
avbuf->status = V4L2BUF_AVAILABLE;
-
+
- if (V4L2_TYPE_IS_OUTPUT(ctx->type))
- return 0;
-
if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type)) {
avbuf->buf.m.planes = avbuf->planes;
avbuf->buf.length = avbuf->num_planes;
-@@ -555,7 +906,20 @@ int ff_v4l2_buffer_initialize(V4L2Buffer
+@@ -555,20 +972,51 @@ int ff_v4l2_buffer_initialize(V4L2Buffer
avbuf->buf.length = avbuf->planes[0].length;
}
-
+
- return ff_v4l2_buffer_enqueue(avbuf);
+ if (!V4L2_TYPE_IS_OUTPUT(ctx->type)) {
+ if (buf_to_m2mctx(avbuf)->output_drm) {
@@ -47019,19 +50852,20 @@ Upstream-status: Pending
+ av_buffer_unref(&bufref);
+ return ret;
}
-
+
int ff_v4l2_buffer_enqueue(V4L2Buffer* avbuf)
-@@ -564,9 +928,27 @@ int ff_v4l2_buffer_enqueue(V4L2Buffer* a
-
- avbuf->buf.flags = avbuf->flags;
-
+ {
+ int ret;
++ int qc;
+
+- avbuf->buf.flags = avbuf->flags;
+ if (avbuf->buf.timestamp.tv_sec || avbuf->buf.timestamp.tv_usec) {
+ av_log(logger(avbuf), AV_LOG_DEBUG, "--- %s pre VIDIOC_QBUF: index %d, ts=%ld.%06ld count=%d\n",
+ avbuf->context->name, avbuf->buf.index,
+ avbuf->buf.timestamp.tv_sec, avbuf->buf.timestamp.tv_usec,
+ avbuf->context->q_count);
+ }
-+
+
ret = ioctl(buf_to_m2mctx(avbuf)->fd, VIDIOC_QBUF, &avbuf->buf);
- if (ret < 0)
- return AVERROR(errno);
@@ -47042,31 +50876,34 @@ Upstream-status: Pending
+ err, strerror(err));
+ return AVERROR(err);
+ }
+
++ // Lock not wanted - if called from buffer free then lock already obtained
++ qc = atomic_fetch_add(&avbuf->context->q_count, 1) + 1;
+ avbuf->status = V4L2BUF_IN_DRIVER;
++ pthread_cond_broadcast(&avbuf->context->cond);
+
-+ ++avbuf->context->q_count;
+ av_log(logger(avbuf), AV_LOG_DEBUG, "--- %s VIDIOC_QBUF: index %d, ts=%ld.%06ld count=%d\n",
+ avbuf->context->name, avbuf->buf.index,
-+ avbuf->buf.timestamp.tv_sec, avbuf->buf.timestamp.tv_usec,
-+ avbuf->context->q_count);
-
- avbuf->status = V4L2BUF_IN_DRIVER;
-
++ avbuf->buf.timestamp.tv_sec, avbuf->buf.timestamp.tv_usec, qc);
+
+ return 0;
+ }
--- a/libavcodec/v4l2_buffers.h
+++ b/libavcodec/v4l2_buffers.h
-@@ -27,25 +27,34 @@
+@@ -27,25 +27,38 @@
#include <stdatomic.h>
#include <linux/videodev2.h>
-
+
+#include "libavutil/hwcontext_drm.h"
#include "avcodec.h"
-
+
enum V4L2Buffer_status {
V4L2BUF_AVAILABLE,
V4L2BUF_IN_DRIVER,
+ V4L2BUF_IN_USE,
V4L2BUF_RET_USER,
};
-
+
/**
* V4L2Buffer (wrapper for v4l2_buffer management)
*/
@@ -47083,49 +50920,70 @@ Upstream-status: Pending
+ */
struct V4L2Context *context;
+ struct ff_weak_link_client *context_wl;
-
+
- /* This object is refcounted per-plane, so we need to keep track
- * of how many context-refs we are holding. */
- AVBufferRef *context_ref;
- atomic_uint context_refcount;
+ /* DRM descriptor */
+ AVDRMFrameDescriptor drm_frame;
-
++ /* For DRM_PRIME encode - need to keep a ref to the source buffer till we
++ * are done
++ */
++ AVBufferRef * ref_buf;
+
/* keep track of the mmap address and mmap length */
struct V4L2Plane_info {
-@@ -70,11 +79,12 @@ typedef struct V4L2Buffer {
- *
- * @param[in] frame The AVFRame to push the information to
- * @param[in] buf The V4L2Buffer to get the information from
-+ * @param[in] no_rescale_pts If non-zero do not rescale PTS
- *
- * @returns 0 in case of success, AVERROR(EINVAL) if the number of planes is incorrect,
- * AVERROR(ENOMEM) if the AVBufferRef can't be created.
- */
--int ff_v4l2_buffer_buf_to_avframe(AVFrame *frame, V4L2Buffer *buf);
-+int ff_v4l2_buffer_buf_to_avframe(AVFrame *frame, V4L2Buffer *buf, int no_rescale_pts);
-
- /**
- * Extracts the data from a V4L2Buffer to an AVPacket
-@@ -98,6 +108,9 @@ int ff_v4l2_buffer_buf_to_avpkt(AVPacket
+@@ -60,7 +73,6 @@ typedef struct V4L2Buffer {
+ struct v4l2_buffer buf;
+ struct v4l2_plane planes[VIDEO_MAX_PLANES];
+
+- int flags;
+ enum V4L2Buffer_status status;
+
+ } V4L2Buffer;
+@@ -98,6 +110,10 @@ int ff_v4l2_buffer_buf_to_avpkt(AVPacket
*/
int ff_v4l2_buffer_avpkt_to_buf(const AVPacket *pkt, V4L2Buffer *out);
-
-+int ff_v4l2_buffer_avpkt_to_buf_ext(const AVPacket *pkt, V4L2Buffer *out,
-+ const void *extdata, size_t extlen, int no_rescale_pts);
+
++int ff_v4l2_buffer_avpkt_to_buf_ext(const AVPacket * const pkt, V4L2Buffer * const out,
++ const void *extdata, size_t extlen,
++ const int64_t timestamp);
+
/**
* Extracts the data from an AVFrame to a V4L2Buffer
*
-@@ -116,7 +129,7 @@ int ff_v4l2_buffer_avframe_to_buf(const
+@@ -106,7 +122,7 @@ int ff_v4l2_buffer_avpkt_to_buf(const AV
+ *
+ * @returns 0 in case of success, a negative AVERROR code otherwise
+ */
+-int ff_v4l2_buffer_avframe_to_buf(const AVFrame *frame, V4L2Buffer *out);
++int ff_v4l2_buffer_avframe_to_buf(const AVFrame *frame, V4L2Buffer *out, const int64_t track_ts);
+
+ /**
+ * Initializes a V4L2Buffer
+@@ -116,7 +132,7 @@ int ff_v4l2_buffer_avframe_to_buf(const
*
* @returns 0 in case of success, a negative AVERROR code otherwise
*/
-int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index);
-+int ff_v4l2_buffer_initialize(AVBufferRef **avbuf, int index, struct V4L2Context *ctx);
-
++int ff_v4l2_buffer_initialize(AVBufferRef **avbuf, int index, struct V4L2Context *ctx, enum v4l2_memory mem);
+
/**
* Enqueues a V4L2Buffer
+@@ -127,5 +143,12 @@ int ff_v4l2_buffer_initialize(V4L2Buffer
+ */
+ int ff_v4l2_buffer_enqueue(V4L2Buffer* avbuf);
+
++static inline void
++ff_v4l2_buffer_set_avail(V4L2Buffer* const avbuf)
++{
++ avbuf->status = V4L2BUF_AVAILABLE;
++ av_buffer_unref(&avbuf->ref_buf);
++}
++
+
+ #endif // AVCODEC_V4L2_BUFFERS_H
--- a/libavcodec/v4l2_context.c
+++ b/libavcodec/v4l2_context.c
@@ -27,11 +27,13 @@
@@ -47139,41 +50997,233 @@ Upstream-status: Pending
#include "v4l2_fmt.h"
#include "v4l2_m2m.h"
+#include "weak_link.h"
-
+
struct v4l2_format_update {
uint32_t v4l2_fmt;
-@@ -53,16 +55,6 @@ static inline AVCodecContext *logger(V4L
- return ctx_to_m2mctx(ctx)->avctx;
+@@ -41,26 +43,168 @@ struct v4l2_format_update {
+ int update_avfmt;
+ };
+
+-static inline V4L2m2mContext *ctx_to_m2mctx(V4L2Context *ctx)
++
++static inline int64_t track_to_pts(AVCodecContext *avctx, unsigned int n)
+ {
+- return V4L2_TYPE_IS_OUTPUT(ctx->type) ?
+- container_of(ctx, V4L2m2mContext, output) :
+- container_of(ctx, V4L2m2mContext, capture);
++ return (int64_t)n;
}
-
+
+-static inline AVCodecContext *logger(V4L2Context *ctx)
++static inline unsigned int pts_to_track(AVCodecContext *avctx, const int64_t pts)
+ {
+- return ctx_to_m2mctx(ctx)->avctx;
++ return (unsigned int)pts;
+ }
+
-static inline unsigned int v4l2_get_width(struct v4l2_format *fmt)
--{
++// FFmpeg requires us to propagate a number of vars from the coded pkt into
++// the decoded frame. The only thing that tracks like that in V4L2 stateful
++// is timestamp. PTS maps to timestamp for this decode. FFmpeg makes no
++// guarantees about PTS being unique or specified for every frame so replace
++// the supplied PTS with a simple incrementing number and keep a circular
++// buffer of all the things we want preserved (including the original PTS)
++// indexed by the tracking no.
++static int64_t
++xlat_pts_pkt_in(AVCodecContext *const avctx, xlat_track_t *const x, const AVPacket *const avpkt)
+ {
- return V4L2_TYPE_IS_MULTIPLANAR(fmt->type) ? fmt->fmt.pix_mp.width : fmt->fmt.pix.width;
--}
--
++ int64_t track_pts;
++
++ // Avoid 0
++ if (++x->track_no == 0)
++ x->track_no = 1;
++
++ track_pts = track_to_pts(avctx, x->track_no);
++
++ av_log(avctx, AV_LOG_TRACE, "In pkt PTS=%" PRId64 ", DTS=%" PRId64 ", track=%" PRId64 ", n=%u\n", avpkt->pts, avpkt->dts, track_pts, x->track_no);
++ x->track_els[x->track_no % FF_V4L2_M2M_TRACK_SIZE] = (V4L2m2mTrackEl){
++ .discard = 0,
++ .pending = 1,
++ .pkt_size = avpkt->size,
++ .pts = avpkt->pts,
++ .dts = avpkt->dts,
++ .reordered_opaque = avctx->reordered_opaque,
++ .pkt_pos = avpkt->pos,
++ .pkt_duration = avpkt->duration,
++ .track_pts = track_pts
++ };
++ return track_pts;
+ }
+
-static inline unsigned int v4l2_get_height(struct v4l2_format *fmt)
--{
++static int64_t
++xlat_pts_frame_in(AVCodecContext *const avctx, xlat_track_t *const x, const AVFrame *const frame)
+ {
- return V4L2_TYPE_IS_MULTIPLANAR(fmt->type) ? fmt->fmt.pix_mp.height : fmt->fmt.pix.height;
--}
--
++ int64_t track_pts;
++
++ // Avoid 0
++ if (++x->track_no == 0)
++ x->track_no = 1;
++
++ track_pts = track_to_pts(avctx, x->track_no);
++
++ av_log(avctx, AV_LOG_TRACE, "In frame PTS=%" PRId64 ", track=%" PRId64 ", n=%u\n", frame->pts, track_pts, x->track_no);
++ x->track_els[x->track_no % FF_V4L2_M2M_TRACK_SIZE] = (V4L2m2mTrackEl){
++ .discard = 0,
++ .pending = 1,
++ .pkt_size = 0,
++ .pts = frame->pts,
++ .dts = AV_NOPTS_VALUE,
++ .reordered_opaque = frame->reordered_opaque,
++ .pkt_pos = frame->pkt_pos,
++ .pkt_duration = frame->pkt_duration,
++ .track_pts = track_pts
++ };
++ return track_pts;
++}
++
++
++// Returns -1 if we should discard the frame
++static int
++xlat_pts_frame_out(AVCodecContext *const avctx,
++ xlat_track_t * const x,
++ AVFrame *const frame)
++{
++ unsigned int n = pts_to_track(avctx, frame->pts) % FF_V4L2_M2M_TRACK_SIZE;
++ V4L2m2mTrackEl *const t = x->track_els + n;
++ if (frame->pts == AV_NOPTS_VALUE || frame->pts != t->track_pts)
++ {
++ av_log(avctx, frame->pts == AV_NOPTS_VALUE ? AV_LOG_DEBUG : AV_LOG_WARNING,
++ "Frame tracking failure: pts=%" PRId64 ", track[%d]=%" PRId64 "\n", frame->pts, n, t->track_pts);
++ frame->pts = AV_NOPTS_VALUE;
++ frame->pkt_dts = AV_NOPTS_VALUE;
++ frame->reordered_opaque = x->last_opaque;
++ frame->pkt_pos = -1;
++ frame->pkt_duration = 0;
++ frame->pkt_size = -1;
++ }
++ else if (!t->discard)
++ {
++ frame->pts = t->pending ? t->pts : AV_NOPTS_VALUE;
++ frame->pkt_dts = t->dts;
++ frame->reordered_opaque = t->reordered_opaque;
++ frame->pkt_pos = t->pkt_pos;
++ frame->pkt_duration = t->pkt_duration;
++ frame->pkt_size = t->pkt_size;
++
++ x->last_opaque = x->track_els[n].reordered_opaque;
++ if (frame->pts != AV_NOPTS_VALUE)
++ x->last_pts = frame->pts;
++ t->pending = 0;
++ }
++ else
++ {
++ av_log(avctx, AV_LOG_DEBUG, "Discard frame (flushed): pts=%" PRId64 ", track[%d]=%" PRId64 "\n", frame->pts, n, t->track_pts);
++ return -1;
++ }
++
++ av_log(avctx, AV_LOG_TRACE, "Out frame PTS=%" PRId64 "/%"PRId64", DTS=%" PRId64 ", track=%"PRId64", n=%d\n",
++ frame->pts, frame->best_effort_timestamp, frame->pkt_dts, t->track_pts, n);
++ return 0;
++}
++
++// Returns -1 if we should discard the frame
++static int
++xlat_pts_pkt_out(AVCodecContext *const avctx,
++ xlat_track_t * const x,
++ AVPacket *const pkt)
++{
++ unsigned int n = pts_to_track(avctx, pkt->pts) % FF_V4L2_M2M_TRACK_SIZE;
++ V4L2m2mTrackEl *const t = x->track_els + n;
++ if (pkt->pts == AV_NOPTS_VALUE || pkt->pts != t->track_pts)
++ {
++ av_log(avctx, pkt->pts == AV_NOPTS_VALUE ? AV_LOG_DEBUG : AV_LOG_WARNING,
++ "Pkt tracking failure: pts=%" PRId64 ", track[%d]=%" PRId64 "\n", pkt->pts, n, t->track_pts);
++ pkt->pts = AV_NOPTS_VALUE;
++ }
++ else if (!t->discard)
++ {
++ pkt->pts = t->pending ? t->pts : AV_NOPTS_VALUE;
++
++ x->last_opaque = x->track_els[n].reordered_opaque;
++ if (pkt->pts != AV_NOPTS_VALUE)
++ x->last_pts = pkt->pts;
++ t->pending = 0;
++ }
++ else
++ {
++ av_log(avctx, AV_LOG_DEBUG, "Discard packet (flushed): pts=%" PRId64 ", track[%d]=%" PRId64 "\n", pkt->pts, n, t->track_pts);
++ return -1;
++ }
++
++ // * Would like something much better than this...xlat(offset + out_count)?
++ pkt->dts = pkt->pts;
++ av_log(avctx, AV_LOG_TRACE, "Out pkt PTS=%" PRId64 ", track=%"PRId64", n=%d\n",
++ pkt->pts, t->track_pts, n);
++ return 0;
++}
++
++
++static inline V4L2m2mContext *ctx_to_m2mctx(const V4L2Context *ctx)
++{
++ return V4L2_TYPE_IS_OUTPUT(ctx->type) ?
++ container_of(ctx, V4L2m2mContext, output) :
++ container_of(ctx, V4L2m2mContext, capture);
++}
++
++static inline AVCodecContext *logger(const V4L2Context *ctx)
++{
++ return ctx_to_m2mctx(ctx)->avctx;
+ }
+
static AVRational v4l2_get_sar(V4L2Context *ctx)
+@@ -81,21 +225,29 @@ static AVRational v4l2_get_sar(V4L2Conte
+ return sar;
+ }
+
+-static inline unsigned int v4l2_resolution_changed(V4L2Context *ctx, struct v4l2_format *fmt2)
++static inline int ctx_buffers_alloced(const V4L2Context * const ctx)
++{
++ return ctx->bufrefs != NULL;
++}
++
++// Width/Height changed or we don't have an alloc in the first place?
++static int ctx_resolution_changed(const V4L2Context *ctx, const struct v4l2_format *fmt2)
{
- struct AVRational sar = { 0, 1 };
-@@ -94,8 +86,8 @@ static inline unsigned int v4l2_resoluti
+- struct v4l2_format *fmt1 = &ctx->format;
+- int ret = V4L2_TYPE_IS_MULTIPLANAR(ctx->type) ?
+- fmt1->fmt.pix_mp.width != fmt2->fmt.pix_mp.width ||
+- fmt1->fmt.pix_mp.height != fmt2->fmt.pix_mp.height
+- :
+- fmt1->fmt.pix.width != fmt2->fmt.pix.width ||
+- fmt1->fmt.pix.height != fmt2->fmt.pix.height;
++ const struct v4l2_format *fmt1 = &ctx->format;
++ int ret = !ctx_buffers_alloced(ctx) ||
++ (V4L2_TYPE_IS_MULTIPLANAR(ctx->type) ?
++ fmt1->fmt.pix_mp.width != fmt2->fmt.pix_mp.width ||
++ fmt1->fmt.pix_mp.height != fmt2->fmt.pix_mp.height
++ :
++ fmt1->fmt.pix.width != fmt2->fmt.pix.width ||
++ fmt1->fmt.pix.height != fmt2->fmt.pix.height);
+
if (ret)
- av_log(logger(ctx), AV_LOG_DEBUG, "%s changed (%dx%d) -> (%dx%d)\n",
+- av_log(logger(ctx), AV_LOG_DEBUG, "%s changed (%dx%d) -> (%dx%d)\n",
++ av_log(logger(ctx), AV_LOG_DEBUG, "V4L2 %s changed: alloc=%d (%dx%d) -> (%dx%d)\n",
ctx->name,
- v4l2_get_width(fmt1), v4l2_get_height(fmt1),
- v4l2_get_width(fmt2), v4l2_get_height(fmt2));
++ ctx_buffers_alloced(ctx),
+ ff_v4l2_get_format_width(fmt1), ff_v4l2_get_format_height(fmt1),
+ ff_v4l2_get_format_width(fmt2), ff_v4l2_get_format_height(fmt2));
-
+
return ret;
}
-@@ -153,58 +145,67 @@ static inline void v4l2_save_to_context(
+@@ -153,90 +305,110 @@ static inline void v4l2_save_to_context(
}
}
-
+
-/**
- * handle resolution change event and end of stream event
- * returns 1 if reinit was successful, negative if it failed
@@ -47192,7 +51242,7 @@ Upstream-status: Pending
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ .target = V4L2_SEL_TGT_COMPOSE
+ };
-
+
- ret = ioctl(s->fd, VIDIOC_DQEVENT, &evt);
- if (ret < 0) {
- av_log(logger(ctx), AV_LOG_ERROR, "%s VIDIOC_DQEVENT\n", ctx->name);
@@ -47201,7 +51251,7 @@ Upstream-status: Pending
+ memset(r, 0, sizeof(*r));
+ if (ioctl(s->fd, VIDIOC_G_SELECTION, &selection))
+ return AVERROR(errno);
-
+
- if (evt.type == V4L2_EVENT_EOS) {
- ctx->done = 1;
- return 0;
@@ -47209,49 +51259,45 @@ Upstream-status: Pending
+ *r = selection.r;
+ return 0;
+}
-
+
- if (evt.type != V4L2_EVENT_SOURCE_CHANGE)
- return 0;
+static int do_source_change(V4L2m2mContext * const s)
+{
+ AVCodecContext *const avctx = s->avctx;
-+
+
+- ret = ioctl(s->fd, VIDIOC_G_FMT, &out_fmt);
+- if (ret) {
+- av_log(logger(ctx), AV_LOG_ERROR, "%s VIDIOC_G_FMT\n", s->output.name);
+- return 0;
+- }
+ int ret;
+ int reinit;
-+ int full_reinit;
+ struct v4l2_format cap_fmt = s->capture.format;
-+ struct v4l2_format out_fmt = s->output.format;
+
-+ s->resize_pending = 0;
+ s->capture.done = 0;
-
- ret = ioctl(s->fd, VIDIOC_G_FMT, &out_fmt);
- if (ret) {
-- av_log(logger(ctx), AV_LOG_ERROR, "%s VIDIOC_G_FMT\n", s->output.name);
-+ av_log(avctx, AV_LOG_ERROR, "%s VIDIOC_G_FMT failed\n", s->output.name);
- return 0;
- }
-
+
ret = ioctl(s->fd, VIDIOC_G_FMT, &cap_fmt);
if (ret) {
- av_log(logger(ctx), AV_LOG_ERROR, "%s VIDIOC_G_FMT\n", s->capture.name);
+ av_log(avctx, AV_LOG_ERROR, "%s VIDIOC_G_FMT failed\n", s->capture.name);
return 0;
}
-
- full_reinit = v4l2_resolution_changed(&s->output, &out_fmt);
- if (full_reinit) {
+
+- full_reinit = v4l2_resolution_changed(&s->output, &out_fmt);
+- if (full_reinit) {
- s->output.height = v4l2_get_height(&out_fmt);
- s->output.width = v4l2_get_width(&out_fmt);
- s->output.sample_aspect_ratio = v4l2_get_sar(&s->output);
-+ s->output.height = ff_v4l2_get_format_height(&out_fmt);
-+ s->output.width = ff_v4l2_get_format_width(&out_fmt);
- }
-+ s->output.sample_aspect_ratio = v4l2_get_sar(&s->output);
-+
+- }
+ get_default_selection(&s->capture, &s->capture.selection);
-
- reinit = v4l2_resolution_changed(&s->capture, &cap_fmt);
++
++ reinit = ctx_resolution_changed(&s->capture, &cap_fmt);
++ if ((s->quirks & FF_V4L2_QUIRK_REINIT_ALWAYS) != 0)
++ reinit = 1;
+
+- reinit = v4l2_resolution_changed(&s->capture, &cap_fmt);
++ s->capture.format = cap_fmt;
if (reinit) {
- s->capture.height = v4l2_get_height(&cap_fmt);
- s->capture.width = v4l2_get_width(&cap_fmt);
@@ -47259,368 +51305,491 @@ Upstream-status: Pending
+ s->capture.height = ff_v4l2_get_format_height(&cap_fmt);
+ s->capture.width = ff_v4l2_get_format_width(&cap_fmt);
}
+
+- if (full_reinit || reinit)
+- s->reinit = 1;
+-
+- if (full_reinit) {
+- ret = ff_v4l2_m2m_codec_full_reinit(s);
+- if (ret) {
+- av_log(logger(ctx), AV_LOG_ERROR, "v4l2_m2m_codec_full_reinit\n");
+- return AVERROR(EINVAL);
+- }
+- goto reinit_run;
++ // If we don't support selection (or it is bust) and we obviously have HD then kludge
++ if ((s->capture.selection.width == 0 || s->capture.selection.height == 0) &&
++ (s->capture.height == 1088 && s->capture.width == 1920)) {
++ s->capture.selection = (struct v4l2_rect){.width = 1920, .height = 1080};
+ }
+
+ s->capture.sample_aspect_ratio = v4l2_get_sar(&s->capture);
+
-+ av_log(avctx, AV_LOG_DEBUG, "Source change: SAR: %d/%d, crop %dx%d @ %d,%d\n",
++ av_log(avctx, AV_LOG_DEBUG, "Source change: SAR: %d/%d, wxh %dx%d crop %dx%d @ %d,%d, reinit=%d\n",
+ s->capture.sample_aspect_ratio.num, s->capture.sample_aspect_ratio.den,
++ s->capture.width, s->capture.height,
+ s->capture.selection.width, s->capture.selection.height,
-+ s->capture.selection.left, s->capture.selection.top);
-
- if (full_reinit || reinit)
- s->reinit = 1;
-@@ -212,34 +213,88 @@ static int v4l2_handle_event(V4L2Context
- if (full_reinit) {
- ret = ff_v4l2_m2m_codec_full_reinit(s);
- if (ret) {
-- av_log(logger(ctx), AV_LOG_ERROR, "v4l2_m2m_codec_full_reinit\n");
-+ av_log(avctx, AV_LOG_ERROR, "v4l2_m2m_codec_full_reinit failed\n");
- return AVERROR(EINVAL);
- }
- goto reinit_run;
- }
-
++ s->capture.selection.left, s->capture.selection.top, reinit);
++
if (reinit) {
- if (s->avctx)
+- ret = ff_set_dimensions(s->avctx, s->capture.width, s->capture.height);
+ if (avctx)
- ret = ff_set_dimensions(s->avctx, s->capture.width, s->capture.height);
++ ret = ff_set_dimensions(s->avctx,
++ s->capture.selection.width != 0 ? s->capture.selection.width : s->capture.width,
++ s->capture.selection.height != 0 ? s->capture.selection.height : s->capture.height);
if (ret < 0)
- av_log(logger(ctx), AV_LOG_WARNING, "update avcodec height and width\n");
+ av_log(avctx, AV_LOG_WARNING, "update avcodec height and width failed\n");
-
+
ret = ff_v4l2_m2m_codec_reinit(s);
if (ret) {
- av_log(logger(ctx), AV_LOG_ERROR, "v4l2_m2m_codec_reinit\n");
+ av_log(avctx, AV_LOG_ERROR, "v4l2_m2m_codec_reinit failed\n");
return AVERROR(EINVAL);
}
++
++ if (s->capture.width > ff_v4l2_get_format_width(&s->capture.format) ||
++ s->capture.height > ff_v4l2_get_format_height(&s->capture.format)) {
++ av_log(avctx, AV_LOG_ERROR, "Format post reinit too small: wanted %dx%d > got %dx%d\n",
++ s->capture.width, s->capture.height,
++ ff_v4l2_get_format_width(&s->capture.format), ff_v4l2_get_format_height(&s->capture.format));
++ return AVERROR(EINVAL);
++ }
++
++ // Update pixel format - should only actually do something on initial change
++ s->capture.av_pix_fmt =
++ ff_v4l2_format_v4l2_to_avfmt(ff_v4l2_get_format_pixelformat(&s->capture.format), AV_CODEC_ID_RAWVIDEO);
++ if (s->output_drm) {
++ avctx->pix_fmt = AV_PIX_FMT_DRM_PRIME;
++ avctx->sw_pix_fmt = s->capture.av_pix_fmt;
++ }
++ else
++ avctx->pix_fmt = s->capture.av_pix_fmt;
++
goto reinit_run;
}
-
+
- /* dummy event received */
- return 0;
+ /* Buffers are OK so just stream off to ack */
-+ av_log(avctx, AV_LOG_DEBUG, "%s: Parameters only\n", __func__);
++ av_log(avctx, AV_LOG_DEBUG, "%s: Parameters only - restart decode\n", __func__);
+
+ ret = ff_v4l2_context_set_status(&s->capture, VIDIOC_STREAMOFF);
+ if (ret)
+ av_log(avctx, AV_LOG_ERROR, "capture VIDIOC_STREAMOFF failed\n");
+ s->draining = 0;
-
+
/* reinit executed */
reinit_run:
+ ret = ff_v4l2_context_set_status(&s->capture, VIDIOC_STREAMON);
return 1;
}
-
-+static int ctx_done(V4L2Context * const ctx)
-+{
-+ int rv = 0;
-+ V4L2m2mContext * const s = ctx_to_m2mctx(ctx);
-+
-+ ctx->done = 1;
-+
-+ if (s->resize_pending && !V4L2_TYPE_IS_OUTPUT(ctx->type))
-+ rv = do_source_change(s);
-+
-+ return rv;
-+}
-+
-+/**
-+ * handle resolution change event and end of stream event
-+ * returns 1 if reinit was successful, negative if it failed
-+ * returns 0 if reinit was not executed
-+ */
-+static int v4l2_handle_event(V4L2Context *ctx)
-+{
-+ V4L2m2mContext * const s = ctx_to_m2mctx(ctx);
-+ struct v4l2_event evt = { 0 };
-+ int ret;
-+
-+ ret = ioctl(s->fd, VIDIOC_DQEVENT, &evt);
-+ if (ret < 0) {
-+ av_log(logger(ctx), AV_LOG_ERROR, "%s VIDIOC_DQEVENT\n", ctx->name);
-+ return 0;
-+ }
-+
-+ av_log(logger(ctx), AV_LOG_INFO, "Dq event %d\n", evt.type);
-+
-+ if (evt.type == V4L2_EVENT_EOS) {
-+// ctx->done = 1;
-+ av_log(logger(ctx), AV_LOG_TRACE, "%s VIDIOC_EVENT_EOS\n", ctx->name);
-+ return 0;
-+ }
-+
-+ if (evt.type != V4L2_EVENT_SOURCE_CHANGE)
-+ return 0;
-+
-+ s->resize_pending = 1;
-+ if (!ctx->done)
-+ return 0;
-+
-+ return do_source_change(s);
-+}
-+
- static int v4l2_stop_decode(V4L2Context *ctx)
- {
- struct v4l2_decoder_cmd cmd = {
-@@ -280,8 +335,26 @@ static int v4l2_stop_encode(V4L2Context
+
+@@ -280,171 +452,277 @@ static int v4l2_stop_encode(V4L2Context
return 0;
}
-
-+static int count_in_driver(const V4L2Context * const ctx)
-+{
-+ int i;
-+ int n = 0;
+
+-static V4L2Buffer* v4l2_dequeue_v4l2buf(V4L2Context *ctx, int timeout)
+-{
+- struct v4l2_plane planes[VIDEO_MAX_PLANES];
+- struct v4l2_buffer buf = { 0 };
+- V4L2Buffer *avbuf;
+- struct pollfd pfd = {
+- .events = POLLIN | POLLRDNORM | POLLPRI | POLLOUT | POLLWRNORM, /* default blocking capture */
+- .fd = ctx_to_m2mctx(ctx)->fd,
++// DQ a buffer
++// Amalgamates all the various ways there are of signalling EOS/Event to
++// generate a consistant EPIPE.
++//
++// Sets ctx->flag_last if next dq would produce EPIPE (i.e. stream has stopped)
++//
++// Returns:
++// 0 Success
++// AVERROR(EPIPE) Nothing more to read
++// AVERROR(ENOSPC) No buffers in Q to put result in
++// * AVERROR(..)
+
-+ if (!ctx->bufrefs)
-+ return -1;
++ static int
++dq_buf(V4L2Context * const ctx, V4L2Buffer ** const ppavbuf)
++{
++ V4L2m2mContext * const m = ctx_to_m2mctx(ctx);
++ AVCodecContext * const avctx = m->avctx;
++ V4L2Buffer * avbuf;
++ const int is_mp = V4L2_TYPE_IS_MULTIPLANAR(ctx->type);
+
-+ for (i = 0; i < ctx->num_buffers; ++i) {
-+ V4L2Buffer *const avbuf = (V4L2Buffer *)ctx->bufrefs[i]->data;
-+ if (avbuf->status == V4L2BUF_IN_DRIVER)
-+ ++n;
-+ }
-+ return n;
-+}
++ struct v4l2_plane planes[VIDEO_MAX_PLANES] = {{0}};
+
- static V4L2Buffer* v4l2_dequeue_v4l2buf(V4L2Context *ctx, int timeout)
- {
-+ V4L2m2mContext * const s = ctx_to_m2mctx(ctx);
-+ const int is_capture = !V4L2_TYPE_IS_OUTPUT(ctx->type);
- struct v4l2_plane planes[VIDEO_MAX_PLANES];
- struct v4l2_buffer buf = { 0 };
- V4L2Buffer *avbuf;
-@@ -290,50 +363,84 @@ static V4L2Buffer* v4l2_dequeue_v4l2buf(
- .fd = ctx_to_m2mctx(ctx)->fd,
++ struct v4l2_buffer buf = {
++ .type = ctx->type,
++ .memory = V4L2_MEMORY_MMAP,
};
- int i, ret;
-+ int no_rx_means_done = 0;
-
+- int i, ret;
+
- if (!V4L2_TYPE_IS_OUTPUT(ctx->type) && ctx->buffers) {
-+ if (is_capture && ctx->bufrefs) {
- for (i = 0; i < ctx->num_buffers; i++) {
+- for (i = 0; i < ctx->num_buffers; i++) {
- if (ctx->buffers[i].status == V4L2BUF_IN_DRIVER)
-+ avbuf = (V4L2Buffer *)ctx->bufrefs[i]->data;
-+ if (avbuf->status == V4L2BUF_IN_DRIVER)
- break;
- }
- if (i == ctx->num_buffers)
+- break;
+- }
+- if (i == ctx->num_buffers)
- av_log(logger(ctx), AV_LOG_WARNING, "All capture buffers returned to "
-+ av_log(logger(ctx), AV_LOG_WARNING, "All capture buffers (%d) returned to "
- "userspace. Increase num_capture_buffers "
- "to prevent device deadlock or dropped "
+- "userspace. Increase num_capture_buffers "
+- "to prevent device deadlock or dropped "
- "packets/frames.\n");
-+ "packets/frames.\n", i);
- }
-
-+#if 0
-+ // I think this is true but pointless
-+ // we will get some other form of EOF signal
-+
- /* if we are draining and there are no more capture buffers queued in the driver we are done */
+- }
+-
+- /* if we are draining and there are no more capture buffers queued in the driver we are done */
- if (!V4L2_TYPE_IS_OUTPUT(ctx->type) && ctx_to_m2mctx(ctx)->draining) {
-+ if (is_capture && ctx_to_m2mctx(ctx)->draining) {
- for (i = 0; i < ctx->num_buffers; i++) {
- /* capture buffer initialization happens during decode hence
- * detection happens at runtime
- */
+- for (i = 0; i < ctx->num_buffers; i++) {
+- /* capture buffer initialization happens during decode hence
+- * detection happens at runtime
+- */
- if (!ctx->buffers)
-+ if (!ctx->bufrefs)
- break;
-
+- break;
+-
- if (ctx->buffers[i].status == V4L2BUF_IN_DRIVER)
-+ avbuf = (V4L2Buffer *)ctx->bufrefs[i]->data;
-+ if (avbuf->status == V4L2BUF_IN_DRIVER)
- goto start;
- }
- ctx->done = 1;
- return NULL;
- }
-+#endif
-
- start:
+- goto start;
+- }
+- ctx->done = 1;
+- return NULL;
+- }
+-
+-start:
- if (V4L2_TYPE_IS_OUTPUT(ctx->type))
- pfd.events = POLLOUT | POLLWRNORM;
- else {
-+ if (is_capture) {
- /* no need to listen to requests for more input while draining */
- if (ctx_to_m2mctx(ctx)->draining)
- pfd.events = POLLIN | POLLRDNORM | POLLPRI;
-+ } else {
-+ pfd.events = POLLOUT | POLLWRNORM;
- }
-+ no_rx_means_done = s->resize_pending && is_capture;
-
- for (;;) {
-- ret = poll(&pfd, 1, timeout);
-+ // If we have a resize pending then all buffers should be Qed
-+ // With a resize pending we should be in drain but evidence suggests
-+ // that not all decoders do this so poll to clear
-+ int t2 = no_rx_means_done ? 0 : timeout < 0 ? 3000 : timeout;
-+ const int e = pfd.events;
+- /* no need to listen to requests for more input while draining */
+- if (ctx_to_m2mctx(ctx)->draining)
+- pfd.events = POLLIN | POLLRDNORM | POLLPRI;
++ *ppavbuf = NULL;
+
-+ ret = poll(&pfd, 1, t2);
++ if (ctx->flag_last)
++ return AVERROR(EPIPE);
+
- if (ret > 0)
- break;
++ if (is_mp) {
++ buf.length = VIDEO_MAX_PLANES;
++ buf.m.planes = planes;
+ }
+
+- for (;;) {
+- ret = poll(&pfd, 1, timeout);
+- if (ret > 0)
+- break;
- if (errno == EINTR)
- continue;
+- return NULL;
++ while (ioctl(m->fd, VIDIOC_DQBUF, &buf) != 0) {
++ const int err = errno;
++ av_assert0(AVERROR(err) < 0);
++ if (err != EINTR) {
++ av_log(avctx, AV_LOG_DEBUG, "%s VIDIOC_DQBUF, errno (%s)\n",
++ ctx->name, av_err2str(AVERROR(err)));
+
-+ if (ret < 0) {
-+ int err = errno;
-+ if (err == EINTR)
-+ continue;
-+ av_log(logger(ctx), AV_LOG_ERROR, "=== poll error %d (%s): events=%#x, cap buffers=%d\n",
-+ err, strerror(err),
-+ e, count_in_driver(ctx));
-+ return NULL;
-+ }
++ if (err == EPIPE)
++ ctx->flag_last = 1;
+
-+ // ret == 0 (timeout)
-+ if (no_rx_means_done) {
-+ av_log(logger(ctx), AV_LOG_DEBUG, "Ctx done on timeout\n");
-+ ret = ctx_done(ctx);
-+ if (ret > 0)
-+ goto start;
++ return AVERROR(err);
+ }
-+ if (timeout == -1)
-+ av_log(logger(ctx), AV_LOG_ERROR, "=== poll unexpected TIMEOUT: events=%#x, cap buffers=%d\n", e, count_in_driver(ctx));;
- return NULL;
}
-
-@@ -343,7 +450,8 @@ start:
- no need to raise a warning */
- if (timeout == 0) {
- for (i = 0; i < ctx->num_buffers; i++) {
++ atomic_fetch_sub(&ctx->q_count, 1);
+
+- /* 0. handle errors */
+- if (pfd.revents & POLLERR) {
+- /* if we are trying to get free buffers but none have been queued yet
+- no need to raise a warning */
+- if (timeout == 0) {
+- for (i = 0; i < ctx->num_buffers; i++) {
- if (ctx->buffers[i].status != V4L2BUF_AVAILABLE)
-+ avbuf = (V4L2Buffer *)ctx->bufrefs[i]->data;
-+ if (avbuf->status != V4L2BUF_AVAILABLE)
- av_log(logger(ctx), AV_LOG_WARNING, "%s POLLERR\n", ctx->name);
- }
- }
-@@ -361,22 +469,25 @@ start:
- ctx->done = 1;
- return NULL;
+- av_log(logger(ctx), AV_LOG_WARNING, "%s POLLERR\n", ctx->name);
+- }
++ avbuf = (V4L2Buffer *)ctx->bufrefs[buf.index]->data;
++ ff_v4l2_buffer_set_avail(avbuf);
++ avbuf->buf = buf;
++ if (is_mp) {
++ memcpy(avbuf->planes, planes, sizeof(planes));
++ avbuf->buf.m.planes = avbuf->planes;
++ }
++ // Done with any attached buffer
++ av_buffer_unref(&avbuf->ref_buf);
++
++ if (V4L2_TYPE_IS_CAPTURE(ctx->type)) {
++ // Zero length cap buffer return == EOS
++ if ((is_mp ? buf.m.planes[0].bytesused : buf.bytesused) == 0) {
++ av_log(avctx, AV_LOG_DEBUG, "Buffer empty - reQ\n");
++
++ // Must reQ so we don't leak
++ // May not matter if the next thing we do is release all the
++ // buffers but better to be tidy.
++ ff_v4l2_buffer_enqueue(avbuf);
++
++ ctx->flag_last = 1;
++ return AVERROR(EPIPE);
}
+- else
+- av_log(logger(ctx), AV_LOG_WARNING, "%s POLLERR\n", ctx->name);
+
+- return NULL;
++#ifdef V4L2_BUF_FLAG_LAST
++ // If flag_last set then this contains data but is the last frame
++ // so remember that but return OK
++ if ((buf.flags & V4L2_BUF_FLAG_LAST) != 0)
++ ctx->flag_last = 1;
++#endif
+ }
+
+- /* 1. handle resolution changes */
+- if (pfd.revents & POLLPRI) {
+- ret = v4l2_handle_event(ctx);
+- if (ret < 0) {
+- /* if re-init failed, abort */
+- ctx->done = 1;
+- return NULL;
+- }
- if (ret) {
- /* if re-init was successful drop the buffer (if there was one)
- * since we had to reconfigure capture (unmap all buffers)
- */
- return NULL;
-- }
-+ if (ret > 0)
-+ goto start;
++ *ppavbuf = avbuf;
++ return 0;
++}
++
++/**
++ * handle resolution change event and end of stream event
++ * Expects to be called after the stream has stopped
++ *
++ * returns 1 if reinit was successful, negative if it failed
++ * returns 0 if reinit was not executed
++ */
++static int
++get_event(V4L2m2mContext * const m)
++{
++ AVCodecContext * const avctx = m->avctx;
++ struct v4l2_event evt = { 0 };
++
++ while (ioctl(m->fd, VIDIOC_DQEVENT, &evt) != 0) {
++ const int rv = AVERROR(errno);
++ if (rv == AVERROR(EINTR))
++ continue;
++ if (rv == AVERROR(EAGAIN)) {
++ av_log(avctx, AV_LOG_WARNING, "V4L2 failed to get expected event - assume EOS\n");
++ return AVERROR_EOF;
+ }
++ av_log(avctx, AV_LOG_ERROR, "V4L2 VIDIOC_DQEVENT: %s\n", av_err2str(rv));
++ return rv;
}
-
- /* 2. dequeue the buffer */
- if (pfd.revents & (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM)) {
-
+
+- /* 2. dequeue the buffer */
+- if (pfd.revents & (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM)) {
++ av_log(avctx, AV_LOG_DEBUG, "Dq event %d\n", evt.type);
+
- if (!V4L2_TYPE_IS_OUTPUT(ctx->type)) {
-+ if (is_capture) {
- /* there is a capture buffer ready */
- if (pfd.revents & (POLLIN | POLLRDNORM))
- goto dequeue;
-
-+ // CAPTURE Q drained
-+ if (no_rx_means_done) {
-+ if (ctx_done(ctx) > 0)
-+ goto start;
-+ return NULL;
-+ }
+- /* there is a capture buffer ready */
+- if (pfd.revents & (POLLIN | POLLRDNORM))
+- goto dequeue;
++ if (evt.type == V4L2_EVENT_EOS) {
++ av_log(avctx, AV_LOG_TRACE, "V4L2 VIDIOC_EVENT_EOS\n");
++ return AVERROR_EOF;
++ }
++
++ if (evt.type == V4L2_EVENT_SOURCE_CHANGE)
++ return do_source_change(m);
+
- /* the driver is ready to accept more input; instead of waiting for the capture
- * buffer to complete we return NULL so input can proceed (we are single threaded)
- */
-@@ -394,37 +505,58 @@ dequeue:
- buf.m.planes = planes;
++ return 0;
++}
++
++
++// Get a buffer
++// If output then just gets the buffer in the expected way
++// If capture then runs the capture state m/c to deal with res change etc.
++// If return value == 0 then *ppavbuf != NULL
++
++static int
++get_qbuf(V4L2Context * const ctx, V4L2Buffer ** const ppavbuf, const int timeout)
++{
++ V4L2m2mContext * const m = ctx_to_m2mctx(ctx);
++ AVCodecContext * const avctx = m->avctx;
++ const int is_cap = V4L2_TYPE_IS_CAPTURE(ctx->type);
++
++ const unsigned int poll_cap = (POLLIN | POLLRDNORM);
++ const unsigned int poll_out = (POLLOUT | POLLWRNORM);
++ const unsigned int poll_event = POLLPRI;
++
++ *ppavbuf = NULL;
+
+- /* the driver is ready to accept more input; instead of waiting for the capture
+- * buffer to complete we return NULL so input can proceed (we are single threaded)
+- */
+- if (pfd.revents & (POLLOUT | POLLWRNORM))
+- return NULL;
++ for (;;) {
++ struct pollfd pfd = {
++ .fd = m->fd,
++ // If capture && stream not started then assume we are waiting for the initial event
++ .events = !is_cap ? poll_out :
++ !ff_v4l2_ctx_eos(ctx) && ctx->streamon ? poll_cap :
++ poll_event,
++ };
++ int ret;
++
++ if (ctx->done) {
++ av_log(avctx, AV_LOG_TRACE, "V4L2 %s already done\n", ctx->name);
++ return AVERROR_EOF;
}
-
+
+-dequeue:
+- memset(&buf, 0, sizeof(buf));
+- buf.memory = V4L2_MEMORY_MMAP;
+- buf.type = ctx->type;
+- if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type)) {
+- memset(planes, 0, sizeof(planes));
+- buf.length = VIDEO_MAX_PLANES;
+- buf.m.planes = planes;
++ // If capture && timeout == -1 then also wait for rx buffer free
++ if (is_cap && timeout == -1 && m->output.streamon && !m->draining)
++ pfd.events |= poll_out;
++
++ // If nothing Qed all we will get is POLLERR - avoid that
++ if ((pfd.events == poll_out && atomic_load(&m->output.q_count) == 0) ||
++ (pfd.events == poll_cap && atomic_load(&m->capture.q_count) == 0) ||
++ (pfd.events == (poll_cap | poll_out) && atomic_load(&m->capture.q_count) == 0 && atomic_load(&m->output.q_count) == 0)) {
++ av_log(avctx, AV_LOG_TRACE, "V4L2 poll %s empty\n", ctx->name);
++ return AVERROR(ENOSPC);
+ }
+
- ret = ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_DQBUF, &buf);
- if (ret) {
- if (errno != EAGAIN) {
- ctx->done = 1;
- if (errno != EPIPE)
-+ while ((ret = ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_DQBUF, &buf)) == -1) {
-+ const int err = errno;
-+ if (err == EINTR)
-+ continue;
-+ if (err != EAGAIN) {
-+ // EPIPE on CAPTURE can be used instead of BUF_FLAG_LAST
-+ if (err != EPIPE || !is_capture)
- av_log(logger(ctx), AV_LOG_DEBUG, "%s VIDIOC_DQBUF, errno (%s)\n",
+- av_log(logger(ctx), AV_LOG_DEBUG, "%s VIDIOC_DQBUF, errno (%s)\n",
- ctx->name, av_err2str(AVERROR(errno)));
-+ ctx->name, av_err2str(AVERROR(err)));
-+ if (ctx_done(ctx) > 0)
-+ goto start;
++ // Timeout kludged s.t. "forever" eventually gives up & produces logging
++ // If waiting for an event when we have seen a last_frame then we expect
++ // it to be ready already so force a short timeout
++ ret = poll(&pfd, 1,
++ ff_v4l2_ctx_eos(ctx) ? 10 :
++ timeout == -1 ? 3000 : timeout);
++ if (ret < 0) {
++ ret = AVERROR(errno); // Remember errno before logging etc.
++ av_assert0(ret < 0);
++ }
++
++ av_log(avctx, AV_LOG_TRACE, "V4L2 poll %s ret=%d, timeout=%d, events=%#x, revents=%#x\n",
++ ctx->name, ret, timeout, pfd.events, pfd.revents);
++
++ if (ret < 0) {
++ if (ret == AVERROR(EINTR))
++ continue;
++ av_log(avctx, AV_LOG_ERROR, "V4L2 %s poll error %d (%s)\n", ctx->name, AVUNERROR(ret), av_err2str(ret));
++ return ret;
++ }
++
++ if (ret == 0) {
++ if (timeout == -1)
++ av_log(avctx, AV_LOG_ERROR, "V4L2 %s poll unexpected timeout: events=%#x\n", ctx->name, pfd.events);
++ if (ff_v4l2_ctx_eos(ctx)) {
++ av_log(avctx, AV_LOG_WARNING, "V4L2 %s poll event timeout\n", ctx->name);
++ ret = get_event(m);
++ if (ret < 0) {
++ ctx->done = 1;
++ return ret;
++ }
}
- return NULL;
+- return NULL;
++ return AVERROR(EAGAIN);
}
-+ --ctx->q_count;
-+ av_log(logger(ctx), AV_LOG_DEBUG, "--- %s VIDIOC_DQBUF OK: index=%d, ts=%ld.%06ld, count=%d, dq=%d\n",
-+ ctx->name, buf.index,
-+ buf.timestamp.tv_sec, buf.timestamp.tv_usec,
-+ ctx->q_count, ++ctx->dq_count);
-+
-+ avbuf = (V4L2Buffer *)ctx->bufrefs[buf.index]->data;
-+ avbuf->status = V4L2BUF_AVAILABLE;
-+ avbuf->buf = buf;
-+ if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type)) {
-+ memcpy(avbuf->planes, planes, sizeof(planes));
-+ avbuf->buf.m.planes = avbuf->planes;
-+ }
-
+
- if (ctx_to_m2mctx(ctx)->draining && !V4L2_TYPE_IS_OUTPUT(ctx->type)) {
-+ if (ctx_to_m2mctx(ctx)->draining && is_capture) {
- int bytesused = V4L2_TYPE_IS_MULTIPLANAR(buf.type) ?
- buf.m.planes[0].bytesused : buf.bytesused;
- if (bytesused == 0) {
-- ctx->done = 1;
-+ av_log(logger(ctx), AV_LOG_DEBUG, "Buffer empty - reQ\n");
-+
-+ // Must reQ so we don't leak
-+ // May not matter if the next thing we do is release all the
-+ // buffers but better to be tidy.
-+ ff_v4l2_buffer_enqueue(avbuf);
+- int bytesused = V4L2_TYPE_IS_MULTIPLANAR(buf.type) ?
+- buf.m.planes[0].bytesused : buf.bytesused;
+- if (bytesused == 0) {
++ if ((pfd.revents & POLLERR) != 0) {
++ av_log(avctx, AV_LOG_WARNING, "V4L2 %s POLLERR\n", ctx->name);
++ return AVERROR_UNKNOWN;
++ }
+
-+ if (ctx_done(ctx) > 0)
-+ goto start;
- return NULL;
++ if ((pfd.revents & poll_event) != 0) {
++ ret = get_event(m);
++ if (ret < 0) {
+ ctx->done = 1;
+- return NULL;
++ return ret;
}
- #ifdef V4L2_BUF_FLAG_LAST
+-#ifdef V4L2_BUF_FLAG_LAST
- if (buf.flags & V4L2_BUF_FLAG_LAST)
- ctx->done = 1;
-+ if (buf.flags & V4L2_BUF_FLAG_LAST) {
-+ av_log(logger(ctx), AV_LOG_TRACE, "FLAG_LAST set\n");
-+ avbuf->status = V4L2BUF_IN_USE; // Avoid flushing this buffer
-+ ctx_done(ctx);
-+ }
- #endif
+-#endif
++ continue;
++ }
++
++ if ((pfd.revents & poll_cap) != 0) {
++ ret = dq_buf(ctx, ppavbuf);
++ if (ret == AVERROR(EPIPE))
++ continue;
++ return ret;
}
-
+
- avbuf = &ctx->buffers[buf.index];
- avbuf->status = V4L2BUF_AVAILABLE;
- avbuf->buf = buf;
- if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type)) {
- memcpy(avbuf->planes, planes, sizeof(planes));
- avbuf->buf.m.planes = avbuf->planes;
-- }
- return avbuf;
++ if ((pfd.revents & poll_out) != 0) {
++ if (is_cap)
++ return AVERROR(EAGAIN);
++ return dq_buf(ctx, ppavbuf);
+ }
+- return avbuf;
++
++ av_log(avctx, AV_LOG_ERROR, "V4L2 poll unexpected events=%#x, revents=%#x\n", pfd.events, pfd.revents);
++ return AVERROR_UNKNOWN;
}
-
-@@ -443,8 +575,9 @@ static V4L2Buffer* v4l2_getfree_v4l2buf(
++}
+
+- return NULL;
++// Clear out flags and timestamps that should should be set by the user
++// Returns the passed avbuf
++static V4L2Buffer *
++clean_v4l2_buffer(V4L2Buffer * const avbuf)
++{
++ struct v4l2_buffer *const buf = &avbuf->buf;
++
++ buf->flags = 0;
++ buf->field = V4L2_FIELD_ANY;
++ buf->timestamp = (struct timeval){0};
++ buf->timecode = (struct v4l2_timecode){0};
++ buf->sequence = 0;
++
++ return avbuf;
+ }
+
+ static V4L2Buffer* v4l2_getfree_v4l2buf(V4L2Context *ctx)
+ {
+- int timeout = 0; /* return when no more buffers to dequeue */
+ int i;
+
+ /* get back as many output buffers as possible */
+ if (V4L2_TYPE_IS_OUTPUT(ctx->type)) {
+- do {
+- } while (v4l2_dequeue_v4l2buf(ctx, timeout));
++ V4L2Buffer * avbuf;
++ do {
++ get_qbuf(ctx, &avbuf, 0);
++ } while (avbuf);
}
-
+
for (i = 0; i < ctx->num_buffers; i++) {
- if (ctx->buffers[i].status == V4L2BUF_AVAILABLE)
- return &ctx->buffers[i];
+ V4L2Buffer * const avbuf = (V4L2Buffer *)ctx->bufrefs[i]->data;
+ if (avbuf->status == V4L2BUF_AVAILABLE)
-+ return avbuf;
++ return clean_v4l2_buffer(avbuf);
}
-
+
return NULL;
-@@ -452,25 +585,45 @@ static V4L2Buffer* v4l2_getfree_v4l2buf(
-
+@@ -452,25 +730,45 @@ static V4L2Buffer* v4l2_getfree_v4l2buf(
+
static int v4l2_release_buffers(V4L2Context* ctx)
{
- struct v4l2_requestbuffers req = {
@@ -47632,12 +51801,12 @@ Upstream-status: Pending
+ int i;
+ int ret = 0;
+ const int fd = ctx_to_m2mctx(ctx)->fd;
-
+
- for (i = 0; i < ctx->num_buffers; i++) {
- V4L2Buffer *buffer = &ctx->buffers[i];
+ // Orphan any buffers in the wild
+ ff_weak_link_break(&ctx->wl_master);
-
+
- for (j = 0; j < buffer->num_planes; j++) {
- struct V4L2Plane_info *p = &buffer->plane_info[j];
- if (p->mm_addr && p->length)
@@ -47672,15 +51841,15 @@ Upstream-status: Pending
+ " 2. drmIoctl(.., DRM_IOCTL_GEM_CLOSE,... )\n");
}
}
-+ ctx->q_count = 0;
-
++ atomic_store(&ctx->q_count, 0);
+
- return ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_REQBUFS, &req);
+ return ret;
}
-
+
static inline int v4l2_try_raw_format(V4L2Context* ctx, enum AVPixelFormat pixfmt)
-@@ -499,6 +652,8 @@ static inline int v4l2_try_raw_format(V4
-
+@@ -499,6 +797,8 @@ static inline int v4l2_try_raw_format(V4
+
static int v4l2_get_raw_format(V4L2Context* ctx, enum AVPixelFormat *p)
{
+ V4L2m2mContext* s = ctx_to_m2mctx(ctx);
@@ -47688,10 +51857,10 @@ Upstream-status: Pending
enum AVPixelFormat pixfmt = ctx->av_pix_fmt;
struct v4l2_fmtdesc fdesc;
int ret;
-@@ -517,6 +672,13 @@ static int v4l2_get_raw_format(V4L2Conte
+@@ -517,6 +817,13 @@ static int v4l2_get_raw_format(V4L2Conte
if (ret)
return AVERROR(EINVAL);
-
+
+ if (priv->pix_fmt != AV_PIX_FMT_NONE) {
+ if (fdesc.pixelformat != ff_v4l2_format_avfmt_to_v4l2(priv->pix_fmt)) {
+ fdesc.index++;
@@ -47702,10 +51871,10 @@ Upstream-status: Pending
pixfmt = ff_v4l2_format_v4l2_to_avfmt(fdesc.pixelformat, AV_CODEC_ID_RAWVIDEO);
ret = v4l2_try_raw_format(ctx, pixfmt);
if (ret){
-@@ -569,18 +731,77 @@ static int v4l2_get_coded_format(V4L2Con
+@@ -569,30 +876,99 @@ static int v4l2_get_coded_format(V4L2Con
*
*****************************************************************************/
-
+
+
+static void flush_all_buffers_status(V4L2Context* const ctx)
+{
@@ -47717,9 +51886,9 @@ Upstream-status: Pending
+ for (i = 0; i < ctx->num_buffers; ++i) {
+ struct V4L2Buffer * const buf = (struct V4L2Buffer *)ctx->bufrefs[i]->data;
+ if (buf->status == V4L2BUF_IN_DRIVER)
-+ buf->status = V4L2BUF_AVAILABLE;
++ ff_v4l2_buffer_set_avail(buf);
+ }
-+ ctx->q_count = 0;
++ atomic_store(&ctx->q_count, 0);
+}
+
+static int stuff_all_buffers(AVCodecContext * avctx, V4L2Context* ctx)
@@ -47749,18 +51918,25 @@ Upstream-status: Pending
int ff_v4l2_context_set_status(V4L2Context* ctx, uint32_t cmd)
{
int type = ctx->type;
- int ret;
+- int ret;
++ int ret = 0;
+ AVCodecContext * const avctx = logger(ctx);
-+
+
+- ret = ioctl(ctx_to_m2mctx(ctx)->fd, cmd, &type);
+- if (ret < 0)
+- return AVERROR(errno);
++ // Avoid doing anything if there is nothing we can do
++ if (cmd == VIDIOC_STREAMOFF && !ctx_buffers_alloced(ctx) && !ctx->streamon)
++ return 0;
+
+- ctx->streamon = (cmd == VIDIOC_STREAMON);
+ ff_mutex_lock(&ctx->lock);
-+
+
+- return 0;
+ if (cmd == VIDIOC_STREAMON && !V4L2_TYPE_IS_OUTPUT(ctx->type))
+ stuff_all_buffers(avctx, ctx);
-
- ret = ioctl(ctx_to_m2mctx(ctx)->fd, cmd, &type);
-- if (ret < 0)
-- return AVERROR(errno);
-+ if (ret < 0) {
++
++ if (ioctl(ctx_to_m2mctx(ctx)->fd, cmd, &type) < 0) {
+ const int err = errno;
+ av_log(avctx, AV_LOG_ERROR, "%s set status %d (%s) failed: err=%d\n", ctx->name,
+ cmd, (cmd == VIDIOC_STREAMON) ? "ON" : "OFF", err);
@@ -47770,73 +51946,153 @@ Upstream-status: Pending
+ {
+ if (cmd == VIDIOC_STREAMOFF)
+ flush_all_buffers_status(ctx);
-
-- ctx->streamon = (cmd == VIDIOC_STREAMON);
++ else
++ ctx->first_buf = 1;
++
+ ctx->streamon = (cmd == VIDIOC_STREAMON);
+ av_log(avctx, AV_LOG_DEBUG, "%s set status %d (%s) OK\n", ctx->name,
+ cmd, (cmd == VIDIOC_STREAMON) ? "ON" : "OFF");
+ }
-
-- return 0;
++
++ // Both stream off & on effectively clear flag_last
++ ctx->flag_last = 0;
++
+ ff_mutex_unlock(&ctx->lock);
+
+ return ret;
}
-
+
int ff_v4l2_context_enqueue_frame(V4L2Context* ctx, const AVFrame* frame)
-@@ -608,7 +829,8 @@ int ff_v4l2_context_enqueue_frame(V4L2Co
+ {
+- V4L2m2mContext *s = ctx_to_m2mctx(ctx);
++ V4L2m2mContext *const s = ctx_to_m2mctx(ctx);
++ AVCodecContext *const avctx = s->avctx;
++ int64_t track_ts;
+ V4L2Buffer* avbuf;
+ int ret;
+
+ if (!frame) {
+ ret = v4l2_stop_encode(ctx);
+ if (ret)
+- av_log(logger(ctx), AV_LOG_ERROR, "%s stop_encode\n", ctx->name);
++ av_log(avctx, AV_LOG_ERROR, "%s stop_encode\n", ctx->name);
+ s->draining= 1;
+ return 0;
+ }
+@@ -601,23 +977,29 @@ int ff_v4l2_context_enqueue_frame(V4L2Co
+ if (!avbuf)
+ return AVERROR(ENOMEM);
+
+- ret = ff_v4l2_buffer_avframe_to_buf(frame, avbuf);
++ track_ts = xlat_pts_frame_in(avctx, &s->xlat, frame);
++
++ ret = ff_v4l2_buffer_avframe_to_buf(frame, avbuf, track_ts);
+ if (ret)
+ return ret;
+
return ff_v4l2_buffer_enqueue(avbuf);
}
-
+
-int ff_v4l2_context_enqueue_packet(V4L2Context* ctx, const AVPacket* pkt)
+int ff_v4l2_context_enqueue_packet(V4L2Context* ctx, const AVPacket* pkt,
-+ const void * extdata, size_t extlen, int no_rescale_pts)
++ const void * extdata, size_t extlen)
{
V4L2m2mContext *s = ctx_to_m2mctx(ctx);
++ AVCodecContext *const avctx = s->avctx;
V4L2Buffer* avbuf;
-@@ -616,8 +838,9 @@ int ff_v4l2_context_enqueue_packet(V4L2C
-
+ int ret;
++ int64_t track_ts;
+
if (!pkt->size) {
ret = v4l2_stop_decode(ctx);
+ // Log but otherwise ignore stop failure
if (ret)
- av_log(logger(ctx), AV_LOG_ERROR, "%s stop_decode\n", ctx->name);
-+ av_log(logger(ctx), AV_LOG_ERROR, "%s stop_decode failed: err=%d\n", ctx->name, ret);
++ av_log(avctx, AV_LOG_ERROR, "%s stop_decode failed: err=%d\n", ctx->name, ret);
s->draining = 1;
return 0;
}
-@@ -626,14 +849,17 @@ int ff_v4l2_context_enqueue_packet(V4L2C
+@@ -626,8 +1008,13 @@ int ff_v4l2_context_enqueue_packet(V4L2C
if (!avbuf)
return AVERROR(EAGAIN);
-
+
- ret = ff_v4l2_buffer_avpkt_to_buf(pkt, avbuf);
- if (ret)
-+ ret = ff_v4l2_buffer_avpkt_to_buf_ext(pkt, avbuf, extdata, extlen, no_rescale_pts);
++ track_ts = xlat_pts_pkt_in(avctx, &s->xlat, pkt);
++
++ ret = ff_v4l2_buffer_avpkt_to_buf_ext(pkt, avbuf, extdata, extlen, track_ts);
+ if (ret == AVERROR(ENOMEM))
+ av_log(logger(ctx), AV_LOG_ERROR, "Buffer overflow in %s: pkt->size=%d > buf->length=%d\n",
+ __func__, pkt->size, avbuf->planes[0].length);
+ else if (ret)
return ret;
-
+
return ff_v4l2_buffer_enqueue(avbuf);
- }
-
--int ff_v4l2_context_dequeue_frame(V4L2Context* ctx, AVFrame* frame, int timeout)
-+int ff_v4l2_context_dequeue_frame(V4L2Context* ctx, AVFrame* frame, int timeout, int no_rescale_pts)
+@@ -635,42 +1022,36 @@ int ff_v4l2_context_enqueue_packet(V4L2C
+
+ int ff_v4l2_context_dequeue_frame(V4L2Context* ctx, AVFrame* frame, int timeout)
{
++ V4L2m2mContext *s = ctx_to_m2mctx(ctx);
++ AVCodecContext *const avctx = s->avctx;
V4L2Buffer *avbuf;
-
-@@ -650,7 +876,7 @@ int ff_v4l2_context_dequeue_frame(V4L2Co
- return AVERROR(EAGAIN);
- }
-
++ int rv;
+
+- /*
+- * timeout=-1 blocks until:
+- * 1. decoded frame available
+- * 2. an input buffer is ready to be dequeued
+- */
+- avbuf = v4l2_dequeue_v4l2buf(ctx, timeout);
+- if (!avbuf) {
+- if (ctx->done)
+- return AVERROR_EOF;
+-
+- return AVERROR(EAGAIN);
+- }
++ do {
++ if ((rv = get_qbuf(ctx, &avbuf, timeout)) != 0)
++ return rv;
++ if ((rv = ff_v4l2_buffer_buf_to_avframe(frame, avbuf)) != 0)
++ return rv;
++ } while (xlat_pts_frame_out(avctx, &s->xlat, frame) != 0);
+
- return ff_v4l2_buffer_buf_to_avframe(frame, avbuf);
-+ return ff_v4l2_buffer_buf_to_avframe(frame, avbuf, no_rescale_pts);
++ return 0;
}
-
+
int ff_v4l2_context_dequeue_packet(V4L2Context* ctx, AVPacket* pkt)
-@@ -702,78 +928,155 @@ int ff_v4l2_context_get_format(V4L2Conte
-
+ {
++ V4L2m2mContext *s = ctx_to_m2mctx(ctx);
++ AVCodecContext *const avctx = s->avctx;
+ V4L2Buffer *avbuf;
++ int rv;
+
+- /*
+- * blocks until:
+- * 1. encoded packet available
+- * 2. an input buffer ready to be dequeued
+- */
+- avbuf = v4l2_dequeue_v4l2buf(ctx, -1);
+- if (!avbuf) {
+- if (ctx->done)
+- return AVERROR_EOF;
++ do {
++ if ((rv = get_qbuf(ctx, &avbuf, -1)) != 0)
++ return rv == AVERROR(ENOSPC) ? AVERROR(EAGAIN) : rv; // Caller not currently expecting ENOSPC
++ if ((rv = ff_v4l2_buffer_buf_to_avpkt(pkt, avbuf)) != 0)
++ return rv;
++ } while (xlat_pts_pkt_out(avctx, &s->xlat, pkt) != 0);
+
+- return AVERROR(EAGAIN);
+- }
+-
+- return ff_v4l2_buffer_buf_to_avpkt(pkt, avbuf);
++ return 0;
+ }
+
+ int ff_v4l2_context_get_format(V4L2Context* ctx, int probe)
+@@ -702,78 +1083,160 @@ int ff_v4l2_context_get_format(V4L2Conte
+
int ff_v4l2_context_set_format(V4L2Context* ctx)
{
- return ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_S_FMT, &ctx->format);
@@ -47864,29 +52120,30 @@ Upstream-status: Pending
+ ret = ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_S_FMT, &ctx->format);
+ return ret;
}
-
+
void ff_v4l2_context_release(V4L2Context* ctx)
{
int ret;
-
+
- if (!ctx->buffers)
+ if (!ctx->bufrefs)
return;
-
+
ret = v4l2_release_buffers(ctx);
if (ret)
av_log(logger(ctx), AV_LOG_WARNING, "V4L2 failed to unmap the %s buffers\n", ctx->name);
-
+
- av_freep(&ctx->buffers);
+ av_freep(&ctx->bufrefs);
+ av_buffer_unref(&ctx->frames_ref);
+
+ ff_mutex_destroy(&ctx->lock);
++ pthread_cond_destroy(&ctx->cond);
}
-
+
-int ff_v4l2_context_init(V4L2Context* ctx)
+
-+static int create_buffers(V4L2Context* const ctx, const unsigned int req_buffers)
++static int create_buffers(V4L2Context* const ctx, const unsigned int req_buffers, const enum v4l2_memory mem)
{
- V4L2m2mContext *s = ctx_to_m2mctx(ctx);
+ V4L2m2mContext * const s = ctx_to_m2mctx(ctx);
@@ -47897,17 +52154,19 @@ Upstream-status: Pending
- av_log(logger(ctx), AV_LOG_ERROR, "type %i not supported\n", ctx->type);
- return AVERROR_PATCHWELCOME;
- }
--
++ int ret;
++ int i;
+
- ret = ioctl(s->fd, VIDIOC_G_FMT, &ctx->format);
- if (ret)
- av_log(logger(ctx), AV_LOG_ERROR, "%s VIDIOC_G_FMT failed\n", ctx->name);
-+ int ret;
-+ int i;
-
++ av_assert0(ctx->bufrefs == NULL);
+
memset(&req, 0, sizeof(req));
- req.count = ctx->num_buffers;
+- req.memory = V4L2_MEMORY_MMAP;
+ req.count = req_buffers;
- req.memory = V4L2_MEMORY_MMAP;
++ req.memory = mem;
req.type = ctx->type;
- ret = ioctl(s->fd, VIDIOC_REQBUFS, &req);
- if (ret < 0) {
@@ -47920,7 +52179,7 @@ Upstream-status: Pending
+ return ret;
+ }
}
-
+
ctx->num_buffers = req.count;
- ctx->buffers = av_mallocz(ctx->num_buffers * sizeof(V4L2Buffer));
- if (!ctx->buffers) {
@@ -47930,7 +52189,7 @@ Upstream-status: Pending
- return AVERROR(ENOMEM);
+ goto fail_release;
}
-
+
- for (i = 0; i < req.count; i++) {
- ctx->buffers[i].context = ctx;
- ret = ff_v4l2_buffer_initialize(&ctx->buffers[i], i);
@@ -47942,14 +52201,14 @@ Upstream-status: Pending
+ }
+
+ for (i = 0; i < ctx->num_buffers; i++) {
-+ ret = ff_v4l2_buffer_initialize(&ctx->bufrefs[i], i, ctx);
++ ret = ff_v4l2_buffer_initialize(&ctx->bufrefs[i], i, ctx, mem);
+ if (ret) {
av_log(logger(ctx), AV_LOG_ERROR, "%s buffer[%d] initialization (%s)\n", ctx->name, i, av_err2str(ret));
- goto error;
+ goto fail_release;
}
}
-
+
av_log(logger(ctx), AV_LOG_DEBUG, "%s: %s %02d buffers initialized: %04ux%04u, sizeimage %08u, bytesperline %08u\n", ctx->name,
V4L2_TYPE_IS_MULTIPLANAR(ctx->type) ? av_fourcc2str(ctx->format.fmt.pix_mp.pixelformat) : av_fourcc2str(ctx->format.fmt.pix.pixelformat),
req.count,
@@ -47959,9 +52218,9 @@ Upstream-status: Pending
+ ff_v4l2_get_format_height(&ctx->format),
V4L2_TYPE_IS_MULTIPLANAR(ctx->type) ? ctx->format.fmt.pix_mp.plane_fmt[0].sizeimage : ctx->format.fmt.pix.sizeimage,
V4L2_TYPE_IS_MULTIPLANAR(ctx->type) ? ctx->format.fmt.pix_mp.plane_fmt[0].bytesperline : ctx->format.fmt.pix.bytesperline);
-
+
return 0;
-
+
-error:
+fail_release:
v4l2_release_buffers(ctx);
@@ -47976,14 +52235,16 @@ Upstream-status: Pending
+
+ // It is not valid to reinit a context without a previous release
+ av_assert0(ctx->bufrefs == NULL);
-+
+
+- av_freep(&ctx->buffers);
+ if (!v4l2_type_supported(ctx)) {
+ av_log(logger(ctx), AV_LOG_ERROR, "type %i not supported\n", ctx->type);
+ return AVERROR_PATCHWELCOME;
+ }
-
-- av_freep(&ctx->buffers);
++
+ ff_mutex_init(&ctx->lock, NULL);
++ pthread_cond_init(&ctx->cond, NULL);
++ atomic_init(&ctx->q_count, 0);
+
+ if (s->output_drm) {
+ AVHWFramesContext *hwframes;
@@ -47997,8 +52258,8 @@ Upstream-status: Pending
+ hwframes = (AVHWFramesContext*)ctx->frames_ref->data;
+ hwframes->format = AV_PIX_FMT_DRM_PRIME;
+ hwframes->sw_format = ctx->av_pix_fmt;
-+ hwframes->width = ctx->width;
-+ hwframes->height = ctx->height;
++ hwframes->width = ctx->width != 0 ? ctx->width : s->avctx->width;
++ hwframes->height = ctx->height != 0 ? ctx->height : s->avctx->height;
+ ret = av_hwframe_ctx_init(ctx->frames_ref);
+ if (ret < 0)
+ goto fail_unref_hwframes;
@@ -48011,12 +52272,12 @@ Upstream-status: Pending
+ goto fail_unref_hwframes;
+ }
+
-+ ret = create_buffers(ctx, ctx->num_buffers);
++ ret = create_buffers(ctx, ctx->num_buffers, ctx->buf_mem);
+ if (ret < 0)
+ goto fail_unref_hwframes;
+
+ return 0;
-
+
+fail_unref_hwframes:
+ av_buffer_unref(&ctx->frames_ref);
+fail_unlock:
@@ -48031,14 +52292,14 @@ Upstream-status: Pending
#include "libavutil/buffer.h"
+#include "libavutil/thread.h"
#include "v4l2_buffers.h"
-
+
typedef struct V4L2Context {
@@ -70,11 +71,18 @@ typedef struct V4L2Context {
*/
int width, height;
AVRational sample_aspect_ratio;
+ struct v4l2_rect selection;
-
+
/**
- * Indexed array of V4L2Buffers
+ * If the default size of buffer is less than this then try to
@@ -48051,50 +52312,98 @@ Upstream-status: Pending
+ * Indexed array of pointers to V4L2Buffers
+ */
+ AVBufferRef **bufrefs;
-
+
/**
* Readonly after init.
-@@ -92,6 +100,12 @@ typedef struct V4L2Context {
+@@ -82,16 +90,38 @@ typedef struct V4L2Context {
+ int num_buffers;
+
+ /**
++ * Buffer memory type V4L2_MEMORY_MMAP or V4L2_MEMORY_DMABUF
++ */
++ enum v4l2_memory buf_mem;
++
++ /**
+ * Whether the stream has been started (VIDIOC_STREAMON has been sent).
+ */
+ int streamon;
+
++ /* 1st buffer after stream on */
++ int first_buf;
++
+ /**
+ * Either no more buffers available or an unrecoverable error was notified
+ * by the V4L2 kernel driver: once set the context has to be exited.
*/
int done;
-
+
++ int flag_last;
++
++ /**
++ * If NZ then when Qing frame/pkt use this rather than the
++ * "real" PTS
++ */
++ uint64_t track_ts;
++
+ AVBufferRef *frames_ref;
-+ int q_count;
-+ int dq_count;
++ atomic_int q_count;
+ struct ff_weak_link_master *wl_master;
+
+ AVMutex lock;
++ pthread_cond_t cond;
} V4L2Context;
-
+
/**
-@@ -156,9 +170,12 @@ int ff_v4l2_context_dequeue_packet(V4L2C
+@@ -156,7 +186,10 @@ int ff_v4l2_context_dequeue_packet(V4L2C
* @param[in] ctx The V4L2Context to dequeue from.
* @param[inout] f The AVFrame to dequeue to.
* @param[in] timeout The timeout for dequeue (-1 to block, 0 to return immediately, or milliseconds)
-+ * @param[in] no_rescale_pts (0 rescale pts, 1 use pts as
-+ * timestamp directly)
+ *
* @return 0 in case of success, AVERROR(EAGAIN) if no buffer was ready, another negative error in case of error.
++ * AVERROR(ENOSPC) if no buffer availible to put
++ * the frame in
*/
--int ff_v4l2_context_dequeue_frame(V4L2Context* ctx, AVFrame* f, int timeout);
-+int ff_v4l2_context_dequeue_frame(V4L2Context* ctx, AVFrame* f, int timeout, int no_rescale_pts);
-
- /**
- * Enqueues a buffer to a V4L2Context from an AVPacket
-@@ -170,7 +187,7 @@ int ff_v4l2_context_dequeue_frame(V4L2Co
+ int ff_v4l2_context_dequeue_frame(V4L2Context* ctx, AVFrame* f, int timeout);
+
+@@ -170,7 +203,7 @@ int ff_v4l2_context_dequeue_frame(V4L2Co
* @param[in] pkt A pointer to an AVPacket.
* @return 0 in case of success, a negative error otherwise.
*/
-int ff_v4l2_context_enqueue_packet(V4L2Context* ctx, const AVPacket* pkt);
-+int ff_v4l2_context_enqueue_packet(V4L2Context* ctx, const AVPacket* pkt, const void * ext_data, size_t ext_size, int no_rescale_pts);
-
++int ff_v4l2_context_enqueue_packet(V4L2Context* ctx, const AVPacket* pkt, const void * ext_data, size_t ext_size);
+
/**
* Enqueues a buffer to a V4L2Context from an AVFrame
--- a/libavcodec/v4l2_m2m.c
+++ b/libavcodec/v4l2_m2m.c
-@@ -215,13 +215,7 @@ int ff_v4l2_m2m_codec_reinit(V4L2m2mCont
+@@ -36,6 +36,14 @@
+ #include "v4l2_fmt.h"
+ #include "v4l2_m2m.h"
+
++static void
++xlat_init(xlat_track_t * const x)
++{
++ memset(x, 0, sizeof(*x));
++ x->last_pts = AV_NOPTS_VALUE;
++}
++
++
+ static inline int v4l2_splane_video(struct v4l2_capability *cap)
+ {
+ if (cap->capabilities & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT) &&
+@@ -68,7 +76,9 @@ static int v4l2_prepare_contexts(V4L2m2m
+
+ s->capture.done = s->output.done = 0;
+ s->capture.name = "capture";
++ s->capture.buf_mem = V4L2_MEMORY_MMAP;
+ s->output.name = "output";
++ s->output.buf_mem = s->input_drm ? V4L2_MEMORY_DMABUF : V4L2_MEMORY_MMAP;
+ atomic_init(&s->refcount, 0);
+ sem_init(&s->refsync, 0, 0);
+
+@@ -215,13 +225,7 @@ int ff_v4l2_m2m_codec_reinit(V4L2m2mCont
av_log(log_ctx, AV_LOG_ERROR, "capture VIDIOC_STREAMOFF\n");
-
+
/* 2. unmap the capture buffers (v4l2 and ffmpeg):
- * we must wait for all references to be released before being allowed
- * to queue new buffers.
@@ -48104,30 +52413,49 @@ Upstream-status: Pending
- while(sem_wait(&s->refsync) == -1 && errno == EINTR);
-
ff_v4l2_context_release(&s->capture);
-
+
/* 3. get the new capture format */
-@@ -328,7 +322,10 @@ static void v4l2_m2m_destroy_context(voi
+@@ -240,7 +244,6 @@ int ff_v4l2_m2m_codec_reinit(V4L2m2mCont
+
+ /* 5. complete reinit */
+ s->draining = 0;
+- s->reinit = 0;
+
+ return 0;
+ }
+@@ -274,7 +277,6 @@ int ff_v4l2_m2m_codec_full_reinit(V4L2m2
+
+ /* start again now that we know the stream dimensions */
+ s->draining = 0;
+- s->reinit = 0;
+
+ ret = ff_v4l2_context_get_format(&s->output, 0);
+ if (ret) {
+@@ -328,7 +330,13 @@ static void v4l2_m2m_destroy_context(voi
ff_v4l2_context_release(&s->capture);
sem_destroy(&s->refsync);
-
+
- close(s->fd);
+ if (s->fd != -1)
+ close(s->fd);
+
++ av_packet_unref(&s->buf_pkt);
++ av_freep(&s->extdata_data);
++
+ av_log(s->avctx, AV_LOG_DEBUG, "V4L2 Context destroyed\n");
-
+
av_free(s);
}
-@@ -338,17 +335,34 @@ int ff_v4l2_m2m_codec_end(V4L2m2mPriv *p
+@@ -338,17 +346,34 @@ int ff_v4l2_m2m_codec_end(V4L2m2mPriv *p
V4L2m2mContext *s = priv->context;
int ret;
-
+
- ret = ff_v4l2_context_set_status(&s->output, VIDIOC_STREAMOFF);
- if (ret)
- av_log(s->avctx, AV_LOG_ERROR, "VIDIOC_STREAMOFF %s\n", s->output.name);
+ if (!s)
+ return 0;
-
+
- ret = ff_v4l2_context_set_status(&s->capture, VIDIOC_STREAMOFF);
- if (ret)
- av_log(s->avctx, AV_LOG_ERROR, "VIDIOC_STREAMOFF %s\n", s->capture.name);
@@ -48145,9 +52473,9 @@ Upstream-status: Pending
+ if (ret)
+ av_log(s->avctx, AV_LOG_ERROR, "VIDIOC_STREAMOFF %s\n", s->capture.name);
+ }
-
+
ff_v4l2_context_release(&s->output);
-
+
+ close(s->fd);
+ s->fd = -1;
+
@@ -48157,20 +52485,65 @@ Upstream-status: Pending
+ s->avctx = NULL;
+ priv->context = NULL;
av_buffer_unref(&priv->context_ref);
-
+
return 0;
+@@ -392,28 +417,33 @@ int ff_v4l2_m2m_codec_init(V4L2m2mPriv *
+ return v4l2_configure_contexts(s);
+ }
+
+-int ff_v4l2_m2m_create_context(V4L2m2mPriv *priv, V4L2m2mContext **s)
++int ff_v4l2_m2m_create_context(V4L2m2mPriv *priv, V4L2m2mContext **pps)
+ {
+- *s = av_mallocz(sizeof(V4L2m2mContext));
+- if (!*s)
++ V4L2m2mContext * const s = av_mallocz(sizeof(V4L2m2mContext));
++
++ *pps = NULL;
++ if (!s)
+ return AVERROR(ENOMEM);
+
+- priv->context_ref = av_buffer_create((uint8_t *) *s, sizeof(V4L2m2mContext),
++ priv->context_ref = av_buffer_create((uint8_t *)s, sizeof(*s),
+ &v4l2_m2m_destroy_context, NULL, 0);
+ if (!priv->context_ref) {
+- av_freep(s);
++ av_free(s);
+ return AVERROR(ENOMEM);
+ }
+
+ /* assign the context */
+- priv->context = *s;
+- (*s)->priv = priv;
++ priv->context = s;
++ s->priv = priv;
+
+ /* populate it */
+- priv->context->capture.num_buffers = priv->num_capture_buffers;
+- priv->context->output.num_buffers = priv->num_output_buffers;
+- priv->context->self_ref = priv->context_ref;
+- priv->context->fd = -1;
++ s->capture.num_buffers = priv->num_capture_buffers;
++ s->output.num_buffers = priv->num_output_buffers;
++ s->self_ref = priv->context_ref;
++ s->fd = -1;
++
++ xlat_init(&s->xlat);
+
++ *pps = s;
+ return 0;
+ }
--- a/libavcodec/v4l2_m2m.h
+++ b/libavcodec/v4l2_m2m.h
@@ -30,6 +30,7 @@
#include <linux/videodev2.h>
-
+
#include "libavcodec/avcodec.h"
+#include "libavutil/pixfmt.h"
#include "v4l2_context.h"
-
+
#define container_of(ptr, type, member) ({ \
-@@ -38,7 +39,18 @@
-
+@@ -38,7 +39,37 @@
+
#define V4L_M2M_DEFAULT_OPTS \
{ "num_output_buffers", "Number of buffers in the output context",\
- OFFSET(num_output_buffers), AV_OPT_TYPE_INT, { .i64 = 16 }, 6, INT_MAX, FLAGS }
@@ -48179,26 +52552,45 @@ Upstream-status: Pending
+#define FF_V4L2_M2M_TRACK_SIZE 128
+typedef struct V4L2m2mTrackEl {
+ int discard; // If we see this buffer its been flushed, so discard
++ int pending;
+ int pkt_size;
+ int64_t pts;
++ int64_t dts;
+ int64_t reordered_opaque;
+ int64_t pkt_pos;
+ int64_t pkt_duration;
+ int64_t track_pts;
+} V4L2m2mTrackEl;
-
++
++typedef struct pts_stats_s
++{
++ void * logctx;
++ const char * name; // For debug
++ unsigned int last_count;
++ unsigned int last_interval;
++ int64_t last_pts;
++ int64_t guess;
++} pts_stats_t;
++
++typedef struct xlat_track_s {
++ unsigned int track_no;
++ int64_t last_pts;
++ int64_t last_opaque;
++ V4L2m2mTrackEl track_els[FF_V4L2_M2M_TRACK_SIZE];
++} xlat_track_t;
+
typedef struct V4L2m2mContext {
char devname[PATH_MAX];
-@@ -53,6 +65,7 @@ typedef struct V4L2m2mContext {
+@@ -52,7 +83,6 @@ typedef struct V4L2m2mContext {
+ AVCodecContext *avctx;
sem_t refsync;
atomic_uint refcount;
- int reinit;
-+ int resize_pending;
-
+- int reinit;
+
/* null frame/packet received */
int draining;
-@@ -63,6 +76,23 @@ typedef struct V4L2m2mContext {
-
+@@ -63,6 +93,36 @@ typedef struct V4L2m2mContext {
+
/* reference back to V4L2m2mPriv */
void *priv;
+
@@ -48207,49 +52599,72 @@ Upstream-status: Pending
+ /* generate DRM frames */
+ int output_drm;
+
++ /* input frames are drmprime */
++ int input_drm;
++
+ /* Frame tracking */
-+ int64_t last_pkt_dts;
-+ int64_t last_opaque;
-+ unsigned int track_no;
-+ V4L2m2mTrackEl track_els[FF_V4L2_M2M_TRACK_SIZE];
++ xlat_track_t xlat;
++ int pending_hw;
++ int pending_n;
++
++ pts_stats_t pts_stat;
+
+ /* req pkt */
+ int req_pkt;
+
+ /* Ext data sent */
+ int extdata_sent;
++ /* Ext data sent in packet - overrides ctx */
++ uint8_t * extdata_data;
++ size_t extdata_size;
++
++#define FF_V4L2_QUIRK_REINIT_ALWAYS 1
++#define FF_V4L2_QUIRK_ENUM_FRAMESIZES_BROKEN 2
++ /* Quirks */
++ unsigned int quirks;
++
} V4L2m2mContext;
-
+
typedef struct V4L2m2mPriv {
-@@ -73,6 +103,7 @@ typedef struct V4L2m2mPriv {
-
+@@ -73,6 +133,7 @@ typedef struct V4L2m2mPriv {
+
int num_output_buffers;
int num_capture_buffers;
+ enum AVPixelFormat pix_fmt;
} V4L2m2mPriv;
-
+
/**
-@@ -126,4 +157,16 @@ int ff_v4l2_m2m_codec_reinit(V4L2m2mCont
+@@ -126,4 +187,26 @@ int ff_v4l2_m2m_codec_reinit(V4L2m2mCont
*/
int ff_v4l2_m2m_codec_full_reinit(V4L2m2mContext *ctx);
-
+
+
-+static inline unsigned int ff_v4l2_get_format_width(struct v4l2_format *fmt)
++static inline unsigned int ff_v4l2_get_format_width(const struct v4l2_format * const fmt)
+{
+ return V4L2_TYPE_IS_MULTIPLANAR(fmt->type) ? fmt->fmt.pix_mp.width : fmt->fmt.pix.width;
+}
+
-+static inline unsigned int ff_v4l2_get_format_height(struct v4l2_format *fmt)
++static inline unsigned int ff_v4l2_get_format_height(const struct v4l2_format * const fmt)
+{
+ return V4L2_TYPE_IS_MULTIPLANAR(fmt->type) ? fmt->fmt.pix_mp.height : fmt->fmt.pix.height;
+}
+
++static inline uint32_t ff_v4l2_get_format_pixelformat(const struct v4l2_format * const fmt)
++{
++ return V4L2_TYPE_IS_MULTIPLANAR(fmt->type) ? fmt->fmt.pix_mp.pixelformat : fmt->fmt.pix.pixelformat;
++}
++
++static inline int ff_v4l2_ctx_eos(const V4L2Context * const ctx)
++{
++ return ctx->flag_last;
++}
++
+
#endif /* AVCODEC_V4L2_M2M_H */
--- a/libavcodec/v4l2_m2m_dec.c
+++ b/libavcodec/v4l2_m2m_dec.c
@@ -23,6 +23,10 @@
-
+
#include <linux/videodev2.h>
#include <sys/ioctl.h>
+
@@ -48259,10 +52674,10 @@ Upstream-status: Pending
#include "libavutil/pixfmt.h"
#include "libavutil/pixdesc.h"
#include "libavutil/opt.h"
-@@ -30,26 +34,51 @@
+@@ -30,75 +34,111 @@
#include "libavcodec/decode.h"
#include "libavcodec/internal.h"
-
+
+#include "libavcodec/hwaccels.h"
+#include "libavcodec/internal.h"
+#include "libavcodec/hwconfig.h"
@@ -48270,7 +52685,80 @@ Upstream-status: Pending
#include "v4l2_context.h"
#include "v4l2_m2m.h"
#include "v4l2_fmt.h"
-
+
+-static int v4l2_try_start(AVCodecContext *avctx)
++// Pick 64 for max last count - that is >1sec at 60fps
++#define STATS_LAST_COUNT_MAX 64
++#define STATS_INTERVAL_MAX (1 << 30)
++
++#ifndef FF_API_BUFFER_SIZE_T
++#define FF_API_BUFFER_SIZE_T 1
++#endif
++
++static int64_t pts_stats_guess(const pts_stats_t * const stats)
+ {
+- V4L2m2mContext *s = ((V4L2m2mPriv*)avctx->priv_data)->context;
+- V4L2Context *const capture = &s->capture;
+- V4L2Context *const output = &s->output;
+- struct v4l2_selection selection = { 0 };
+- int ret;
++ if (stats->last_pts == AV_NOPTS_VALUE ||
++ stats->last_interval == 0 ||
++ stats->last_count >= STATS_LAST_COUNT_MAX)
++ return AV_NOPTS_VALUE;
++ return stats->last_pts + (int64_t)(stats->last_count - 1) * (int64_t)stats->last_interval;
++}
+
+- /* 1. start the output process */
+- if (!output->streamon) {
+- ret = ff_v4l2_context_set_status(output, VIDIOC_STREAMON);
+- if (ret < 0) {
+- av_log(avctx, AV_LOG_DEBUG, "VIDIOC_STREAMON on output context\n");
+- return ret;
++static void pts_stats_add(pts_stats_t * const stats, int64_t pts)
++{
++ if (pts == AV_NOPTS_VALUE || pts == stats->last_pts) {
++ if (stats->last_count < STATS_LAST_COUNT_MAX)
++ ++stats->last_count;
++ return;
++ }
++
++ if (stats->last_pts != AV_NOPTS_VALUE) {
++ const int64_t interval = pts - stats->last_pts;
++
++ if (interval < 0 || interval >= STATS_INTERVAL_MAX ||
++ stats->last_count >= STATS_LAST_COUNT_MAX) {
++ if (stats->last_interval != 0)
++ av_log(stats->logctx, AV_LOG_DEBUG, "%s: %s: Bad interval: %" PRId64 "/%d\n",
++ __func__, stats->name, interval, stats->last_count);
++ stats->last_interval = 0;
++ }
++ else {
++ const int64_t frame_time = interval / (int64_t)stats->last_count;
++
++ if (frame_time != stats->last_interval)
++ av_log(stats->logctx, AV_LOG_DEBUG, "%s: %s: New interval: %u->%" PRId64 "/%d=%" PRId64 "\n",
++ __func__, stats->name, stats->last_interval, interval, stats->last_count, frame_time);
++ stats->last_interval = frame_time;
+ }
+ }
+
+- if (capture->streamon)
++ stats->last_pts = pts;
++ stats->last_count = 1;
++}
++
++static void pts_stats_init(pts_stats_t * const stats, void * logctx, const char * name)
++{
++ *stats = (pts_stats_t){
++ .logctx = logctx,
++ .name = name,
++ .last_count = 1,
++ .last_interval = 0,
++ .last_pts = AV_NOPTS_VALUE
++ };
++}
++
+static int check_output_streamon(AVCodecContext *const avctx, V4L2m2mContext *const s)
+{
+ int ret;
@@ -48280,81 +52768,43 @@ Upstream-status: Pending
+ };
+
+ if (s->output.streamon)
-+ return 0;
-+
-+ ret = ff_v4l2_context_set_status(&s->output, VIDIOC_STREAMON);
-+ if (ret < 0)
-+ av_log(avctx, AV_LOG_ERROR, "VIDIOC_STREAMON on output context\n");
-+
-+ if (!s->capture.streamon || ret < 0)
-+ return ret;
-+
-+ ret = ioctl(s->fd, VIDIOC_DECODER_CMD, &cmd);
-+ if (ret < 0)
-+ av_log(avctx, AV_LOG_ERROR, "VIDIOC_DECODER_CMD start error: %d\n", errno);
-+ else
-+ av_log(avctx, AV_LOG_DEBUG, "VIDIOC_DECODER_CMD start OK\n");
-+
-+ return ret;
-+}
-+
- static int v4l2_try_start(AVCodecContext *avctx)
- {
- V4L2m2mContext *s = ((V4L2m2mPriv*)avctx->priv_data)->context;
- V4L2Context *const capture = &s->capture;
-- V4L2Context *const output = &s->output;
- struct v4l2_selection selection = { 0 };
- int ret;
-
- /* 1. start the output process */
-- if (!output->streamon) {
-- ret = ff_v4l2_context_set_status(output, VIDIOC_STREAMON);
-- if (ret < 0) {
-- av_log(avctx, AV_LOG_DEBUG, "VIDIOC_STREAMON on output context\n");
-- return ret;
-- }
-- }
-+ if ((ret = check_output_streamon(avctx, s)) != 0)
-+ return ret;
-
- if (capture->streamon)
return 0;
-@@ -63,15 +92,29 @@ static int v4l2_try_start(AVCodecContext
+
+- /* 2. get the capture format */
+- capture->format.type = capture->type;
+- ret = ioctl(s->fd, VIDIOC_G_FMT, &capture->format);
+- if (ret) {
+- av_log(avctx, AV_LOG_WARNING, "VIDIOC_G_FMT ioctl\n");
++ ret = ff_v4l2_context_set_status(&s->output, VIDIOC_STREAMON);
++ if (ret != 0) {
++ av_log(avctx, AV_LOG_ERROR, "VIDIOC_STREAMON on output context: %s\n", av_err2str(ret));
+ return ret;
}
-
- /* 2.1 update the AVCodecContext */
+
+- /* 2.1 update the AVCodecContext */
- avctx->pix_fmt = ff_v4l2_format_v4l2_to_avfmt(capture->format.fmt.pix_mp.pixelformat, AV_CODEC_ID_RAWVIDEO);
- capture->av_pix_fmt = avctx->pix_fmt;
-+ capture->av_pix_fmt =
-+ ff_v4l2_format_v4l2_to_avfmt(capture->format.fmt.pix_mp.pixelformat, AV_CODEC_ID_RAWVIDEO);
-+ if (s->output_drm) {
-+ avctx->pix_fmt = AV_PIX_FMT_DRM_PRIME;
-+ avctx->sw_pix_fmt = capture->av_pix_fmt;
-+ }
-+ else
-+ avctx->pix_fmt = capture->av_pix_fmt;
-
- /* 3. set the crop parameters */
-+#if 1
-+ selection.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-+ selection.target = V4L2_SEL_TGT_CROP_DEFAULT;
-+ ret = ioctl(s->fd, VIDIOC_G_SELECTION, &selection);
-+ av_log(avctx, AV_LOG_INFO, "Post G selection ret=%d, err=%d %dx%d\n", ret, errno, selection.r.width, selection.r.height);
-+#else
- selection.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- selection.r.height = avctx->coded_height;
- selection.r.width = avctx->coded_width;
-+ av_log(avctx, AV_LOG_INFO, "Try selection %dx%d\n", avctx->coded_width, avctx->coded_height);
- ret = ioctl(s->fd, VIDIOC_S_SELECTION, &selection);
+-
+- /* 3. set the crop parameters */
+- selection.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+- selection.r.height = avctx->coded_height;
+- selection.r.width = avctx->coded_width;
+- ret = ioctl(s->fd, VIDIOC_S_SELECTION, &selection);
- if (!ret) {
-+ av_log(avctx, AV_LOG_INFO, "Post S selection ret=%d, err=%d %dx%d\n", ret, errno, selection.r.width, selection.r.height);
-+ if (1) {
- ret = ioctl(s->fd, VIDIOC_G_SELECTION, &selection);
- if (ret) {
- av_log(avctx, AV_LOG_WARNING, "VIDIOC_G_SELECTION ioctl\n");
-@@ -82,15 +125,7 @@ static int v4l2_try_start(AVCodecContext
- capture->width = selection.r.width;
- }
+- ret = ioctl(s->fd, VIDIOC_G_SELECTION, &selection);
+- if (ret) {
+- av_log(avctx, AV_LOG_WARNING, "VIDIOC_G_SELECTION ioctl\n");
+- } else {
+- av_log(avctx, AV_LOG_DEBUG, "crop output %dx%d\n", selection.r.width, selection.r.height);
+- /* update the size of the resulting frame */
+- capture->height = selection.r.height;
+- capture->width = selection.r.width;
+- }
++ // STREAMON should do implicit START so this just for those that don't.
++ // It is optional so don't worry if it fails
++ if (ioctl(s->fd, VIDIOC_DECODER_CMD, &cmd) < 0) {
++ ret = AVERROR(errno);
++ av_log(avctx, AV_LOG_WARNING, "VIDIOC_DECODER_CMD start error: %s\n", av_err2str(ret));
}
-
- /* 4. init the capture context now that we have the capture format */
@@ -48364,131 +52814,133 @@ Upstream-status: Pending
- av_log(avctx, AV_LOG_ERROR, "can't request capture buffers\n");
- return AVERROR(ENOMEM);
- }
++ else {
++ av_log(avctx, AV_LOG_TRACE, "VIDIOC_DECODER_CMD start OK\n");
+ }
++ return 0;
++}
+
+- /* 5. start the capture process */
+- ret = ff_v4l2_context_set_status(capture, VIDIOC_STREAMON);
+- if (ret) {
+- av_log(avctx, AV_LOG_DEBUG, "VIDIOC_STREAMON, on capture context\n");
+- return ret;
- }
-+#endif
-
- /* 5. start the capture process */
- ret = ff_v4l2_context_set_status(capture, VIDIOC_STREAMON);
-@@ -133,52 +168,312 @@ static int v4l2_prepare_decoder(V4L2m2mC
++static int v4l2_try_start(AVCodecContext *avctx)
++{
++ V4L2m2mContext * const s = ((V4L2m2mPriv*)avctx->priv_data)->context;
++ int ret;
+
++ /* 1. start the output process */
++ if ((ret = check_output_streamon(avctx, s)) != 0)
++ return ret;
return 0;
}
-
+
+@@ -133,52 +173,525 @@ static int v4l2_prepare_decoder(V4L2m2mC
+ return 0;
+ }
+
-static int v4l2_receive_frame(AVCodecContext *avctx, AVFrame *frame)
-+static inline int64_t track_to_pts(AVCodecContext *avctx, unsigned int n)
++static void
++set_best_effort_pts(AVCodecContext *const avctx,
++ pts_stats_t * const ps,
++ AVFrame *const frame)
+{
-+ return (int64_t)n;
++ pts_stats_add(ps, frame->pts);
++
++#if FF_API_PKT_PTS
++FF_DISABLE_DEPRECATION_WARNINGS
++ frame->pkt_pts = frame->pts;
++FF_ENABLE_DEPRECATION_WARNINGS
++#endif
++ frame->best_effort_timestamp = pts_stats_guess(ps);
++ // If we can't guess from just PTS - try DTS
++ if (frame->best_effort_timestamp == AV_NOPTS_VALUE)
++ frame->best_effort_timestamp = frame->pkt_dts;
++
++ // We can't emulate what s/w does in a useful manner and using the
++ // "correct" answer seems to just confuse things.
++ frame->pkt_dts = frame->pts;
++ av_log(avctx, AV_LOG_TRACE, "Out PTS=%" PRId64 "/%"PRId64", DTS=%" PRId64 "\n",
++ frame->pts, frame->best_effort_timestamp, frame->pkt_dts);
+}
+
-+static inline unsigned int pts_to_track(AVCodecContext *avctx, const int64_t pts)
++static void
++xlat_flush(xlat_track_t * const x)
+{
-+ return (unsigned int)pts;
++ unsigned int i;
++ for (i = 0; i != FF_V4L2_M2M_TRACK_SIZE; ++i) {
++ x->track_els[i].pending = 0;
++ x->track_els[i].discard = 1;
++ }
++ x->last_pts = AV_NOPTS_VALUE;
+}
+
-+// FFmpeg requires us to propagate a number of vars from the coded pkt into
-+// the decoded frame. The only thing that tracks like that in V4L2 stateful
-+// is timestamp. PTS maps to timestamp for this decode. FFmpeg makes no
-+// guarantees about PTS being unique or specified for every frame so replace
-+// the supplied PTS with a simple incrementing number and keep a circular
-+// buffer of all the things we want preserved (including the original PTS)
-+// indexed by the tracking no.
-+static void
-+xlat_pts_in(AVCodecContext *const avctx, V4L2m2mContext *const s, AVPacket *const avpkt)
++static int
++xlat_pending(const xlat_track_t * const x)
+{
-+ int64_t track_pts;
++ unsigned int n = x->track_no % FF_V4L2_M2M_TRACK_SIZE;
++ unsigned int i;
++ int r = 0;
++ int64_t now = AV_NOPTS_VALUE;
+
-+ // Avoid 0
-+ if (++s->track_no == 0)
-+ s->track_no = 1;
++ for (i = 0; i < 32; ++i, n = (n - 1) % FF_V4L2_M2M_TRACK_SIZE) {
++ const V4L2m2mTrackEl * const t = x->track_els + n;
+
-+ track_pts = track_to_pts(avctx, s->track_no);
++ if (!t->pending)
++ continue;
+
-+ av_log(avctx, AV_LOG_TRACE, "In PTS=%" PRId64 ", DTS=%" PRId64 ", track=%" PRId64 ", n=%u\n", avpkt->pts, avpkt->dts, track_pts, s->track_no);
-+ s->last_pkt_dts = avpkt->dts;
-+ s->track_els[s->track_no % FF_V4L2_M2M_TRACK_SIZE] = (V4L2m2mTrackEl){
-+ .discard = 0,
-+ .pkt_size = avpkt->size,
-+ .pts = avpkt->pts,
-+ .reordered_opaque = avctx->reordered_opaque,
-+ .pkt_pos = avpkt->pos,
-+ .pkt_duration = avpkt->duration,
-+ .track_pts = track_pts
-+ };
-+ avpkt->pts = track_pts;
-+}
++ if (now == AV_NOPTS_VALUE)
++ now = t->dts;
+
-+// Returns -1 if we should discard the frame
-+static int
-+xlat_pts_out(AVCodecContext *const avctx, V4L2m2mContext *const s, AVFrame *const frame)
-+{
-+ unsigned int n = pts_to_track(avctx, frame->pts) % FF_V4L2_M2M_TRACK_SIZE;
-+ const V4L2m2mTrackEl *const t = s->track_els + n;
-+ if (frame->pts == AV_NOPTS_VALUE || frame->pts != t->track_pts)
-+ {
-+ av_log(avctx, AV_LOG_INFO, "Tracking failure: pts=%" PRId64 ", track[%d]=%" PRId64 "\n", frame->pts, n, t->track_pts);
-+ frame->pts = AV_NOPTS_VALUE;
-+ frame->pkt_dts = s->last_pkt_dts;
-+ frame->reordered_opaque = s->last_opaque;
-+ frame->pkt_pos = -1;
-+ frame->pkt_duration = 0;
-+ frame->pkt_size = -1;
++ if (t->pts == AV_NOPTS_VALUE ||
++ ((now == AV_NOPTS_VALUE || t->pts <= now) &&
++ (x->last_pts == AV_NOPTS_VALUE || t->pts > x->last_pts)))
++ ++r;
+ }
-+ else if (!t->discard)
-+ {
-+ frame->pts = t->pts;
-+ frame->pkt_dts = s->last_pkt_dts;
-+ frame->reordered_opaque = t->reordered_opaque;
-+ frame->pkt_pos = t->pkt_pos;
-+ frame->pkt_duration = t->pkt_duration;
-+ frame->pkt_size = t->pkt_size;
+
-+ s->last_opaque = s->track_els[n].reordered_opaque;
-+ s->track_els[n].pts = AV_NOPTS_VALUE; // If we hit this again deny accurate knowledge of PTS
-+ }
-+ else
-+ {
-+ av_log(avctx, AV_LOG_DEBUG, "Discard frame (flushed): pts=%" PRId64 ", track[%d]=%" PRId64 "\n", frame->pts, n, t->track_pts);
-+ return -1;
-+ }
++ // If we never get any ideas about PTS vs DTS allow a lot more buffer
++ if (now == AV_NOPTS_VALUE)
++ r -= 16;
+
-+#if FF_API_PKT_PTS
-+FF_DISABLE_DEPRECATION_WARNINGS
-+ frame->pkt_pts = frame->pts;
-+FF_ENABLE_DEPRECATION_WARNINGS
-+#endif
-+ frame->best_effort_timestamp = frame->pts;
-+ frame->pkt_dts = frame->pts; // We can't emulate what s/w does in a useful manner?
-+ av_log(avctx, AV_LOG_TRACE, "Out PTS=%" PRId64 ", DTS=%" PRId64 "\n", frame->pts, frame->pkt_dts);
-+ return 0;
++ return r;
+}
+
+static inline int stream_started(const V4L2m2mContext * const s) {
-+ return s->capture.streamon && s->output.streamon;
++ return s->output.streamon;
+}
+
+#define NQ_OK 0
+#define NQ_Q_FULL 1
+#define NQ_SRC_EMPTY 2
-+#define NQ_DRAINING 3
-+#define NQ_DEAD 4
++#define NQ_NONE 3
++#define NQ_DRAINING 4
++#define NQ_DEAD 5
+
+#define TRY_DQ(nq_status) ((nq_status) >= NQ_OK && (nq_status) <= NQ_DRAINING)
++#define RETRY_NQ(nq_status) ((nq_status) == NQ_Q_FULL || (nq_status) == NQ_NONE)
++
++// do_not_get If true then no new packet will be got but status will
++// be set appropriately
+
+// AVERROR_EOF Flushing an already flushed stream
+// -ve Error (all errors except EOF are unexpected)
+// NQ_OK (0) OK
+// NQ_Q_FULL Dst full (retry if we think V4L2 Q has space now)
+// NQ_SRC_EMPTY Src empty (do not retry)
++// NQ_NONE Enqueue not attempted
+// NQ_DRAINING At EOS, dQ dest until EOS there too
+// NQ_DEAD Not running (do not retry, do not attempt capture dQ)
+
-+static int try_enqueue_src(AVCodecContext * const avctx, V4L2m2mContext * const s)
++static int try_enqueue_src(AVCodecContext * const avctx, V4L2m2mContext * const s, const int do_not_get)
{
- V4L2m2mContext *s = ((V4L2m2mPriv*)avctx->priv_data)->context;
- V4L2Context *const capture = &s->capture;
- V4L2Context *const output = &s->output;
- AVPacket avpkt = {0};
int ret;
-
+
- if (s->buf_pkt.size) {
- avpkt = s->buf_pkt;
- memset(&s->buf_pkt, 0, sizeof(AVPacket));
@@ -48498,8 +52950,50 @@ Upstream-status: Pending
+ // If we don't already have a coded packet - get a new one
+ // We will already have a coded pkt if the output Q was full last time we
+ // tried to Q it
-+ if (!s->buf_pkt.size) {
-+ ret = ff_decode_get_packet(avctx, &s->buf_pkt);
++ if (!s->buf_pkt.size && !do_not_get) {
++ unsigned int i;
++
++ for (i = 0; i < 256; ++i) {
++ uint8_t * side_data;
++#if FF_API_BUFFER_SIZE_T
++ int side_size;
++#else
++ size_t side_size;
++#endif
++ ret = ff_decode_get_packet(avctx, &s->buf_pkt);
++ if (ret != 0)
++ break;
++
++ // New extradata is the only side-data we undertand
++ side_data = av_packet_get_side_data(&s->buf_pkt, AV_PKT_DATA_NEW_EXTRADATA, &side_size);
++ if (side_data) {
++ av_log(avctx, AV_LOG_DEBUG, "New extradata\n");
++ av_freep(&s->extdata_data);
++ if ((s->extdata_data = av_malloc(side_size ? side_size : 1)) == NULL) {
++ av_log(avctx, AV_LOG_ERROR, "Failed to alloc %d bytes of extra data\n", (int)side_size);
++ return AVERROR(ENOMEM);
++ }
++ memcpy(s->extdata_data, side_data, side_size);
++ s->extdata_size = side_size;
++ s->extdata_sent = 0;
++ }
++
++ if (s->buf_pkt.size != 0)
++ break;
++
++ if (s->buf_pkt.side_data_elems == 0) {
++ av_log(avctx, AV_LOG_WARNING, "Empty pkt from ff_decode_get_packet - treating as EOF\n");
++ ret = AVERROR_EOF;
++ break;
++ }
++
++ // Retry a side-data only pkt
++ }
++ // If i >= 256 something has gone wrong
++ if (i >= 256) {
++ av_log(avctx, AV_LOG_ERROR, "Too many side-data only packets\n");
++ return AVERROR(EIO);
++ }
+
+ if (ret == AVERROR(EAGAIN)) {
+ if (!stream_started(s)) {
@@ -48523,7 +53017,7 @@ Upstream-status: Pending
+ if (!s->draining) {
+ // Calling enqueue with an empty pkt starts drain
+ av_assert0(s->buf_pkt.size == 0);
-+ ret = ff_v4l2_context_enqueue_packet(&s->output, &s->buf_pkt, NULL, 0, 1);
++ ret = ff_v4l2_context_enqueue_packet(&s->output, &s->buf_pkt, NULL, 0);
+ if (ret) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to start drain: ret=%d\n", ret);
+ return ret;
@@ -48536,22 +53030,37 @@ Upstream-status: Pending
+ av_log(avctx, AV_LOG_ERROR, "Failed to get coded packet: err=%d\n", ret);
return ret;
+ }
-+
-+ xlat_pts_in(avctx, s, &s->buf_pkt);
}
-
+
- if (s->draining)
- goto dequeue;
-+ if ((ret = check_output_streamon(avctx, s)) != 0)
-+ return ret;
-
++ if (s->draining) {
++ if (s->buf_pkt.size) {
++ av_log(avctx, AV_LOG_WARNING, "Unexpected input whilst draining\n");
++ av_packet_unref(&s->buf_pkt);
++ }
++ return NQ_DRAINING;
++ }
+
- ret = ff_v4l2_context_enqueue_packet(output, &avpkt);
- if (ret < 0) {
- if (ret != AVERROR(EAGAIN))
- return ret;
-+ ret = ff_v4l2_context_enqueue_packet(&s->output, &s->buf_pkt,
-+ avctx->extradata, s->extdata_sent ? 0 : avctx->extradata_size,
-+ 1);
++ if (!s->buf_pkt.size)
++ return NQ_NONE;
+
+- s->buf_pkt = avpkt;
+- /* no input buffers available, continue dequeing */
+- }
++ if ((ret = check_output_streamon(avctx, s)) != 0)
++ return ret;
++
++ if (s->extdata_sent)
++ ret = ff_v4l2_context_enqueue_packet(&s->output, &s->buf_pkt, NULL, 0);
++ else if (s->extdata_data)
++ ret = ff_v4l2_context_enqueue_packet(&s->output, &s->buf_pkt, s->extdata_data, s->extdata_size);
++ else
++ ret = ff_v4l2_context_enqueue_packet(&s->output, &s->buf_pkt, avctx->extradata, avctx->extradata_size);
+
+ if (ret == AVERROR(EAGAIN)) {
+ // Out of input buffers - keep packet
@@ -48561,19 +53070,19 @@ Upstream-status: Pending
+ // In all other cases we are done with this packet
+ av_packet_unref(&s->buf_pkt);
+ s->extdata_sent = 1;
-
-- s->buf_pkt = avpkt;
-- /* no input buffers available, continue dequeing */
-+ if (ret) {
-+ av_log(avctx, AV_LOG_ERROR, "Packet enqueue failure: err=%d\n", ret);
-+ return ret;
-+ }
- }
-
+
- if (avpkt.size) {
- ret = v4l2_try_start(avctx);
-- if (ret) {
+ if (ret) {
- av_packet_unref(&avpkt);
++ av_log(avctx, AV_LOG_ERROR, "Packet enqueue failure: err=%d\n", ret);
++ return ret;
++ }
++ }
+
+- /* cant recover */
+- if (ret == AVERROR(ENOMEM))
+- return ret;
+ // Start if we haven't
+ {
+ const int ret2 = v4l2_try_start(avctx);
@@ -48582,62 +53091,139 @@ Upstream-status: Pending
+ ret = (ret2 == AVERROR(ENOMEM)) ? ret2 : NQ_DEAD;
+ }
+ }
-
-- /* cant recover */
-- if (ret == AVERROR(ENOMEM))
-- return ret;
++
+ return ret;
+}
-
++
++static int qbuf_wait(AVCodecContext * const avctx, V4L2Context * const ctx)
++{
++ int rv = 0;
+
- return 0;
++ ff_mutex_lock(&ctx->lock);
++
++ while (atomic_load(&ctx->q_count) == 0 && ctx->streamon) {
++ if (pthread_cond_wait(&ctx->cond, &ctx->lock) != 0) {
++ rv = AVERROR(errno);
++ av_log(avctx, AV_LOG_ERROR, "Cond wait failure: %s\n", av_err2str(rv));
++ break;
+ }
+ }
+
+-dequeue:
+- if (!s->buf_pkt.size)
+- av_packet_unref(&avpkt);
+- return ff_v4l2_context_dequeue_frame(capture, frame, -1);
++ ff_mutex_unlock(&ctx->lock);
++ return rv;
++}
++
++// Number of frames over what xlat_pending returns that we keep *16
++// This is a min value - if it appears to be too small the threshold should
++// adjust dynamically.
++#define PENDING_HW_MIN (3 * 16)
++// Offset to use when setting dynamically
++// Set to %16 == 15 to avoid the threshold changing immediately as we relax
++#define PENDING_HW_OFFSET (PENDING_HW_MIN - 1)
++// Number of consecutive times we've failed to get a frame when we prefer it
++// before we increase the prefer threshold (5ms * N = max expected decode
++// time)
++#define PENDING_N_THRESHOLD 6
++
+static int v4l2_receive_frame(AVCodecContext *avctx, AVFrame *frame)
+{
+ V4L2m2mContext *const s = ((V4L2m2mPriv*)avctx->priv_data)->context;
-+ int src_rv;
++ int src_rv = NQ_OK;
+ int dst_rv = 1; // Non-zero (done), non-negative (error) number
++ unsigned int i = 0;
+
+ do {
-+ src_rv = try_enqueue_src(avctx, s);
-+
-+ // If we got a frame last time and we have nothing to enqueue then
-+ // return now. rv will be AVERROR(EAGAIN) indicating that we want more input
++ const int pending = xlat_pending(&s->xlat);
++ const int prefer_dq = (pending > s->pending_hw / 16);
++ const int last_src_rv = src_rv;
++
++ // Enqueue another pkt for decode if
++ // (a) We don't have a lot of stuff in the buffer already OR
++ // (b) ... we (think we) do but we've failed to get a frame already OR
++ // (c) We've dequeued a lot of frames without asking for input
++ src_rv = try_enqueue_src(avctx, s, !(!prefer_dq || i != 0 || s->req_pkt > 2));
++
++ // If we got a frame last time or we've already tried to get a frame and
++ // we have nothing to enqueue then return now. rv will be AVERROR(EAGAIN)
++ // indicating that we want more input.
+ // This should mean that once decode starts we enter a stable state where
+ // we alternately ask for input and produce output
-+ if (s->req_pkt && src_rv == NQ_SRC_EMPTY)
++ if ((i != 0 || s->req_pkt) && src_rv == NQ_SRC_EMPTY)
+ break;
+
-+ if (src_rv == NQ_Q_FULL && dst_rv == AVERROR(EAGAIN)) {
-+ av_log(avctx, AV_LOG_WARNING, "Poll says src Q has space but enqueue fail");
-+ src_rv = NQ_SRC_EMPTY; // If we can't enqueue pretend that there is nothing to enqueue
++ if (src_rv == NQ_Q_FULL && last_src_rv == NQ_Q_FULL) {
++ av_log(avctx, AV_LOG_WARNING, "Poll thinks src Q has space; none found\n");
++ break;
+ }
+
+ // Try to get a new frame if
+ // (a) we haven't already got one AND
+ // (b) enqueue returned a status indicating that decode should be attempted
+ if (dst_rv != 0 && TRY_DQ(src_rv)) {
-+ do {
-+ // Dequeue frame will unref any previous contents of frame
-+ // if it returns success so we don't need an explicit unref
-+ // when discarding
-+ // This returns AVERROR(EAGAIN) if there isn't a frame ready yet
-+ // but there is room in the input Q
-+ dst_rv = ff_v4l2_context_dequeue_frame(&s->capture, frame, -1, 1);
++ // Pick a timeout depending on state
++ const int t =
++ src_rv == NQ_DRAINING ? 300 :
++ prefer_dq ? 5 :
++ src_rv == NQ_Q_FULL ? -1 : 0;
++
++ // Dequeue frame will unref any previous contents of frame
++ // if it returns success so we don't need an explicit unref
++ // when discarding
++ // This returns AVERROR(EAGAIN) on timeout or if
++ // there is room in the input Q and timeout == -1
++ dst_rv = ff_v4l2_context_dequeue_frame(&s->capture, frame, t);
++
++ // Failure due to no buffer in Q?
++ if (dst_rv == AVERROR(ENOSPC)) {
++ // Wait & retry
++ if ((dst_rv = qbuf_wait(avctx, &s->capture)) == 0) {
++ dst_rv = ff_v4l2_context_dequeue_frame(&s->capture, frame, t);
++ }
++ }
+
-+ if (dst_rv == AVERROR_EOF && (s->draining || s->capture.done))
-+ av_log(avctx, AV_LOG_DEBUG, "Dequeue EOF: draining=%d, cap.done=%d\n",
-+ s->draining, s->capture.done);
-+ else if (dst_rv && dst_rv != AVERROR(EAGAIN))
-+ av_log(avctx, AV_LOG_ERROR, "Packet dequeue failure: draining=%d, cap.done=%d, err=%d\n",
-+ s->draining, s->capture.done, dst_rv);
++ // Adjust dynamic pending threshold
++ if (dst_rv == 0) {
++ if (--s->pending_hw < PENDING_HW_MIN)
++ s->pending_hw = PENDING_HW_MIN;
++ s->pending_n = 0;
+
-+ // Go again if we got a frame that we need to discard
-+ } while (dst_rv == 0 && xlat_pts_out(avctx, s, frame));
++ set_best_effort_pts(avctx, &s->pts_stat, frame);
++ }
++ else if (dst_rv == AVERROR(EAGAIN)) {
++ if (prefer_dq && ++s->pending_n > PENDING_N_THRESHOLD) {
++ s->pending_hw = pending * 16 + PENDING_HW_OFFSET;
++ s->pending_n = 0;
++ }
++ }
++
++ if (dst_rv == AVERROR(EAGAIN) && src_rv == NQ_DRAINING) {
++ av_log(avctx, AV_LOG_WARNING, "Timeout in drain - assume EOF");
++ dst_rv = AVERROR_EOF;
++ s->capture.done = 1;
++ }
++ else if (dst_rv == AVERROR_EOF && (s->draining || s->capture.done))
++ av_log(avctx, AV_LOG_DEBUG, "Dequeue EOF: draining=%d, cap.done=%d\n",
++ s->draining, s->capture.done);
++ else if (dst_rv && dst_rv != AVERROR(EAGAIN))
++ av_log(avctx, AV_LOG_ERROR, "Packet dequeue failure: draining=%d, cap.done=%d, err=%d\n",
++ s->draining, s->capture.done, dst_rv);
++ }
++
++ ++i;
++ if (i >= 256) {
++ av_log(avctx, AV_LOG_ERROR, "Unexpectedly large retry count: %d\n", i);
++ src_rv = AVERROR(EIO);
+ }
+
+ // Continue trying to enqueue packets if either
+ // (a) we succeeded last time OR
-+ // (b) enqueue failed due to input Q full AND there is now room
-+ } while (src_rv == NQ_OK || (src_rv == NQ_Q_FULL && dst_rv == AVERROR(EAGAIN)) );
++ // (b) we didn't ret a frame and we can retry the input
++ } while (src_rv == NQ_OK || (dst_rv == AVERROR(EAGAIN) && RETRY_NQ(src_rv)));
+
+ // Ensure that the frame contains nothing if we aren't returning a frame
+ // (might happen when discarding)
@@ -48645,7 +53231,7 @@ Upstream-status: Pending
+ av_frame_unref(frame);
+
+ // If we got a frame this time ask for a pkt next time
-+ s->req_pkt = (dst_rv == 0);
++ s->req_pkt = (dst_rv == 0) ? s->req_pkt + 1 : 0;
+
+#if 0
+ if (dst_rv == 0)
@@ -48655,8 +53241,8 @@ Upstream-status: Pending
+ av_log(avctx, AV_LOG_ERROR, "Streamoff and die?\n");
+ ff_v4l2_context_set_status(&s->capture, VIDIOC_STREAMOFF);
+ return -1;
- }
- }
++ }
++ }
+#endif
+
+ return dst_rv == 0 ? 0 :
@@ -48687,18 +53273,113 @@ Upstream-status: Pending
+}
+#endif
+
++static int
++check_size(AVCodecContext * const avctx, V4L2m2mContext * const s)
++{
++ unsigned int i;
++ const uint32_t fcc = ff_v4l2_get_format_pixelformat(&s->capture.format);
++ const uint32_t w = avctx->coded_width;
++ const uint32_t h = avctx->coded_height;
++
++ if (w == 0 || h == 0 || fcc == 0) {
++ av_log(avctx, AV_LOG_TRACE, "%s: Size %dx%d or fcc %s empty\n", __func__, w, h, av_fourcc2str(fcc));
++ return 0;
++ }
++ if ((s->quirks & FF_V4L2_QUIRK_ENUM_FRAMESIZES_BROKEN) != 0) {
++ av_log(avctx, AV_LOG_TRACE, "%s: Skipped (quirk): Size %dx%d, fcc %s\n", __func__, w, h, av_fourcc2str(fcc));
++ return 0;
++ }
++
++ for (i = 0;; ++i) {
++ struct v4l2_frmsizeenum fs = {
++ .index = i,
++ .pixel_format = fcc,
++ };
++
++ while (ioctl(s->fd, VIDIOC_ENUM_FRAMESIZES, &fs) != 0) {
++ const int err = AVERROR(errno);
++ if (err == AVERROR(EINTR))
++ continue;
++ if (i == 0 && err == AVERROR(ENOTTY)) {
++ av_log(avctx, AV_LOG_DEBUG, "Framesize enum not supported\n");
++ return 0;
++ }
++ if (err != AVERROR(EINVAL)) {
++ av_log(avctx, AV_LOG_ERROR, "Failed to enum framesizes: %s", av_err2str(err));
++ return err;
++ }
++ av_log(avctx, AV_LOG_WARNING, "Failed to find Size=%dx%d, fmt=%s in %u frame size enums\n",
++ w, h, av_fourcc2str(fcc), i);
++ return err;
++ }
++
++ switch (fs.type) {
++ case V4L2_FRMSIZE_TYPE_DISCRETE:
++ av_log(avctx, AV_LOG_TRACE, "%s[%d]: Discrete: %dx%d\n", __func__, i,
++ fs.discrete.width,fs.discrete.height);
++ if (w == fs.discrete.width && h == fs.discrete.height)
++ return 0;
++ break;
++ case V4L2_FRMSIZE_TYPE_STEPWISE:
++ av_log(avctx, AV_LOG_TRACE, "%s[%d]: Stepwise: Min: %dx%d Max: %dx%d, Step: %dx%d\n", __func__, i,
++ fs.stepwise.min_width, fs.stepwise.min_height,
++ fs.stepwise.max_width, fs.stepwise.max_height,
++ fs.stepwise.step_width,fs.stepwise.step_height);
++ if (w >= fs.stepwise.min_width && w <= fs.stepwise.max_width &&
++ h >= fs.stepwise.min_height && h <= fs.stepwise.max_height &&
++ (w - fs.stepwise.min_width) % fs.stepwise.step_width == 0 &&
++ (h - fs.stepwise.min_height) % fs.stepwise.step_height == 0)
++ return 0;
++ break;
++ case V4L2_FRMSIZE_TYPE_CONTINUOUS:
++ av_log(avctx, AV_LOG_TRACE, "%s[%d]: Continuous: Min: %dx%d Max: %dx%d, Step: %dx%d\n", __func__, i,
++ fs.stepwise.min_width, fs.stepwise.min_height,
++ fs.stepwise.max_width, fs.stepwise.max_height,
++ fs.stepwise.step_width,fs.stepwise.step_height);
++ if (w >= fs.stepwise.min_width && w <= fs.stepwise.max_width &&
++ h >= fs.stepwise.min_height && h <= fs.stepwise.max_height)
++ return 0;
++ break;
++ default:
++ av_log(avctx, AV_LOG_ERROR, "Unexpected framesize enum: %d", fs.type);
++ return AVERROR(EINVAL);
++ }
++ }
++}
++
++static int
++get_quirks(AVCodecContext * const avctx, V4L2m2mContext * const s)
++{
++ struct v4l2_capability cap;
++
++ memset(&cap, 0, sizeof(cap));
++ while (ioctl(s->fd, VIDIOC_QUERYCAP, &cap) != 0) {
++ int err = errno;
++ if (err == EINTR)
++ continue;
++ av_log(avctx, AV_LOG_ERROR, "V4L2: Failed to get capabilities: %s\n", strerror(err));
++ return AVERROR(err);
++ }
++
++ // Could be made table driven if we have a few more but right now there
++ // seems no point
++
++ // Meson (amlogic) always gives a resolution changed event after output
++ // streamon and userspace must (re)allocate capture buffers and streamon
++ // capture to clear the event even if the capture buffers were the right
++ // size in the first place.
++ if (strcmp(cap.driver, "meson-vdec") == 0)
++ s->quirks |= FF_V4L2_QUIRK_REINIT_ALWAYS | FF_V4L2_QUIRK_ENUM_FRAMESIZES_BROKEN;
++
++ av_log(avctx, AV_LOG_DEBUG, "Driver '%s': Quirks=%#x\n", cap.driver, s->quirks);
++ return 0;
++}
++
++// This heuristic is for H264 but use for everything
+static uint32_t max_coded_size(const AVCodecContext * const avctx)
+{
+ uint32_t wxh = avctx->coded_width * avctx->coded_height;
+ uint32_t size;
-
--dequeue:
-- if (!s->buf_pkt.size)
-- av_packet_unref(&avpkt);
-- return ff_v4l2_context_dequeue_frame(capture, frame, -1);
-+ // Currently the only thing we try to set our own limits for is H264
-+ if (avctx->codec_id != AV_CODEC_ID_H264)
-+ return 0;
+
+ size = wxh * 3 / 2;
+ // H.264 Annex A table A-1 gives minCR which is either 2 or 4
@@ -48711,27 +53392,53 @@ Upstream-status: Pending
+ // with small WxH
+ return size + (1 << 16);
}
-
+
static av_cold int v4l2_decode_init(AVCodecContext *avctx)
-@@ -186,8 +481,12 @@ static av_cold int v4l2_decode_init(AVCo
+@@ -186,12 +699,29 @@ static av_cold int v4l2_decode_init(AVCo
V4L2Context *capture, *output;
V4L2m2mContext *s;
V4L2m2mPriv *priv = avctx->priv_data;
+ int gf_pix_fmt;
int ret;
-
+
+ av_log(avctx, AV_LOG_TRACE, "<<< %s\n", __func__);
+
++ if (avctx->codec_id == AV_CODEC_ID_H264) {
++ if (avctx->ticks_per_frame == 1) {
++ if(avctx->time_base.den < INT_MAX/2) {
++ avctx->time_base.den *= 2;
++ } else
++ avctx->time_base.num /= 2;
++ }
++ avctx->ticks_per_frame = 2;
++ }
++
+ av_log(avctx, AV_LOG_INFO, "level=%d\n", avctx->level);
ret = ff_v4l2_m2m_create_context(priv, &s);
if (ret < 0)
return ret;
-@@ -204,17 +503,43 @@ static av_cold int v4l2_decode_init(AVCo
-
+
++ pts_stats_init(&s->pts_stat, avctx, "decoder");
++ s->pending_hw = PENDING_HW_MIN;
++
+ capture = &s->capture;
+ output = &s->output;
+
+@@ -199,34 +729,127 @@ static av_cold int v4l2_decode_init(AVCo
+ * by the v4l2 driver; this event will trigger a full pipeline reconfig and
+ * the proper values will be retrieved from the kernel driver.
+ */
+- output->height = capture->height = avctx->coded_height;
+- output->width = capture->width = avctx->coded_width;
++// output->height = capture->height = avctx->coded_height;
++// output->width = capture->width = avctx->coded_width;
++ output->height = capture->height = 0;
++ output->width = capture->width = 0;
+
output->av_codec_id = avctx->codec_id;
output->av_pix_fmt = AV_PIX_FMT_NONE;
+ output->min_buf_size = max_coded_size(avctx);
-
+
capture->av_codec_id = AV_CODEC_ID_RAWVIDEO;
capture->av_pix_fmt = avctx->pix_fmt;
+ capture->min_buf_size = 0;
@@ -48743,15 +53450,21 @@ Upstream-status: Pending
+ * check the v4l2_get_drm_frame function.
+ */
+
++ avctx->sw_pix_fmt = avctx->pix_fmt;
+ gf_pix_fmt = ff_get_format(avctx, avctx->codec->pix_fmts);
-+ av_log(avctx, AV_LOG_DEBUG, "avctx requested=%d (%s); get_format requested=%d (%s)\n",
-+ avctx->pix_fmt, av_get_pix_fmt_name(avctx->pix_fmt), gf_pix_fmt, av_get_pix_fmt_name(gf_pix_fmt));
++ av_log(avctx, AV_LOG_DEBUG, "avctx requested=%d (%s) %dx%d; get_format requested=%d (%s)\n",
++ avctx->pix_fmt, av_get_pix_fmt_name(avctx->pix_fmt),
++ avctx->coded_width, avctx->coded_height,
++ gf_pix_fmt, av_get_pix_fmt_name(gf_pix_fmt));
+
-+ s->output_drm = 0;
+ if (gf_pix_fmt == AV_PIX_FMT_DRM_PRIME || avctx->pix_fmt == AV_PIX_FMT_DRM_PRIME) {
+ avctx->pix_fmt = AV_PIX_FMT_DRM_PRIME;
+ s->output_drm = 1;
+ }
++ else {
++ capture->av_pix_fmt = gf_pix_fmt;
++ s->output_drm = 0;
++ }
+
+ s->device_ref = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_DRM);
+ if (!s->device_ref) {
@@ -48762,7 +53475,7 @@ Upstream-status: Pending
+ ret = av_hwdevice_ctx_init(s->device_ref);
+ if (ret < 0)
+ return ret;
-
+
s->avctx = avctx;
ret = ff_v4l2_m2m_codec_init(priv);
if (ret) {
@@ -48772,15 +53485,24 @@ Upstream-status: Pending
-
return ret;
}
-
-@@ -223,10 +548,53 @@ static av_cold int v4l2_decode_init(AVCo
-
+
+- return v4l2_prepare_decoder(s);
++ if ((ret = v4l2_prepare_decoder(s)) < 0)
++ return ret;
++
++ if ((ret = get_quirks(avctx, s)) != 0)
++ return ret;
++
++ if ((ret = check_size(avctx, s)) != 0)
++ return ret;
++
++ return 0;
+ }
+
static av_cold int v4l2_decode_close(AVCodecContext *avctx)
{
- V4L2m2mPriv *priv = avctx->priv_data;
- V4L2m2mContext *s = priv->context;
-- av_packet_unref(&s->buf_pkt);
-- return ff_v4l2_m2m_codec_end(priv);
+ int rv;
+ av_log(avctx, AV_LOG_TRACE, "<<< %s\n", __func__);
+ rv = ff_v4l2_m2m_codec_end(avctx->priv_data);
@@ -48802,7 +53524,6 @@ Upstream-status: Pending
+ V4L2m2mContext * const s = priv->context;
+ V4L2Context * const output = &s->output;
+ V4L2Context * const capture = &s->capture;
-+ int ret, i;
+
+ av_log(avctx, AV_LOG_TRACE, "<<< %s: streamon=%d\n", __func__, output->streamon);
+
@@ -48810,14 +53531,23 @@ Upstream-status: Pending
+ // states like EOS processing so don't try to optimize out (having got it
+ // wrong once)
+
-+ ret = ff_v4l2_context_set_status(output, VIDIOC_STREAMOFF);
-+ if (ret < 0)
-+ av_log(avctx, AV_LOG_ERROR, "VIDIOC_STREAMOFF %s error: %d\n", output->name, ret);
++ ff_v4l2_context_set_status(output, VIDIOC_STREAMOFF);
++
++ // Clear any buffered input packet
+ av_packet_unref(&s->buf_pkt);
+- return ff_v4l2_m2m_codec_end(priv);
++
++ // Clear a pending EOS
++ if (ff_v4l2_ctx_eos(capture)) {
++ // Arguably we could delay this but this is easy and doesn't require
++ // thought or extra vars
++ ff_v4l2_context_set_status(capture, VIDIOC_STREAMOFF);
++ ff_v4l2_context_set_status(capture, VIDIOC_STREAMON);
++ }
+
+ // V4L2 makes no guarantees about whether decoded frames are flushed or not
+ // so mark all frames we are tracking to be discarded if they appear
-+ for (i = 0; i != FF_V4L2_M2M_TRACK_SIZE; ++i)
-+ s->track_els[i].discard = 1;
++ xlat_flush(&s->xlat);
+
+ // resend extradata
+ s->extdata_sent = 0;
@@ -48829,9 +53559,9 @@ Upstream-status: Pending
+ // Stream on will occur when we actually submit a new frame
+ av_log(avctx, AV_LOG_TRACE, ">>> %s\n", __func__);
}
-
+
#define OFFSET(x) offsetof(V4L2m2mPriv, x)
-@@ -235,10 +603,16 @@ static av_cold int v4l2_decode_close(AVC
+@@ -235,10 +858,16 @@ static av_cold int v4l2_decode_close(AVC
static const AVOption options[] = {
V4L_M2M_DEFAULT_OPTS,
{ "num_capture_buffers", "Number of buffers in the capture context",
@@ -48840,7 +53570,7 @@ Upstream-status: Pending
+ { "pixel_format", "Pixel format to be used by the decoder", OFFSET(pix_fmt), AV_OPT_TYPE_PIXEL_FMT, {.i64 = AV_PIX_FMT_NONE}, AV_PIX_FMT_NONE, AV_PIX_FMT_NB, FLAGS },
{ NULL},
};
-
+
+static const AVCodecHWConfigInternal *v4l2_m2m_hw_configs[] = {
+ HW_CONFIG_INTERNAL(DRM_PRIME),
+ NULL
@@ -48849,7 +53579,7 @@ Upstream-status: Pending
#define M2MDEC_CLASS(NAME) \
static const AVClass v4l2_m2m_ ## NAME ## _dec_class = { \
.class_name = #NAME "_v4l2m2m_decoder", \
-@@ -259,9 +633,15 @@ static const AVOption options[] = {
+@@ -259,9 +888,15 @@ static const AVOption options[] = {
.init = v4l2_decode_init, \
.receive_frame = v4l2_receive_frame, \
.close = v4l2_decode_close, \
@@ -48865,7 +53595,366 @@ Upstream-status: Pending
+ .hw_configs = v4l2_m2m_hw_configs, \
.wrapper_name = "v4l2m2m", \
}
-
+
+--- a/libavcodec/v4l2_m2m_enc.c
++++ b/libavcodec/v4l2_m2m_enc.c
+@@ -24,6 +24,8 @@
+ #include <linux/videodev2.h>
+ #include <sys/ioctl.h>
+ #include <search.h>
++#include <drm_fourcc.h>
++
+ #include "libavcodec/avcodec.h"
+ #include "libavcodec/internal.h"
+ #include "libavutil/pixdesc.h"
+@@ -37,6 +39,34 @@
+ #define MPEG_CID(x) V4L2_CID_MPEG_VIDEO_##x
+ #define MPEG_VIDEO(x) V4L2_MPEG_VIDEO_##x
+
++// P030 should be defined in drm_fourcc.h and hopefully will be sometime
++// in the future but until then...
++#ifndef DRM_FORMAT_P030
++#define DRM_FORMAT_P030 fourcc_code('P', '0', '3', '0')
++#endif
++
++#ifndef DRM_FORMAT_NV15
++#define DRM_FORMAT_NV15 fourcc_code('N', 'V', '1', '5')
++#endif
++
++#ifndef DRM_FORMAT_NV20
++#define DRM_FORMAT_NV20 fourcc_code('N', 'V', '2', '0')
++#endif
++
++#ifndef V4L2_CID_CODEC_BASE
++#define V4L2_CID_CODEC_BASE V4L2_CID_MPEG_BASE
++#endif
++
++// V4L2_PIX_FMT_NV12_10_COL128 and V4L2_PIX_FMT_NV12_COL128 should be defined
++// in videodev2.h hopefully will be sometime in the future but until then...
++#ifndef V4L2_PIX_FMT_NV12_10_COL128
++#define V4L2_PIX_FMT_NV12_10_COL128 v4l2_fourcc('N', 'C', '3', '0')
++#endif
++
++#ifndef V4L2_PIX_FMT_NV12_COL128
++#define V4L2_PIX_FMT_NV12_COL128 v4l2_fourcc('N', 'C', '1', '2') /* 12 Y/CbCr 4:2:0 128 pixel wide column */
++#endif
++
+ static inline void v4l2_set_timeperframe(V4L2m2mContext *s, unsigned int num, unsigned int den)
+ {
+ struct v4l2_streamparm parm = { 0 };
+@@ -147,15 +177,14 @@ static inline int v4l2_mpeg4_profile_fro
+ static int v4l2_check_b_frame_support(V4L2m2mContext *s)
+ {
+ if (s->avctx->max_b_frames)
+- av_log(s->avctx, AV_LOG_WARNING, "Encoder does not support b-frames yet\n");
++ av_log(s->avctx, AV_LOG_WARNING, "Encoder does not support %d b-frames yet\n", s->avctx->max_b_frames);
+
+- v4l2_set_ext_ctrl(s, MPEG_CID(B_FRAMES), 0, "number of B-frames", 0);
++ v4l2_set_ext_ctrl(s, MPEG_CID(B_FRAMES), s->avctx->max_b_frames, "number of B-frames", 1);
+ v4l2_get_ext_ctrl(s, MPEG_CID(B_FRAMES), &s->avctx->max_b_frames, "number of B-frames", 0);
+ if (s->avctx->max_b_frames == 0)
+ return 0;
+
+ avpriv_report_missing_feature(s->avctx, "DTS/PTS calculation for V4L2 encoding");
+-
+ return AVERROR_PATCHWELCOME;
+ }
+
+@@ -270,13 +299,184 @@ static int v4l2_prepare_encoder(V4L2m2mC
+ return 0;
+ }
+
++static int avdrm_to_v4l2(struct v4l2_format * const format, const AVFrame * const frame)
++{
++ const AVDRMFrameDescriptor *const src = (const AVDRMFrameDescriptor *)frame->data[0];
++
++ const uint32_t drm_fmt = src->layers[0].format;
++ // Treat INVALID as LINEAR
++ const uint64_t mod = src->objects[0].format_modifier == DRM_FORMAT_MOD_INVALID ?
++ DRM_FORMAT_MOD_LINEAR : src->objects[0].format_modifier;
++ uint32_t pix_fmt = 0;
++ uint32_t w = 0;
++ uint32_t h = 0;
++ uint32_t bpl = src->layers[0].planes[0].pitch;
++
++ // We really don't expect multiple layers
++ // All formats that we currently cope with are single object
++
++ if (src->nb_layers != 1 || src->nb_objects != 1)
++ return AVERROR(EINVAL);
++
++ switch (drm_fmt) {
++ case DRM_FORMAT_YUV420:
++ if (mod == DRM_FORMAT_MOD_LINEAR) {
++ if (src->layers[0].nb_planes != 3)
++ break;
++ pix_fmt = V4L2_PIX_FMT_YUV420;
++ h = src->layers[0].planes[1].offset / bpl;
++ w = bpl;
++ }
++ break;
++
++ case DRM_FORMAT_NV12:
++ if (mod == DRM_FORMAT_MOD_LINEAR) {
++ if (src->layers[0].nb_planes != 2)
++ break;
++ pix_fmt = V4L2_PIX_FMT_NV12;
++ h = src->layers[0].planes[1].offset / bpl;
++ w = bpl;
++ }
++ else if (fourcc_mod_broadcom_mod(mod) == DRM_FORMAT_MOD_BROADCOM_SAND128) {
++ if (src->layers[0].nb_planes != 2)
++ break;
++ pix_fmt = V4L2_PIX_FMT_NV12_COL128;
++ w = bpl;
++ h = src->layers[0].planes[1].offset / 128;
++ bpl = fourcc_mod_broadcom_param(mod);
++ }
++ break;
++
++ case DRM_FORMAT_P030:
++ if (fourcc_mod_broadcom_mod(mod) == DRM_FORMAT_MOD_BROADCOM_SAND128) {
++ if (src->layers[0].nb_planes != 2)
++ break;
++ pix_fmt = V4L2_PIX_FMT_NV12_10_COL128;
++ w = bpl / 2; // Matching lie to how we construct this
++ h = src->layers[0].planes[1].offset / 128;
++ bpl = fourcc_mod_broadcom_param(mod);
++ }
++ break;
++
++ default:
++ break;
++ }
++
++ if (!pix_fmt)
++ return AVERROR(EINVAL);
++
++ if (V4L2_TYPE_IS_MULTIPLANAR(format->type)) {
++ struct v4l2_pix_format_mplane *const pix = &format->fmt.pix_mp;
++
++ pix->width = w;
++ pix->height = h;
++ pix->pixelformat = pix_fmt;
++ pix->plane_fmt[0].bytesperline = bpl;
++ pix->num_planes = 1;
++ }
++ else {
++ struct v4l2_pix_format *const pix = &format->fmt.pix;
++
++ pix->width = w;
++ pix->height = h;
++ pix->pixelformat = pix_fmt;
++ pix->bytesperline = bpl;
++ }
++
++ return 0;
++}
++
++// Do we have similar enough formats to be usable?
++static int fmt_eq(const struct v4l2_format * const a, const struct v4l2_format * const b)
++{
++ if (a->type != b->type)
++ return 0;
++
++ if (V4L2_TYPE_IS_MULTIPLANAR(a->type)) {
++ const struct v4l2_pix_format_mplane *const pa = &a->fmt.pix_mp;
++ const struct v4l2_pix_format_mplane *const pb = &b->fmt.pix_mp;
++ unsigned int i;
++ if (pa->pixelformat != pb->pixelformat ||
++ pa->num_planes != pb->num_planes)
++ return 0;
++ for (i = 0; i != pa->num_planes; ++i) {
++ if (pa->plane_fmt[i].bytesperline != pb->plane_fmt[i].bytesperline)
++ return 0;
++ }
++ }
++ else {
++ const struct v4l2_pix_format *const pa = &a->fmt.pix;
++ const struct v4l2_pix_format *const pb = &b->fmt.pix;
++ if (pa->pixelformat != pb->pixelformat ||
++ pa->bytesperline != pb->bytesperline)
++ return 0;
++ }
++ return 1;
++}
++
++
+ static int v4l2_send_frame(AVCodecContext *avctx, const AVFrame *frame)
+ {
+ V4L2m2mContext *s = ((V4L2m2mPriv*)avctx->priv_data)->context;
+ V4L2Context *const output = &s->output;
+
++ // Signal EOF if needed
++ if (!frame) {
++ return ff_v4l2_context_enqueue_frame(output, frame);
++ }
++
++ if (s->input_drm && !output->streamon) {
++ int rv;
++ struct v4l2_format req_format = {.type = output->format.type};
++
++ // Set format when we first get a buffer
++ if ((rv = avdrm_to_v4l2(&req_format, frame)) != 0) {
++ av_log(avctx, AV_LOG_ERROR, "Failed to get V4L2 format from DRM_PRIME frame\n");
++ return rv;
++ }
++
++ ff_v4l2_context_release(output);
++
++ output->format = req_format;
++
++ if ((rv = ff_v4l2_context_set_format(output)) != 0) {
++ av_log(avctx, AV_LOG_ERROR, "Failed to set V4L2 format\n");
++ return rv;
++ }
++
++ if (!fmt_eq(&req_format, &output->format)) {
++ av_log(avctx, AV_LOG_ERROR, "Format mismatch after setup\n");
++ return AVERROR(EINVAL);
++ }
++
++ output->selection.top = frame->crop_top;
++ output->selection.left = frame->crop_left;
++ output->selection.width = av_frame_cropped_width(frame);
++ output->selection.height = av_frame_cropped_height(frame);
++
++ if ((rv = ff_v4l2_context_init(output)) != 0) {
++ av_log(avctx, AV_LOG_ERROR, "Failed to (re)init context\n");
++ return rv;
++ }
++
++ {
++ struct v4l2_selection selection = {
++ .type = V4L2_BUF_TYPE_VIDEO_OUTPUT,
++ .target = V4L2_SEL_TGT_CROP,
++ .r = output->selection
++ };
++ if (ioctl(s->fd, VIDIOC_S_SELECTION, &selection) != 0) {
++ av_log(avctx, AV_LOG_WARNING, "S_SELECTION (CROP) %dx%d @ %d,%d failed: %s\n",
++ selection.r.width, selection.r.height, selection.r.left, selection.r.top,
++ av_err2str(AVERROR(errno)));
++ }
++ av_log(avctx, AV_LOG_TRACE, "S_SELECTION (CROP) %dx%d @ %d,%d OK\n",
++ selection.r.width, selection.r.height, selection.r.left, selection.r.top);
++ }
++ }
++
+ #ifdef V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME
+- if (frame && frame->pict_type == AV_PICTURE_TYPE_I)
++ if (frame->pict_type == AV_PICTURE_TYPE_I)
+ v4l2_set_ext_ctrl(s, MPEG_CID(FORCE_KEY_FRAME), 0, "force key frame", 1);
+ #endif
+
+@@ -310,7 +510,70 @@ static int v4l2_receive_packet(AVCodecCo
+ }
+
+ dequeue:
+- return ff_v4l2_context_dequeue_packet(capture, avpkt);
++ if ((ret = ff_v4l2_context_dequeue_packet(capture, avpkt)) != 0)
++ return ret;
++
++ if (capture->first_buf == 1) {
++ uint8_t * data;
++ const int len = avpkt->size;
++
++ // 1st buffer after streamon should be SPS/PPS
++ capture->first_buf = 2;
++
++ // Clear both possible stores so there is no chance of confusion
++ av_freep(&s->extdata_data);
++ s->extdata_size = 0;
++ av_freep(&avctx->extradata);
++ avctx->extradata_size = 0;
++
++ if ((data = av_malloc(len + AV_INPUT_BUFFER_PADDING_SIZE)) != NULL)
++ memcpy(data, avpkt->data, len);
++
++ av_packet_unref(avpkt);
++
++ if (data == NULL)
++ return AVERROR(ENOMEM);
++
++ // We need to copy the header, but keep local if not global
++ if ((avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) != 0) {
++ avctx->extradata = data;
++ avctx->extradata_size = len;
++ }
++ else {
++ s->extdata_data = data;
++ s->extdata_size = len;
++ }
++
++ if ((ret = ff_v4l2_context_dequeue_packet(capture, avpkt)) != 0)
++ return ret;
++ }
++
++ // First frame must be key so mark as such even if encoder forgot
++ if (capture->first_buf == 2)
++ avpkt->flags |= AV_PKT_FLAG_KEY;
++
++ // Add SPS/PPS to the start of every key frame if non-global headers
++ if ((avpkt->flags & AV_PKT_FLAG_KEY) != 0 && s->extdata_size != 0) {
++ const size_t newlen = s->extdata_size + avpkt->size;
++ AVBufferRef * const buf = av_buffer_alloc(newlen + AV_INPUT_BUFFER_PADDING_SIZE);
++
++ if (buf == NULL) {
++ av_packet_unref(avpkt);
++ return AVERROR(ENOMEM);
++ }
++
++ memcpy(buf->data, s->extdata_data, s->extdata_size);
++ memcpy(buf->data + s->extdata_size, avpkt->data, avpkt->size);
++
++ av_buffer_unref(&avpkt->buf);
++ avpkt->buf = buf;
++ avpkt->data = buf->data;
++ avpkt->size = newlen;
++ }
++
++// av_log(avctx, AV_LOG_INFO, "%s: PTS out=%"PRId64", size=%d, ret=%d\n", __func__, avpkt->pts, avpkt->size, ret);
++ capture->first_buf = 0;
++ return 0;
+ }
+
+ static av_cold int v4l2_encode_init(AVCodecContext *avctx)
+@@ -322,6 +585,8 @@ static av_cold int v4l2_encode_init(AVCo
+ uint32_t v4l2_fmt_output;
+ int ret;
+
++ av_log(avctx, AV_LOG_INFO, " <<< %s: fmt=%d/%d\n", __func__, avctx->pix_fmt, avctx->sw_pix_fmt);
++
+ ret = ff_v4l2_m2m_create_context(priv, &s);
+ if (ret < 0)
+ return ret;
+@@ -329,13 +594,17 @@ static av_cold int v4l2_encode_init(AVCo
+ capture = &s->capture;
+ output = &s->output;
+
++ s->input_drm = (avctx->pix_fmt == AV_PIX_FMT_DRM_PRIME);
++
+ /* common settings output/capture */
+ output->height = capture->height = avctx->height;
+ output->width = capture->width = avctx->width;
+
+ /* output context */
+ output->av_codec_id = AV_CODEC_ID_RAWVIDEO;
+- output->av_pix_fmt = avctx->pix_fmt;
++ output->av_pix_fmt = !s->input_drm ? avctx->pix_fmt :
++ avctx->sw_pix_fmt != AV_PIX_FMT_NONE ? avctx->sw_pix_fmt :
++ AV_PIX_FMT_YUV420P;
+
+ /* capture context */
+ capture->av_codec_id = avctx->codec_id;
+@@ -354,7 +623,7 @@ static av_cold int v4l2_encode_init(AVCo
+ v4l2_fmt_output = output->format.fmt.pix.pixelformat;
+
+ pix_fmt_output = ff_v4l2_format_v4l2_to_avfmt(v4l2_fmt_output, AV_CODEC_ID_RAWVIDEO);
+- if (pix_fmt_output != avctx->pix_fmt) {
++ if (!s->input_drm && pix_fmt_output != avctx->pix_fmt) {
+ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt_output);
+ av_log(avctx, AV_LOG_ERROR, "Encoder requires %s pixel format.\n", desc->name);
+ return AVERROR(EINVAL);
--- /dev/null
+++ b/libavcodec/v4l2_req_decode_q.c
@@ -0,0 +1,84 @@
@@ -49780,16 +54869,26 @@ Upstream-status: Pending
+#include "v4l2_req_hevc_vx.c"
+
--- /dev/null
++++ b/libavcodec/v4l2_req_hevc_v3.c
+@@ -0,0 +1,3 @@
++#define HEVC_CTRLS_VERSION 3
++#include "v4l2_req_hevc_vx.c"
++
+--- /dev/null
++++ b/libavcodec/v4l2_req_hevc_v4.c
+@@ -0,0 +1,3 @@
++#define HEVC_CTRLS_VERSION 4
++#include "v4l2_req_hevc_vx.c"
++
+--- /dev/null
+++ b/libavcodec/v4l2_req_hevc_vx.c
-@@ -0,0 +1,1188 @@
+@@ -0,0 +1,1365 @@
+// File included by v4l2_req_hevc_v* - not compiled on its own
+
+#include "decode.h"
+#include "hevcdec.h"
+#include "hwconfig.h"
+
-+#include "v4l2_request_hevc.h"
-+
+#if HEVC_CTRLS_VERSION == 1
+#include "hevc-ctrls-v1.h"
+
@@ -49798,10 +54897,39 @@ Upstream-status: Pending
+
+#elif HEVC_CTRLS_VERSION == 2
+#include "hevc-ctrls-v2.h"
++#elif HEVC_CTRLS_VERSION == 3
++#include "hevc-ctrls-v3.h"
++#elif HEVC_CTRLS_VERSION == 4
++#include <linux/v4l2-controls.h>
++#if !defined(V4L2_CID_STATELESS_HEVC_SPS)
++#include "hevc-ctrls-v4.h"
++#endif
+#else
+#error Unknown HEVC_CTRLS_VERSION
+#endif
+
++#ifndef V4L2_CID_STATELESS_HEVC_SPS
++#define V4L2_CID_STATELESS_HEVC_SPS V4L2_CID_MPEG_VIDEO_HEVC_SPS
++#define V4L2_CID_STATELESS_HEVC_PPS V4L2_CID_MPEG_VIDEO_HEVC_PPS
++#define V4L2_CID_STATELESS_HEVC_SLICE_PARAMS V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS
++#define V4L2_CID_STATELESS_HEVC_SCALING_MATRIX V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX
++#define V4L2_CID_STATELESS_HEVC_DECODE_PARAMS V4L2_CID_MPEG_VIDEO_HEVC_DECODE_PARAMS
++#define V4L2_CID_STATELESS_HEVC_DECODE_MODE V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE
++#define V4L2_CID_STATELESS_HEVC_START_CODE V4L2_CID_MPEG_VIDEO_HEVC_START_CODE
++
++#define V4L2_STATELESS_HEVC_DECODE_MODE_SLICE_BASED V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED
++#define V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_FRAME_BASED
++#define V4L2_STATELESS_HEVC_START_CODE_NONE V4L2_MPEG_VIDEO_HEVC_START_CODE_NONE
++#define V4L2_STATELESS_HEVC_START_CODE_ANNEX_B V4L2_MPEG_VIDEO_HEVC_START_CODE_ANNEX_B
++#endif
++
++// Should be in videodev2 but we might not have a good enough one
++#ifndef V4L2_PIX_FMT_HEVC_SLICE
++#define V4L2_PIX_FMT_HEVC_SLICE v4l2_fourcc('S', '2', '6', '5') /* HEVC parsed slices */
++#endif
++
++#include "v4l2_request_hevc.h"
++
+#include "libavutil/hwcontext_drm.h"
+
+#include <semaphore.h>
@@ -49837,11 +54965,16 @@ Upstream-status: Pending
+ struct v4l2_ctrl_hevc_slice_params * slice_params;
+ struct slice_info * slices;
+
++ size_t num_offsets;
++ size_t alloced_offsets;
++ uint32_t *offsets;
++
+} V4L2MediaReqDescriptor;
+
+struct slice_info {
+ const uint8_t * ptr;
+ size_t len; // bytes
++ size_t n_offsets;
+};
+
+// Handy container for accumulating controls before setting
@@ -49929,6 +55062,7 @@ Upstream-status: Pending
+ }
+}
+
++#if HEVC_CTRLS_VERSION <= 2
+static int find_frame_rps_type(const HEVCContext *h, uint64_t timestamp)
+{
+ const HEVCFrame *frame;
@@ -49954,6 +55088,7 @@ Upstream-status: Pending
+
+ return 0;
+}
++#endif
+
+static unsigned int
+get_ref_pic_index(const HEVCContext *h, const HEVCFrame *frame,
@@ -49998,7 +55133,7 @@ Upstream-status: Pending
+ if (rd->num_slices >= rd->alloced_slices) {
+ struct v4l2_ctrl_hevc_slice_params * p2;
+ struct slice_info * s2;
-+ size_t n2 = rd->num_slices == 0 ? 8 : rd->num_slices * 2;
++ size_t n2 = rd->alloced_slices == 0 ? 8 : rd->alloced_slices * 2;
+
+ p2 = av_realloc_array(rd->slice_params, n2, sizeof(*p2));
+ if (p2 == NULL)
@@ -50016,6 +55151,23 @@ Upstream-status: Pending
+ return 0;
+}
+
++static int offsets_add(V4L2MediaReqDescriptor *const rd, const size_t n, const unsigned * const offsets)
++{
++ if (rd->num_offsets + n > rd->alloced_offsets) {
++ size_t n2 = rd->alloced_slices == 0 ? 128 : rd->alloced_slices * 2;
++ void * p2;
++ while (rd->num_offsets + n > n2)
++ n2 *= 2;
++ if ((p2 = av_realloc_array(rd->offsets, n2, sizeof(*rd->offsets))) == NULL)
++ return AVERROR(ENOMEM);
++ rd->offsets = p2;
++ rd->alloced_offsets = n2;
++ }
++ for (size_t i = 0; i != n; ++i)
++ rd->offsets[rd->num_offsets++] = offsets[i] - 1;
++ return 0;
++}
++
+static unsigned int
+fill_dpb_entries(const HEVCContext * const h, struct v4l2_hevc_dpb_entry * const entries)
+{
@@ -50029,12 +55181,21 @@ Upstream-status: Pending
+ struct v4l2_hevc_dpb_entry * const entry = entries + n++;
+
+ entry->timestamp = frame_capture_dpb(frame->frame);
++#if HEVC_CTRLS_VERSION <= 2
+ entry->rps = find_frame_rps_type(h, entry->timestamp);
++#else
++ entry->flags = (frame->flags & HEVC_FRAME_FLAG_LONG_REF) == 0 ? 0 :
++ V4L2_HEVC_DPB_ENTRY_LONG_TERM_REFERENCE;
++#endif
+ entry->field_pic = frame->frame->interlaced_frame;
+
++#if HEVC_CTRLS_VERSION <= 3
+ /* TODO: Interleaved: Get the POC for each field. */
+ entry->pic_order_cnt[0] = frame->poc;
+ entry->pic_order_cnt[1] = frame->poc;
++#else
++ entry->pic_order_cnt_val = frame->poc;
++#endif
+ }
+ }
+ return n;
@@ -50060,8 +55221,11 @@ Upstream-status: Pending
+
+ *slice_params = (struct v4l2_ctrl_hevc_slice_params) {
+ .bit_size = bit_size,
++#if HEVC_CTRLS_VERSION <= 3
+ .data_bit_offset = bit_offset,
-+
++#else
++ .data_byte_offset = bit_offset / 8 + 1,
++#endif
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */
+ .slice_segment_addr = sh->slice_segment_addr,
+
@@ -50144,6 +55308,7 @@ Upstream-status: Pending
+ fill_pred_table(h, &slice_params->pred_weight_table);
+
+ slice_params->num_entry_point_offsets = sh->num_entry_point_offsets;
++#if HEVC_CTRLS_VERSION <= 3
+ if (slice_params->num_entry_point_offsets > 256) {
+ slice_params->num_entry_point_offsets = 256;
+ av_log(NULL, AV_LOG_ERROR, "%s: Currently only 256 entry points are supported, but slice has %d entry points.\n", __func__, sh->num_entry_point_offsets);
@@ -50151,6 +55316,7 @@ Upstream-status: Pending
+
+ for (i = 0; i < slice_params->num_entry_point_offsets; i++)
+ slice_params->entry_point_offset_minus1[i] = sh->entry_point_offset[i] - 1;
++#endif
+}
+
+#if HEVC_CTRLS_VERSION >= 2
@@ -50526,51 +55692,66 @@ Upstream-status: Pending
+#if HEVC_CTRLS_VERSION >= 2
+ struct v4l2_ctrl_hevc_decode_params * const dec,
+#endif
-+ struct v4l2_ctrl_hevc_slice_params * const slices,
-+ const unsigned int slice_no,
-+ const unsigned int slice_count)
++ struct v4l2_ctrl_hevc_slice_params * const slices, const unsigned int slice_count,
++ void * const offsets, const size_t offset_count)
+{
+ int rv;
++#if HEVC_CTRLS_VERSION >= 2
++ unsigned int n = 3;
++#else
++ unsigned int n = 2;
++#endif
+
-+ struct v4l2_ext_control control[] = {
++ struct v4l2_ext_control control[6] = {
+ {
-+ .id = V4L2_CID_MPEG_VIDEO_HEVC_SPS,
++ .id = V4L2_CID_STATELESS_HEVC_SPS,
+ .ptr = &controls->sps,
+ .size = sizeof(controls->sps),
+ },
+ {
-+ .id = V4L2_CID_MPEG_VIDEO_HEVC_PPS,
++ .id = V4L2_CID_STATELESS_HEVC_PPS,
+ .ptr = &controls->pps,
+ .size = sizeof(controls->pps),
+ },
+#if HEVC_CTRLS_VERSION >= 2
+ {
-+ .id = V4L2_CID_MPEG_VIDEO_HEVC_DECODE_PARAMS,
++ .id = V4L2_CID_STATELESS_HEVC_DECODE_PARAMS,
+ .ptr = dec,
+ .size = sizeof(*dec),
+ },
+#endif
-+ {
-+ .id = V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS,
-+ .ptr = slices + slice_no,
++ };
++
++ if (slices)
++ control[n++] = (struct v4l2_ext_control) {
++ .id = V4L2_CID_STATELESS_HEVC_SLICE_PARAMS,
++ .ptr = slices,
+ .size = sizeof(*slices) * slice_count,
-+ },
-+ // Optional
-+ {
-+ .id = V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX,
++ };
++
++ if (controls->has_scaling)
++ control[n++] = (struct v4l2_ext_control) {
++ .id = V4L2_CID_STATELESS_HEVC_SCALING_MATRIX,
+ .ptr = &controls->scaling_matrix,
+ .size = sizeof(controls->scaling_matrix),
-+ },
-+ };
++ };
+
-+ rv = mediabufs_ctl_set_ext_ctrls(ctx->mbufs, mreq, control,
-+ controls->has_scaling ?
-+ FF_ARRAY_ELEMS(control) :
-+ FF_ARRAY_ELEMS(control) - 1);
++#if HEVC_CTRLS_VERSION >= 4
++ if (offsets)
++ control[n++] = (struct v4l2_ext_control) {
++ .id = V4L2_CID_STATELESS_HEVC_ENTRY_POINT_OFFSETS,
++ .ptr = offsets,
++ .size = sizeof(((struct V4L2MediaReqDescriptor *)0)->offsets[0]) * offset_count,
++ };
++#endif
++
++ rv = mediabufs_ctl_set_ext_ctrls(ctx->mbufs, mreq, control, n);
+
+ return rv;
+}
+
++// This only works because we started out from a single coded frame buffer
++// that will remain intact until after end_frame
+static int v4l2_request_hevc_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
+{
+ const HEVCContext * const h = avctx->priv_data;
@@ -50579,18 +55760,45 @@ Upstream-status: Pending
+ int bcount = get_bits_count(&h->HEVClc->gb);
+ uint32_t boff = (ptr_from_index(buffer, bcount/8 + 1) - (buffer + bcount/8 + 1)) * 8 + bcount;
+
++ const unsigned int n = rd->num_slices;
++ const unsigned int block_start = (n / ctx->max_slices) * ctx->max_slices;
++
+ int rv;
+ struct slice_info * si;
+
++ // This looks dodgy but we know that FFmpeg has parsed this from a buffer
++ // that contains the entire frame including the start code
++ if (ctx->start_code == V4L2_STATELESS_HEVC_START_CODE_ANNEX_B) {
++ buffer -= 3;
++ size += 3;
++ boff += 24;
++ if (buffer[0] != 0 || buffer[1] != 0 || buffer[2] != 1) {
++ av_log(avctx, AV_LOG_ERROR, "Start code requested but missing %02x:%02x:%02x\n",
++ buffer[0], buffer[1], buffer[2]);
++ }
++ }
++
++ if (ctx->decode_mode == V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED) {
++ if (rd->slices == NULL) {
++ if ((rd->slices = av_mallocz(sizeof(*rd->slices))) == NULL)
++ return AVERROR(ENOMEM);
++ rd->slices->ptr = buffer;
++ rd->num_slices = 1;
++ }
++ rd->slices->len = buffer - rd->slices->ptr + size;
++ return 0;
++ }
++
+ if ((rv = slice_add(rd)) != 0)
+ return rv;
+
-+ si = rd->slices + rd->num_slices - 1;
++ si = rd->slices + n;
+ si->ptr = buffer;
+ si->len = size;
++ si->n_offsets = rd->num_offsets;
+
-+ if (ctx->multi_slice && rd->num_slices > 1) {
-+ struct slice_info *const si0 = rd->slices;
++ if (n != block_start) {
++ struct slice_info *const si0 = rd->slices + block_start;
+ const size_t offset = (buffer - si0->ptr);
+ boff += offset * 8;
+ size += offset;
@@ -50598,12 +55806,15 @@ Upstream-status: Pending
+ }
+
+#if HEVC_CTRLS_VERSION >= 2
-+ if (rd->num_slices == 1)
++ if (n == 0)
+ fill_decode_params(h, &rd->dec);
-+ fill_slice_params(h, &rd->dec, rd->slice_params + rd->num_slices - 1, size * 8, boff);
++ fill_slice_params(h, &rd->dec, rd->slice_params + n, size * 8, boff);
+#else
-+ fill_slice_params(h, rd->slice_params + rd->num_slices - 1, size * 8, boff);
++ fill_slice_params(h, rd->slice_params + n, size * 8, boff);
+#endif
++ if (ctx->max_offsets != 0 &&
++ (rv = offsets_add(rd, h->sh.num_entry_point_offsets, h->sh.entry_point_offset)) != 0)
++ return rv;
+
+ return 0;
+}
@@ -50629,10 +55840,13 @@ Upstream-status: Pending
+{
+ V4L2RequestContextHEVC * const ctx = avctx->internal->hwaccel_priv_data;
+
++ const int is_last = (j == rd->num_slices);
+ struct slice_info *const si = rd->slices + i;
+ struct media_request * req = NULL;
+ struct qent_src * src = NULL;
+ MediaBufsStatus stat;
++ void * offsets = rd->offsets + rd->slices[i].n_offsets;
++ size_t n_offsets = (is_last ? rd->num_offsets : rd->slices[j].n_offsets) - rd->slices[i].n_offsets;
+
+ if ((req = media_request_get(ctx->mpool)) == NULL) {
+ av_log(avctx, AV_LOG_ERROR, "%s: Failed to alloc media request\n", __func__);
@@ -50644,8 +55858,8 @@ Upstream-status: Pending
+#if HEVC_CTRLS_VERSION >= 2
+ &rd->dec,
+#endif
-+ rd->slice_params,
-+ i, j - i)) {
++ rd->slice_params + i, j - i,
++ offsets, n_offsets)) {
+ av_log(avctx, AV_LOG_ERROR, "%s: Failed to set req ctls\n", __func__);
+ goto fail1;
+ }
@@ -50665,13 +55879,9 @@ Upstream-status: Pending
+ goto fail2;
+ }
+
-+#warning ANNEX_B start code
-+// if (ctx->start_code == V4L2_MPEG_VIDEO_HEVC_START_CODE_ANNEX_B) {
-+// }
-+
+ stat = mediabufs_start_request(ctx->mbufs, &req, &src,
+ i == 0 ? rd->qe_dst : NULL,
-+ j == rd->num_slices);
++ is_last);
+
+ if (stat != MEDIABUFS_STATUS_SUCCESS) {
+ av_log(avctx, AV_LOG_ERROR, "%s: Failed to start request\n", __func__);
@@ -50736,18 +55946,11 @@ Upstream-status: Pending
+ }
+
+ // Send as slices
-+ if (ctx->multi_slice)
-+ {
-+ if ((rv = send_slice(avctx, rd, &rc, 0, rd->num_slices)) != 0)
++ for (i = 0; i < rd->num_slices; i += ctx->max_slices) {
++ const unsigned int e = FFMIN(rd->num_slices, i + ctx->max_slices);
++ if ((rv = send_slice(avctx, rd, &rc, i, e)) != 0)
+ goto fail;
+ }
-+ else
-+ {
-+ for (i = 0; i != rd->num_slices; ++i) {
-+ if ((rv = send_slice(avctx, rd, &rc, i, i + 1)) != 0)
-+ goto fail;
-+ }
-+ }
+
+ // Set the drm_prime desriptor
+ drm_from_format(&rd->drm, mediabufs_dst_fmt(ctx->mbufs));
@@ -50762,6 +55965,12 @@ Upstream-status: Pending
+ return rv;
+}
+
++static inline int
++ctrl_valid(const struct v4l2_query_ext_ctrl * const c, const int64_t v)
++{
++ return v >= c->minimum && v <= c->maximum;
++}
++
+// Initial check & init
+static int
+probe(AVCodecContext * const avctx, V4L2RequestContextHEVC * const ctx)
@@ -50773,17 +55982,19 @@ Upstream-status: Pending
+
+ // Check for var slice array
+ struct v4l2_query_ext_ctrl qc[] = {
-+ { .id = V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS },
-+ { .id = V4L2_CID_MPEG_VIDEO_HEVC_SPS },
-+ { .id = V4L2_CID_MPEG_VIDEO_HEVC_PPS },
-+ { .id = V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX },
++ { .id = V4L2_CID_STATELESS_HEVC_SLICE_PARAMS },
++ { .id = V4L2_CID_STATELESS_HEVC_DECODE_MODE, },
++ { .id = V4L2_CID_STATELESS_HEVC_SPS },
++ { .id = V4L2_CID_STATELESS_HEVC_PPS },
++ { .id = V4L2_CID_STATELESS_HEVC_SCALING_MATRIX },
+#if HEVC_CTRLS_VERSION >= 2
-+ { .id = V4L2_CID_MPEG_VIDEO_HEVC_DECODE_PARAMS },
++ { .id = V4L2_CID_STATELESS_HEVC_DECODE_PARAMS },
+#endif
+ };
+ // Order & size must match!
+ static const size_t ctrl_sizes[] = {
+ sizeof(struct v4l2_ctrl_hevc_slice_params),
++ sizeof(int32_t),
+ sizeof(struct v4l2_ctrl_hevc_sps),
+ sizeof(struct v4l2_ctrl_hevc_pps),
+ sizeof(struct v4l2_ctrl_hevc_scaling_matrix),
@@ -50793,26 +56004,44 @@ Upstream-status: Pending
+ };
+ const unsigned int noof_ctrls = FF_ARRAY_ELEMS(qc);
+
-+ if (mediabufs_ctl_query_ext_ctrls(ctx->mbufs, qc, noof_ctrls)) {
-+ av_log(avctx, AV_LOG_DEBUG, "Probed V%d control missing\n", HEVC_CTRLS_VERSION);
++#if HEVC_CTRLS_VERSION == 2
++ if (mediabufs_ctl_driver_version(ctx->mbufs) >= MEDIABUFS_DRIVER_VERSION(5, 18, 0))
+ return AVERROR(EINVAL);
-+ }
-+ for (i = 0; i != noof_ctrls; ++i) {
-+ if (ctrl_sizes[i] != qc[i].elem_size) {
-+ av_log(avctx, AV_LOG_DEBUG, "Probed V%d control %d size mismatch %u != %u\n",
-+ HEVC_CTRLS_VERSION, i, ctrl_sizes[i], qc[i].elem_size);
++#elif HEVC_CTRLS_VERSION == 3
++ if (mediabufs_ctl_driver_version(ctx->mbufs) < MEDIABUFS_DRIVER_VERSION(5, 18, 0))
++ return AVERROR(EINVAL);
++#endif
++
++ mediabufs_ctl_query_ext_ctrls(ctx->mbufs, qc, noof_ctrls);
++ i = 0;
++#if HEVC_CTRLS_VERSION >= 4
++ // Skip slice check if no slice mode
++ if (qc[1].type != 0 && !ctrl_valid(qc + 1, V4L2_STATELESS_HEVC_DECODE_MODE_SLICE_BASED))
++ i = 1;
++#else
++ // Fail frame mode silently for anything prior to V4
++ if (qc[1].type == 0 || !ctrl_valid(qc + 1, V4L2_STATELESS_HEVC_DECODE_MODE_SLICE_BASED))
++ return AVERROR(EINVAL);
++#endif
++ for (; i != noof_ctrls; ++i) {
++ if (qc[i].type == 0) {
++ av_log(avctx, AV_LOG_DEBUG, "Probed V%d control %#x missing\n", HEVC_CTRLS_VERSION, qc[i].id);
++ return AVERROR(EINVAL);
++ }
++ if (ctrl_sizes[i] != (size_t)qc[i].elem_size) {
++ av_log(avctx, AV_LOG_DEBUG, "Probed V%d control %d size mismatch %zu != %zu\n",
++ HEVC_CTRLS_VERSION, i, ctrl_sizes[i], (size_t)qc[i].elem_size);
+ return AVERROR(EINVAL);
+ }
+ }
+
+ fill_sps(&ctrl_sps, sps);
+
-+ if (mediabufs_set_ext_ctrl(ctx->mbufs, NULL, V4L2_CID_MPEG_VIDEO_HEVC_SPS, &ctrl_sps, sizeof(ctrl_sps))) {
++ if (mediabufs_set_ext_ctrl(ctx->mbufs, NULL, V4L2_CID_STATELESS_HEVC_SPS, &ctrl_sps, sizeof(ctrl_sps))) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to set initial SPS\n");
+ return AVERROR(EINVAL);
+ }
+
-+ ctx->multi_slice = (qc[0].flags & V4L2_CTRL_FLAG_DYNAMIC_ARRAY) != 0;
+ return 0;
+}
+
@@ -50823,39 +56052,64 @@ Upstream-status: Pending
+ int ret;
+
+ struct v4l2_query_ext_ctrl querys[] = {
-+ { .id = V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE, },
-+ { .id = V4L2_CID_MPEG_VIDEO_HEVC_START_CODE, },
-+ { .id = V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS, },
++ { .id = V4L2_CID_STATELESS_HEVC_DECODE_MODE, },
++ { .id = V4L2_CID_STATELESS_HEVC_START_CODE, },
++ { .id = V4L2_CID_STATELESS_HEVC_SLICE_PARAMS, },
++#if HEVC_CTRLS_VERSION >= 4
++ { .id = V4L2_CID_STATELESS_HEVC_ENTRY_POINT_OFFSETS, },
++#endif
+ };
+
+ struct v4l2_ext_control ctrls[] = {
-+ { .id = V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE, },
-+ { .id = V4L2_CID_MPEG_VIDEO_HEVC_START_CODE, },
++ { .id = V4L2_CID_STATELESS_HEVC_DECODE_MODE, },
++ { .id = V4L2_CID_STATELESS_HEVC_START_CODE, },
+ };
+
+ mediabufs_ctl_query_ext_ctrls(ctx->mbufs, querys, FF_ARRAY_ELEMS(querys));
+
-+ ctx->decode_mode = querys[0].default_value;
++ ctx->max_slices = (!(querys[2].flags & V4L2_CTRL_FLAG_DYNAMIC_ARRAY) ||
++ querys[2].nr_of_dims != 1 || querys[2].dims[0] == 0) ?
++ 1 : querys[2].dims[0];
++ av_log(avctx, AV_LOG_DEBUG, "%s: Max slices %d\n", __func__, ctx->max_slices);
+
-+ if (ctx->decode_mode != V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED &&
-+ ctx->decode_mode != V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_FRAME_BASED) {
-+ av_log(avctx, AV_LOG_ERROR, "%s: unsupported decode mode, %d\n", __func__, ctx->decode_mode);
-+ return AVERROR(EINVAL);
-+ }
++#if HEVC_CTRLS_VERSION >= 4
++ ctx->max_offsets = (querys[3].type == 0 || querys[3].nr_of_dims != 1) ?
++ 0 : querys[3].dims[0];
++ av_log(avctx, AV_LOG_DEBUG, "%s: Entry point offsets %d\n", __func__, ctx->max_offsets);
++#else
++ ctx->max_offsets = 0;
++#endif
+
-+ ctx->start_code = querys[1].default_value;
-+ if (ctx->start_code != V4L2_MPEG_VIDEO_HEVC_START_CODE_NONE &&
-+ ctx->start_code != V4L2_MPEG_VIDEO_HEVC_START_CODE_ANNEX_B) {
-+ av_log(avctx, AV_LOG_ERROR, "%s: unsupported start code, %d\n", __func__, ctx->start_code);
++ if (querys[0].default_value == V4L2_STATELESS_HEVC_DECODE_MODE_SLICE_BASED ||
++ querys[0].default_value == V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED)
++ ctx->decode_mode = querys[0].default_value;
++ else if (ctrl_valid(querys + 0, V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED))
++ ctx->decode_mode = V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED;
++ else if (ctrl_valid(querys + 0, V4L2_STATELESS_HEVC_DECODE_MODE_SLICE_BASED))
++ ctx->decode_mode = V4L2_STATELESS_HEVC_DECODE_MODE_SLICE_BASED;
++ else {
++ av_log(avctx, AV_LOG_ERROR, "%s: unsupported decode mode\n", __func__);
+ return AVERROR(EINVAL);
+ }
+
-+ ctx->max_slices = querys[2].elems;
-+ if (ctx->max_slices > MAX_SLICES) {
-+ av_log(avctx, AV_LOG_ERROR, "%s: unsupported max slices, %d\n", __func__, ctx->max_slices);
++ if (querys[1].default_value == V4L2_STATELESS_HEVC_START_CODE_NONE ||
++ querys[1].default_value == V4L2_STATELESS_HEVC_START_CODE_ANNEX_B)
++ ctx->start_code = querys[1].default_value;
++ else if (ctrl_valid(querys + 1, V4L2_STATELESS_HEVC_START_CODE_ANNEX_B))
++ ctx->start_code = V4L2_STATELESS_HEVC_START_CODE_ANNEX_B;
++ else if (ctrl_valid(querys + 1, V4L2_STATELESS_HEVC_START_CODE_NONE))
++ ctx->start_code = V4L2_STATELESS_HEVC_START_CODE_NONE;
++ else {
++ av_log(avctx, AV_LOG_ERROR, "%s: unsupported start code\n", __func__);
+ return AVERROR(EINVAL);
+ }
+
++ // If we are in slice mode & START_CODE_NONE supported then pick that
++ // as it doesn't require the slightly dodgy look backwards in our raw buffer
++ if (ctx->decode_mode == V4L2_STATELESS_HEVC_DECODE_MODE_SLICE_BASED &&
++ ctrl_valid(querys + 1, V4L2_STATELESS_HEVC_START_CODE_NONE))
++ ctx->start_code = V4L2_STATELESS_HEVC_START_CODE_NONE;
++
+ ctrls[0].value = ctx->decode_mode;
+ ctrls[1].value = ctx->start_code;
+
@@ -50878,6 +56132,7 @@ Upstream-status: Pending
+
+ av_freep(&rd->slices);
+ av_freep(&rd->slice_params);
++ av_freep(&rd->offsets);
+
+ av_free(rd);
+}
@@ -50904,6 +56159,7 @@ Upstream-status: Pending
+ return ref;
+}
+
++#if 0
+static void v4l2_req_pool_free(void *opaque)
+{
+ av_log(NULL, AV_LOG_DEBUG, "%s: opaque=%p\n", __func__, opaque);
@@ -50915,6 +56171,7 @@ Upstream-status: Pending
+
+ av_buffer_pool_uninit(&hwfc->pool);
+}
++#endif
+
+static int frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx)
+{
@@ -50931,7 +56188,7 @@ Upstream-status: Pending
+ hwfc->width = vfmt->fmt.pix.width;
+ hwfc->height = vfmt->fmt.pix.height;
+ }
-+
++#if 0
+ hwfc->pool = av_buffer_pool_init2(sizeof(V4L2MediaReqDescriptor), avctx, v4l2_req_frame_alloc, v4l2_req_pool_free);
+ if (!hwfc->pool)
+ return AVERROR(ENOMEM);
@@ -50950,12 +56207,32 @@ Upstream-status: Pending
+ default:
+ hwfc->initial_pool_size += 2;
+ }
-+
++#endif
+ av_log(avctx, AV_LOG_DEBUG, "%s: avctx=%p ctx=%p hw_frames_ctx=%p hwfc=%p pool=%p width=%d height=%d initial_pool_size=%d\n", __func__, avctx, ctx, hw_frames_ctx, hwfc, hwfc->pool, hwfc->width, hwfc->height, hwfc->initial_pool_size);
+
+ return 0;
+}
+
++static int alloc_frame(AVCodecContext * avctx, AVFrame *frame)
++{
++ int rv;
++
++ frame->buf[0] = v4l2_req_frame_alloc(avctx, sizeof(V4L2MediaReqDescriptor));
++ if (!frame->buf[0])
++ return AVERROR(ENOMEM);
++
++ frame->data[0] = frame->buf[0]->data;
++
++ frame->hw_frames_ctx = av_buffer_ref(avctx->hw_frames_ctx);
++
++ if ((rv = ff_attach_decode_data(frame)) != 0) {
++ av_log(avctx, AV_LOG_ERROR, "Failed to attach decode data to frame\n");
++ av_frame_unref(frame);
++ return rv;
++ }
++
++ return 0;
++}
+
+const v4l2_req_decode_fns V(ff_v4l2_req_hevc) = {
+ .src_pix_fmt_v4l2 = V4L2_PIX_FMT_HEVC_SLICE,
@@ -50968,11 +56245,12 @@ Upstream-status: Pending
+ .end_frame = v4l2_request_hevc_end_frame,
+ .abort_frame = v4l2_request_hevc_abort_frame,
+ .frame_params = frame_params,
++ .alloc_frame = alloc_frame,
+};
+
--- /dev/null
+++ b/libavcodec/v4l2_req_media.c
-@@ -0,0 +1,1569 @@
+@@ -0,0 +1,1601 @@
+/*
+ * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
+ *
@@ -51388,7 +56666,7 @@ Upstream-status: Pending
+ free(be_dst);
+}
+
-+static struct qent_dst * qe_dst_new(void)
++static struct qent_dst* qe_dst_new(struct ff_weak_link_master * const wl)
+{
+ struct qent_dst *const be_dst = malloc(sizeof(*be_dst));
+ if (!be_dst)
@@ -51396,7 +56674,8 @@ Upstream-status: Pending
+ *be_dst = (struct qent_dst){
+ .base = QENT_BASE_INITIALIZER,
+ .lock = PTHREAD_MUTEX_INITIALIZER,
-+ .cond = PTHREAD_COND_INITIALIZER
++ .cond = PTHREAD_COND_INITIALIZER,
++ .mbc_wl = ff_weak_link_ref(wl)
+ };
+ return be_dst;
+}
@@ -51568,6 +56847,7 @@ Upstream-status: Pending
+ int vfd;
+ bool stream_on;
+ bool polling;
++ bool dst_fixed; // Dst Q is fixed size
+ pthread_mutex_t lock;
+ struct buf_pool * src;
+ struct buf_pool * dst;
@@ -51577,6 +56857,7 @@ Upstream-status: Pending
+
+ struct v4l2_format src_fmt;
+ struct v4l2_format dst_fmt;
++ struct v4l2_capability capability;
+};
+
+static int qe_v4l2_queue(struct qent_base *const be,
@@ -51747,13 +57028,13 @@ Upstream-status: Pending
+{
+ if (!be->dh[0] || len > dmabuf_size(be->dh[0])) {
+ size_t newsize = round_up_size(len);
-+ request_log("%s: Overrun %d > %d; trying %d\n", __func__, len, dmabuf_size(be->dh[0]), newsize);
++ request_log("%s: Overrun %zd > %zd; trying %zd\n", __func__, len, dmabuf_size(be->dh[0]), newsize);
+ if (!dbsc) {
+ request_log("%s: No dmbabuf_ctrl for realloc\n", __func__);
+ return -ENOMEM;
+ }
+ if ((be->dh[0] = dmabuf_realloc(dbsc, be->dh[0], newsize)) == NULL) {
-+ request_log("%s: Realloc %d failed\n", __func__, newsize);
++ request_log("%s: Realloc %zd failed\n", __func__, newsize);
+ return -ENOMEM;
+ }
+ }
@@ -52069,10 +57350,13 @@ Upstream-status: Pending
+ return MEDIABUFS_STATUS_SUCCESS;
+}
+
-+static int create_dst_buf(struct mediabufs_ctl *const mbc)
++// Returns noof buffers created, -ve for error
++static int create_dst_bufs(struct mediabufs_ctl *const mbc, unsigned int n, struct qent_dst * const qes[])
+{
++ unsigned int i;
++
+ struct v4l2_create_buffers cbuf = {
-+ .count = 1,
++ .count = n,
+ .memory = V4L2_MEMORY_DMABUF,
+ .format = mbc->dst_fmt,
+ };
@@ -52084,7 +57368,14 @@ Upstream-status: Pending
+ return -err;
+ }
+ }
-+ return cbuf.index;
++
++ if (cbuf.count != n)
++ request_warn(mbc->dc, "%s: Created %d of %d V4L2 buffers requested\n", __func__, cbuf.count, n);
++
++ for (i = 0; i != cbuf.count; ++i)
++ qes[i]->base.index = cbuf.index + i;
++
++ return cbuf.count;
+}
+
+struct qent_dst* mediabufs_dst_qent_alloc(struct mediabufs_ctl *const mbc, struct dmabufs_ctl *const dbsc)
@@ -52092,27 +57383,29 @@ Upstream-status: Pending
+ struct qent_dst * be_dst;
+
+ if (mbc == NULL) {
-+ be_dst = qe_dst_new();
++ be_dst = qe_dst_new(NULL);
+ if (be_dst)
+ be_dst->base.status = QENT_IMPORT;
+ return be_dst;
+ }
+
-+ be_dst = base_to_dst(queue_tryget_free(mbc->dst));
-+ if (!be_dst) {
-+ int index;
-+
-+ be_dst = qe_dst_new();
++ if (mbc->dst_fixed) {
++ be_dst = base_to_dst(queue_get_free(mbc->dst));
+ if (!be_dst)
+ return NULL;
++ }
++ else {
++ be_dst = base_to_dst(queue_tryget_free(mbc->dst));
++ if (!be_dst) {
++ be_dst = qe_dst_new(mbc->this_wlm);
++ if (!be_dst)
++ return NULL;
+
-+ if ((be_dst->mbc_wl = ff_weak_link_ref(mbc->this_wlm)) == NULL ||
-+ (index = create_dst_buf(mbc)) < 0) {
-+ qe_dst_free(be_dst);
-+ return NULL;
++ if (create_dst_bufs(mbc, 1, &be_dst) != 1) {
++ qe_dst_free(be_dst);
++ return NULL;
++ }
+ }
-+
-+ be_dst->base.index = (uint32_t)index;
+ }
+
+ if (qe_alloc_from_fmt(&be_dst->base, dbsc, &mbc->dst_fmt)) {
@@ -52166,29 +57459,42 @@ Upstream-status: Pending
+ return status;
+}
+
-+MediaBufsStatus mediabufs_dst_slots_create(struct mediabufs_ctl *const mbc, unsigned int n)
++// ** This is a mess if we get partial alloc but without any way to remove
++// individual V4L2 Q members we are somewhat stuffed
++MediaBufsStatus mediabufs_dst_slots_create(struct mediabufs_ctl *const mbc, const unsigned int n, const bool fixed)
+{
-+ // **** request buffers
+ unsigned int i;
++ int a = 0;
++ unsigned int qc;
++ struct qent_dst * qes[32];
++
++ if (n > 32)
++ return MEDIABUFS_ERROR_ALLOCATION_FAILED;
+
-+ for (i = 0; i != n; ++i)
++ // Create qents first as it is hard to get rid of the V4L2 buffers on error
++ for (qc = 0; qc != n; ++qc)
+ {
-+ int index;
-+ struct qent_dst * const be_dst = qe_dst_new();
-+ if (!be_dst)
-+ return MEDIABUFS_ERROR_OPERATION_FAILED;
++ if ((qes[qc] = qe_dst_new(mbc->this_wlm)) == NULL)
++ goto fail;
++ }
+
-+ index = create_dst_buf(mbc);
-+ if (index < 0) {
-+ qe_dst_free(be_dst);
-+ return MEDIABUFS_ERROR_OPERATION_FAILED;
-+ }
++ if ((a = create_dst_bufs(mbc, n, qes)) < 0)
++ goto fail;
+
-+ // Add index to free chain
-+ be_dst->base.index = (uint32_t)index;
-+ queue_put_free(mbc->dst, &be_dst->base);
-+ }
++ for (i = 0; i != a; ++i)
++ queue_put_free(mbc->dst, &qes[i]->base);
++
++ if (a != n)
++ goto fail;
++
++ mbc->dst_fixed = fixed;
+ return MEDIABUFS_STATUS_SUCCESS;
++
++fail:
++ for (i = (a < 0 ? 0 : a); i != qc; ++i)
++ qe_dst_free(qes[i]);
++
++ return MEDIABUFS_ERROR_ALLOCATION_FAILED;
+}
+
+struct qent_src *mediabufs_src_qent_get(struct mediabufs_ctl *const mbc)
@@ -52446,20 +57752,24 @@ Upstream-status: Pending
+ mediabufs_ctl_delete(mbc);
+}
+
++unsigned int mediabufs_ctl_driver_version(struct mediabufs_ctl *const mbc)
++{
++ return mbc->capability.version;
++}
++
+static int set_capabilities(struct mediabufs_ctl *const mbc)
+{
-+ struct v4l2_capability capability = { 0 };
+ uint32_t caps;
+
-+ if (ioctl(mbc->vfd, VIDIOC_QUERYCAP, &capability)) {
++ if (ioctl(mbc->vfd, VIDIOC_QUERYCAP, &mbc->capability)) {
+ int err = errno;
+ request_err(mbc->dc, "Failed to get capabilities: %s\n", strerror(err));
+ return -err;
+ }
+
-+ caps = (capability.capabilities & V4L2_CAP_DEVICE_CAPS) != 0 ?
-+ capability.device_caps :
-+ capability.capabilities;
++ caps = (mbc->capability.capabilities & V4L2_CAP_DEVICE_CAPS) != 0 ?
++ mbc->capability.device_caps :
++ mbc->capability.capabilities;
+
+ if ((caps & V4L2_CAP_VIDEO_M2M_MPLANE) != 0) {
+ mbc->src_fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
@@ -52544,7 +57854,7 @@ Upstream-status: Pending
+
--- /dev/null
+++ b/libavcodec/v4l2_req_media.h
-@@ -0,0 +1,148 @@
+@@ -0,0 +1,154 @@
+/*
+e.h
+*
@@ -52646,11 +57956,14 @@ Upstream-status: Pending
+ struct qent_dst *const dst_be,
+ const bool is_final);
+// Get / alloc a dst buffer & associate with a slot
-+// * BEWARE * Currently has no alloc limit
++// If the dst pool is empty then behaviour depends on the fixed flag passed to
++// dst_slots_create. Default is !fixed = unlimited alloc
+struct qent_dst* mediabufs_dst_qent_alloc(struct mediabufs_ctl *const mbc,
+ struct dmabufs_ctl *const dbsc);
+// Create dst slots without alloc
-+MediaBufsStatus mediabufs_dst_slots_create(struct mediabufs_ctl *const mbc, unsigned int n);
++// If fixed true then qent_alloc will only get slots from this pool and will
++// block until a qent has been unrefed
++MediaBufsStatus mediabufs_dst_slots_create(struct mediabufs_ctl *const mbc, const unsigned int n, const bool fixed);
+
+MediaBufsStatus mediabufs_stream_on(struct mediabufs_ctl *const mbc);
+MediaBufsStatus mediabufs_stream_off(struct mediabufs_ctl *const mbc);
@@ -52686,6 +57999,9 @@ Upstream-status: Pending
+ struct dmabufs_ctl * const dbsc,
+ unsigned int n);
+
++#define MEDIABUFS_DRIVER_VERSION(a, b, c) (((a) << 16) | ((b) << 8) | (c))
++unsigned int mediabufs_ctl_driver_version(struct mediabufs_ctl *const mbc);
++
+struct mediabufs_ctl * mediabufs_ctl_new(void * const dc,
+ const char *vpath, struct pollqueue *const pq);
+void mediabufs_ctl_unref(struct mediabufs_ctl **const pmbc);
@@ -52695,7 +58011,7 @@ Upstream-status: Pending
+#endif
--- /dev/null
+++ b/libavcodec/v4l2_req_pollqueue.c
-@@ -0,0 +1,363 @@
+@@ -0,0 +1,361 @@
+#include <errno.h>
+#include <limits.h>
+#include <poll.h>
@@ -52885,19 +58201,19 @@ Upstream-status: Pending
+ unsigned int i;
+ unsigned int n = 0;
+ struct polltask *pt;
++ struct polltask *pt_next;
+ uint64_t now = pollqueue_now(0);
+ int timeout = -1;
+ int rv;
+
-+ for (pt = pq->head; pt; pt = pt->next) {
++ for (pt = pq->head; pt; pt = pt_next) {
+ int64_t t;
+
++ pt_next = pt->next;
++
+ if (pt->state == POLLTASK_Q_KILL) {
-+ struct polltask * const prev = pt->prev;
+ pollqueue_rem_task(pq, pt);
+ sem_post(&pt->kill_sem);
-+ if ((pt = prev) == NULL)
-+ break;
+ continue;
+ }
+
@@ -52936,8 +58252,8 @@ Upstream-status: Pending
+ * infinite looping
+ */
+ pq->no_prod = true;
-+ for (i = 0, pt = pq->head; i < n; ++i) {
-+ struct polltask *const pt_next = pt->next;
++ for (i = 0, pt = pq->head; i < n; ++i, pt = pt_next) {
++ pt_next = pt->next;
+
+ /* Pending? */
+ if (a[i].revents ||
@@ -52961,8 +58277,6 @@ Upstream-status: Pending
+ if (pt->state == POLLTASK_RUN_KILL)
+ sem_post(&pt->kill_sem);
+ }
-+
-+ pt = pt_next;
+ }
+ pq->no_prod = false;
+
@@ -53082,12 +58396,13 @@ Upstream-status: Pending
+#endif /* POLLQUEUE_H_ */
--- /dev/null
+++ b/libavcodec/v4l2_req_utils.h
-@@ -0,0 +1,21 @@
+@@ -0,0 +1,22 @@
+#include "libavutil/log.h"
+
+#define request_log(...) av_log(NULL, AV_LOG_INFO, __VA_ARGS__)
+
+#define request_err(_ctx, ...) av_log(_ctx, AV_LOG_ERROR, __VA_ARGS__)
++#define request_warn(_ctx, ...) av_log(_ctx, AV_LOG_WARNING, __VA_ARGS__)
+#define request_info(_ctx, ...) av_log(_ctx, AV_LOG_INFO, __VA_ARGS__)
+#define request_debug(_ctx, ...) av_log(_ctx, AV_LOG_DEBUG, __VA_ARGS__)
+
@@ -53106,7 +58421,7 @@ Upstream-status: Pending
+
--- /dev/null
+++ b/libavcodec/v4l2_request_hevc.c
-@@ -0,0 +1,280 @@
+@@ -0,0 +1,315 @@
+/*
+ * This file is part of FFmpeg.
+ *
@@ -53194,6 +58509,13 @@ Upstream-status: Pending
+ return ctx->fns->frame_params(avctx, hw_frames_ctx);
+}
+
++static int v4l2_req_hevc_alloc_frame(AVCodecContext * avctx, AVFrame *frame)
++{
++ V4L2RequestContextHEVC * const ctx = avctx->internal->hwaccel_priv_data;
++ return ctx->fns->alloc_frame(avctx, frame);
++}
++
++
+static int v4l2_request_hevc_uninit(AVCodecContext *avctx)
+{
+ V4L2RequestContextHEVC * const ctx = avctx->internal->hwaccel_priv_data;
@@ -53248,6 +58570,17 @@ Upstream-status: Pending
+
+ av_log(avctx, AV_LOG_DEBUG, "<<< %s\n", __func__);
+
++ // Give up immediately if this is something that we have no code to deal with
++ if (h->ps.sps->chroma_format_idc != 1) {
++ av_log(avctx, AV_LOG_WARNING, "chroma_format_idc(%d) != 1: Not implemented\n", h->ps.sps->chroma_format_idc);
++ return AVERROR_PATCHWELCOME;
++ }
++ if (!(h->ps.sps->bit_depth == 10 || h->ps.sps->bit_depth == 8) ||
++ h->ps.sps->bit_depth != h->ps.sps->bit_depth_chroma) {
++ av_log(avctx, AV_LOG_WARNING, "Bit depth Y:%d C:%d: Not implemented\n", h->ps.sps->bit_depth, h->ps.sps->bit_depth_chroma);
++ return AVERROR_PATCHWELCOME;
++ }
++
+ if ((ret = devscan_build(avctx, &ctx->devscan)) != 0) {
+ av_log(avctx, AV_LOG_WARNING, "Failed to find any V4L2 devices\n");
+ return (AVERROR(-ret));
@@ -53300,7 +58633,15 @@ Upstream-status: Pending
+ goto fail4;
+ }
+
-+ if (V2(ff_v4l2_req_hevc, 2).probe(avctx, ctx) == 0) {
++ if (V2(ff_v4l2_req_hevc, 4).probe(avctx, ctx) == 0) {
++ av_log(avctx, AV_LOG_DEBUG, "HEVC API version 4 probed successfully\n");
++ ctx->fns = &V2(ff_v4l2_req_hevc, 4);
++ }
++ else if (V2(ff_v4l2_req_hevc, 3).probe(avctx, ctx) == 0) {
++ av_log(avctx, AV_LOG_DEBUG, "HEVC API version 3 probed successfully\n");
++ ctx->fns = &V2(ff_v4l2_req_hevc, 3);
++ }
++ else if (V2(ff_v4l2_req_hevc, 2).probe(avctx, ctx) == 0) {
+ av_log(avctx, AV_LOG_DEBUG, "HEVC API version 2 probed successfully\n");
+ ctx->fns = &V2(ff_v4l2_req_hevc, 2);
+ }
@@ -53325,9 +58666,18 @@ Upstream-status: Pending
+ goto fail4;
+ }
+
-+ if (mediabufs_dst_slots_create(ctx->mbufs, 1)) {
-+ av_log(avctx, AV_LOG_ERROR, "Failed to create destination slots\n");
-+ goto fail4;
++ {
++ unsigned int dst_slots = sps->temporal_layer[sps->max_sub_layers - 1].max_dec_pic_buffering +
++ avctx->thread_count + (avctx->extra_hw_frames > 0 ? avctx->extra_hw_frames : 6);
++ av_log(avctx, AV_LOG_DEBUG, "Slots=%d: Reordering=%d, threads=%d, hw+=%d\n", dst_slots,
++ sps->temporal_layer[sps->max_sub_layers - 1].max_dec_pic_buffering,
++ avctx->thread_count, avctx->extra_hw_frames);
++
++ // extra_hw_frames is -1 if unset
++ if (mediabufs_dst_slots_create(ctx->mbufs, dst_slots, (avctx->extra_hw_frames > 0))) {
++ av_log(avctx, AV_LOG_ERROR, "Failed to create destination slots\n");
++ goto fail4;
++ }
+ }
+
+ if (mediabufs_stream_on(ctx->mbufs)) {
@@ -53376,7 +58726,7 @@ Upstream-status: Pending
+ .type = AVMEDIA_TYPE_VIDEO,
+ .id = AV_CODEC_ID_HEVC,
+ .pix_fmt = AV_PIX_FMT_DRM_PRIME,
-+// .alloc_frame = v4l2_request_hevc_alloc_frame,
++ .alloc_frame = v4l2_req_hevc_alloc_frame,
+ .start_frame = v4l2_req_hevc_start_frame,
+ .decode_slice = v4l2_req_hevc_decode_slice,
+ .end_frame = v4l2_req_hevc_end_frame,
@@ -53389,7 +58739,7 @@ Upstream-status: Pending
+};
--- /dev/null
+++ b/libavcodec/v4l2_request_hevc.h
-@@ -0,0 +1,100 @@
+@@ -0,0 +1,101 @@
+#ifndef AVCODEC_V4L2_REQUEST_HEVC_H
+#define AVCODEC_V4L2_REQUEST_HEVC_H
+
@@ -53437,8 +58787,6 @@ Upstream-status: Pending
+#define V4L2_CTRL_FLAG_DYNAMIC_ARRAY 0x0800
+#endif
+
-+#define MAX_SLICES 128
-+
+#define VCAT(name, version) name##_v##version
+#define V2(n,v) VCAT(n, v)
+#define V(n) V2(n, HEVC_CTRLS_VERSION)
@@ -53455,10 +58803,10 @@ Upstream-status: Pending
+
+ unsigned int timestamp; // ?? maybe uint64_t
+
-+ int multi_slice;
+ int decode_mode;
+ int start_code;
-+ int max_slices;
++ unsigned int max_slices; // 0 => not wanted (frame mode)
++ unsigned int max_offsets; // 0 => not wanted
+
+ req_decode_q decode_q;
+
@@ -53483,16 +58831,121 @@ Upstream-status: Pending
+ int (*end_frame)(AVCodecContext *avctx);
+ void (*abort_frame)(AVCodecContext *avctx);
+ int (*frame_params)(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx);
++ int (*alloc_frame)(AVCodecContext * avctx, AVFrame *frame);
+} v4l2_req_decode_fns;
+
+
+extern const v4l2_req_decode_fns V2(ff_v4l2_req_hevc, 1);
+extern const v4l2_req_decode_fns V2(ff_v4l2_req_hevc, 2);
++extern const v4l2_req_decode_fns V2(ff_v4l2_req_hevc, 3);
++extern const v4l2_req_decode_fns V2(ff_v4l2_req_hevc, 4);
+
+#endif
+--- a/libavcodec/vc1dec.c
++++ b/libavcodec/vc1dec.c
+@@ -486,7 +486,7 @@ static av_cold int vc1_decode_init(AVCod
+ size = next - start - 4;
+ if (size <= 0)
+ continue;
+- buf2_size = vc1_unescape_buffer(start + 4, size, buf2);
++ buf2_size = v->vc1dsp.vc1_unescape_buffer(start + 4, size, buf2);
+ init_get_bits(&gb, buf2, buf2_size * 8);
+ switch (AV_RB32(start)) {
+ case VC1_CODE_SEQHDR:
+@@ -689,7 +689,7 @@ static int vc1_decode_frame(AVCodecConte
+ case VC1_CODE_FRAME:
+ if (avctx->hwaccel)
+ buf_start = start;
+- buf_size2 = vc1_unescape_buffer(start + 4, size, buf2);
++ buf_size2 = v->vc1dsp.vc1_unescape_buffer(start + 4, size, buf2);
+ break;
+ case VC1_CODE_FIELD: {
+ int buf_size3;
+@@ -706,8 +706,8 @@ static int vc1_decode_frame(AVCodecConte
+ ret = AVERROR(ENOMEM);
+ goto err;
+ }
+- buf_size3 = vc1_unescape_buffer(start + 4, size,
+- slices[n_slices].buf);
++ buf_size3 = v->vc1dsp.vc1_unescape_buffer(start + 4, size,
++ slices[n_slices].buf);
+ init_get_bits(&slices[n_slices].gb, slices[n_slices].buf,
+ buf_size3 << 3);
+ slices[n_slices].mby_start = avctx->coded_height + 31 >> 5;
+@@ -718,7 +718,7 @@ static int vc1_decode_frame(AVCodecConte
+ break;
+ }
+ case VC1_CODE_ENTRYPOINT: /* it should be before frame data */
+- buf_size2 = vc1_unescape_buffer(start + 4, size, buf2);
++ buf_size2 = v->vc1dsp.vc1_unescape_buffer(start + 4, size, buf2);
+ init_get_bits(&s->gb, buf2, buf_size2 * 8);
+ ff_vc1_decode_entry_point(avctx, v, &s->gb);
+ break;
+@@ -735,8 +735,8 @@ static int vc1_decode_frame(AVCodecConte
+ ret = AVERROR(ENOMEM);
+ goto err;
+ }
+- buf_size3 = vc1_unescape_buffer(start + 4, size,
+- slices[n_slices].buf);
++ buf_size3 = v->vc1dsp.vc1_unescape_buffer(start + 4, size,
++ slices[n_slices].buf);
+ init_get_bits(&slices[n_slices].gb, slices[n_slices].buf,
+ buf_size3 << 3);
+ slices[n_slices].mby_start = get_bits(&slices[n_slices].gb, 9);
+@@ -770,7 +770,7 @@ static int vc1_decode_frame(AVCodecConte
+ ret = AVERROR(ENOMEM);
+ goto err;
+ }
+- buf_size3 = vc1_unescape_buffer(divider + 4, buf + buf_size - divider - 4, slices[n_slices].buf);
++ buf_size3 = v->vc1dsp.vc1_unescape_buffer(divider + 4, buf + buf_size - divider - 4, slices[n_slices].buf);
+ init_get_bits(&slices[n_slices].gb, slices[n_slices].buf,
+ buf_size3 << 3);
+ slices[n_slices].mby_start = s->mb_height + 1 >> 1;
+@@ -779,9 +779,9 @@ static int vc1_decode_frame(AVCodecConte
+ n_slices1 = n_slices - 1;
+ n_slices++;
+ }
+- buf_size2 = vc1_unescape_buffer(buf, divider - buf, buf2);
++ buf_size2 = v->vc1dsp.vc1_unescape_buffer(buf, divider - buf, buf2);
+ } else {
+- buf_size2 = vc1_unescape_buffer(buf, buf_size, buf2);
++ buf_size2 = v->vc1dsp.vc1_unescape_buffer(buf, buf_size, buf2);
+ }
+ init_get_bits(&s->gb, buf2, buf_size2*8);
+ } else
+--- a/libavcodec/vc1dsp.c
++++ b/libavcodec/vc1dsp.c
+@@ -32,6 +32,7 @@
+ #include "rnd_avg.h"
+ #include "vc1dsp.h"
+ #include "startcode.h"
++#include "vc1_common.h"
+
+ /* Apply overlap transform to horizontal edge */
+ static void vc1_v_overlap_c(uint8_t *src, int stride)
+@@ -1028,6 +1029,7 @@ av_cold void ff_vc1dsp_init(VC1DSPContex
+ #endif /* CONFIG_WMV3IMAGE_DECODER || CONFIG_VC1IMAGE_DECODER */
+
+ dsp->startcode_find_candidate = ff_startcode_find_candidate_c;
++ dsp->vc1_unescape_buffer = vc1_unescape_buffer;
+
+ if (ARCH_AARCH64)
+ ff_vc1dsp_init_aarch64(dsp);
+--- a/libavcodec/vc1dsp.h
++++ b/libavcodec/vc1dsp.h
+@@ -80,6 +80,9 @@ typedef struct VC1DSPContext {
+ * one or more further zero bytes and a one byte.
+ */
+ int (*startcode_find_candidate)(const uint8_t *buf, int size);
++
++ /* Copy a buffer, removing startcode emulation escape bytes as we go */
++ int (*vc1_unescape_buffer)(const uint8_t *src, int size, uint8_t *dst);
+ } VC1DSPContext;
+
+ void ff_vc1dsp_init(VC1DSPContext* c);
--- /dev/null
+++ b/libavcodec/weak_link.c
-@@ -0,0 +1,100 @@
+@@ -0,0 +1,102 @@
+#include <stdlib.h>
+#include <pthread.h>
+#include <stdatomic.h>
@@ -53549,6 +59002,8 @@ Upstream-status: Pending
+
+struct ff_weak_link_client* ff_weak_link_ref(struct ff_weak_link_master * w)
+{
++ if (!w)
++ return NULL;
+ atomic_fetch_add(&w->ref_count, 1);
+ return (struct ff_weak_link_client*)w;
+}
@@ -53630,7 +59085,7 @@ Upstream-status: Pending
+OBJS-$(CONFIG_VOUT_RPI_OUTDEV) += rpi_vout.o
OBJS-$(CONFIG_XCBGRAB_INDEV) += xcbgrab.o
OBJS-$(CONFIG_XV_OUTDEV) += xv.o
-
+
--- a/libavdevice/alldevices.c
+++ b/libavdevice/alldevices.c
@@ -52,6 +52,9 @@ extern AVOutputFormat ff_sndio_muxer;
@@ -53642,7 +59097,7 @@ Upstream-status: Pending
+extern AVOutputFormat ff_vout_rpi_muxer;
extern AVInputFormat ff_xcbgrab_demuxer;
extern AVOutputFormat ff_xv_muxer;
-
+
--- /dev/null
+++ b/libavdevice/drm_vout.c
@@ -0,0 +1,643 @@
@@ -53856,7 +59311,7 @@ Upstream-status: Pending
+
+ while (drmWaitVBlank(de->drm_fd, &vbl)) {
+ if (errno != EINTR) {
-+ av_log(s, AV_LOG_WARNING, "drmWaitVBlank failed: %s\n", ERRSTR);
++// av_log(s, AV_LOG_WARNING, "drmWaitVBlank failed: %s\n", ERRSTR);
+ break;
+ }
+ }
@@ -54291,7 +59746,7 @@ Upstream-status: Pending
+
--- /dev/null
+++ b/libavdevice/egl_vout.c
-@@ -0,0 +1,825 @@
+@@ -0,0 +1,816 @@
+/*
+ * Copyright (c) 2020 John Cox for Raspberry Pi Trading
+ *
@@ -54334,16 +59789,8 @@ Upstream-status: Pending
+#include <stdatomic.h>
+#include <unistd.h>
+
-+#include "drm_fourcc.h"
-+#include <drm.h>
-+#include <drm_mode.h>
-+#include <xf86drm.h>
-+#include <xf86drmMode.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
-+#include <X11/Xlib-xcb.h>
-+#include <xcb/xcb.h>
-+#include <xcb/dri3.h>
+
+#include "libavutil/rpi_sand_fns.h"
+
@@ -54555,8 +60002,7 @@ Upstream-status: Pending
+ XMapWindow(dpy, win);
+
+ {
-+ EGLSurface surf = eglCreateWindowSurface(egl_dpy, config,
-+ (void *)(uintptr_t)win, NULL);
++ EGLSurface surf = eglCreateWindowSurface(egl_dpy, config, (EGLNativeWindowType)win, NULL);
+ if (!surf) {
+ av_log(s, AV_LOG_ERROR, "Error: eglCreateWindowSurface failed\n");
+ return -1;
@@ -55656,7 +61102,15 @@ Upstream-status: Pending
+};
--- a/libavfilter/Makefile
+++ b/libavfilter/Makefile
-@@ -434,6 +434,7 @@ OBJS-$(CONFIG_TRANSPOSE_OPENCL_FILTER)
+@@ -218,6 +218,7 @@ OBJS-$(CONFIG_DEFLATE_FILTER)
+ OBJS-$(CONFIG_DEFLICKER_FILTER) += vf_deflicker.o
+ OBJS-$(CONFIG_DEINTERLACE_QSV_FILTER) += vf_deinterlace_qsv.o
+ OBJS-$(CONFIG_DEINTERLACE_VAAPI_FILTER) += vf_deinterlace_vaapi.o vaapi_vpp.o
++OBJS-$(CONFIG_DEINTERLACE_V4L2M2M_FILTER) += vf_deinterlace_v4l2m2m.o
+ OBJS-$(CONFIG_DEJUDDER_FILTER) += vf_dejudder.o
+ OBJS-$(CONFIG_DELOGO_FILTER) += vf_delogo.o
+ OBJS-$(CONFIG_DENOISE_VAAPI_FILTER) += vf_misc_vaapi.o vaapi_vpp.o
+@@ -434,6 +435,7 @@ OBJS-$(CONFIG_TRANSPOSE_OPENCL_FILTER)
OBJS-$(CONFIG_TRANSPOSE_VAAPI_FILTER) += vf_transpose_vaapi.o vaapi_vpp.o
OBJS-$(CONFIG_TRIM_FILTER) += trim.o
OBJS-$(CONFIG_UNPREMULTIPLY_FILTER) += vf_premultiply.o framesync.o
@@ -55666,7 +61120,15 @@ Upstream-status: Pending
opencl/unsharp.o
--- a/libavfilter/allfilters.c
+++ b/libavfilter/allfilters.c
-@@ -414,6 +414,7 @@ extern AVFilter ff_vf_transpose_opencl;
+@@ -204,6 +204,7 @@ extern AVFilter ff_vf_dedot;
+ extern AVFilter ff_vf_deflate;
+ extern AVFilter ff_vf_deflicker;
+ extern AVFilter ff_vf_deinterlace_qsv;
++extern AVFilter ff_vf_deinterlace_v4l2m2m;
+ extern AVFilter ff_vf_deinterlace_vaapi;
+ extern AVFilter ff_vf_dejudder;
+ extern AVFilter ff_vf_delogo;
+@@ -414,6 +415,7 @@ extern AVFilter ff_vf_transpose_opencl;
extern AVFilter ff_vf_transpose_vaapi;
extern AVFilter ff_vf_trim;
extern AVFilter ff_vf_unpremultiply;
@@ -55683,13 +61145,13 @@ Upstream-status: Pending
+#if CONFIG_UNSAND_FILTER
+#include "libavutil/rpi_sand_fns.h"
+#endif
-
+
#define FF_INTERNAL_FIELDS 1
#include "framequeue.h"
@@ -427,6 +430,19 @@ static int can_merge_formats(AVFilterFor
}
}
-
+
+#if CONFIG_UNSAND_FILTER
+static int has_sand_format(const AVFilterFormats * const ff)
+{
@@ -55711,13 +61173,13 @@ Upstream-status: Pending
AVFilterLink *link = filter->inputs[j];
int convert_needed = 0;
+ unsigned int extra_convert_tried = 0;
-
+
if (!link)
continue;
@@ -514,11 +531,14 @@ static int query_formats(AVFilterGraph *
)
#undef MERGE_DISPATCH
-
+
- if (convert_needed) {
+ while (convert_needed) {
AVFilterContext *convert;
@@ -55727,7 +61189,7 @@ Upstream-status: Pending
+ int can_retry = 0;
+
+ convert_needed = 0;
-
+
if (graph->disable_auto_convert) {
av_log(log_ctx, AV_LOG_ERROR,
@@ -531,19 +551,45 @@ static int query_formats(AVFilterGraph *
@@ -55760,7 +61222,7 @@ Upstream-status: Pending
+ inst_name, "", NULL,
+ graph)) < 0)
+ return ret;
-
+
- if ((ret = avfilter_graph_create_filter(&convert, filter,
- inst_name, graph->scale_sws_opts, NULL,
- graph)) < 0)
@@ -55813,7 +61275,7 @@ Upstream-status: Pending
--- a/libavfilter/buffersrc.c
+++ b/libavfilter/buffersrc.c
@@ -210,7 +210,7 @@ static int av_buffersrc_add_frame_intern
-
+
switch (ctx->outputs[0]->type) {
case AVMEDIA_TYPE_VIDEO:
- CHECK_VIDEO_PARAM_CHANGE(ctx, s, frame->width, frame->height,
@@ -55822,6 +61284,1345 @@ Upstream-status: Pending
break;
case AVMEDIA_TYPE_AUDIO:
--- /dev/null
++++ b/libavfilter/vf_deinterlace_v4l2m2m.c
+@@ -0,0 +1,1336 @@
++/*
++ * This file is part of FFmpeg.
++ *
++ * FFmpeg is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * FFmpeg is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/**
++ * @file
++ * deinterlace video filter - V4L2 M2M
++ */
++
++#include <drm_fourcc.h>
++
++#include <linux/videodev2.h>
++
++#include <dirent.h>
++#include <fcntl.h>
++#include <poll.h>
++#include <stdatomic.h>
++#include <stdio.h>
++#include <string.h>
++#include <sys/ioctl.h>
++#include <sys/mman.h>
++#include <unistd.h>
++
++#include "libavutil/avassert.h"
++#include "libavutil/avstring.h"
++#include "libavutil/common.h"
++#include "libavutil/hwcontext.h"
++#include "libavutil/hwcontext_drm.h"
++#include "libavutil/internal.h"
++#include "libavutil/mathematics.h"
++#include "libavutil/opt.h"
++#include "libavutil/pixdesc.h"
++#include "libavutil/time.h"
++
++#define FF_INTERNAL_FIELDS 1
++#include "framequeue.h"
++#include "filters.h"
++#include "avfilter.h"
++#include "formats.h"
++#include "internal.h"
++#include "video.h"
++
++typedef struct V4L2Queue V4L2Queue;
++typedef struct DeintV4L2M2MContextShared DeintV4L2M2MContextShared;
++
++typedef struct V4L2PlaneInfo {
++ int bytesperline;
++ size_t length;
++} V4L2PlaneInfo;
++
++typedef struct V4L2Buffer {
++ int enqueued;
++ int reenqueue;
++ int fd;
++ struct v4l2_buffer buffer;
++ AVFrame frame;
++ struct v4l2_plane planes[VIDEO_MAX_PLANES];
++ int num_planes;
++ V4L2PlaneInfo plane_info[VIDEO_MAX_PLANES];
++ AVDRMFrameDescriptor drm_frame;
++ V4L2Queue *q;
++} V4L2Buffer;
++
++typedef struct V4L2Queue {
++ struct v4l2_format format;
++ int num_buffers;
++ V4L2Buffer *buffers;
++ DeintV4L2M2MContextShared *ctx;
++} V4L2Queue;
++
++typedef struct pts_stats_s
++{
++ void * logctx;
++ const char * name; // For debug
++ unsigned int last_count;
++ unsigned int last_interval;
++ int64_t last_pts;
++} pts_stats_t;
++
++#define PTS_TRACK_SIZE 32
++typedef struct pts_track_el_s
++{
++ uint32_t n;
++ unsigned int interval;
++ AVFrame * props;
++} pts_track_el_t;
++
++typedef struct pts_track_s
++{
++ uint32_t n;
++ uint32_t last_n;
++ int got_2;
++ void * logctx;
++ pts_stats_t stats;
++ pts_track_el_t a[PTS_TRACK_SIZE];
++} pts_track_t;
++
++typedef struct DeintV4L2M2MContextShared {
++ void * logctx; // For logging - will be NULL when done
++
++ int fd;
++ int done;
++ int width;
++ int height;
++ int orig_width;
++ int orig_height;
++ atomic_uint refcount;
++
++ AVBufferRef *hw_frames_ctx;
++
++ unsigned int field_order;
++
++ pts_track_t track;
++
++ V4L2Queue output;
++ V4L2Queue capture;
++} DeintV4L2M2MContextShared;
++
++typedef struct DeintV4L2M2MContext {
++ const AVClass *class;
++
++ DeintV4L2M2MContextShared *shared;
++} DeintV4L2M2MContext;
++
++static unsigned int pts_stats_interval(const pts_stats_t * const stats)
++{
++ return stats->last_interval;
++}
++
++// Pick 64 for max last count - that is >1sec at 60fps
++#define STATS_LAST_COUNT_MAX 64
++#define STATS_INTERVAL_MAX (1 << 30)
++static void pts_stats_add(pts_stats_t * const stats, int64_t pts)
++{
++ if (pts == AV_NOPTS_VALUE || pts == stats->last_pts) {
++ if (stats->last_count < STATS_LAST_COUNT_MAX)
++ ++stats->last_count;
++ return;
++ }
++
++ if (stats->last_pts != AV_NOPTS_VALUE) {
++ const int64_t interval = pts - stats->last_pts;
++
++ if (interval < 0 || interval >= STATS_INTERVAL_MAX ||
++ stats->last_count >= STATS_LAST_COUNT_MAX) {
++ if (stats->last_interval != 0)
++ av_log(stats->logctx, AV_LOG_DEBUG, "%s: %s: Bad interval: %" PRId64 "/%d\n",
++ __func__, stats->name, interval, stats->last_count);
++ stats->last_interval = 0;
++ }
++ else {
++ const int64_t frame_time = interval / (int64_t)stats->last_count;
++
++ if (frame_time != stats->last_interval)
++ av_log(stats->logctx, AV_LOG_DEBUG, "%s: %s: New interval: %u->%" PRId64 "/%d=%" PRId64 "\n",
++ __func__, stats->name, stats->last_interval, interval, stats->last_count, frame_time);
++ stats->last_interval = frame_time;
++ }
++ }
++
++ stats->last_pts = pts;
++ stats->last_count = 1;
++}
++
++static void pts_stats_init(pts_stats_t * const stats, void * logctx, const char * name)
++{
++ *stats = (pts_stats_t){
++ .logctx = logctx,
++ .name = name,
++ .last_count = 1,
++ .last_interval = 0,
++ .last_pts = AV_NOPTS_VALUE
++ };
++}
++
++static inline uint32_t pts_track_next_n(pts_track_t * const trk)
++{
++ if (++trk->n == 0)
++ trk->n = 1;
++ return trk->n;
++}
++
++static int pts_track_get_frame(pts_track_t * const trk, const struct timeval tv, AVFrame * const dst)
++{
++ uint32_t n = (uint32_t)(tv.tv_usec / 2 + tv.tv_sec * 500000);
++ pts_track_el_t * t;
++
++ // As a first guess assume that n==0 means last frame
++ if (n == 0) {
++ n = trk->last_n;
++ if (n == 0)
++ goto fail;
++ }
++
++ t = trk->a + (n & (PTS_TRACK_SIZE - 1));
++
++ if (t->n != n) {
++ av_log(trk->logctx, AV_LOG_ERROR, "%s: track failure: got %u, expected %u\n", __func__, n, trk->n);
++ goto fail;
++ }
++
++ // 1st frame is simple - just believe it
++ if (n != trk->last_n) {
++ trk->last_n = n;
++ trk->got_2 = 0;
++ return av_frame_copy_props(dst, t->props);
++ }
++
++ // Only believe in a single interpolated frame
++ if (trk->got_2)
++ goto fail;
++ trk->got_2 = 1;
++
++ av_frame_copy_props(dst, t->props);
++
++
++ // If we can't guess - don't
++ if (t->interval == 0) {
++ dst->best_effort_timestamp = AV_NOPTS_VALUE;
++ dst->pts = AV_NOPTS_VALUE;
++ dst->pkt_dts = AV_NOPTS_VALUE;
++ }
++ else {
++ if (dst->best_effort_timestamp != AV_NOPTS_VALUE)
++ dst->best_effort_timestamp += t->interval / 2;
++ if (dst->pts != AV_NOPTS_VALUE)
++ dst->pts += t->interval / 2;
++ if (dst->pkt_dts != AV_NOPTS_VALUE)
++ dst->pkt_dts += t->interval / 2;
++ }
++
++ return 0;
++
++fail:
++ trk->last_n = 0;
++ trk->got_2 = 0;
++ dst->pts = AV_NOPTS_VALUE;
++ dst->pkt_dts = AV_NOPTS_VALUE;
++ return 0;
++}
++
++static struct timeval pts_track_add_frame(pts_track_t * const trk, const AVFrame * const src)
++{
++ const uint32_t n = pts_track_next_n(trk);
++ pts_track_el_t * const t = trk->a + (n & (PTS_TRACK_SIZE - 1));
++
++ pts_stats_add(&trk->stats, src->pts);
++
++ t->n = n;
++ t->interval = pts_stats_interval(&trk->stats); // guess that next interval is the same as the last
++ av_frame_unref(t->props);
++ av_frame_copy_props(t->props, src);
++
++ // We now know what the previous interval was, rather than having to guess,
++ // so set it. There is a better than decent chance that this is before
++ // we use it.
++ if (t->interval != 0) {
++ pts_track_el_t * const prev_t = trk->a + ((n - 1) & (PTS_TRACK_SIZE - 1));
++ prev_t->interval = t->interval;
++ }
++
++ // In case deinterlace interpolates frames use every other usec
++ return (struct timeval){.tv_sec = n / 500000, .tv_usec = (n % 500000) * 2};
++}
++
++static void pts_track_uninit(pts_track_t * const trk)
++{
++ unsigned int i;
++ for (i = 0; i != PTS_TRACK_SIZE; ++i) {
++ trk->a[i].n = 0;
++ av_frame_free(&trk->a[i].props);
++ }
++}
++
++static int pts_track_init(pts_track_t * const trk, void *logctx)
++{
++ unsigned int i;
++ trk->n = 1;
++ pts_stats_init(&trk->stats, logctx, "track");
++ for (i = 0; i != PTS_TRACK_SIZE; ++i) {
++ trk->a[i].n = 0;
++ if ((trk->a[i].props = av_frame_alloc()) == NULL) {
++ pts_track_uninit(trk);
++ return AVERROR(ENOMEM);
++ }
++ }
++ return 0;
++}
++
++static int deint_v4l2m2m_prepare_context(DeintV4L2M2MContextShared *ctx)
++{
++ struct v4l2_capability cap;
++ int ret;
++
++ memset(&cap, 0, sizeof(cap));
++ ret = ioctl(ctx->fd, VIDIOC_QUERYCAP, &cap);
++ if (ret < 0)
++ return ret;
++
++ if (!(cap.capabilities & V4L2_CAP_STREAMING))
++ return AVERROR(EINVAL);
++
++ if (cap.capabilities & V4L2_CAP_VIDEO_M2M) {
++ ctx->capture.format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++ ctx->output.format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
++
++ return 0;
++ }
++
++ if (cap.capabilities & V4L2_CAP_VIDEO_M2M_MPLANE) {
++ ctx->capture.format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
++ ctx->output.format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
++
++ return 0;
++ }
++
++ return AVERROR(EINVAL);
++}
++
++static int deint_v4l2m2m_try_format(V4L2Queue *queue)
++{
++ struct v4l2_format *fmt = &queue->format;
++ DeintV4L2M2MContextShared *ctx = queue->ctx;
++ int ret, field;
++
++ ret = ioctl(ctx->fd, VIDIOC_G_FMT, fmt);
++ if (ret)
++ av_log(ctx->logctx, AV_LOG_ERROR, "VIDIOC_G_FMT failed: %d\n", ret);
++
++ if (V4L2_TYPE_IS_OUTPUT(fmt->type))
++ field = V4L2_FIELD_INTERLACED_TB;
++ else
++ field = V4L2_FIELD_NONE;
++
++ if (V4L2_TYPE_IS_MULTIPLANAR(fmt->type)) {
++ fmt->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_YUV420;
++ fmt->fmt.pix_mp.field = field;
++ fmt->fmt.pix_mp.width = ctx->width;
++ fmt->fmt.pix_mp.height = ctx->height;
++ } else {
++ fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;
++ fmt->fmt.pix.field = field;
++ fmt->fmt.pix.width = ctx->width;
++ fmt->fmt.pix.height = ctx->height;
++ }
++
++ av_log(ctx->logctx, AV_LOG_DEBUG, "%s: Trying format for type %d, wxh: %dx%d, fmt: %08x, size %u bpl %u pre\n", __func__,
++ fmt->type, fmt->fmt.pix_mp.width, fmt->fmt.pix_mp.height,
++ fmt->fmt.pix_mp.pixelformat,
++ fmt->fmt.pix_mp.plane_fmt[0].sizeimage, fmt->fmt.pix_mp.plane_fmt[0].bytesperline);
++
++ ret = ioctl(ctx->fd, VIDIOC_TRY_FMT, fmt);
++ if (ret)
++ return AVERROR(EINVAL);
++
++ av_log(ctx->logctx, AV_LOG_DEBUG, "%s: Trying format for type %d, wxh: %dx%d, fmt: %08x, size %u bpl %u post\n", __func__,
++ fmt->type, fmt->fmt.pix_mp.width, fmt->fmt.pix_mp.height,
++ fmt->fmt.pix_mp.pixelformat,
++ fmt->fmt.pix_mp.plane_fmt[0].sizeimage, fmt->fmt.pix_mp.plane_fmt[0].bytesperline);
++
++ if (V4L2_TYPE_IS_MULTIPLANAR(fmt->type)) {
++ if ((fmt->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_YUV420 &&
++ fmt->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_NV12) ||
++ fmt->fmt.pix_mp.field != field) {
++ av_log(ctx->logctx, AV_LOG_DEBUG, "format not supported for type %d\n", fmt->type);
++
++ return AVERROR(EINVAL);
++ }
++ } else {
++ if ((fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_YUV420 &&
++ fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_NV12) ||
++ fmt->fmt.pix.field != field) {
++ av_log(ctx->logctx, AV_LOG_DEBUG, "format not supported for type %d\n", fmt->type);
++
++ return AVERROR(EINVAL);
++ }
++ }
++
++ return 0;
++}
++
++static int deint_v4l2m2m_set_format(V4L2Queue *queue, uint32_t pixelformat, uint32_t field, int width, int height, int pitch, int ysize)
++{
++ struct v4l2_format *fmt = &queue->format;
++ DeintV4L2M2MContextShared *ctx = queue->ctx;
++ int ret;
++
++ struct v4l2_selection sel = {
++ .type = fmt->type,
++ .target = V4L2_TYPE_IS_OUTPUT(fmt->type) ? V4L2_SEL_TGT_CROP_BOUNDS : V4L2_SEL_TGT_COMPOSE_BOUNDS,
++ };
++
++ // This works for most single object 4:2:0 types
++ if (V4L2_TYPE_IS_MULTIPLANAR(fmt->type)) {
++ fmt->fmt.pix_mp.pixelformat = pixelformat;
++ fmt->fmt.pix_mp.field = field;
++ fmt->fmt.pix_mp.width = width;
++ fmt->fmt.pix_mp.height = ysize / pitch;
++ fmt->fmt.pix_mp.plane_fmt[0].bytesperline = pitch;
++ fmt->fmt.pix_mp.plane_fmt[0].sizeimage = ysize + (ysize >> 1);
++ } else {
++ fmt->fmt.pix.pixelformat = pixelformat;
++ fmt->fmt.pix.field = field;
++ fmt->fmt.pix.width = width;
++ fmt->fmt.pix.height = height;
++ fmt->fmt.pix.sizeimage = 0;
++ fmt->fmt.pix.bytesperline = 0;
++ }
++
++ ret = ioctl(ctx->fd, VIDIOC_S_FMT, fmt);
++ if (ret) {
++ ret = AVERROR(errno);
++ av_log(ctx->logctx, AV_LOG_ERROR, "VIDIOC_S_FMT failed: %d\n", ret);
++ return ret;
++ }
++
++ if (pixelformat != fmt->fmt.pix.pixelformat) {
++ av_log(ctx->logctx, AV_LOG_ERROR, "Format not supported: %s; S_FMT returned %s\n", av_fourcc2str(pixelformat), av_fourcc2str(fmt->fmt.pix.pixelformat));
++ return AVERROR(EINVAL);
++ }
++
++ ret = ioctl(ctx->fd, VIDIOC_G_SELECTION, &sel);
++ if (ret) {
++ ret = AVERROR(errno);
++ av_log(ctx->logctx, AV_LOG_WARNING, "VIDIOC_G_SELECTION failed: %d\n", ret);
++ }
++
++ sel.r.width = width;
++ sel.r.height = height;
++ sel.r.left = 0;
++ sel.r.top = 0;
++ sel.target = V4L2_TYPE_IS_OUTPUT(fmt->type) ? V4L2_SEL_TGT_CROP : V4L2_SEL_TGT_COMPOSE,
++ sel.flags = V4L2_SEL_FLAG_LE;
++
++ ret = ioctl(ctx->fd, VIDIOC_S_SELECTION, &sel);
++ if (ret) {
++ ret = AVERROR(errno);
++ av_log(ctx->logctx, AV_LOG_WARNING, "VIDIOC_S_SELECTION failed: %d\n", ret);
++ }
++
++ return 0;
++}
++
++static int deint_v4l2m2m_probe_device(DeintV4L2M2MContextShared *ctx, char *node)
++{
++ int ret;
++
++ ctx->fd = open(node, O_RDWR | O_NONBLOCK, 0);
++ if (ctx->fd < 0)
++ return AVERROR(errno);
++
++ ret = deint_v4l2m2m_prepare_context(ctx);
++ if (ret)
++ goto fail;
++
++ ret = deint_v4l2m2m_try_format(&ctx->capture);
++ if (ret)
++ goto fail;
++
++ ret = deint_v4l2m2m_try_format(&ctx->output);
++ if (ret)
++ goto fail;
++
++ return 0;
++
++fail:
++ close(ctx->fd);
++ ctx->fd = -1;
++
++ return ret;
++}
++
++static int deint_v4l2m2m_find_device(DeintV4L2M2MContextShared *ctx)
++{
++ int ret = AVERROR(EINVAL);
++ struct dirent *entry;
++ char node[PATH_MAX];
++ DIR *dirp;
++
++ dirp = opendir("/dev");
++ if (!dirp)
++ return AVERROR(errno);
++
++ for (entry = readdir(dirp); entry; entry = readdir(dirp)) {
++
++ if (strncmp(entry->d_name, "video", 5))
++ continue;
++
++ snprintf(node, sizeof(node), "/dev/%s", entry->d_name);
++ av_log(ctx->logctx, AV_LOG_DEBUG, "probing device %s\n", node);
++ ret = deint_v4l2m2m_probe_device(ctx, node);
++ if (!ret)
++ break;
++ }
++
++ closedir(dirp);
++
++ if (ret) {
++ av_log(ctx->logctx, AV_LOG_ERROR, "Could not find a valid device\n");
++ ctx->fd = -1;
++
++ return ret;
++ }
++
++ av_log(ctx->logctx, AV_LOG_INFO, "Using device %s\n", node);
++
++ return 0;
++}
++
++static int deint_v4l2m2m_enqueue_buffer(V4L2Buffer *buf)
++{
++ int ret;
++
++ ret = ioctl(buf->q->ctx->fd, VIDIOC_QBUF, &buf->buffer);
++ if (ret < 0)
++ return AVERROR(errno);
++
++ buf->enqueued = 1;
++
++ return 0;
++}
++
++static int v4l2_buffer_export_drm(V4L2Buffer* avbuf, const uint32_t pixelformat)
++{
++ struct v4l2_exportbuffer expbuf;
++ int i, ret;
++ uint64_t mod = DRM_FORMAT_MOD_LINEAR;
++ uint32_t fmt = 0;
++
++ switch (pixelformat) {
++ case V4L2_PIX_FMT_NV12:
++ fmt = DRM_FORMAT_NV12;
++ break;
++ case V4L2_PIX_FMT_YUV420:
++ fmt = DRM_FORMAT_YUV420;
++ break;
++ default:
++ return AVERROR(EINVAL);
++ }
++
++ avbuf->drm_frame.layers[0].format = fmt;
++
++ for (i = 0; i < avbuf->num_planes; i++) {
++ memset(&expbuf, 0, sizeof(expbuf));
++
++ expbuf.index = avbuf->buffer.index;
++ expbuf.type = avbuf->buffer.type;
++ expbuf.plane = i;
++
++ ret = ioctl(avbuf->q->ctx->fd, VIDIOC_EXPBUF, &expbuf);
++ if (ret < 0)
++ return AVERROR(errno);
++
++ avbuf->fd = expbuf.fd;
++
++ if (V4L2_TYPE_IS_MULTIPLANAR(avbuf->buffer.type)) {
++ /* drm frame */
++ avbuf->drm_frame.objects[i].size = avbuf->buffer.m.planes[i].length;
++ avbuf->drm_frame.objects[i].fd = expbuf.fd;
++ avbuf->drm_frame.objects[i].format_modifier = mod;
++ } else {
++ /* drm frame */
++ avbuf->drm_frame.objects[0].size = avbuf->buffer.length;
++ avbuf->drm_frame.objects[0].fd = expbuf.fd;
++ avbuf->drm_frame.objects[0].format_modifier = mod;
++ }
++ }
++
++ return 0;
++}
++
++static int deint_v4l2m2m_allocate_buffers(V4L2Queue *queue)
++{
++ struct v4l2_format *fmt = &queue->format;
++ DeintV4L2M2MContextShared *ctx = queue->ctx;
++ struct v4l2_requestbuffers req;
++ int ret, i, j, multiplanar;
++ uint32_t memory;
++
++ memory = V4L2_TYPE_IS_OUTPUT(fmt->type) ?
++ V4L2_MEMORY_DMABUF : V4L2_MEMORY_MMAP;
++
++ multiplanar = V4L2_TYPE_IS_MULTIPLANAR(fmt->type);
++
++ memset(&req, 0, sizeof(req));
++ req.count = queue->num_buffers;
++ req.memory = memory;
++ req.type = fmt->type;
++
++ ret = ioctl(ctx->fd, VIDIOC_REQBUFS, &req);
++ if (ret < 0) {
++ av_log(ctx->logctx, AV_LOG_ERROR, "VIDIOC_REQBUFS failed: %s\n", strerror(errno));
++
++ return AVERROR(errno);
++ }
++
++ queue->num_buffers = req.count;
++ queue->buffers = av_mallocz(queue->num_buffers * sizeof(V4L2Buffer));
++ if (!queue->buffers) {
++ av_log(ctx->logctx, AV_LOG_ERROR, "malloc enomem\n");
++
++ return AVERROR(ENOMEM);
++ }
++
++ for (i = 0; i < queue->num_buffers; i++) {
++ V4L2Buffer *buf = &queue->buffers[i];
++
++ buf->enqueued = 0;
++ buf->fd = -1;
++ buf->q = queue;
++
++ buf->buffer.type = fmt->type;
++ buf->buffer.memory = memory;
++ buf->buffer.index = i;
++
++ if (multiplanar) {
++ buf->buffer.length = VIDEO_MAX_PLANES;
++ buf->buffer.m.planes = buf->planes;
++ }
++
++ ret = ioctl(ctx->fd, VIDIOC_QUERYBUF, &buf->buffer);
++ if (ret < 0) {
++ ret = AVERROR(errno);
++
++ goto fail;
++ }
++
++ if (multiplanar)
++ buf->num_planes = buf->buffer.length;
++ else
++ buf->num_planes = 1;
++
++ for (j = 0; j < buf->num_planes; j++) {
++ V4L2PlaneInfo *info = &buf->plane_info[j];
++
++ if (multiplanar) {
++ info->bytesperline = fmt->fmt.pix_mp.plane_fmt[j].bytesperline;
++ info->length = buf->buffer.m.planes[j].length;
++ } else {
++ info->bytesperline = fmt->fmt.pix.bytesperline;
++ info->length = buf->buffer.length;
++ }
++ }
++
++ if (!V4L2_TYPE_IS_OUTPUT(fmt->type)) {
++ ret = deint_v4l2m2m_enqueue_buffer(buf);
++ if (ret)
++ goto fail;
++
++ ret = v4l2_buffer_export_drm(buf, multiplanar ? fmt->fmt.pix_mp.pixelformat : fmt->fmt.pix.pixelformat);
++ if (ret)
++ goto fail;
++ }
++ }
++
++ return 0;
++
++fail:
++ for (i = 0; i < queue->num_buffers; i++)
++ if (queue->buffers[i].fd >= 0)
++ close(queue->buffers[i].fd);
++ av_free(queue->buffers);
++ queue->buffers = NULL;
++
++ return ret;
++}
++
++static int deint_v4l2m2m_streamon(V4L2Queue *queue)
++{
++ DeintV4L2M2MContextShared * const ctx = queue->ctx;
++ int type = queue->format.type;
++ int ret;
++
++ ret = ioctl(ctx->fd, VIDIOC_STREAMON, &type);
++ av_log(ctx->logctx, AV_LOG_DEBUG, "%s: type:%d ret:%d errno:%d\n", __func__, type, ret, AVERROR(errno));
++ if (ret < 0)
++ return AVERROR(errno);
++
++ return 0;
++}
++
++static int deint_v4l2m2m_streamoff(V4L2Queue *queue)
++{
++ DeintV4L2M2MContextShared * const ctx = queue->ctx;
++ int type = queue->format.type;
++ int ret;
++
++ ret = ioctl(ctx->fd, VIDIOC_STREAMOFF, &type);
++ av_log(ctx->logctx, AV_LOG_DEBUG, "%s: type:%d ret:%d errno:%d\n", __func__, type, ret, AVERROR(errno));
++ if (ret < 0)
++ return AVERROR(errno);
++
++ return 0;
++}
++
++// timeout in ms
++static V4L2Buffer* deint_v4l2m2m_dequeue_buffer(V4L2Queue *queue, int timeout)
++{
++ struct v4l2_plane planes[VIDEO_MAX_PLANES];
++ DeintV4L2M2MContextShared *ctx = queue->ctx;
++ struct v4l2_buffer buf = { 0 };
++ V4L2Buffer* avbuf = NULL;
++ struct pollfd pfd;
++ short events;
++ int ret;
++
++ if (V4L2_TYPE_IS_OUTPUT(queue->format.type))
++ events = POLLOUT | POLLWRNORM;
++ else
++ events = POLLIN | POLLRDNORM;
++
++ pfd.events = events;
++ pfd.fd = ctx->fd;
++
++ for (;;) {
++ ret = poll(&pfd, 1, timeout);
++ if (ret > 0)
++ break;
++ if (errno == EINTR)
++ continue;
++ return NULL;
++ }
++
++ if (pfd.revents & POLLERR)
++ return NULL;
++
++ if (pfd.revents & events) {
++ memset(&buf, 0, sizeof(buf));
++ buf.memory = V4L2_MEMORY_MMAP;
++ buf.type = queue->format.type;
++ if (V4L2_TYPE_IS_MULTIPLANAR(queue->format.type)) {
++ memset(planes, 0, sizeof(planes));
++ buf.length = VIDEO_MAX_PLANES;
++ buf.m.planes = planes;
++ }
++
++ ret = ioctl(ctx->fd, VIDIOC_DQBUF, &buf);
++ if (ret) {
++ if (errno != EAGAIN)
++ av_log(ctx->logctx, AV_LOG_DEBUG, "VIDIOC_DQBUF, errno (%s)\n",
++ av_err2str(AVERROR(errno)));
++ return NULL;
++ }
++
++ avbuf = &queue->buffers[buf.index];
++ avbuf->enqueued = 0;
++ avbuf->buffer = buf;
++ if (V4L2_TYPE_IS_MULTIPLANAR(queue->format.type)) {
++ memcpy(avbuf->planes, planes, sizeof(planes));
++ avbuf->buffer.m.planes = avbuf->planes;
++ }
++ return avbuf;
++ }
++
++ return NULL;
++}
++
++static V4L2Buffer *deint_v4l2m2m_find_free_buf(V4L2Queue *queue)
++{
++ int i;
++ V4L2Buffer *buf = NULL;
++
++ for (i = 0; i < queue->num_buffers; i++)
++ if (!queue->buffers[i].enqueued) {
++ buf = &queue->buffers[i];
++ break;
++ }
++ return buf;
++}
++
++static void deint_v4l2m2m_unref_queued(V4L2Queue *queue)
++{
++ int i;
++ V4L2Buffer *buf = NULL;
++
++ if (!queue || !queue->buffers)
++ return;
++ for (i = 0; i < queue->num_buffers; i++) {
++ buf = &queue->buffers[i];
++ if (queue->buffers[i].enqueued)
++ av_frame_unref(&buf->frame);
++ }
++}
++
++static void recycle_q(V4L2Queue * const queue)
++{
++ V4L2Buffer* avbuf;
++ while (avbuf = deint_v4l2m2m_dequeue_buffer(queue, 0), avbuf) {
++ av_frame_unref(&avbuf->frame);
++ }
++}
++
++static int count_enqueued(V4L2Queue *queue)
++{
++ int i;
++ int n = 0;
++
++ if (queue->buffers == NULL)
++ return 0;
++
++ for (i = 0; i < queue->num_buffers; i++)
++ if (queue->buffers[i].enqueued)
++ ++n;
++ return n;
++}
++
++static int deint_v4l2m2m_enqueue_frame(V4L2Queue * const queue, AVFrame * const frame)
++{
++ DeintV4L2M2MContextShared *const ctx = queue->ctx;
++ AVDRMFrameDescriptor *drm_desc = (AVDRMFrameDescriptor *)frame->data[0];
++ V4L2Buffer *buf;
++ int i;
++
++ if (V4L2_TYPE_IS_OUTPUT(queue->format.type))
++ recycle_q(queue);
++
++ buf = deint_v4l2m2m_find_free_buf(queue);
++ if (!buf) {
++ av_log(ctx->logctx, AV_LOG_ERROR, "%s: error %d finding free buf\n", __func__, 0);
++ return AVERROR(EAGAIN);
++ }
++ if (V4L2_TYPE_IS_MULTIPLANAR(buf->buffer.type))
++ for (i = 0; i < drm_desc->nb_objects; i++)
++ buf->buffer.m.planes[i].m.fd = drm_desc->objects[i].fd;
++ else
++ buf->buffer.m.fd = drm_desc->objects[0].fd;
++
++ buf->buffer.field = !frame->interlaced_frame ? V4L2_FIELD_NONE :
++ frame->top_field_first ? V4L2_FIELD_INTERLACED_TB :
++ V4L2_FIELD_INTERLACED_BT;
++
++ if (ctx->field_order != buf->buffer.field) {
++ av_log(ctx->logctx, AV_LOG_DEBUG, "%s: Field changed: %d->%d\n", __func__, ctx->field_order, buf->buffer.field);
++ ctx->field_order = buf->buffer.field;
++ }
++
++ buf->buffer.timestamp = pts_track_add_frame(&ctx->track, frame);
++
++ buf->drm_frame.objects[0].fd = drm_desc->objects[0].fd;
++
++ av_frame_move_ref(&buf->frame, frame);
++
++ return deint_v4l2m2m_enqueue_buffer(buf);
++}
++
++static void deint_v4l2m2m_destroy_context(DeintV4L2M2MContextShared *ctx)
++{
++ if (atomic_fetch_sub(&ctx->refcount, 1) == 1) {
++ V4L2Queue *capture = &ctx->capture;
++ V4L2Queue *output = &ctx->output;
++ int i;
++
++ av_log(NULL, AV_LOG_DEBUG, "%s - destroying context\n", __func__);
++
++ if (ctx->fd >= 0) {
++ deint_v4l2m2m_streamoff(capture);
++ deint_v4l2m2m_streamoff(output);
++ }
++
++ if (capture->buffers)
++ for (i = 0; i < capture->num_buffers; i++) {
++ capture->buffers[i].q = NULL;
++ if (capture->buffers[i].fd >= 0)
++ close(capture->buffers[i].fd);
++ }
++
++ deint_v4l2m2m_unref_queued(output);
++
++ av_buffer_unref(&ctx->hw_frames_ctx);
++
++ if (capture->buffers)
++ av_free(capture->buffers);
++
++ if (output->buffers)
++ av_free(output->buffers);
++
++ if (ctx->fd >= 0) {
++ close(ctx->fd);
++ ctx->fd = -1;
++ }
++
++ av_free(ctx);
++ }
++}
++
++static void v4l2_free_buffer(void *opaque, uint8_t *unused)
++{
++ V4L2Buffer *buf = opaque;
++ DeintV4L2M2MContextShared *ctx = buf->q->ctx;
++
++ if (!ctx->done)
++ deint_v4l2m2m_enqueue_buffer(buf);
++
++ deint_v4l2m2m_destroy_context(ctx);
++}
++
++static uint8_t * v4l2_get_drm_frame(V4L2Buffer *avbuf, int height)
++{
++ AVDRMFrameDescriptor *drm_desc = &avbuf->drm_frame;
++ AVDRMLayerDescriptor *layer;
++
++ /* fill the DRM frame descriptor */
++ drm_desc->nb_objects = avbuf->num_planes;
++ drm_desc->nb_layers = 1;
++
++ layer = &drm_desc->layers[0];
++ layer->nb_planes = avbuf->num_planes;
++
++ for (int i = 0; i < avbuf->num_planes; i++) {
++ layer->planes[i].object_index = i;
++ layer->planes[i].offset = 0;
++ layer->planes[i].pitch = avbuf->plane_info[i].bytesperline;
++ }
++
++ switch (layer->format) {
++ case DRM_FORMAT_YUYV:
++ layer->nb_planes = 1;
++ break;
++
++ case DRM_FORMAT_NV12:
++ case DRM_FORMAT_NV21:
++ if (avbuf->num_planes > 1)
++ break;
++
++ layer->nb_planes = 2;
++
++ layer->planes[1].object_index = 0;
++ layer->planes[1].offset = avbuf->plane_info[0].bytesperline *
++ height;
++ layer->planes[1].pitch = avbuf->plane_info[0].bytesperline;
++ break;
++
++ case DRM_FORMAT_YUV420:
++ if (avbuf->num_planes > 1)
++ break;
++
++ layer->nb_planes = 3;
++
++ layer->planes[1].object_index = 0;
++ layer->planes[1].offset = avbuf->plane_info[0].bytesperline *
++ height;
++ layer->planes[1].pitch = avbuf->plane_info[0].bytesperline >> 1;
++
++ layer->planes[2].object_index = 0;
++ layer->planes[2].offset = layer->planes[1].offset +
++ ((avbuf->plane_info[0].bytesperline *
++ height) >> 2);
++ layer->planes[2].pitch = avbuf->plane_info[0].bytesperline >> 1;
++ break;
++
++ default:
++ drm_desc->nb_layers = 0;
++ break;
++ }
++
++ return (uint8_t *) drm_desc;
++}
++
++// timeout in ms
++static int deint_v4l2m2m_dequeue_frame(V4L2Queue *queue, AVFrame* frame, int timeout)
++{
++ DeintV4L2M2MContextShared *ctx = queue->ctx;
++ V4L2Buffer* avbuf;
++
++ av_log(ctx->logctx, AV_LOG_TRACE, "<<< %s\n", __func__);
++
++ avbuf = deint_v4l2m2m_dequeue_buffer(queue, timeout);
++ if (!avbuf) {
++ av_log(ctx->logctx, AV_LOG_DEBUG, "%s: No buffer to dequeue (timeout=%d)\n", __func__, timeout);
++ return AVERROR(EAGAIN);
++ }
++
++ // Fill in PTS and anciliary info from src frame
++ // we will want to overwrite some fields as only the pts/dts
++ // fields are updated with new timing in this fn
++ pts_track_get_frame(&ctx->track, avbuf->buffer.timestamp, frame);
++
++ frame->buf[0] = av_buffer_create((uint8_t *) &avbuf->drm_frame,
++ sizeof(avbuf->drm_frame), v4l2_free_buffer,
++ avbuf, AV_BUFFER_FLAG_READONLY);
++ if (!frame->buf[0]) {
++ av_log(ctx->logctx, AV_LOG_ERROR, "%s: error %d creating buffer\n", __func__, 0);
++ return AVERROR(ENOMEM);
++ }
++
++ atomic_fetch_add(&ctx->refcount, 1);
++
++ frame->data[0] = (uint8_t *)v4l2_get_drm_frame(avbuf, ctx->orig_height);
++ frame->format = AV_PIX_FMT_DRM_PRIME;
++ if (ctx->hw_frames_ctx)
++ frame->hw_frames_ctx = av_buffer_ref(ctx->hw_frames_ctx);
++ frame->height = ctx->height;
++ frame->width = ctx->width;
++
++ // Not interlaced now
++ frame->interlaced_frame = 0;
++ frame->top_field_first = 0;
++ // Pkt duration halved
++ frame->pkt_duration /= 2;
++
++ if (avbuf->buffer.flags & V4L2_BUF_FLAG_ERROR) {
++ av_log(ctx->logctx, AV_LOG_ERROR, "driver decode error\n");
++ frame->decode_error_flags |= FF_DECODE_ERROR_INVALID_BITSTREAM;
++ }
++
++ av_log(ctx->logctx, AV_LOG_TRACE, ">>> %s: PTS=%"PRId64"\n", __func__, frame->pts);
++ return 0;
++}
++
++static int deint_v4l2m2m_config_props(AVFilterLink *outlink)
++{
++ AVFilterLink *inlink = outlink->src->inputs[0];
++ AVFilterContext *avctx = outlink->src;
++ DeintV4L2M2MContext *priv = avctx->priv;
++ DeintV4L2M2MContextShared *ctx = priv->shared;
++ int ret;
++
++ ctx->height = avctx->inputs[0]->h;
++ ctx->width = avctx->inputs[0]->w;
++
++ av_log(priv, AV_LOG_DEBUG, "%s: %dx%d\n", __func__, ctx->width, ctx->height);
++
++ outlink->time_base = inlink->time_base;
++ outlink->w = inlink->w;
++ outlink->h = inlink->h;
++ outlink->sample_aspect_ratio = inlink->sample_aspect_ratio;
++ outlink->format = inlink->format;
++ outlink->frame_rate = (AVRational) {1, 0}; // Deny knowledge of frame rate
++
++ ret = deint_v4l2m2m_find_device(ctx);
++ if (ret)
++ return ret;
++
++ if (inlink->hw_frames_ctx) {
++ ctx->hw_frames_ctx = av_buffer_ref(inlink->hw_frames_ctx);
++ if (!ctx->hw_frames_ctx)
++ return AVERROR(ENOMEM);
++ }
++ return 0;
++}
++
++static int deint_v4l2m2m_query_formats(AVFilterContext *avctx)
++{
++ static const enum AVPixelFormat pixel_formats[] = {
++ AV_PIX_FMT_DRM_PRIME,
++ AV_PIX_FMT_YUV420P,
++ AV_PIX_FMT_NONE,
++ };
++
++ return ff_set_common_formats(avctx, ff_make_format_list(pixel_formats));
++}
++
++static uint32_t desc_pixelformat(const AVDRMFrameDescriptor * const drm_desc)
++{
++ const int is_linear = (drm_desc->objects[0].format_modifier == DRM_FORMAT_MOD_LINEAR ||
++ drm_desc->objects[0].format_modifier == DRM_FORMAT_MOD_INVALID);
++
++ switch (drm_desc->layers[0].format) {
++ case DRM_FORMAT_YUV420:
++ if (is_linear)
++ return drm_desc->nb_objects == 1 ? V4L2_PIX_FMT_YUV420 : 0;
++ break;
++ case DRM_FORMAT_NV12:
++ if (is_linear)
++ return drm_desc->nb_objects == 1 ? V4L2_PIX_FMT_NV12 : 0;
++ break;
++ default:
++ break;
++ }
++ return 0;
++}
++
++static int deint_v4l2m2m_filter_frame(AVFilterLink *link, AVFrame *in)
++{
++ AVFilterContext *avctx = link->dst;
++ DeintV4L2M2MContext *priv = avctx->priv;
++ DeintV4L2M2MContextShared *ctx = priv->shared;
++ V4L2Queue *capture = &ctx->capture;
++ V4L2Queue *output = &ctx->output;
++ int ret;
++
++ av_log(priv, AV_LOG_DEBUG, "<<< %s: input pts: %"PRId64" (%"PRId64") field :%d interlaced: %d aspect:%d/%d\n",
++ __func__, in->pts, AV_NOPTS_VALUE, in->top_field_first, in->interlaced_frame, in->sample_aspect_ratio.num, in->sample_aspect_ratio.den);
++ av_log(priv, AV_LOG_DEBUG, "--- %s: in status in %d/ot %d; out status in %d/out %d\n", __func__,
++ avctx->inputs[0]->status_in, avctx->inputs[0]->status_out, avctx->outputs[0]->status_in, avctx->outputs[0]->status_out);
++
++ if (ctx->field_order == V4L2_FIELD_ANY) {
++ const AVDRMFrameDescriptor * const drm_desc = (AVDRMFrameDescriptor *)in->data[0];
++ const uint32_t pixelformat = desc_pixelformat(drm_desc);
++
++ if (pixelformat == 0) {
++ av_log(avctx, AV_LOG_ERROR, "Unsupported DRM format %s in %d objects, modifier %#" PRIx64 "\n",
++ av_fourcc2str(drm_desc->layers[0].format),
++ drm_desc->nb_objects, drm_desc->objects[0].format_modifier);
++ return AVERROR(EINVAL);
++ }
++
++ ctx->orig_width = drm_desc->layers[0].planes[0].pitch;
++ ctx->orig_height = drm_desc->layers[0].planes[1].offset / ctx->orig_width;
++
++ av_log(priv, AV_LOG_DEBUG, "%s: %dx%d (%td,%td)\n", __func__, ctx->width, ctx->height,
++ drm_desc->layers[0].planes[0].pitch, drm_desc->layers[0].planes[1].offset);
++
++ ret = deint_v4l2m2m_set_format(output, pixelformat, ctx->field_order, ctx->width, ctx->height, ctx->orig_width, drm_desc->layers[0].planes[1].offset);
++ if (ret)
++ return ret;
++
++ ret = deint_v4l2m2m_set_format(capture, pixelformat, V4L2_FIELD_NONE, ctx->width, ctx->height, ctx->orig_width, drm_desc->layers[0].planes[1].offset);
++ if (ret)
++ return ret;
++
++ ret = deint_v4l2m2m_allocate_buffers(capture);
++ if (ret)
++ return ret;
++
++ ret = deint_v4l2m2m_streamon(capture);
++ if (ret)
++ return ret;
++
++ ret = deint_v4l2m2m_allocate_buffers(output);
++ if (ret)
++ return ret;
++
++ ret = deint_v4l2m2m_streamon(output);
++ if (ret)
++ return ret;
++
++ if (in->top_field_first)
++ ctx->field_order = V4L2_FIELD_INTERLACED_TB;
++ else
++ ctx->field_order = V4L2_FIELD_INTERLACED_BT;
++
++ }
++
++ ret = deint_v4l2m2m_enqueue_frame(output, in);
++
++ av_log(priv, AV_LOG_TRACE, ">>> %s: %s\n", __func__, av_err2str(ret));
++ return ret;
++}
++
++static int deint_v4l2m2m_activate(AVFilterContext *avctx)
++{
++ DeintV4L2M2MContext * const priv = avctx->priv;
++ DeintV4L2M2MContextShared *const s = priv->shared;
++ AVFilterLink * const outlink = avctx->outputs[0];
++ AVFilterLink * const inlink = avctx->inputs[0];
++ int n = 0;
++ int cn = 99;
++ int instatus = 0;
++ int64_t inpts = 0;
++ int did_something = 0;
++
++ av_log(priv, AV_LOG_TRACE, "<<< %s\n", __func__);
++
++ FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, avctx);
++
++ ff_inlink_acknowledge_status(inlink, &instatus, &inpts);
++
++ if (!ff_outlink_frame_wanted(outlink)) {
++ av_log(priv, AV_LOG_TRACE, "%s: Not wanted out\n", __func__);
++ }
++ else if (s->field_order != V4L2_FIELD_ANY) // Can't DQ if no setup!
++ {
++ AVFrame * frame = av_frame_alloc();
++ int rv;
++
++again:
++ recycle_q(&s->output);
++ n = count_enqueued(&s->output);
++
++ if (frame == NULL) {
++ av_log(priv, AV_LOG_ERROR, "%s: error allocating frame\n", __func__);
++ return AVERROR(ENOMEM);
++ }
++
++ rv = deint_v4l2m2m_dequeue_frame(&s->capture, frame, n > 4 ? 300 : 0);
++ if (rv != 0) {
++ av_frame_free(&frame);
++ if (rv != AVERROR(EAGAIN)) {
++ av_log(priv, AV_LOG_ERROR, ">>> %s: DQ fail: %s\n", __func__, av_err2str(rv));
++ return rv;
++ }
++ }
++ else {
++ frame->interlaced_frame = 0;
++ // frame is always consumed by filter_frame - even on error despite
++ // a somewhat confusing comment in the header
++ rv = ff_filter_frame(outlink, frame);
++
++ if (instatus != 0) {
++ av_log(priv, AV_LOG_TRACE, "%s: eof loop\n", __func__);
++ goto again;
++ }
++
++ av_log(priv, AV_LOG_TRACE, "%s: Filtered: %s\n", __func__, av_err2str(rv));
++ did_something = 1;
++ }
++
++ cn = count_enqueued(&s->capture);
++ }
++
++ if (instatus != 0) {
++ ff_outlink_set_status(outlink, instatus, inpts);
++ av_log(priv, AV_LOG_TRACE, ">>> %s: Status done: %s\n", __func__, av_err2str(instatus));
++ return 0;
++ }
++
++ recycle_q(&s->output);
++ n = count_enqueued(&s->output);
++
++ while (n < 6) {
++ AVFrame * frame;
++ int rv;
++
++ if ((rv = ff_inlink_consume_frame(inlink, &frame)) < 0) {
++ av_log(priv, AV_LOG_ERROR, "%s: consume in failed: %s\n", __func__, av_err2str(rv));
++ return rv;
++ }
++
++ if (frame == NULL) {
++ av_log(priv, AV_LOG_TRACE, "%s: No frame\n", __func__);
++ break;
++ }
++
++ rv = deint_v4l2m2m_filter_frame(inlink, frame);
++ av_frame_free(&frame);
++
++ if (rv != 0)
++ return rv;
++
++ av_log(priv, AV_LOG_TRACE, "%s: Q frame\n", __func__);
++ ++n;
++ }
++
++ if (n < 6) {
++ ff_inlink_request_frame(inlink);
++ did_something = 1;
++ av_log(priv, AV_LOG_TRACE, "%s: req frame\n", __func__);
++ }
++
++ if (n > 4 && ff_outlink_frame_wanted(outlink)) {
++ ff_filter_set_ready(avctx, 1);
++ did_something = 1;
++ av_log(priv, AV_LOG_TRACE, "%s: ready\n", __func__);
++ }
++
++ av_log(priv, AV_LOG_TRACE, ">>> %s: OK (n=%d, cn=%d)\n", __func__, n, cn);
++ return did_something ? 0 : FFERROR_NOT_READY;
++}
++
++static av_cold int deint_v4l2m2m_init(AVFilterContext *avctx)
++{
++ DeintV4L2M2MContext * const priv = avctx->priv;
++ DeintV4L2M2MContextShared * const ctx = av_mallocz(sizeof(DeintV4L2M2MContextShared));
++
++ if (!ctx) {
++ av_log(priv, AV_LOG_ERROR, "%s: error %d allocating context\n", __func__, 0);
++ return AVERROR(ENOMEM);
++ }
++ priv->shared = ctx;
++ ctx->logctx = priv;
++ ctx->fd = -1;
++ ctx->output.ctx = ctx;
++ ctx->output.num_buffers = 8;
++ ctx->capture.ctx = ctx;
++ ctx->capture.num_buffers = 12;
++ ctx->done = 0;
++ ctx->field_order = V4L2_FIELD_ANY;
++
++ pts_track_init(&ctx->track, priv);
++
++ atomic_init(&ctx->refcount, 1);
++
++ return 0;
++}
++
++static void deint_v4l2m2m_uninit(AVFilterContext *avctx)
++{
++ DeintV4L2M2MContext *priv = avctx->priv;
++ DeintV4L2M2MContextShared *ctx = priv->shared;
++
++ ctx->done = 1;
++ ctx->logctx = NULL; // Log to NULL works, log to missing crashes
++ pts_track_uninit(&ctx->track);
++ deint_v4l2m2m_destroy_context(ctx);
++}
++
++static const AVOption deinterlace_v4l2m2m_options[] = {
++ { NULL },
++};
++
++AVFILTER_DEFINE_CLASS(deinterlace_v4l2m2m);
++
++static const AVFilterPad deint_v4l2m2m_inputs[] = {
++ {
++ .name = "default",
++ .type = AVMEDIA_TYPE_VIDEO,
++ },
++ { NULL }
++};
++
++static const AVFilterPad deint_v4l2m2m_outputs[] = {
++ {
++ .name = "default",
++ .type = AVMEDIA_TYPE_VIDEO,
++ .config_props = deint_v4l2m2m_config_props,
++ },
++ { NULL }
++};
++
++AVFilter ff_vf_deinterlace_v4l2m2m = {
++ .name = "deinterlace_v4l2m2m",
++ .description = NULL_IF_CONFIG_SMALL("V4L2 M2M deinterlacer"),
++ .priv_size = sizeof(DeintV4L2M2MContext),
++ .init = &deint_v4l2m2m_init,
++ .uninit = &deint_v4l2m2m_uninit,
++ .query_formats = &deint_v4l2m2m_query_formats,
++ .inputs = deint_v4l2m2m_inputs,
++ .outputs = deint_v4l2m2m_outputs,
++ .priv_class = &deinterlace_v4l2m2m_class,
++ .activate = deint_v4l2m2m_activate,
++};
+--- /dev/null
+++ b/libavfilter/vf_unsand.c
@@ -0,0 +1,234 @@
+/*
@@ -56063,7 +62864,7 @@ Upstream-status: Pending
@@ -3051,6 +3051,40 @@ static int has_codec_parameters(AVStream
return 1;
}
-
+
+#if CONFIG_HEVC_RPI_DECODER && CONFIG_HEVC_DECODER
+// This should be quite general purpose but avoid possible conflicts
+// by limiting usage to cases wehere we know it works.
@@ -56165,10 +62966,10 @@ Upstream-status: Pending
sha512.h \
@@ -86,6 +87,7 @@ HEADERS = adler32.h
tx.h \
-
+
HEADERS-$(CONFIG_LZO) += lzo.h
+HEADERS-$(CONFIG-RPI) += rpi_sand_fn_pw.h
-
+
ARCH_HEADERS = bswap.h \
intmath.h \
@@ -180,6 +182,7 @@ OBJS-$(CONFIG_LZO)
@@ -56184,14 +62985,14 @@ Upstream-status: Pending
@@ -1,4 +1,6 @@
OBJS += aarch64/cpu.o \
aarch64/float_dsp_init.o \
-
+
-NEON-OBJS += aarch64/float_dsp_neon.o
+NEON-OBJS += aarch64/float_dsp_neon.o \
+ aarch64/rpi_sand_neon.o \
+
--- /dev/null
+++ b/libavutil/aarch64/rpi_sand_neon.S
-@@ -0,0 +1,676 @@
+@@ -0,0 +1,781 @@
+/*
+Copyright (c) 2021 Michael Eiler
+
@@ -56252,7 +63053,7 @@ Upstream-status: Pending
+
+ // this is the value we have to add to the src pointer after reading a complete block
+ // it will move the address to the start of the next block
-+ // w10 = stride2 * stride1 - stride1
++ // w10 = stride2 * stride1 - stride1
+ mov w10, w4
+ lsl w10, w10, #7
+ sub w10, w10, #128
@@ -56279,7 +63080,7 @@ Upstream-status: Pending
+ // copy 128 bytes (a full block) into the vector registers v0-v7 and increase the src address by 128
+ // fortunately these aren't callee saved ones, meaning we don't need to backup them
+ ld1 { v0.16b, v1.16b, v2.16b, v3.16b}, [x13], #64
-+ ld1 { v4.16b, v5.16b, v6.16b, v7.16b}, [x13], #64
++ ld1 { v4.16b, v5.16b, v6.16b, v7.16b}, [x13], #64
+
+ // write these registers back to the destination vector and increase the dst address by 128
+ st1 { v0.16b, v1.16b, v2.16b, v3.16b }, [x0], #64
@@ -56310,13 +63111,13 @@ Upstream-status: Pending
+ add w5, w5, #1
+ b incomplete_block_loop_y8
+incomplete_block_loop_end_y8:
-+
-+
-+ // increase the row offset by 128 (stride1)
++
++
++ // increase the row offset by 128 (stride1)
+ add w11, w11, #128
+ // increment the row counter
+ add w12, w12, #1
-+
++
+ // process the next row if we haven't finished yet
+ cmp w15, w12
+ bgt row_loop
@@ -56380,7 +63181,7 @@ Upstream-status: Pending
+ beq no_main_c8
+
+block_loop_c8:
-+ // load the full block -> 128 bytes, the block contains 64 interleaved U and V values
++ // load the full block -> 128 bytes, the block contains 64 interleaved U and V values
+ ld2 { v0.16b, v1.16b }, [x13], #32
+ ld2 { v2.16b, v3.16b }, [x13], #32
+ ld2 { v4.16b, v5.16b }, [x13], #32
@@ -56403,14 +63204,14 @@ Upstream-status: Pending
+ // increment row counter and move src to the beginning of the next block
+ add w14, w14, #1
+ add x13, x13, x10
-+
++
+ // jump to block_loop_c8 iff the block count is smaller than the number of full blocks
+ cmp w8, w14
+ bgt block_loop_c8
+
+no_main_c8:
+ // handle incomplete block at the end of every row
-+ eor w5, w5, w5 // point counter, this might be
++ eor w5, w5, w5 // point counter, this might be
+incomplete_block_loop_c8:
+ cmp w5, w9
+ bge incomplete_block_loop_end_c8
@@ -56442,228 +63243,6 @@ Upstream-status: Pending
+ ret
+endfunc
+
-+//void ff_rpi_sand30_lines_to_planar_y16(
-+// uint8_t * dest, // [x0]
-+// unsigned int dst_stride, // [w1] -> assumed to be equal to _w
-+// const uint8_t * src, // [x2]
-+// unsigned int src_stride1, // [w3] -> 128
-+// unsigned int src_stride2, // [w4]
-+// unsigned int _x, // [w5]
-+// unsigned int y, // [w6]
-+// unsigned int _w, // [w7]
-+// unsigned int h); // [sp, #0]
-+
-+function ff_rpi_sand30_lines_to_planar_y16, export=1
-+ stp x19, x20, [sp, #-48]!
-+ stp x21, x22, [sp, #16]
-+ stp x23, x24, [sp, #32]
-+
-+ // w6 = argument h
-+ ldr w6, [sp, #48]
-+
-+ // slice_inc = ((stride2 - 1) * stride1)
-+ mov w5, w4
-+ sub w5, w5, #1
-+ lsl w5, w5, #7
-+
-+ // total number of bytes per row = (width / 3) * 4
-+ mov w8, w7
-+ mov w9, #3
-+ udiv w8, w8, w9
-+ lsl w8, w8, #2
-+
-+ // number of full 128 byte blocks to be processed
-+ mov w9, #96
-+ udiv w9, w7, w9 // = (width * 4) / (3*128) = width/96
-+
-+ // w10 = number of full integers to process (4 bytes)
-+ // w11 = remaning zero to two 10bit values still to copy over
-+ mov w12, #96
-+ mul w12, w9, w12
-+ sub w12, w7, w12 // width - blocks*96 = remaining points per row
-+ mov w11, #3
-+ udiv w10, w12, w11 // full integers to process = w12 / 3
-+ mul w11, w10, w11 // #integers *3
-+ sub w11, w12, w11 // remaining 0-2 points = remaining points - integers*3
-+
-+ // increase w9 by one if w10+w11 is not zero, and decrease the row count by one
-+ // this is to efficiently copy incomplete blocks at the end of the rows
-+ // the last row is handled explicitly to avoid writing out of bounds
-+ add w22, w10, w11
-+ cmp w22, #0
-+ cset w22, ne // 1 iff w10+w11 not zero, 0 otherwise
-+ add w9, w9, w22
-+ sub w6, w6, #1
-+
-+ // store the number of bytes in w20 which we copy too much for every row
-+ // when the width of the frame is not a multiple of 96 (128bytes storing 96 10bit values)
-+ mov w20, #96*2
-+ mul w20, w20, w9
-+ sub w20, w1, w20
-+
-+ mov w23, #0 // flag to check whether the last line had already been processed
-+
-+ // bitmask to clear the uppper 6bits of the result values
-+ mov x19, #0x03ff03ff03ff03ff
-+ dup v22.2d, x19
-+
-+ // row counter = 0
-+ eor w12, w12, w12
-+row_loop_y16:
-+ cmp w12, w6 // jump to row_loop_y16_fin if we processed all rows
-+ bge row_loop_y16_fin
-+
-+ mov x13, x2 // row src
-+ eor w14, w14, w14 // full block counter
-+block_loop_y16:
-+ cmp w14, w9
-+ bge block_loop_y16_fin
-+
-+ // load 64 bytes
-+ ld1 { v0.4s, v1.4s, v2.4s, v3.4s }, [x13], #64
-+
-+ // process v0 and v1
-+ xtn v16.4h, v0.4s
-+ ushr v0.4s, v0.4s, #10
-+ xtn v17.4h, v0.4s
-+ ushr v0.4s, v0.4s, #10
-+ xtn v18.4h, v0.4s
-+
-+ xtn2 v16.8h, v1.4s
-+ and v16.16b, v16.16b, v22.16b
-+ ushr v1.4s, v1.4s, #10
-+ xtn2 v17.8h, v1.4s
-+ and v17.16b, v17.16b, v22.16b
-+ ushr v1.4s, v1.4s, #10
-+ xtn2 v18.8h, v1.4s
-+ and v18.16b, v18.16b, v22.16b
-+
-+ st3 { v16.8h, v17.8h, v18.8h }, [x0], #48
-+
-+ // process v2 and v3
-+ xtn v23.4h, v2.4s
-+ ushr v2.4s, v2.4s, #10
-+ xtn v24.4h, v2.4s
-+ ushr v2.4s, v2.4s, #10
-+ xtn v25.4h, v2.4s
-+
-+ xtn2 v23.8h, v3.4s
-+ and v23.16b, v23.16b, v22.16b
-+ ushr v3.4s, v3.4s, #10
-+ xtn2 v24.8h, v3.4s
-+ and v24.16b, v24.16b, v22.16b
-+ ushr v3.4s, v3.4s, #10
-+ xtn2 v25.8h, v3.4s
-+ and v25.16b, v25.16b, v22.16b
-+
-+ st3 { v23.8h, v24.8h, v25.8h }, [x0], #48
-+
-+ // load the second half of the block -> 64 bytes into registers v4-v7
-+ ld1 { v4.4s, v5.4s, v6.4s, v7.4s }, [x13], #64
-+
-+ // process v4 and v5
-+ xtn v16.4h, v4.4s
-+ ushr v4.4s, v4.4s, #10
-+ xtn v17.4h, v4.4s
-+ ushr v4.4s, v4.4s, #10
-+ xtn v18.4h, v4.4s
-+
-+ xtn2 v16.8h, v5.4s
-+ and v16.16b, v16.16b, v22.16b
-+ ushr v5.4s, v5.4s, #10
-+ xtn2 v17.8h, v5.4s
-+ and v17.16b, v17.16b, v22.16b
-+ ushr v5.4s, v5.4s, #10
-+ xtn2 v18.8h, v5.4s
-+ and v18.16b, v18.16b, v22.16b
-+
-+ st3 { v16.8h, v17.8h, v18.8h }, [x0], #48
-+
-+ // v6 and v7
-+ xtn v23.4h, v6.4s
-+ ushr v6.4s, v6.4s, #10
-+ xtn v24.4h, v6.4s
-+ ushr v6.4s, v6.4s, #10
-+ xtn v25.4h, v6.4s
-+
-+ xtn2 v23.8h, v7.4s
-+ and v23.16b, v23.16b, v22.16b
-+ ushr v7.4s, v7.4s, #10
-+ xtn2 v24.8h, v7.4s
-+ and v24.16b, v24.16b, v22.16b
-+ ushr v7.4s, v7.4s, #10
-+ xtn2 v25.8h, v7.4s
-+ and v25.16b, v25.16b, v22.16b
-+
-+ st3 { v23.8h, v24.8h, v25.8h }, [x0], #48
-+
-+ add x13, x13, x5 // row src += slice_inc
-+ add w14, w14, #1
-+ b block_loop_y16
-+block_loop_y16_fin:
-+
-+
-+
-+
-+ add x2, x2, #128 // src += stride1 (start of the next row)
-+ add x0, x0, w20, sxtw // subtract the bytes we copied too much from dst
-+ add w12, w12, #1
-+ b row_loop_y16
-+row_loop_y16_fin:
-+
-+ // check whether we have incomplete blocks at the end of every row
-+ // in that case decrease row block count by one
-+ // change height back to it's original value (meaning increase it by 1)
-+ // and jump back to another iteration of row_loop_y16
-+
-+ cmp w23, #1
-+ beq row_loop_y16_fin2 // don't continue here if we already processed the last row
-+ add w6, w6, #1 // increase height to the original value
-+ sub w9, w9, w22 // block count - 1 or 0, depending on the remaining bytes count
-+ mov w23, #1
-+ b row_loop_y16
-+row_loop_y16_fin2:
-+
-+ sub x0, x0, w20, sxtw // with the last row we didn't actually move the dst ptr to far ahead, therefore readd the diference
-+
-+ // now we've got to handle the last block in the last row
-+ eor w12, w12, w12 // w12 = 0 = counter
-+integer_loop_y16:
-+ cmp w12, w10
-+ bge integer_loop_y16_fin
-+ ldr w14, [x13], #4
-+ and w15, w14, #0x3ff
-+ strh w15, [x0], #2
-+ lsr w14, w14, #10
-+ and w15, w14, #0x3ff
-+ strh w15, [x0], #2
-+ lsr w14, w14, #10
-+ and w15, w14, #0x3ff
-+ strh w15, [x0], #2
-+ add w12, w12, #1
-+ b integer_loop_y16
-+integer_loop_y16_fin:
-+
-+final_values_y16:
-+ // remaining point count = w11
-+ ldr w14, [x13], #4
-+ cmp w11, #0
-+ beq final_values_y16_fin
-+ and w15, w14, #0x3ff
-+ strh w15, [x0], #2
-+ cmp w11, #1
-+ beq final_values_y16_fin
-+ lsr w14, w14, #10
-+ and w15, w14, #0x3ff
-+ strh w15, [x0], #2
-+final_values_y16_fin:
-+
-+ ldp x23, x24, [sp, #32]
-+ ldp x21, x22, [sp, #16]
-+ ldp x19, x20, [sp], #48
-+ ret
-+endfunc
-+
+//void ff_rpi_sand30_lines_to_planar_c16(
+// uint8_t * dst_u, // [x0]
+// unsigned int dst_stride_u, // [w1] == _w*2
@@ -56671,7 +63250,7 @@ Upstream-status: Pending
+// unsigned int dst_stride_v, // [w3] == _w*2
+// const uint8_t * src, // [x4]
+// unsigned int stride1, // [w5] == 128
-+// unsigned int stride2, // [w6]
++// unsigned int stride2, // [w6]
+// unsigned int _x, // [w7] == 0
+// unsigned int y, // [sp, #0] == 0
+// unsigned int _w, // [sp, #8] -> w3
@@ -56694,7 +63273,7 @@ Upstream-status: Pending
+ and v5.16b, v5.16b, v16.16b
+ and v6.16b, v6.16b, v16.16b
+ st3 { v4.8h, v5.8h, v6.8h }, [sp], #48
-+
++
+ xtn v4.4h, v2.4s
+ ushr v2.4s, v2.4s, #10
+ xtn v5.4h, v2.4s
@@ -56841,7 +63420,7 @@ Upstream-status: Pending
+ ldr w22, [x4], #4
+ str w22, [x0], #2
+ lsr w22, w22, #16
-+ str w22, [x2], #2
++ str w22, [x2], #2
+
+ add w20, w20, #1
+ b rem_pix_c16_loop
@@ -56868,9 +63447,336 @@ Upstream-status: Pending
+// unsigned int _w,
+// unsigned int h);
+
++// void ff_rpi_sand30_lines_to_planar_y8(
++// uint8_t * dest, : x0
++// unsigned int dst_stride, : w1
++// const uint8_t * src, : x2
++// unsigned int src_stride1, : w3, always 128
++// unsigned int src_stride2, : w4
++// unsigned int _x, : w5
++// unsigned int y, : w6
++// unsigned int _w, : w7
++// unsigned int h); : [sp, #0]
++//
++// Assumes that we are starting on a stripe boundary and that overreading
++// within the stripe is OK. However it does respect the dest size for wri
++
++function ff_rpi_sand30_lines_to_planar_y16, export=1
++ lsl w4, w4, #7
++ sub w4, w4, #64
++ sub w1, w1, w7, lsl #1
++ uxtw x6, w6
++ add x8, x2, x6, lsl #7
++ ldr w6, [sp, #0]
++
++10:
++ mov x2, x8
++ mov w5, w7
++1:
++ ld1 {v0.4s, v1.4s, v2.4s, v3.4s}, [x2], #64
++ ld1 {v4.4s, v5.4s, v6.4s, v7.4s}, [x2], x4
++
++ subs w5, w5, #96
++
++ // v0, v1
++
++ shrn v18.4h, v0.4s, #14
++ xtn v16.4h, v0.4s
++ shrn v17.4h, v0.4s, #10
++
++ shrn2 v18.8h, v1.4s, #14
++ xtn2 v16.8h, v1.4s
++ shrn2 v17.8h, v1.4s, #10
++
++ ushr v18.8h, v18.8h, #6
++ bic v16.8h, #0xfc, lsl #8
++ bic v17.8h, #0xfc, lsl #8
++
++ // v2, v3
++
++ shrn v21.4h, v2.4s, #14
++ xtn v19.4h, v2.4s
++ shrn v20.4h, v2.4s, #10
++
++ shrn2 v21.8h, v3.4s, #14
++ xtn2 v19.8h, v3.4s
++ shrn2 v20.8h, v3.4s, #10
++
++ ushr v21.8h, v21.8h, #6
++ bic v19.8h, #0xfc, lsl #8
++ bic v20.8h, #0xfc, lsl #8
++
++ // v4, v5
++
++ shrn v24.4h, v4.4s, #14
++ xtn v22.4h, v4.4s
++ shrn v23.4h, v4.4s, #10
++
++ shrn2 v24.8h, v5.4s, #14
++ xtn2 v22.8h, v5.4s
++ shrn2 v23.8h, v5.4s, #10
++
++ ushr v24.8h, v24.8h, #6
++ bic v22.8h, #0xfc, lsl #8
++ bic v23.8h, #0xfc, lsl #8
++
++ // v6, v7
++
++ shrn v27.4h, v6.4s, #14
++ xtn v25.4h, v6.4s
++ shrn v26.4h, v6.4s, #10
++
++ shrn2 v27.8h, v7.4s, #14
++ xtn2 v25.8h, v7.4s
++ shrn2 v26.8h, v7.4s, #10
++
++ ushr v27.8h, v27.8h, #6
++ bic v25.8h, #0xfc, lsl #8
++ bic v26.8h, #0xfc, lsl #8
++
++ blt 2f
++
++ st3 {v16.8h, v17.8h, v18.8h}, [x0], #48
++ st3 {v19.8h, v20.8h, v21.8h}, [x0], #48
++ st3 {v22.8h, v23.8h, v24.8h}, [x0], #48
++ st3 {v25.8h, v26.8h, v27.8h}, [x0], #48
++
++ bne 1b
++
++11:
++ subs w6, w6, #1
++ add x0, x0, w1, uxtw
++ add x8, x8, #128
++ bne 10b
++
++ ret
++
++// Partial final write
++2:
++ cmp w5, #48-96
++ blt 1f
++ st3 {v16.8h, v17.8h, v18.8h}, [x0], #48
++ st3 {v19.8h, v20.8h, v21.8h}, [x0], #48
++ beq 11b
++ mov v16.16b, v22.16b
++ mov v17.16b, v23.16b
++ sub w5, w5, #48
++ mov v18.16b, v24.16b
++ mov v19.16b, v25.16b
++ mov v20.16b, v26.16b
++ mov v21.16b, v27.16b
++1:
++ cmp w5, #24-96
++ blt 1f
++ st3 {v16.8h, v17.8h, v18.8h}, [x0], #48
++ beq 11b
++ mov v16.16b, v19.16b
++ mov v17.16b, v20.16b
++ sub w5, w5, #24
++ mov v18.16b, v21.16b
++1:
++ cmp w5, #12-96
++ blt 1f
++ st3 {v16.4h, v17.4h, v18.4h}, [x0], #24
++ beq 11b
++ mov v16.2d[0], v16.2d[1]
++ sub w5, w5, #12
++ mov v17.2d[0], v17.2d[1]
++ mov v18.2d[0], v18.2d[1]
++1:
++ cmp w5, #6-96
++ blt 1f
++ st3 {v16.h, v17.h, v18.h}[0], [x0], #6
++ st3 {v16.h, v17.h, v18.h}[1], [x0], #6
++ beq 11b
++ mov v16.2s[0], v16.2s[1]
++ sub w5, w5, #6
++ mov v17.2s[0], v17.2s[1]
++ mov v18.2s[0], v18.2s[1]
++1:
++ cmp w5, #3-96
++ blt 1f
++ st3 {v16.h, v17.h, v18.h}[0], [x0], #6
++ beq 11b
++ mov v16.4h[0], v16.4h[1]
++ sub w5, w5, #3
++ mov v17.4h[0], v17.4h[1]
++1:
++ cmp w5, #2-96
++ blt 1f
++ st2 {v16.h, v17.h}[0], [x0], #4
++ b 11b
++1:
++ st1 {v16.h}[0], [x0], #2
++ b 11b
++
++endfunc
++
++// void ff_rpi_sand30_lines_to_planar_y8(
++// uint8_t * dest, : x0
++// unsigned int dst_stride, : w1
++// const uint8_t * src, : x2
++// unsigned int src_stride1, : w3, always 128
++// unsigned int src_stride2, : w4
++// unsigned int _x, : w5
++// unsigned int y, : w6
++// unsigned int _w, : w7
++// unsigned int h); : [sp, #0]
++//
++// Assumes that we are starting on a stripe boundary and that overreading
++// within the stripe is OK. However it does respect the dest size for wri
++
++function ff_rpi_sand30_lines_to_planar_y8, export=1
++ lsl w4, w4, #7
++ sub w4, w4, #64
++ sub w1, w1, w7
++ uxtw x6, w6
++ add x8, x2, x6, lsl #7
++ ldr w6, [sp, #0]
++
++10:
++ mov x2, x8
++ mov w5, w7
++1:
++ ld1 {v0.4s, v1.4s, v2.4s, v3.4s}, [x2], #64
++ ld1 {v4.4s, v5.4s, v6.4s, v7.4s}, [x2], x4
++
++ subs w5, w5, #96
++
++ // v0, v1
++
++ shrn v18.4h, v0.4s, #16
++ xtn v16.4h, v0.4s
++ shrn v17.4h, v0.4s, #12
++
++ shrn2 v18.8h, v1.4s, #16
++ xtn2 v16.8h, v1.4s
++ shrn2 v17.8h, v1.4s, #12
++
++ shrn v18.8b, v18.8h, #6
++ shrn v16.8b, v16.8h, #2
++ xtn v17.8b, v17.8h
++
++ // v2, v3
++
++ shrn v21.4h, v2.4s, #16
++ xtn v19.4h, v2.4s
++ shrn v20.4h, v2.4s, #12
++
++ shrn2 v21.8h, v3.4s, #16
++ xtn2 v19.8h, v3.4s
++ shrn2 v20.8h, v3.4s, #12
++
++ shrn2 v18.16b, v21.8h, #6
++ shrn2 v16.16b, v19.8h, #2
++ xtn2 v17.16b, v20.8h
++
++ // v4, v5
++
++ shrn v24.4h, v4.4s, #16
++ xtn v22.4h, v4.4s
++ shrn v23.4h, v4.4s, #12
++
++ shrn2 v24.8h, v5.4s, #16
++ xtn2 v22.8h, v5.4s
++ shrn2 v23.8h, v5.4s, #12
++
++ shrn v21.8b, v24.8h, #6
++ shrn v19.8b, v22.8h, #2
++ xtn v20.8b, v23.8h
++
++ // v6, v7
++
++ shrn v27.4h, v6.4s, #16
++ xtn v25.4h, v6.4s
++ shrn v26.4h, v6.4s, #12
++
++ shrn2 v27.8h, v7.4s, #16
++ xtn2 v25.8h, v7.4s
++ shrn2 v26.8h, v7.4s, #12
++
++ shrn2 v21.16b, v27.8h, #6
++ shrn2 v19.16b, v25.8h, #2
++ xtn2 v20.16b, v26.8h
++
++ blt 2f
++
++ st3 {v16.16b, v17.16b, v18.16b}, [x0], #48
++ st3 {v19.16b, v20.16b, v21.16b}, [x0], #48
++
++ bne 1b
++
++11:
++ subs w6, w6, #1
++ add x0, x0, w1, uxtw
++ add x8, x8, #128
++ bne 10b
++
++ ret
++
++// Partial final write
++2:
++ cmp w5, #48-96
++ blt 1f
++ st3 {v16.16b, v17.16b, v18.16b}, [x0], #48
++ beq 11b
++ mov v16.16b, v22.16b
++ mov v17.16b, v23.16b
++ sub w5, w5, #48
++ mov v18.16b, v24.16b
++1:
++ cmp w5, #24-96
++ blt 1f
++ st3 {v16.8b, v17.8b, v18.8b}, [x0], #24
++ beq 11b
++ mov v16.2d[0], v16.2d[1]
++ sub w5, w5, #24
++ mov v17.2d[0], v17.2d[1]
++ mov v18.2d[0], v18.2d[1]
++1:
++ cmp w5, #12-96
++ blt 1f
++ st3 {v16.b, v17.b, v18.b}[0], [x0], #3
++ st3 {v16.b, v17.b, v18.b}[1], [x0], #3
++ st3 {v16.b, v17.b, v18.b}[2], [x0], #3
++ st3 {v16.b, v17.b, v18.b}[3], [x0], #3
++ beq 11b
++ mov v16.2s[0], v16.2s[1]
++ sub w5, w5, #12
++ mov v17.2s[0], v17.2s[1]
++ mov v18.2s[0], v18.2s[1]
++1:
++ cmp w5, #6-96
++ blt 1f
++ st3 {v16.b, v17.b, v18.b}[0], [x0], #3
++ st3 {v16.b, v17.b, v18.b}[1], [x0], #3
++ beq 11b
++ mov v16.4h[0], v16.4h[1]
++ sub w5, w5, #6
++ mov v17.4h[0], v17.4h[1]
++ mov v18.4h[0], v18.4h[1]
++1:
++ cmp w5, #3-96
++ blt 1f
++ st3 {v16.b, v17.b, v18.b}[0], [x0], #3
++ beq 11b
++ mov v16.8b[0], v16.8b[1]
++ sub w5, w5, #3
++ mov v17.8b[0], v17.8b[1]
++1:
++ cmp w5, #2-96
++ blt 1f
++ st2 {v16.b, v17.b}[0], [x0], #2
++ b 11b
++1:
++ st1 {v16.b}[0], [x0], #1
++ b 11b
++
++endfunc
++
--- /dev/null
+++ b/libavutil/aarch64/rpi_sand_neon.h
-@@ -0,0 +1,55 @@
+@@ -0,0 +1,59 @@
+/*
+Copyright (c) 2021 Michael Eiler
+
@@ -56922,6 +63828,10 @@ Upstream-status: Pending
+ uint8_t * dst_v, unsigned int dst_stride_v, const uint8_t * src, unsigned int stride1,
+ unsigned int stride2, unsigned int _x, unsigned int y, unsigned int _w, unsigned int h);
+
++void ff_rpi_sand30_lines_to_planar_y8(uint8_t * dest, unsigned int dst_stride,
++ const uint8_t * src, unsigned int src_stride1, unsigned int src_stride2,
++ unsigned int _x, unsigned int y, unsigned int _w, unsigned int h);
++
+#ifdef __cplusplus
+}
+#endif
@@ -56929,13 +63839,13 @@ Upstream-status: Pending
--- a/libavutil/arm/Makefile
+++ b/libavutil/arm/Makefile
@@ -6,3 +6,4 @@ VFP-OBJS += arm/float_dsp_init_vfp.o
-
+
NEON-OBJS += arm/float_dsp_init_neon.o \
arm/float_dsp_neon.o \
+ arm/rpi_sand_neon.o \
--- /dev/null
+++ b/libavutil/arm/rpi_sand_neon.S
-@@ -0,0 +1,768 @@
+@@ -0,0 +1,925 @@
+/*
+Copyright (c) 2018 Raspberry Pi (Trading) Ltd.
+All rights reserved.
@@ -57298,7 +64208,6 @@ Upstream-status: Pending
+ ldr r6, [sp, #36]
+ ldr r7, [sp, #32] @ y
+ mov r12, #48
-+ vmov.u16 q15, #0x3ff
+ sub r3, #1
+ lsl r3, #7
+ sub r1, r1, r6, lsl #1
@@ -57314,37 +64223,33 @@ Upstream-status: Pending
+ vldm r2!, {q10-q13}
+ add lr, #64
+
-+ vshr.u32 q14, q10, #20 @ Cannot vshrn.u32 #20!
++ vshrn.u32 d4 , q10, #14 @ Cannot vshrn.u32 #20!
+ ands lr, #127
+ vshrn.u32 d2, q10, #10
+ vmovn.u32 d0, q10
-+ vmovn.u32 d4, q14
+
-+ vshr.u32 q14, q11, #20
++ vshrn.u32 d5, q11, #14
+ it eq
+ addeq r2, r3
+ vshrn.u32 d3, q11, #10
+ vmovn.u32 d1, q11
-+ vmovn.u32 d5, q14
+
+ subs r5, #48
-+ vand q0, q15
-+ vand q1, q15
-+ vand q2, q15
++ vshr.u16 q2, #6
++ vbic.u16 q0, #0xfc00
++ vbic.u16 q1, #0xfc00
+
-+ vshr.u32 q14, q12, #20
++ vshrn.u32 d20, q12, #14
+ vshrn.u32 d18, q12, #10
+ vmovn.u32 d16, q12
-+ vmovn.u32 d20, q14
+
-+ vshr.u32 q14, q13, #20
++ vshrn.u32 d21, q13, #14
+ vshrn.u32 d19, q13, #10
+ vmovn.u32 d17, q13
-+ vmovn.u32 d21, q14
+
-+ vand q8, q15
-+ vand q9, q15
-+ vand q10, q15
++ vshr.u16 q10, #6
++ vbic.u16 q8, #0xfc00
++ vbic.u16 q9 , #0xfc00
+ blt 2f
+
+ vst3.16 {d0, d2, d4}, [r0], r12
@@ -57437,7 +64342,6 @@ Upstream-status: Pending
+ ldr r7, [sp, #48]
+ ldr r9, [sp, #52]
+ mov r12, #48
-+ vmov.u16 q15, #0x3ff
+ sub r8, #1
+ lsl r8, #7
+ add r5, r5, r7, lsl #7
@@ -57453,48 +64357,44 @@ Upstream-status: Pending
+ add lr, #64
+
+ @ N.B. unpack [0,1,2] -> (reg order) 1, 0, 2
-+ vshr.u32 q14, q0, #20
-+ vshrn.u32 d16, q0, #10
++ vshrn.u32 d20, q0, #14
+ vmovn.u32 d18, q0
++ vshrn.u32 d0, q0, #10
+ ands lr, #127
-+ vmovn.u32 d20, q14
+
-+ vshr.u32 q14, q1, #20
-+ vshrn.u32 d17, q1, #10
++ vshrn.u32 d21, q1, #14
+ vmovn.u32 d19, q1
-+ vmovn.u32 d21, q14
++ vshrn.u32 d1, q1, #10
+
-+ vshr.u32 q14, q2, #20
+ vshrn.u32 d22, q2, #10
-+ vmovn.u32 d24, q2
-+ vmovn.u32 d26, q14
++ vmovn.u32 d2, q2
++ vshrn.u32 d4, q2, #14
+
-+ vshr.u32 q14, q3, #20
-+ vshrn.u32 d23, q3, #10
-+ vmovn.u32 d25, q3
+ add r10, r0, #24
-+ vmovn.u32 d27, q14
++ vshrn.u32 d23, q3, #10
++ vmovn.u32 d3, q3
++ vshrn.u32 d5, q3, #14
+
+ it eq
+ addeq r4, r8
-+ vuzp.16 q8, q11
-+ vuzp.16 q9, q12
-+ vuzp.16 q10, q13
++ vuzp.16 q0, q11
++ vuzp.16 q9, q1
++ vuzp.16 q10, q2
+
-+ @ q8 V0, V3,.. -> q0
++ @ q0 V0, V3,..
+ @ q9 U0, U3...
+ @ q10 U1, U4...
+ @ q11 U2, U5,..
-+ @ q12 V1, V4,.. -> q1
-+ @ q13 V2, V5,.. -> q2
++ @ q1 V1, V4,
++ @ q2 V2, V5,..
+
+ subs r6, #24
-+ vand q11, q15
-+ vand q9, q15
-+ vand q10, q15
-+ vand q0, q8, q15
-+ vand q1, q12, q15
-+ vand q2, q13, q15
++ vbic.u16 q11, #0xfc00
++ vbic.u16 q9, #0xfc00
++ vshr.u16 q10, #6
++ vshr.u16 q2, #6
++ vbic.u16 q0, #0xfc00
++ vbic.u16 q1, #0xfc00
+
+ blt 2f
+
@@ -57703,10 +64603,177 @@ Upstream-status: Pending
+endfunc
+
+
++@ void ff_rpi_sand30_lines_to_planar_y8(
++@ uint8_t * dest, // [r0]
++@ unsigned int dst_stride, // [r1]
++@ const uint8_t * src, // [r2]
++@ unsigned int src_stride1, // [r3] Ignored - assumed 128
++@ unsigned int src_stride2, // [sp, #0] -> r3
++@ unsigned int _x, // [sp, #4] Ignored - 0
++@ unsigned int y, // [sp, #8] (r7 in prefix)
++@ unsigned int _w, // [sp, #12] -> r6 (cur r5)
++@ unsigned int h); // [sp, #16] -> r7
++@
++@ Assumes that we are starting on a stripe boundary and that overreading
++@ within the stripe is OK. However it does respect the dest size for wri
++
++function ff_rpi_sand30_lines_to_planar_y8, export=1
++ push {r4-r8, lr} @ +24
++ ldr r3, [sp, #24]
++ ldr r6, [sp, #36]
++ ldr r7, [sp, #32] @ y
++ mov r12, #48
++ lsl r3, #7
++ sub r1, r1, r6
++ add r8, r2, r7, lsl #7
++ ldr r7, [sp, #40]
++
++10:
++ mov r2, r8
++ add r4, r0, #24
++ mov r5, r6
++1:
++ vldm r2, {q8-q15}
++
++ subs r5, #96
++
++ vmovn.u32 d0, q8
++ vshrn.u32 d2, q8, #12
++ vshrn.u32 d4, q8, #16 @ Cannot vshrn.u32 #20!
++
++ add r2, r3
++
++ vmovn.u32 d1, q9
++ vshrn.u32 d3, q9, #12
++ vshrn.u32 d5, q9, #16
++
++ pld [r2, #0]
++
++ vshrn.u16 d0, q0, #2
++ vmovn.u16 d1, q1
++ vshrn.u16 d2, q2, #6
++
++ vmovn.u32 d16, q10
++ vshrn.u32 d18, q10, #12
++ vshrn.u32 d20, q10, #16
++
++ vmovn.u32 d17, q11
++ vshrn.u32 d19, q11, #12
++ vshrn.u32 d21, q11, #16
++
++ pld [r2, #64]
++
++ vshrn.u16 d4, q8, #2
++ vmovn.u16 d5, q9
++ vshrn.u16 d6, q10, #6
++
++ vmovn.u32 d16, q12
++ vshrn.u32 d18, q12, #12
++ vshrn.u32 d20, q12, #16
++
++ vmovn.u32 d17, q13
++ vshrn.u32 d19, q13, #12
++ vshrn.u32 d21, q13, #16
++
++ vshrn.u16 d16, q8, #2
++ vmovn.u16 d17, q9
++ vshrn.u16 d18, q10, #6
++
++ vmovn.u32 d20, q14
++ vshrn.u32 d22, q14, #12
++ vshrn.u32 d24, q14, #16
++
++ vmovn.u32 d21, q15
++ vshrn.u32 d23, q15, #12
++ vshrn.u32 d25, q15, #16
++
++ vshrn.u16 d20, q10, #2
++ vmovn.u16 d21, q11
++ vshrn.u16 d22, q12, #6
++
++ blt 2f
++
++ vst3.8 {d0, d1, d2}, [r0], r12
++ vst3.8 {d4, d5, d6}, [r4], r12
++ vst3.8 {d16, d17, d18}, [r0], r12
++ vst3.8 {d20, d21, d22}, [r4], r12
++
++ bne 1b
++
++11:
++ subs r7, #1
++ add r0, r1
++ add r8, #128
++ bne 10b
++
++ pop {r4-r8, pc}
++
++@ Partial final write
++2:
++ cmp r5, #48-96
++ blt 1f
++ vst3.8 {d0, d1, d2}, [r0], r12
++ vst3.8 {d4, d5, d6}, [r4], r12
++ beq 11b
++ vmov q0, q8
++ vmov q2, q10
++ sub r5, #48
++ vmov d2, d18
++ vmov d6, d22
++1:
++ cmp r5, #24-96
++ blt 1f
++ vst3.8 {d0, d1, d2}, [r0]!
++ beq 11b
++ vmov q0, q2
++ sub r5, #24
++ vmov d2, d6
++1:
++ cmp r5, #12-96
++ blt 1f
++ vst3.8 {d0[0], d1[0], d2[0]}, [r0]!
++ vst3.8 {d0[1], d1[1], d2[1]}, [r0]!
++ vst3.8 {d0[2], d1[2], d2[2]}, [r0]!
++ vst3.8 {d0[3], d1[3], d2[3]}, [r0]!
++ beq 11b
++ vmov s0, s1
++ sub r5, #12
++ vmov s2, s3
++ vmov s4, s5
++1:
++ cmp r5, #6-96
++ blt 1f
++ vst3.8 {d0[0], d1[0], d2[0]}, [r0]!
++ vst3.8 {d0[1], d1[1], d2[1]}, [r0]!
++ add r0, #12
++ beq 11b
++ vshr.u32 d0, #16
++ sub r5, #6
++ vshr.u32 d1, #16
++ vshr.u32 d2, #16
++1:
++ cmp r5, #3-96
++ blt 1f
++ vst3.8 {d0[0], d1[0], d2[0]}, [r0]!
++ beq 11b
++ sub r5, #3
++ vshr.u32 d0, #8
++ vshr.u32 d1, #8
++1:
++ cmp r5, #2-96
++ blt 1f
++ vst2.8 {d0[0], d1[0]}, [r0]!
++ b 11b
++1:
++ vst1.8 {d0[0]}, [r0]!
++ b 11b
++
++endfunc
++
+
--- /dev/null
+++ b/libavutil/arm/rpi_sand_neon.h
-@@ -0,0 +1,99 @@
+@@ -0,0 +1,110 @@
+/*
+Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+All rights reserved.
@@ -57804,6 +64871,17 @@ Upstream-status: Pending
+ unsigned int _w, // [sp, #12] -> r6 (cur r5)
+ unsigned int h); // [sp, #16] -> r7
+
++void ff_rpi_sand30_lines_to_planar_y8(
++ uint8_t * dest, // [r0]
++ unsigned int dst_stride, // [r1]
++ const uint8_t * src, // [r2]
++ unsigned int src_stride1, // [r3] Ignored - assumed 128
++ unsigned int src_stride2, // [sp, #0] -> r3
++ unsigned int _x, // [sp, #4] Ignored - 0
++ unsigned int y, // [sp, #8] (r7 in prefix)
++ unsigned int _w, // [sp, #12] -> r6 (cur r5)
++ unsigned int h); // [sp, #16] -> r7
++
+#endif // AVUTIL_ARM_SAND_NEON_H
+
--- a/libavutil/frame.c
@@ -57811,7 +64889,7 @@ Upstream-status: Pending
@@ -16,6 +16,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-
+
+#include "config.h"
+
#include "channel_layout.h"
@@ -57824,13 +64902,13 @@ Upstream-status: Pending
+#if CONFIG_SAND
+#include "rpi_sand_fns.h"
+#endif
-
+
#if FF_API_FRAME_GET_SET
MAKE_ACCESSORS(AVFrame, frame, int64_t, best_effort_timestamp)
@@ -902,6 +907,12 @@ int av_frame_apply_cropping(AVFrame *fra
(frame->crop_top + frame->crop_bottom) >= frame->height)
return AVERROR(ERANGE);
-
+
+#if CONFIG_SAND
+ // Sand cannot be cropped - do not try
+ if (av_rpi_is_sand_format(frame->format))
@@ -57845,7 +64923,7 @@ Upstream-status: Pending
@@ -968,6 +968,16 @@ int av_frame_apply_cropping(AVFrame *fra
*/
const char *av_frame_side_data_name(enum AVFrameSideDataType type);
-
+
+
+static inline int av_frame_cropped_width(const AVFrame * const frame)
+{
@@ -57866,11 +64944,11 @@ Upstream-status: Pending
#include <sys/mman.h>
#include <unistd.h>
+#include <sys/ioctl.h>
-
+
#include <drm.h>
+#include <libdrm/drm_fourcc.h>
#include <xf86drm.h>
-
+
#include "avassert.h"
@@ -28,6 +30,11 @@
#include "hwcontext_drm.h"
@@ -57881,13 +64959,13 @@ Upstream-status: Pending
+#include <linux/mman.h>
+#include <linux/dma-buf.h>
+#include <linux/dma-heap.h>
-
-
+
+
static void drm_device_free(AVHWDeviceContext *hwdev)
@@ -43,6 +50,11 @@ static int drm_device_create(AVHWDeviceC
AVDRMDeviceContext *hwctx = hwdev->hwctx;
drmVersionPtr version;
-
+
+ if (device == NULL) {
+ hwctx->fd = -1;
+ return 0;
@@ -57905,7 +64983,7 @@ Upstream-status: Pending
size_t length[AV_DRM_MAX_PLANES];
+ int fds[AV_DRM_MAX_PLANES];
} DRMMapping;
-
+
+static int dmasync(const int fd, const unsigned int flags)
+{
+ struct dma_buf_sync sync = {
@@ -57926,19 +65004,19 @@ Upstream-status: Pending
{
DRMMapping *map = hwmap->priv;
int i;
-
+
- for (i = 0; i < map->nb_regions; i++)
+ for (i = 0; i < map->nb_regions; i++) {
munmap(map->address[i], map->length[i]);
+ dmasync(map->fds[i], DMA_BUF_SYNC_END | map->dmaflags);
+ }
-
+
av_free(map);
}
@@ -114,15 +145,28 @@ static int drm_map_frame(AVHWFramesConte
if (!map)
return AVERROR(ENOMEM);
-
+
+ for (i = 0; i < AV_DRM_MAX_PLANES; i++)
+ map->fds[i] = -1;
+
@@ -57956,7 +65034,7 @@ Upstream-status: Pending
+
+ if (dst->format == AV_PIX_FMT_NONE)
+ dst->format = hwfc->sw_format;
-
+
av_assert0(desc->nb_objects <= AV_DRM_MAX_PLANES);
for (i = 0; i < desc->nb_objects; i++) {
- addr = mmap(NULL, desc->objects[i].size, mmap_prot, MAP_SHARED,
@@ -57968,7 +65046,7 @@ Upstream-status: Pending
if (addr == MAP_FAILED) {
err = AVERROR(errno);
@@ -151,6 +195,23 @@ static int drm_map_frame(AVHWFramesConte
-
+
dst->width = src->width;
dst->height = src->height;
+ dst->crop_top = src->crop_top;
@@ -57988,12 +65066,12 @@ Upstream-status: Pending
+ // *** Are we sure src->height is actually what we want ???
+ }
+#endif
-
+
err = ff_hwframe_map_create(src->hw_frames_ctx, dst, src,
&drm_unmap_frame, map);
@@ -160,7 +221,9 @@ static int drm_map_frame(AVHWFramesConte
return 0;
-
+
fail:
- for (i = 0; i < desc->nb_objects; i++) {
+ for (i = 0; i < AV_DRM_MAX_PLANES; i++) {
@@ -58002,13 +65080,23 @@ Upstream-status: Pending
if (map->address[i])
munmap(map->address[i], map->length[i]);
}
-@@ -178,7 +241,15 @@ static int drm_transfer_get_formats(AVHW
- if (!pix_fmts)
+@@ -172,16 +235,29 @@ static int drm_transfer_get_formats(AVHW
+ enum AVHWFrameTransferDirection dir,
+ enum AVPixelFormat **formats)
+ {
+- enum AVPixelFormat *pix_fmts;
++ enum AVPixelFormat *p;
+
+- pix_fmts = av_malloc_array(2, sizeof(*pix_fmts));
+- if (!pix_fmts)
++ p = *formats = av_malloc_array(3, sizeof(*p));
++ if (!p)
return AVERROR(ENOMEM);
-
+
- pix_fmts[0] = ctx->sw_format;
+- pix_fmts[1] = AV_PIX_FMT_NONE;
+ // **** Offer native sand too ????
-+ pix_fmts[0] =
++ *p++ =
+#if CONFIG_SAND
+ ctx->sw_format == AV_PIX_FMT_RPI4_8 || ctx->sw_format == AV_PIX_FMT_SAND128 ?
+ AV_PIX_FMT_YUV420P :
@@ -58016,21 +65104,30 @@ Upstream-status: Pending
+ AV_PIX_FMT_YUV420P10LE :
+#endif
+ ctx->sw_format;
- pix_fmts[1] = AV_PIX_FMT_NONE;
-
- *formats = pix_fmts;
-@@ -197,18 +268,80 @@ static int drm_transfer_data_from(AVHWFr
++
++#if CONFIG_SAND
++ if (ctx->sw_format == AV_PIX_FMT_RPI4_10 ||
++ ctx->sw_format == AV_PIX_FMT_RPI4_8 || ctx->sw_format == AV_PIX_FMT_SAND128)
++ *p++ = AV_PIX_FMT_NV12;
++#endif
+
+- *formats = pix_fmts;
++ *p = AV_PIX_FMT_NONE;
+ return 0;
+ }
+
+@@ -197,18 +273,63 @@ static int drm_transfer_data_from(AVHWFr
map = av_frame_alloc();
if (!map)
return AVERROR(ENOMEM);
- map->format = dst->format;
-
+
+ // Map to default
+ map->format = AV_PIX_FMT_NONE;
err = drm_map_frame(hwfc, map, src, AV_HWFRAME_MAP_READ);
if (err)
goto fail;
-
+
- map->width = dst->width;
- map->height = dst->height;
+#if 0
@@ -58054,29 +65151,12 @@ Upstream-status: Pending
+ const unsigned int w = FFMIN(dst->width, map->width);
+ const unsigned int h = FFMIN(dst->height, map->height);
+
-+ if (map->format == AV_PIX_FMT_RPI4_8 && dst->format == AV_PIX_FMT_YUV420P) {
-+ av_rpi_sand_to_planar_y8(dst->data[0], dst->linesize[0],
-+ map->data[0],
-+ 128, stride2,
-+ 0, 0, w, h);
-+ av_rpi_sand_to_planar_c8(dst->data[1], dst->linesize[1],
-+ dst->data[2], dst->linesize[2],
-+ map->data[1],
-+ 128, stride2,
-+ 0, 0, w / 2, h / 2);
-+ }
-+ else if (map->format == AV_PIX_FMT_RPI4_10 && dst->format == AV_PIX_FMT_YUV420P10LE) {
-+ av_rpi_sand30_to_planar_y16(dst->data[0], dst->linesize[0],
-+ map->data[0],
-+ 128, stride2,
-+ 0, 0, w, h);
-+ av_rpi_sand30_to_planar_c16(dst->data[1], dst->linesize[1],
-+ dst->data[2], dst->linesize[2],
-+ map->data[1],
-+ 128, stride2,
-+ 0, 0, w / 2, h / 2);
-+ }
-+ else
++ map->crop_top = 0;
++ map->crop_bottom = 0;
++ map->crop_left = 0;
++ map->crop_right = 0;
++
++ if (av_rpi_sand_to_planar_frame(dst, map) != 0)
+ {
+ av_log(hwfc, AV_LOG_ERROR, "%s: Incompatible output pixfmt for sand\n", __func__);
+ err = AVERROR(EINVAL);
@@ -58094,30 +65174,30 @@ Upstream-status: Pending
+ map->height = dst->height;
+ err = av_frame_copy(dst, map);
+ }
-
+
- err = av_frame_copy(dst, map);
if (err)
+ {
+ av_log(hwfc, AV_LOG_ERROR, "%s: Copy fail\n", __func__);
goto fail;
+ }
-
+
err = 0;
fail:
-@@ -223,7 +356,10 @@ static int drm_transfer_data_to(AVHWFram
+@@ -223,7 +344,10 @@ static int drm_transfer_data_to(AVHWFram
int err;
-
+
if (src->width > hwfc->width || src->height > hwfc->height)
+ {
+ av_log(hwfc, AV_LOG_ERROR, "%s: H/w mismatch: %d/%d, %d/%d\n", __func__, dst->width, hwfc->width, dst->height, hwfc->height);
return AVERROR(EINVAL);
+ }
-
+
map = av_frame_alloc();
if (!map)
--- a/libavutil/pixdesc.c
+++ b/libavutil/pixdesc.c
-@@ -2371,6 +2371,38 @@ static const AVPixFmtDescriptor av_pix_f
+@@ -2371,6 +2371,50 @@ static const AVPixFmtDescriptor av_pix_f
.name = "vulkan",
.flags = AV_PIX_FMT_FLAG_HWACCEL,
},
@@ -58140,17 +65220,29 @@ Upstream-status: Pending
+ .log2_chroma_h = 1,
+ .comp = {
+ { 0, 2, 0, 0, 10, 0, 9, 1 }, /* Y */
-+ { 1, 4, 0, 0, 10, 1, 9, 1 }, /* U */
-+ { 1, 4, 1, 0, 10, 1, 9, 2 }, /* V */
++ { 1, 4, 0, 0, 10, 3, 9, 1 }, /* U */
++ { 1, 4, 2, 0, 10, 3, 9, 3 }, /* V */
++ },
++ .flags = 0,
++ },
++ [AV_PIX_FMT_SAND64_16] = {
++ .name = "sand64_16",
++ .nb_components = 3,
++ .log2_chroma_w = 1,
++ .log2_chroma_h = 1,
++ .comp = {
++ { 0, 2, 0, 0, 16, 0, 15, 1 }, /* Y */
++ { 1, 4, 0, 0, 16, 3, 15, 1 }, /* U */
++ { 1, 4, 2, 0, 16, 3, 15, 3 }, /* V */
+ },
+ .flags = 0,
+ },
+ [AV_PIX_FMT_RPI4_8] = {
-+ .name = "rpi",
++ .name = "rpi4_8",
+ .flags = AV_PIX_FMT_FLAG_HWACCEL,
+ },
+ [AV_PIX_FMT_RPI4_10] = {
-+ .name = "rpi",
++ .name = "rpi4_10",
+ .flags = AV_PIX_FMT_FLAG_HWACCEL,
+ },
};
@@ -58159,7 +65251,7 @@ Upstream-status: Pending
--- a/libavutil/pixfmt.h
+++ b/libavutil/pixfmt.h
@@ -357,6 +357,12 @@ enum AVPixelFormat {
-
+
AV_PIX_FMT_Y210BE, ///< packed YUV 4:2:2 like YUYV422, 20bpp, data in the high bits, big-endian
AV_PIX_FMT_Y210LE, ///< packed YUV 4:2:2 like YUYV422, 20bpp, data in the high bits, little-endian
+// RPI - not on ifdef so can be got at by calling progs
@@ -58168,7 +65260,7 @@ Upstream-status: Pending
+ AV_PIX_FMT_SAND64_16, ///< 4:2:0 16-bit 64x*Y stripe, 32x*UV stripe, then next x stripe, mysterious padding
+ AV_PIX_FMT_RPI4_8,
+ AV_PIX_FMT_RPI4_10,
-
+
AV_PIX_FMT_NB ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions
};
--- /dev/null
@@ -58403,7 +65495,7 @@ Upstream-status: Pending
+
--- /dev/null
+++ b/libavutil/rpi_sand_fns.c
-@@ -0,0 +1,356 @@
+@@ -0,0 +1,445 @@
+/*
+Copyright (c) 2018 Raspberry Pi (Trading) Ltd.
+All rights reserved.
@@ -58635,6 +65727,75 @@ Upstream-status: Pending
+ }
+}
+
++// Fetches a single patch - offscreen fixup not done here
++// w <= stride1
++// single lose bottom 2 bits truncation
++// _x & _w in pixels, strides in bytes
++void av_rpi_sand30_to_planar_y8(uint8_t * dst, const unsigned int dst_stride,
++ const uint8_t * src,
++ unsigned int stride1, unsigned int stride2,
++ unsigned int _x, unsigned int y,
++ unsigned int _w, unsigned int h)
++{
++ const unsigned int x0 = (_x / 3) * 4; // Byte offset of the word
++ const unsigned int xskip0 = _x - (x0 >> 2) * 3;
++ const unsigned int x1 = ((_x + _w) / 3) * 4;
++ const unsigned int xrem1 = _x + _w - (x1 >> 2) * 3;
++ const unsigned int mask = stride1 - 1;
++ const uint8_t * p0 = src + (x0 & mask) + y * stride1 + (x0 & ~mask) * stride2;
++ const unsigned int slice_inc = ((stride2 - 1) * stride1) >> 2; // RHS of a stripe to LHS of next in words
++
++#if HAVE_SAND_ASM
++ if (_x == 0) {
++ ff_rpi_sand30_lines_to_planar_y8(dst, dst_stride, src, stride1, stride2, _x, y, _w, h);
++ return;
++ }
++#endif
++
++ if (x0 == x1) {
++ // *******************
++ // Partial single word xfer
++ return;
++ }
++
++ for (unsigned int i = 0; i != h; ++i, dst += dst_stride, p0 += stride1)
++ {
++ unsigned int x = x0;
++ const uint32_t * p = (const uint32_t *)p0;
++ uint8_t * d = dst;
++
++ if (xskip0 != 0) {
++ const uint32_t p3 = *p++;
++
++ if (xskip0 == 1)
++ *d++ = (p3 >> 12) & 0xff;
++ *d++ = (p3 >> 22) & 0xff;
++
++ if (((x += 4) & mask) == 0)
++ p += slice_inc;
++ }
++
++ while (x != x1) {
++ const uint32_t p3 = *p++;
++ *d++ = (p3 >> 2) & 0xff;
++ *d++ = (p3 >> 12) & 0xff;
++ *d++ = (p3 >> 22) & 0xff;
++
++ if (((x += 4) & mask) == 0)
++ p += slice_inc;
++ }
++
++ if (xrem1 != 0) {
++ const uint32_t p3 = *p;
++
++ *d++ = (p3 >> 2) & 0xff;
++ if (xrem1 == 2)
++ *d++ = (p3 >> 12) & 0xff;
++ }
++ }
++}
++
++
+
+// w/h in pixels
+void av_rpi_sand16_to_sand8(uint8_t * dst, const unsigned int dst_stride1, const unsigned int dst_stride2,
@@ -58716,6 +65877,16 @@ Upstream-status: Pending
+ av_rpi_sand_frame_stride1(src), av_rpi_sand_frame_stride2(src),
+ x/2, y/2, w/2, h/2);
+ break;
++ case AV_PIX_FMT_NV12:
++ av_rpi_sand_to_planar_y8(dst->data[0], dst->linesize[0],
++ src->data[0],
++ av_rpi_sand_frame_stride1(src), av_rpi_sand_frame_stride2(src),
++ x, y, w, h);
++ av_rpi_sand_to_planar_y8(dst->data[1], dst->linesize[1],
++ src->data[1],
++ av_rpi_sand_frame_stride1(src), av_rpi_sand_frame_stride2(src),
++ x/2, y/2, w, h/2);
++ break;
+ default:
+ return -1;
+ }
@@ -58750,6 +65921,16 @@ Upstream-status: Pending
+ av_rpi_sand_frame_stride1(src), av_rpi_sand_frame_stride2(src),
+ x/2, y/2, w/2, h/2);
+ break;
++ case AV_PIX_FMT_NV12:
++ av_rpi_sand30_to_planar_y8(dst->data[0], dst->linesize[0],
++ src->data[0],
++ av_rpi_sand_frame_stride1(src), av_rpi_sand_frame_stride2(src),
++ x, y, w, h);
++ av_rpi_sand30_to_planar_y8(dst->data[1], dst->linesize[1],
++ src->data[1],
++ av_rpi_sand_frame_stride1(src), av_rpi_sand_frame_stride2(src),
++ x/2, y/2, w, h/2);
++ break;
+ default:
+ return -1;
+ }
@@ -58762,7 +65943,7 @@ Upstream-status: Pending
+}
--- /dev/null
+++ b/libavutil/rpi_sand_fns.h
-@@ -0,0 +1,183 @@
+@@ -0,0 +1,188 @@
+/*
+Copyright (c) 2018 Raspberry Pi (Trading) Ltd.
+All rights reserved.
@@ -58850,6 +66031,11 @@ Upstream-status: Pending
+ unsigned int _x, unsigned int y,
+ unsigned int _w, unsigned int h);
+
++void av_rpi_sand30_to_planar_y8(uint8_t * dst, const unsigned int dst_stride,
++ const uint8_t * src,
++ unsigned int stride1, unsigned int stride2,
++ unsigned int _x, unsigned int y,
++ unsigned int _w, unsigned int h);
+
+// w/h in pixels
+void av_rpi_sand16_to_sand8(uint8_t * dst, const unsigned int dst_stride1, const unsigned int dst_stride2,
@@ -58948,34 +66134,64 @@ Upstream-status: Pending
+
--- /dev/null
+++ b/pi-util/BUILD.txt
-@@ -0,0 +1,29 @@
+@@ -0,0 +1,59 @@
+Building Pi FFmpeg
+==================
+
-+Configuration:
-+=============
++Current only building on a Pi is supported.
++This builds ffmpeg the way I've tested it
++
++Get all dependencies - the current package dependencies are good enough
++
++$ sudo apt-get build-dep ffmpeg
+
-+These instructions work for cross compiles from Ubuntu 16.04 & Ubuntu
-+18.04. I would expect most other linux environments to work but I haven't
-+tried them.
++Configure using the pi-util/conf_native.sh script
++-------------------------------------------------
+
-+pi-util/conf_pi2.sh
++This sets the normal release options and creates an ouutput dir to build into
++The directory name will depend on system and options but will be under out/
+
-+contains suitable options to build the code for Pi2/3. It expects to find
-+git clones of
++There are a few choices here
++ --mmal build including the legacy mmal-based decoders and zero-copy code
++ this requires appropriate libraries which currently will exist for
++ armv7 but not arm64
++ --noshared
++ Build a static image rather than a shared library one. Static is
++ easier for testing as there is no need to worry about library
++ paths being confused and therefore running the wrong code, Shared
++ is what is needed, in most cases, when building for use by other
++ programs.
++
++So for a static build
++---------------------
++
++$ pi-util/conf_native.sh --noshared
++
++$ make -j8 -C out/<wherever the script said it was building to>
++
++You can now run ffmpeg directly from where it was built
++
++For a shared build
++------------------
+
-+https://github.com/raspberrypi/tools
-+https://github.com/raspberrypi/firmware
++$ pi-util/conf_native.sh
+
-+in the parent of the FFmpeg directory. I recommend using --depth 1 to avoid a
-+lot of history you don't want.
++You will normally want an install target if shared. Note that the script has
++set this up to be generated in out/<builddir>/install, you don't have to worry
++about overwriting your system libs.
+
-+If you have a copy of qasm.py in ../local/bin then the .qasm sources will be
-+rebuilt. Otherwise the prebuilt .c & .h files will be used.
-+Likewise ../local/bin/vasmvidcore_std will enable VPU code rebuild
++$ make -j8 -C out/<builddir> install
+
-+pi-util/conf_p1.sh should configure for Pi1. Beware that as of this time
-+H265 QPU acceleration is broken on Pi1 and so it is disabled.
++You can now set LD_LIBRARY_PATH appropriately and run ffmpeg from where it was
++built or install the image on the system - you have to be careful to get rid
++of all other ffmpeg libs or confusion may result. There is a little script
++that wipes all other versions - obviously use with care!
++
++$ sudo pi-util/clean_usr_libs.sh
++
++Then simply copying from the install to /usr works
++
++$ sudo cp -r out/<builddir>/install/* /usr
+
+
--- /dev/null
@@ -59137,29 +66353,32 @@ Upstream-status: Pending
+
--- /dev/null
+++ b/pi-util/clean_usr_libs.sh
-@@ -0,0 +1,23 @@
+@@ -0,0 +1,26 @@
+set -e
+U=/usr/lib/arm-linux-gnueabihf
+rm -f $U/libavcodec.*
+rm -f $U/libavdevice.*
+rm -f $U/libavfilter.*
+rm -f $U/libavformat.*
-+rm -f $U/libavresample.*
+rm -f $U/libavutil.*
++rm -f $U/libswresample.*
++rm -f $U/libswscale.*
+U=/usr/lib/arm-linux-gnueabihf/neon/vfp
+rm -f $U/libavcodec.*
+rm -f $U/libavdevice.*
+rm -f $U/libavfilter.*
+rm -f $U/libavformat.*
-+rm -f $U/libavresample.*
+rm -f $U/libavutil.*
++rm -f $U/libswresample.*
++rm -f $U/libswscale.*
+U=/usr/lib/aarch64-linux-gnu
+rm -f $U/libavcodec.*
+rm -f $U/libavdevice.*
+rm -f $U/libavfilter.*
+rm -f $U/libavformat.*
-+rm -f $U/libavresample.*
+rm -f $U/libavutil.*
++rm -f $U/libswresample.*
++rm -f $U/libswscale.*
+
--- /dev/null
+++ b/pi-util/conf_arm64_native.sh
@@ -59706,57 +66925,90 @@ Upstream-status: Pending
+1,WPP_F_ericsson_MAIN_2,WPP_F_ericsson_MAIN_2.bit,WPP_F_ericsson_MAIN_2_yuv.md5
--- /dev/null
+++ b/pi-util/conf_native.sh
-@@ -0,0 +1,78 @@
+@@ -0,0 +1,106 @@
+echo "Configure for native build"
+
+FFSRC=`pwd`
-+MC=`uname -m`
++MC=`dpkg --print-architecture`
++BUILDBASE=$FFSRC/out
+
+#RPI_KEEPS="-save-temps=obj"
+RPI_KEEPS=""
+
-+if [ "$MC" == "aarch64" ]; then
++NOSHARED=
++MMAL=
++
++while [ "$1" != "" ] ; do
++ case $1 in
++ --noshared)
++ NOSHARED=1
++ ;;
++ --mmal)
++ MMAL=1
++ ;;
++ *)
++ echo "Usage $0: [--noshared] [--mmal]"
++ exit 1
++ ;;
++ esac
++ shift
++done
++
++
++MCOPTS=
++RPI_INCLUDES=
++RPI_LIBDIRS=
++RPI_DEFINES=
++RPI_EXTRALIBS=
++
++if [ "$MC" == "arm64" ]; then
+ echo "M/C aarch64"
+ A=aarch64-linux-gnu
+ B=arm64
-+ MCOPTS=
-+ RPI_INCLUDES=
-+ RPI_LIBDIRS=
-+ RPI_DEFINES=
-+ RPI_EXTRALIBS=
-+ RPIOPTS="--disable-mmal --enable-sand"
-+else
++elif [ "$MC" == "armhf" ]; then
+ echo "M/C armv7"
+ A=arm-linux-gnueabihf
+ B=armv7
+ MCOPTS="--arch=armv6t2 --cpu=cortex-a7"
++ RPI_DEFINES=-mfpu=neon-vfpv4
++else
++ echo Unexpected architecture $MC
++ exit 1
++fi
++
++if [ $MMAL ]; then
+ RPI_OPT_VC=/opt/vc
+ RPI_INCLUDES="-I$RPI_OPT_VC/include -I$RPI_OPT_VC/include/interface/vcos/pthreads -I$RPI_OPT_VC/include/interface/vmcs_host/linux"
+ RPI_LIBDIRS="-L$RPI_OPT_VC/lib"
-+ RPI_DEFINES="-D__VCCOREVER__=0x4000000 -mfpu=neon-vfpv4"
++ RPI_DEFINES="$RPI_DEFINES -D__VCCOREVER__=0x4000000"
+ RPI_EXTRALIBS="-Wl,--start-group -lbcm_host -lmmal -lmmal_util -lmmal_core -lvcos -lvcsm -lvchostif -lvchiq_arm -Wl,--end-group"
+ RPIOPTS="--enable-mmal --enable-rpi"
++else
++ RPIOPTS="--disable-mmal --enable-sand"
+fi
++
+C=`lsb_release -sc`
+V=`cat RELEASE`
+
+SHARED_LIBS="--enable-shared"
-+if [ "$1" == "--noshared" ]; then
++if [ $NOSHARED ]; then
+ SHARED_LIBS="--disable-shared"
-+ OUT=out/$B-$C-$V-static-rel
++ OUT=$BUILDBASE/$B-$C-$V-static-rel
+ echo Static libs
+else
+ echo Shared libs
-+ OUT=out/$B-$C-$V-shared-rel
++ OUT=$BUILDBASE/$B-$C-$V-shared-rel
+fi
+
-+USR_PREFIX=$FFSRC/$OUT/install
++USR_PREFIX=$OUT/install
+LIB_PREFIX=$USR_PREFIX/lib/$A
+INC_PREFIX=$USR_PREFIX/include/$A
+
+echo Destination directory: $OUT
-+mkdir -p $FFSRC/$OUT
-+cd $FFSRC/$OUT
++mkdir -p $OUT
++# Nothing under here need worry git - including this .gitignore!
++echo "**" > $BUILDBASE/.gitignore
++cd $OUT
+
+$FFSRC/configure \
+ --prefix=$USR_PREFIX\
@@ -59767,10 +67019,8 @@ Upstream-status: Pending
+ --disable-thumb\
+ --enable-v4l2-request\
+ --enable-libdrm\
-+ --enable-epoxy\
-+ --enable-libudev\
-+ --enable-vout-drm\
+ --enable-vout-egl\
++ --enable-vout-drm\
+ $SHARED_LIBS\
+ $RPIOPTS\
+ --extra-cflags="-ggdb $RPI_KEEPS $RPI_DEFINES $RPI_INCLUDES"\
@@ -59779,118 +67029,13 @@ Upstream-status: Pending
+ --extra-libs="$RPI_EXTRALIBS"\
+ --extra-version="rpi"
+
-+# --enable-decoder=hevc_rpi\
-+# --enable-extra-warnings\
-+# --arch=armv71\
-+
-+# gcc option for getting asm listing
-+# -Wa,-ahls
---- /dev/null
-+++ b/pi-util/conf_pi1.sh
-@@ -0,0 +1,39 @@
-+echo "Configure for Pi1"
-+
-+RPI_TOOLROOT=`pwd`/../tools/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf
-+RPI_OPT_VC=`pwd`/../firmware/hardfp/opt/vc
-+
-+RPI_INCLUDES="-I$RPI_OPT_VC/include -I$RPI_OPT_VC/include/interface/vcos/pthreads -I$RPI_OPT_VC/include/interface/vmcs_host/linux"
-+RPI_LIBDIRS="-L$RPI_TOOLROOT/lib -L$RPI_OPT_VC/lib"
-+#RPI_KEEPS="-save-temps=obj"
-+RPI_KEEPS=""
-+
-+SHARED_LIBS="--enable-shared"
-+if [ "$1" == "--noshared" ]; then
-+ SHARED_LIBS="--disable-shared"
-+ echo Static libs
-+else
-+ echo Shared libs
-+fi
-+
-+./configure --enable-cross-compile\
-+ --cpu=arm1176jzf-s\
-+ --arch=arm\
-+ --disable-neon\
-+ --target-os=linux\
-+ --disable-stripping\
-+ --enable-mmal\
-+ $SHARED_LIBS\
-+ --extra-cflags="-g $RPI_KEEPS $RPI_INCLUDES"\
-+ --extra-cxxflags="$RPI_INCLUDES"\
-+ --extra-ldflags="$RPI_LIBDIRS -Wl,-rpath=/opt/vc/lib,-rpath-link=$RPI_OPT_VC/lib,-rpath=/lib,-rpath=/usr/lib,-rpath-link=$RPI_TOOLROOT/lib,-rpath-link=$RPI_TOOLROOT/lib"\
-+ --extra-libs="-Wl,--start-group -lbcm_host -lmmal -lmmal_util -lmmal_core -lvcos -lvcsm -lvchostif -lvchiq_arm"\
-+ --cross-prefix=$RPI_TOOLROOT/bin/arm-linux-gnueabihf-
-+
-+
-+# --enable-extra-warnings\
-+# --arch=armv71\
-+# --enable-shared\
-+
-+# gcc option for getting asm listing
-+# -Wa,-ahls
---- /dev/null
-+++ b/pi-util/conf_pi2.sh
-@@ -0,0 +1,57 @@
-+echo "Configure for Pi2/3"
-+
-+FFSRC=`pwd`
-+
-+RPI_TOOLROOT=$FFSRC/../tools/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf
-+RPI_OPT_VC=$FFSRC/../firmware/hardfp/opt/vc
-+
-+RPI_INCLUDES="-I$RPI_OPT_VC/include -I$RPI_OPT_VC/include/interface/vcos/pthreads -I$RPI_OPT_VC/include/interface/vmcs_host/linux"
-+RPI_LIBDIRS="-L$RPI_TOOLROOT/lib -L$RPI_OPT_VC/lib"
-+RPI_DEFINES="-D__VCCOREVER__=0x4000000 -mfpu=neon-vfpv4"
-+#RPI_KEEPS="-save-temps=obj"
-+RPI_KEEPS=""
-+
-+SHARED_LIBS="--enable-shared"
-+if [ "$1" == "--noshared" ]; then
-+ SHARED_LIBS="--disable-shared"
-+ OUT=out/x-armv7-static-rel
-+ echo Static libs
-+else
-+ echo Shared libs
-+ OUT=out/x-armv7-shared-rel
-+fi
-+
-+USR_PREFIX=$FFSRC/$OUT/install
-+LIB_PREFIX=$USR_PREFIX/lib/arm-linux-gnueabihf
-+INC_PREFIX=$USR_PREFIX/include/arm-linux-gnueabihf
-+
-+mkdir -p $FFSRC/$OUT
-+cd $FFSRC/$OUT
-+
-+$FFSRC/configure --enable-cross-compile\
-+ --prefix=$USR_PREFIX\
-+ --libdir=$LIB_PREFIX\
-+ --incdir=$INC_PREFIX\
-+ --arch=armv6t2\
-+ --cpu=cortex-a7\
-+ --target-os=linux\
-+ --disable-stripping\
-+ --disable-thumb\
-+ --enable-mmal\
-+ --enable-rpi\
-+ $SHARED_LIBS\
-+ --extra-cflags="-ggdb $RPI_KEEPS $RPI_DEFINES $RPI_INCLUDES"\
-+ --extra-cxxflags="$RPI_DEFINES $RPI_INCLUDES"\
-+ --extra-ldflags="$RPI_LIBDIRS -Wl,-rpath=/opt/vc/lib,-rpath-link=$RPI_OPT_VC/lib,-rpath=/lib,-rpath=/usr/lib,-rpath-link=$RPI_TOOLROOT/lib,-rpath-link=$RPI_TOOLROOT/lib"\
-+ --extra-libs="-Wl,--start-group -lbcm_host -lmmal -lmmal_util -lmmal_core -lvcos -lvcsm -lvchostif -lvchiq_arm"\
-+ --cross-prefix=$RPI_TOOLROOT/bin/arm-linux-gnueabihf-
-+
-+# --enable-shared\
-+
-+# --enable-decoder=hevc_rpi\
-+# --enable-extra-warnings\
-+# --arch=armv71\
-+# --enable-shared\
+
+# gcc option for getting asm listing
+# -Wa,-ahls
--- /dev/null
+++ b/pi-util/ffconf.py
@@ -0,0 +1,215 @@
-+#!/usr/bin/env python
++#!/usr/bin/env python3
+
+import string
+import os
@@ -59967,16 +67112,16 @@ Upstream-status: Pending
+ pass
+
+ if m1 and m2 and m1.group() == m2.group():
-+ print >> flog, "Match: " + m1.group()
++ print("Match: " + m1.group(), file=flog)
+ rv = 0
+ elif not m1:
-+ print >> flog, "****** Cannot find m1"
++ print("****** Cannot find m1", file=flog)
+ rv = 3
+ elif not m2:
-+ print >> flog, "****** Cannot find m2"
++ print("****** Cannot find m2", file=flog)
+ rv = 2
+ else:
-+ print >> flog, "****** Mismatch: " + m1.group() + " != " + m2.group()
++ print("****** Mismatch: " + m1.group() + " != " + m2.group(), file=flog)
+ rv = 1
+ flog.close()
+ return rv
@@ -60022,7 +67167,7 @@ Upstream-status: Pending
+ exp_test = int(a[0])
+ if (exp_test and runtest(a[1], tests)):
+ name = a[1]
-+ print "==== ", name,
++ print ("==== ", name, end="")
+ sys.stdout.flush()
+
+ rv = testone(os.path.join(test_root, name), name, a[2], a[3], a[4], dectype=dectype, vcodec=vcodec, ffmpeg_exec=ffmpeg_exec)
@@ -60033,31 +67178,31 @@ Upstream-status: Pending
+
+ if (rv == 0):
+ if exp_test == 2:
-+ print ": * OK *"
++ print(": * OK *")
+ unx_success.append(name)
+ else:
-+ print ": ok"
++ print(": ok")
+ elif exp_test == 2 and rv == 1:
-+ print ": fail"
++ print(": fail")
+ elif exp_test == 3 and rv == 2:
+ # Call an expected "crash" an abort
-+ print ": abort"
++ print(": abort")
+ else:
+ unx_failures.append(name)
+ if rv == 1:
-+ print ": * FAIL *"
++ print(": * FAIL *")
+ elif (rv == 2) :
-+ print ": * CRASH *"
++ print(": * CRASH *")
+ elif (rv == 3) :
-+ print ": * MD5 MISSING *"
++ print(": * MD5 MISSING *")
+ else :
-+ print ": * BANG *"
++ print(": * BANG *")
+
+ if unx_failures or unx_success:
-+ print "Unexpected Failures:", unx_failures
-+ print "Unexpected Success: ", unx_success
++ print("Unexpected Failures:", unx_failures)
++ print("Unexpected Success: ", unx_success)
+ else:
-+ print "All tests normal:", successes, "ok,", failures, "failed"
++ print("All tests normal:", successes, "ok,", failures, "failed")
+
+
+class ConfCSVDialect(csv.Dialect):
@@ -60567,3 +67712,630 @@ Upstream-status: Pending
+
+ do_logparse(args.logfile)
+
+--- a/tests/checkasm/Makefile
++++ b/tests/checkasm/Makefile
+@@ -9,8 +9,10 @@ AVCODECOBJS-$(CONFIG_G722DSP)
+ AVCODECOBJS-$(CONFIG_H264DSP) += h264dsp.o
+ AVCODECOBJS-$(CONFIG_H264PRED) += h264pred.o
+ AVCODECOBJS-$(CONFIG_H264QPEL) += h264qpel.o
++AVCODECOBJS-$(CONFIG_IDCTDSP) += idctdsp.o
+ AVCODECOBJS-$(CONFIG_LLVIDDSP) += llviddsp.o
+ AVCODECOBJS-$(CONFIG_LLVIDENCDSP) += llviddspenc.o
++AVCODECOBJS-$(CONFIG_VC1DSP) += vc1dsp.o
+ AVCODECOBJS-$(CONFIG_VP8DSP) += vp8dsp.o
+ AVCODECOBJS-$(CONFIG_VIDEODSP) += videodsp.o
+
+--- a/tests/checkasm/checkasm.c
++++ b/tests/checkasm/checkasm.c
+@@ -121,6 +121,9 @@ static const struct {
+ #if CONFIG_HUFFYUV_DECODER
+ { "huffyuvdsp", checkasm_check_huffyuvdsp },
+ #endif
++ #if CONFIG_IDCTDSP
++ { "idctdsp", checkasm_check_idctdsp },
++ #endif
+ #if CONFIG_JPEG2000_DECODER
+ { "jpeg2000dsp", checkasm_check_jpeg2000dsp },
+ #endif
+@@ -145,6 +148,9 @@ static const struct {
+ #if CONFIG_V210_ENCODER
+ { "v210enc", checkasm_check_v210enc },
+ #endif
++ #if CONFIG_VC1DSP
++ { "vc1dsp", checkasm_check_vc1dsp },
++ #endif
+ #if CONFIG_VP8DSP
+ { "vp8dsp", checkasm_check_vp8dsp },
+ #endif
+--- a/tests/checkasm/checkasm.h
++++ b/tests/checkasm/checkasm.h
+@@ -60,6 +60,7 @@ void checkasm_check_hevc_add_res(void);
+ void checkasm_check_hevc_idct(void);
+ void checkasm_check_hevc_sao(void);
+ void checkasm_check_huffyuvdsp(void);
++void checkasm_check_idctdsp(void);
+ void checkasm_check_jpeg2000dsp(void);
+ void checkasm_check_llviddsp(void);
+ void checkasm_check_llviddspenc(void);
+@@ -73,6 +74,7 @@ void checkasm_check_sw_scale(void);
+ void checkasm_check_utvideodsp(void);
+ void checkasm_check_v210dec(void);
+ void checkasm_check_v210enc(void);
++void checkasm_check_vc1dsp(void);
+ void checkasm_check_vf_eq(void);
+ void checkasm_check_vf_gblur(void);
+ void checkasm_check_vf_hflip(void);
+--- /dev/null
++++ b/tests/checkasm/idctdsp.c
+@@ -0,0 +1,98 @@
++/*
++ * Copyright (c) 2022 Ben Avison
++ *
++ * This file is part of FFmpeg.
++ *
++ * FFmpeg is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * FFmpeg is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with FFmpeg; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#include <string.h>
++
++#include "checkasm.h"
++
++#include "libavcodec/idctdsp.h"
++
++#include "libavutil/common.h"
++#include "libavutil/internal.h"
++#include "libavutil/intreadwrite.h"
++#include "libavutil/mem_internal.h"
++
++#define IDCTDSP_TEST(func) { #func, offsetof(IDCTDSPContext, func) },
++
++typedef struct {
++ const char *name;
++ size_t offset;
++} test;
++
++#define RANDOMIZE_BUFFER16(name, size) \
++ do { \
++ int i; \
++ for (i = 0; i < size; ++i) { \
++ uint16_t r = rnd() % 0x201 - 0x100; \
++ AV_WN16A(name##0 + i, r); \
++ AV_WN16A(name##1 + i, r); \
++ } \
++ } while (0)
++
++#define RANDOMIZE_BUFFER8(name, size) \
++ do { \
++ int i; \
++ for (i = 0; i < size; ++i) { \
++ uint8_t r = rnd(); \
++ name##0[i] = r; \
++ name##1[i] = r; \
++ } \
++ } while (0)
++
++static void check_add_put_clamped(void)
++{
++ /* Source buffers are only as big as needed, since any over-read won't affect results */
++ LOCAL_ALIGNED_16(int16_t, src0, [64]);
++ LOCAL_ALIGNED_16(int16_t, src1, [64]);
++ /* Destination buffers have borders of one row above/below and 8 columns left/right to catch overflows */
++ LOCAL_ALIGNED_8(uint8_t, dst0, [10 * 24]);
++ LOCAL_ALIGNED_8(uint8_t, dst1, [10 * 24]);
++
++ AVCodecContext avctx = { 0 };
++ IDCTDSPContext h;
++
++ const test tests[] = {
++ IDCTDSP_TEST(add_pixels_clamped)
++ IDCTDSP_TEST(put_pixels_clamped)
++ IDCTDSP_TEST(put_signed_pixels_clamped)
++ };
++
++ ff_idctdsp_init(&h, &avctx);
++
++ for (size_t t = 0; t < FF_ARRAY_ELEMS(tests); ++t) {
++ void (*func)(const int16_t *, uint8_t * ptrdiff_t) = *(void **)((intptr_t) &h + tests[t].offset);
++ if (check_func(func, "idctdsp.%s", tests[t].name)) {
++ declare_func_emms(AV_CPU_FLAG_MMX, void, const int16_t *, uint8_t *, ptrdiff_t);
++ RANDOMIZE_BUFFER16(src, 64);
++ RANDOMIZE_BUFFER8(dst, 10 * 24);
++ call_ref(src0, dst0 + 24 + 8, 24);
++ call_new(src1, dst1 + 24 + 8, 24);
++ if (memcmp(dst0, dst1, 10 * 24))
++ fail();
++ bench_new(src1, dst1 + 24 + 8, 24);
++ }
++ }
++}
++
++void checkasm_check_idctdsp(void)
++{
++ check_add_put_clamped();
++ report("idctdsp");
++}
+--- /dev/null
++++ b/tests/checkasm/vc1dsp.c
+@@ -0,0 +1,452 @@
++/*
++ * Copyright (c) 2022 Ben Avison
++ *
++ * This file is part of FFmpeg.
++ *
++ * FFmpeg is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * FFmpeg is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with FFmpeg; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#include <string.h>
++
++#include "checkasm.h"
++
++#include "libavcodec/vc1dsp.h"
++
++#include "libavutil/common.h"
++#include "libavutil/internal.h"
++#include "libavutil/intreadwrite.h"
++#include "libavutil/mem_internal.h"
++
++#define VC1DSP_TEST(func) { #func, offsetof(VC1DSPContext, func) },
++#define VC1DSP_SIZED_TEST(func, width, height) { #func, offsetof(VC1DSPContext, func), width, height },
++
++typedef struct {
++ const char *name;
++ size_t offset;
++ int width;
++ int height;
++} test;
++
++typedef struct matrix {
++ size_t width;
++ size_t height;
++ float d[];
++} matrix;
++
++static const matrix T8 = { 8, 8, {
++ 12, 12, 12, 12, 12, 12, 12, 12,
++ 16, 15, 9, 4, -4, -9, -15, -16,
++ 16, 6, -6, -16, -16, -6, 6, 16,
++ 15, -4, -16, -9, 9, 16, 4, -15,
++ 12, -12, -12, 12, 12, -12, -12, 12,
++ 9, -16, 4, 15, -15, -4, 16, -9,
++ 6, -16, 16, -6, -6, 16, -16, 6,
++ 4, -9, 15, -16, 16, -15, 9, -4
++} };
++
++static const matrix T4 = { 4, 4, {
++ 17, 17, 17, 17,
++ 22, 10, -10, -22,
++ 17, -17, -17, 17,
++ 10, -22, 22, -10
++} };
++
++static const matrix T8t = { 8, 8, {
++ 12, 16, 16, 15, 12, 9, 6, 4,
++ 12, 15, 6, -4, -12, -16, -16, -9,
++ 12, 9, -6, -16, -12, 4, 16, 15,
++ 12, 4, -16, -9, 12, 15, -6, -16,
++ 12, -4, -16, 9, 12, -15, -6, 16,
++ 12, -9, -6, 16, -12, -4, 16, -15,
++ 12, -15, 6, 4, -12, 16, -16, 9,
++ 12, -16, 16, -15, 12, -9, 6, -4
++} };
++
++static const matrix T4t = { 4, 4, {
++ 17, 22, 17, 10,
++ 17, 10, -17, -22,
++ 17, -10, -17, 22,
++ 17, -22, 17, -10
++} };
++
++static matrix *new_matrix(size_t width, size_t height)
++{
++ matrix *out = av_mallocz(sizeof (matrix) + height * width * sizeof (float));
++ if (out == NULL) {
++ fprintf(stderr, "Memory allocation failure\n");
++ exit(EXIT_FAILURE);
++ }
++ out->width = width;
++ out->height = height;
++ return out;
++}
++
++static matrix *multiply(const matrix *a, const matrix *b)
++{
++ matrix *out;
++ if (a->width != b->height) {
++ fprintf(stderr, "Incompatible multiplication\n");
++ exit(EXIT_FAILURE);
++ }
++ out = new_matrix(b->width, a->height);
++ for (int j = 0; j < out->height; ++j)
++ for (int i = 0; i < out->width; ++i) {
++ float sum = 0;
++ for (int k = 0; k < a->width; ++k)
++ sum += a->d[j * a->width + k] * b->d[k * b->width + i];
++ out->d[j * out->width + i] = sum;
++ }
++ return out;
++}
++
++static void normalise(matrix *a)
++{
++ for (int j = 0; j < a->height; ++j)
++ for (int i = 0; i < a->width; ++i) {
++ float *p = a->d + j * a->width + i;
++ *p *= 64;
++ if (a->height == 4)
++ *p /= (const unsigned[]) { 289, 292, 289, 292 } [j];
++ else
++ *p /= (const unsigned[]) { 288, 289, 292, 289, 288, 289, 292, 289 } [j];
++ if (a->width == 4)
++ *p /= (const unsigned[]) { 289, 292, 289, 292 } [i];
++ else
++ *p /= (const unsigned[]) { 288, 289, 292, 289, 288, 289, 292, 289 } [i];
++ }
++}
++
++static void divide_and_round_nearest(matrix *a, float by)
++{
++ for (int j = 0; j < a->height; ++j)
++ for (int i = 0; i < a->width; ++i) {
++ float *p = a->d + j * a->width + i;
++ *p = rintf(*p / by);
++ }
++}
++
++static void tweak(matrix *a)
++{
++ for (int j = 4; j < a->height; ++j)
++ for (int i = 0; i < a->width; ++i) {
++ float *p = a->d + j * a->width + i;
++ *p += 1;
++ }
++}
++
++/* The VC-1 spec places restrictions on the values permitted at three
++ * different stages:
++ * - D: the input coefficients in frequency domain
++ * - E: the intermediate coefficients, inverse-transformed only horizontally
++ * - R: the fully inverse-transformed coefficients
++ *
++ * To fully cater for the ranges specified requires various intermediate
++ * values to be held to 17-bit precision; yet these conditions do not appear
++ * to be utilised in real-world streams. At least some assembly
++ * implementations have chosen to restrict these values to 16-bit precision,
++ * to accelerate the decoding of real-world streams at the cost of strict
++ * adherence to the spec. To avoid our test marking these as failures,
++ * reduce our random inputs.
++ */
++#define ATTENUATION 4
++
++static matrix *generate_inverse_quantized_transform_coefficients(size_t width, size_t height)
++{
++ matrix *raw, *tmp, *D, *E, *R;
++ raw = new_matrix(width, height);
++ for (int i = 0; i < width * height; ++i)
++ raw->d[i] = (int) (rnd() % (1024/ATTENUATION)) - 512/ATTENUATION;
++ tmp = multiply(height == 8 ? &T8 : &T4, raw);
++ D = multiply(tmp, width == 8 ? &T8t : &T4t);
++ normalise(D);
++ divide_and_round_nearest(D, 1);
++ for (int i = 0; i < width * height; ++i) {
++ if (D->d[i] < -2048/ATTENUATION || D->d[i] > 2048/ATTENUATION-1) {
++ /* Rare, so simply try again */
++ av_free(raw);
++ av_free(tmp);
++ av_free(D);
++ return generate_inverse_quantized_transform_coefficients(width, height);
++ }
++ }
++ E = multiply(D, width == 8 ? &T8 : &T4);
++ divide_and_round_nearest(E, 8);
++ for (int i = 0; i < width * height; ++i)
++ if (E->d[i] < -4096/ATTENUATION || E->d[i] > 4096/ATTENUATION-1) {
++ /* Rare, so simply try again */
++ av_free(raw);
++ av_free(tmp);
++ av_free(D);
++ av_free(E);
++ return generate_inverse_quantized_transform_coefficients(width, height);
++ }
++ R = multiply(height == 8 ? &T8t : &T4t, E);
++ tweak(R);
++ divide_and_round_nearest(R, 128);
++ for (int i = 0; i < width * height; ++i)
++ if (R->d[i] < -512/ATTENUATION || R->d[i] > 512/ATTENUATION-1) {
++ /* Rare, so simply try again */
++ av_free(raw);
++ av_free(tmp);
++ av_free(D);
++ av_free(E);
++ av_free(R);
++ return generate_inverse_quantized_transform_coefficients(width, height);
++ }
++ av_free(raw);
++ av_free(tmp);
++ av_free(E);
++ av_free(R);
++ return D;
++}
++
++#define RANDOMIZE_BUFFER16(name, size) \
++ do { \
++ int i; \
++ for (i = 0; i < size; ++i) { \
++ uint16_t r = rnd(); \
++ AV_WN16A(name##0 + i, r); \
++ AV_WN16A(name##1 + i, r); \
++ } \
++ } while (0)
++
++#define RANDOMIZE_BUFFER8(name, size) \
++ do { \
++ int i; \
++ for (i = 0; i < size; ++i) { \
++ uint8_t r = rnd(); \
++ name##0[i] = r; \
++ name##1[i] = r; \
++ } \
++ } while (0)
++
++#define RANDOMIZE_BUFFER8_MID_WEIGHTED(name, size) \
++ do { \
++ uint8_t *p##0 = name##0, *p##1 = name##1; \
++ int i = (size); \
++ while (i-- > 0) { \
++ int x = 0x80 | (rnd() & 0x7F); \
++ x >>= rnd() % 9; \
++ if (rnd() & 1) \
++ x = -x; \
++ *p##1++ = *p##0++ = 0x80 + x; \
++ } \
++ } while (0)
++
++static void check_inv_trans_inplace(void)
++{
++ /* Inverse transform input coefficients are stored in a 16-bit buffer
++ * with row stride of 8 coefficients irrespective of transform size.
++ * vc1_inv_trans_8x8 differs from the others in two ways: coefficients
++ * are stored in column-major order, and the outputs are written back
++ * to the input buffer, so we oversize it slightly to catch overruns. */
++ LOCAL_ALIGNED_16(int16_t, inv_trans_in0, [10 * 8]);
++ LOCAL_ALIGNED_16(int16_t, inv_trans_in1, [10 * 8]);
++
++ VC1DSPContext h;
++
++ ff_vc1dsp_init(&h);
++
++ if (check_func(h.vc1_inv_trans_8x8, "vc1dsp.vc1_inv_trans_8x8")) {
++ matrix *coeffs;
++ declare_func_emms(AV_CPU_FLAG_MMX, void, int16_t *);
++ RANDOMIZE_BUFFER16(inv_trans_in, 10 * 8);
++ coeffs = generate_inverse_quantized_transform_coefficients(8, 8);
++ for (int j = 0; j < 8; ++j)
++ for (int i = 0; i < 8; ++i) {
++ int idx = 8 + i * 8 + j;
++ inv_trans_in1[idx] = inv_trans_in0[idx] = coeffs->d[j * 8 + i];
++ }
++ call_ref(inv_trans_in0 + 8);
++ call_new(inv_trans_in1 + 8);
++ if (memcmp(inv_trans_in0, inv_trans_in1, 10 * 8 * sizeof (int16_t)))
++ fail();
++ bench_new(inv_trans_in1 + 8);
++ av_free(coeffs);
++ }
++}
++
++static void check_inv_trans_adding(void)
++{
++ /* Inverse transform input coefficients are stored in a 16-bit buffer
++ * with row stride of 8 coefficients irrespective of transform size. */
++ LOCAL_ALIGNED_16(int16_t, inv_trans_in0, [8 * 8]);
++ LOCAL_ALIGNED_16(int16_t, inv_trans_in1, [8 * 8]);
++
++ /* For all but vc1_inv_trans_8x8, the inverse transform is narrowed and
++ * added with saturation to an array of unsigned 8-bit values. Oversize
++ * this by 8 samples left and right and one row above and below. */
++ LOCAL_ALIGNED_8(uint8_t, inv_trans_out0, [10 * 24]);
++ LOCAL_ALIGNED_8(uint8_t, inv_trans_out1, [10 * 24]);
++
++ VC1DSPContext h;
++
++ const test tests[] = {
++ VC1DSP_SIZED_TEST(vc1_inv_trans_8x4, 8, 4)
++ VC1DSP_SIZED_TEST(vc1_inv_trans_4x8, 4, 8)
++ VC1DSP_SIZED_TEST(vc1_inv_trans_4x4, 4, 4)
++ VC1DSP_SIZED_TEST(vc1_inv_trans_8x8_dc, 8, 8)
++ VC1DSP_SIZED_TEST(vc1_inv_trans_8x4_dc, 8, 4)
++ VC1DSP_SIZED_TEST(vc1_inv_trans_4x8_dc, 4, 8)
++ VC1DSP_SIZED_TEST(vc1_inv_trans_4x4_dc, 4, 4)
++ };
++
++ ff_vc1dsp_init(&h);
++
++ for (size_t t = 0; t < FF_ARRAY_ELEMS(tests); ++t) {
++ void (*func)(uint8_t *, ptrdiff_t, int16_t *) = *(void **)((intptr_t) &h + tests[t].offset);
++ if (check_func(func, "vc1dsp.%s", tests[t].name)) {
++ matrix *coeffs;
++ declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *, ptrdiff_t, int16_t *);
++ RANDOMIZE_BUFFER16(inv_trans_in, 8 * 8);
++ RANDOMIZE_BUFFER8(inv_trans_out, 10 * 24);
++ coeffs = generate_inverse_quantized_transform_coefficients(tests[t].width, tests[t].height);
++ for (int j = 0; j < tests[t].height; ++j)
++ for (int i = 0; i < tests[t].width; ++i) {
++ int idx = j * 8 + i;
++ inv_trans_in1[idx] = inv_trans_in0[idx] = coeffs->d[j * tests[t].width + i];
++ }
++ call_ref(inv_trans_out0 + 24 + 8, 24, inv_trans_in0);
++ call_new(inv_trans_out1 + 24 + 8, 24, inv_trans_in1);
++ if (memcmp(inv_trans_out0, inv_trans_out1, 10 * 24))
++ fail();
++ bench_new(inv_trans_out1 + 24 + 8, 24, inv_trans_in1 + 8);
++ av_free(coeffs);
++ }
++ }
++}
++
++static void check_loop_filter(void)
++{
++ /* Deblocking filter buffers are big enough to hold a 16x16 block,
++ * plus 16 columns left and 4 rows above to hold filter inputs
++ * (depending on whether v or h neighbouring block edge, oversized
++ * horizontally to maintain 16-byte alignment) plus 16 columns and
++ * 4 rows below to catch write overflows */
++ LOCAL_ALIGNED_16(uint8_t, filter_buf0, [24 * 48]);
++ LOCAL_ALIGNED_16(uint8_t, filter_buf1, [24 * 48]);
++
++ VC1DSPContext h;
++
++ const test tests[] = {
++ VC1DSP_TEST(vc1_v_loop_filter4)
++ VC1DSP_TEST(vc1_h_loop_filter4)
++ VC1DSP_TEST(vc1_v_loop_filter8)
++ VC1DSP_TEST(vc1_h_loop_filter8)
++ VC1DSP_TEST(vc1_v_loop_filter16)
++ VC1DSP_TEST(vc1_h_loop_filter16)
++ };
++
++ ff_vc1dsp_init(&h);
++
++ for (size_t t = 0; t < FF_ARRAY_ELEMS(tests); ++t) {
++ void (*func)(uint8_t *, ptrdiff_t, int) = *(void **)((intptr_t) &h + tests[t].offset);
++ declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *, ptrdiff_t, int);
++ if (check_func(func, "vc1dsp.%s", tests[t].name)) {
++ for (int count = 1000; count > 0; --count) {
++ int pq = rnd() % 31 + 1;
++ RANDOMIZE_BUFFER8_MID_WEIGHTED(filter_buf, 24 * 48);
++ call_ref(filter_buf0 + 4 * 48 + 16, 48, pq);
++ call_new(filter_buf1 + 4 * 48 + 16, 48, pq);
++ if (memcmp(filter_buf0, filter_buf1, 24 * 48))
++ fail();
++ }
++ }
++ for (int j = 0; j < 24; ++j)
++ for (int i = 0; i < 48; ++i)
++ filter_buf1[j * 48 + i] = 0x60 + 0x40 * (i >= 16 && j >= 4);
++ if (check_func(func, "vc1dsp.%s_bestcase", tests[t].name))
++ bench_new(filter_buf1 + 4 * 48 + 16, 48, 1);
++ if (check_func(func, "vc1dsp.%s_worstcase", tests[t].name))
++ bench_new(filter_buf1 + 4 * 48 + 16, 48, 31);
++ }
++}
++
++#define TEST_UNESCAPE \
++ do { \
++ for (int count = 100; count > 0; --count) { \
++ escaped_offset = rnd() & 7; \
++ unescaped_offset = rnd() & 7; \
++ escaped_len = (1u << (rnd() % 8) + 3) - (rnd() & 7); \
++ RANDOMIZE_BUFFER8(unescaped, UNESCAPE_BUF_SIZE); \
++ len0 = call_ref(escaped0 + escaped_offset, escaped_len, unescaped0 + unescaped_offset); \
++ len1 = call_new(escaped1 + escaped_offset, escaped_len, unescaped1 + unescaped_offset); \
++ if (len0 != len1 || memcmp(unescaped0, unescaped1, UNESCAPE_BUF_SIZE)) \
++ fail(); \
++ } \
++ } while (0)
++
++static void check_unescape(void)
++{
++ /* This appears to be a typical length of buffer in use */
++#define LOG2_UNESCAPE_BUF_SIZE 17
++#define UNESCAPE_BUF_SIZE (1u<<LOG2_UNESCAPE_BUF_SIZE)
++ LOCAL_ALIGNED_8(uint8_t, escaped0, [UNESCAPE_BUF_SIZE]);
++ LOCAL_ALIGNED_8(uint8_t, escaped1, [UNESCAPE_BUF_SIZE]);
++ LOCAL_ALIGNED_8(uint8_t, unescaped0, [UNESCAPE_BUF_SIZE]);
++ LOCAL_ALIGNED_8(uint8_t, unescaped1, [UNESCAPE_BUF_SIZE]);
++
++ VC1DSPContext h;
++
++ ff_vc1dsp_init(&h);
++
++ if (check_func(h.vc1_unescape_buffer, "vc1dsp.vc1_unescape_buffer")) {
++ int len0, len1, escaped_offset, unescaped_offset, escaped_len;
++ declare_func_emms(AV_CPU_FLAG_MMX, int, const uint8_t *, int, uint8_t *);
++
++ /* Test data which consists of escapes sequences packed as tightly as possible */
++ for (int x = 0; x < UNESCAPE_BUF_SIZE; ++x)
++ escaped1[x] = escaped0[x] = 3 * (x % 3 == 0);
++ TEST_UNESCAPE;
++
++ /* Test random data */
++ RANDOMIZE_BUFFER8(escaped, UNESCAPE_BUF_SIZE);
++ TEST_UNESCAPE;
++
++ /* Test data with escape sequences at random intervals */
++ for (int x = 0; x <= UNESCAPE_BUF_SIZE - 4;) {
++ int gap, gap_msb;
++ escaped1[x+0] = escaped0[x+0] = 0;
++ escaped1[x+1] = escaped0[x+1] = 0;
++ escaped1[x+2] = escaped0[x+2] = 3;
++ escaped1[x+3] = escaped0[x+3] = rnd() & 3;
++ gap_msb = 2u << (rnd() % 8);
++ gap = (rnd() &~ -gap_msb) | gap_msb;
++ x += gap;
++ }
++ TEST_UNESCAPE;
++
++ /* Test data which is known to contain no escape sequences */
++ memset(escaped0, 0xFF, UNESCAPE_BUF_SIZE);
++ memset(escaped1, 0xFF, UNESCAPE_BUF_SIZE);
++ TEST_UNESCAPE;
++
++ /* Benchmark the no-escape-sequences case */
++ bench_new(escaped1, UNESCAPE_BUF_SIZE, unescaped1);
++ }
++}
++
++void checkasm_check_vc1dsp(void)
++{
++ check_inv_trans_inplace();
++ check_inv_trans_adding();
++ report("inv_trans");
++
++ check_loop_filter();
++ report("loop_filter");
++
++ check_unescape();
++ report("unescape_buffer");
++}
+--- a/tests/fate/checkasm.mak
++++ b/tests/fate/checkasm.mak
+@@ -16,6 +16,7 @@ FATE_CHECKASM = fate-checkasm-aacpsdsp
+ fate-checkasm-hevc_add_res \
+ fate-checkasm-hevc_idct \
+ fate-checkasm-hevc_sao \
++ fate-checkasm-idctdsp \
+ fate-checkasm-jpeg2000dsp \
+ fate-checkasm-llviddsp \
+ fate-checkasm-llviddspenc \
+@@ -27,6 +28,7 @@ FATE_CHECKASM = fate-checkasm-aacpsdsp
+ fate-checkasm-sw_scale \
+ fate-checkasm-v210dec \
+ fate-checkasm-v210enc \
++ fate-checkasm-vc1dsp \
+ fate-checkasm-vf_blend \
+ fate-checkasm-vf_colorspace \
+ fate-checkasm-vf_eq \
diff --git a/meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/0005-fix_flags.diff b/meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/0005-fix-flags.diff
index 1eb10749f1..ab6f139af6 100644
--- a/meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/0005-fix_flags.diff
+++ b/meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/0005-fix-flags.diff
@@ -1,8 +1,11 @@
-Upstream-status: Pending
+Upstream-Status: Inappropriate
+
+RPI-Distro repo clones original ffmpeg and applies patches to enable
+raspiberry pi support.
--- a/configure
+++ b/configure
-@@ -6467,11 +6467,9 @@ enabled mbedtls && { check_pkg
+@@ -6471,11 +6471,9 @@ enabled mbedtls && { check_pkg
die "ERROR: mbedTLS not found"; }
enabled mediacodec && { enabled jni || die "ERROR: mediacodec requires --enable-jni"; }
( enabled rpi ||
diff --git a/meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/2001-configure-setup-for-OE-core-usage.patch b/meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/2001-configure-setup-for-OE-core-usage.patch
new file mode 100644
index 0000000000..f1538275d2
--- /dev/null
+++ b/meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/2001-configure-setup-for-OE-core-usage.patch
@@ -0,0 +1,82 @@
+From 01e738a8f1414acd0102e432bbc15b4e603fd956 Mon Sep 17 00:00:00 2001
+From: Vincent Davis Jr <vince@underview.tech>
+Date: Thu, 8 Dec 2022 10:34:20 -0600
+Subject: [PATCH] configure: setup for OE-core usage
+
+Upstream-Status: Inappropriate
+
+RPI-Distro repo clones original ffmpeg and applies patches to enable
+raspiberry pi support.
+
+Add global CFLAGS and LDFLAGS. So, that when
+./configure runs test it's able to locate proper
+headers and libs in a cross-compile environment.
+
+Add new check to opengl. None of the above headers
+exists and we also should be using GLESv2.
+
+Update where compiler finds OMX_Core.h
+
+Only check that sdl2 version greater than 2.0.1
+
+Signed-off-by: Vincent Davis Jr <vince@underview.tech>
+---
+ configure | 16 +++++++++-------
+ 1 file changed, 9 insertions(+), 7 deletions(-)
+
+diff --git a/configure b/configure
+index 723b81f1..0c7f2654 100755
+--- a/configure
++++ b/configure
+@@ -5746,6 +5746,9 @@ enable_weak_pic() {
+ }
+
+ enabled pic && enable_weak_pic
++# Set CFLAGS and LDFLAGS globally
++add_cflags -I${sysroot}/usr/include/ -I${sysroot}/usr/include/IL -I${sysroot}/usr/include/drm
++add_ldflags -L${sysroot}/usr/lib/
+
+ test_cc <<EOF || die "Symbol mangling check failed."
+ int ff_extern;
+@@ -6471,8 +6474,7 @@ enabled mbedtls && { check_pkg_config mbedtls mbedtls mbedtls/x509_crt
+ die "ERROR: mbedTLS not found"; }
+ enabled mediacodec && { enabled jni || die "ERROR: mediacodec requires --enable-jni"; }
+ ( enabled rpi ||
+- enabled mmal ) && { { add_cflags -isystem/opt/vc/include/ -isystem/opt/vc/include/interface/vmcs_host/linux -isystem/opt/vc/include/interface/vcos/pthreads -fgnu89-inline &&
+- add_ldflags -L/opt/vc/lib/ &&
++ enabled mmal ) && { { add_cflags -I${sysroot}/usr/include/interface/vmcs_host/linux -I${sysroot}/usr/include/interface/vcos/pthreads -fgnu89-inline &&
+ check_lib mmal interface/mmal/mmal.h mmal_port_connect -lmmal_core -lmmal_util -lmmal_vc_client -lbcm_host -lvcsm -lvchostif -lvchiq_arm -lvcos; } ||
+ die "ERROR: mmal not found" &&
+ check_func_headers interface/mmal/mmal.h "MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS"; }
+@@ -6492,15 +6494,15 @@ enabled opengl && { check_lib opengl GL/glx.h glXGetProcAddress "-lGL
+ check_lib opengl windows.h wglGetProcAddress "-lopengl32 -lgdi32" ||
+ check_lib opengl OpenGL/gl3.h glGetError "-Wl,-framework,OpenGL" ||
+ check_lib opengl ES2/gl.h glGetError "-isysroot=${sysroot} -Wl,-framework,OpenGLES" ||
++ check_lib opengl GLES2/gl2.h glGetError "-lGLESv2" ||
+ die "ERROR: opengl not found."
+ }
+-enabled omx_rpi && { test_code cc OMX_Core.h OMX_IndexConfigBrcmVideoRequestIFrame ||
++enabled omx_rpi && { test_code cc IL/OMX_Core.h OMX_IndexConfigBrcmVideoRequestIFrame ||
+ { ! enabled cross_compile &&
+- add_cflags -isystem/opt/vc/include/IL &&
+- test_code cc OMX_Core.h OMX_IndexConfigBrcmVideoRequestIFrame; } ||
++ test_code cc IL/OMX_Core.h OMX_IndexConfigBrcmVideoRequestIFrame; } ||
+ die "ERROR: OpenMAX IL headers from raspberrypi/firmware not found"; } &&
+ enable omx
+-enabled omx && require_headers OMX_Core.h
++enabled omx && require_headers IL/OMX_Core.h
+ enabled openssl && { check_pkg_config openssl openssl openssl/ssl.h OPENSSL_init_ssl ||
+ check_pkg_config openssl openssl openssl/ssl.h SSL_library_init ||
+ check_lib openssl openssl/ssl.h OPENSSL_init_ssl -lssl -lcrypto ||
+@@ -6540,7 +6542,7 @@ fi
+
+ if enabled sdl2; then
+ SDL2_CONFIG="${cross_prefix}sdl2-config"
+- test_pkg_config sdl2 "sdl2 >= 2.0.1 sdl2 < 2.1.0" SDL_events.h SDL_PollEvent
++ test_pkg_config sdl2 "sdl2 >= 2.0.1" SDL_events.h SDL_PollEvent
+ if disabled sdl2 && "${SDL2_CONFIG}" --version > /dev/null 2>&1; then
+ sdl2_cflags=$("${SDL2_CONFIG}" --cflags)
+ sdl2_extralibs=$("${SDL2_CONFIG}" --libs)
+--
+2.38.1
+
diff --git a/meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/2002-libavdevice-opengl_enc-update-dynamic-function-loader.patch b/meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/2002-libavdevice-opengl_enc-update-dynamic-function-loader.patch
new file mode 100644
index 0000000000..43a9191885
--- /dev/null
+++ b/meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/2002-libavdevice-opengl_enc-update-dynamic-function-loader.patch
@@ -0,0 +1,111 @@
+From be426ad76c3e486f1364dd292cf8e1c633c80e91 Mon Sep 17 00:00:00 2001
+From: Vincent Davis Jr <vince@underview.tech>
+Date: Thu, 8 Dec 2022 10:39:47 -0600
+Subject: [PATCH] libavdevice: opengl_enc.c update dynamic function loader
+
+Upstream-Status: Inappropriate
+
+RPI-Distro repo clones original ffmpeg and applies patches to enable
+raspiberry pi support.
+
+For meta-raspberrypi ffmpeg builds, when opengl
+is enabled do_compile will fail. Reasion is that
+glGetProcAddress is undefined in either GLES2/gl2.h
+or GLES2/gl2ext.h.
+
+define SelectedGetProcAddress to SDL_GL_GetProcAddress
+if sdl2 is included. If not included, define function
+pointers at compile time versus runtime.
+
+Signed-off-by: Vincent Davis Jr <vince@underview.tech>
+---
+ libavdevice/opengl_enc.c | 44 ++++++++++++++++++++++++++++++++++++----
+ 1 file changed, 40 insertions(+), 4 deletions(-)
+
+diff --git a/libavdevice/opengl_enc.c b/libavdevice/opengl_enc.c
+index 2bdb8da7..eabc1bf8 100644
+--- a/libavdevice/opengl_enc.c
++++ b/libavdevice/opengl_enc.c
+@@ -37,12 +37,13 @@
+ #include <OpenGL/gl3.h>
+ #elif HAVE_ES2_GL_H
+ #include <ES2/gl.h>
+-#else
+-#include <GL/gl.h>
+-#include <GL/glext.h>
+ #endif
+ #if HAVE_GLXGETPROCADDRESS
+ #include <GL/glx.h>
++#else
++#define GL_GLEXT_PROTOTYPES
++#include <GLES2/gl2.h>
++#include <GLES2/gl2ext.h>
+ #endif
+
+ #if CONFIG_SDL2
+@@ -493,8 +494,14 @@ static int av_cold opengl_load_procedures(OpenGLContext *opengl)
+
+ #if HAVE_GLXGETPROCADDRESS
+ #define SelectedGetProcAddress glXGetProcAddress
++#define CAN_DYNAMIC_LOAD 1
+ #elif HAVE_WGLGETPROCADDRESS
+ #define SelectedGetProcAddress wglGetProcAddress
++#elif CONFIG_SDL2
++#define SelectedGetProcAddress SDL_GL_GetProcAddress
++#define CAN_DYNAMIC_LOAD 1
++#else
++#define CAN_DYNAMIC_LOAD 0
+ #endif
+
+ #define LOAD_OPENGL_FUN(name, type) \
+@@ -504,7 +511,8 @@ static int av_cold opengl_load_procedures(OpenGLContext *opengl)
+ return AVERROR(ENOSYS); \
+ }
+
+-#if CONFIG_SDL2
++#if CAN_DYNAMIC_LOAD
++#if CONFIG_SDL2
+ if (!opengl->no_window)
+ return opengl_sdl_load_procedures(opengl);
+ #endif
+@@ -534,9 +542,37 @@ static int av_cold opengl_load_procedures(OpenGLContext *opengl)
+ LOAD_OPENGL_FUN(glGetShaderInfoLog, FF_PFNGLGETSHADERINFOLOGPROC)
+ LOAD_OPENGL_FUN(glEnableVertexAttribArray, FF_PFNGLENABLEVERTEXATTRIBARRAYPROC)
+ LOAD_OPENGL_FUN(glVertexAttribPointer, FF_PFNGLVERTEXATTRIBPOINTERPROC)
++#else
++ procs->glActiveTexture = glActiveTexture;
++ procs->glGenBuffers = glGenBuffers;
++ procs->glDeleteBuffers = glDeleteBuffers;
++ procs->glBufferData = glBufferData;
++ procs->glBindBuffer = glBindBuffer;
++ procs->glGetAttribLocation = glGetAttribLocation;
++ procs->glGetUniformLocation = glGetUniformLocation;
++ procs->glUniform1f = glUniform1f;
++ procs->glUniform1i = glUniform1i;
++ procs->glUniformMatrix4fv = glUniformMatrix4fv;
++ procs->glCreateProgram = glCreateProgram;
++ procs->glDeleteProgram = glDeleteProgram;
++ procs->glUseProgram = glUseProgram;
++ procs->glLinkProgram = glLinkProgram;
++ procs->glGetProgramiv = glGetProgramiv;
++ procs->glGetProgramInfoLog = glGetProgramInfoLog;
++ procs->glAttachShader = glAttachShader;
++ procs->glCreateShader = glCreateShader;
++ procs->glDeleteShader = glDeleteShader;
++ procs->glCompileShader = glCompileShader;
++ procs->glShaderSource = glShaderSource;
++ procs->glGetShaderiv = glGetShaderiv;
++ procs->glGetShaderInfoLog = glGetShaderInfoLog;
++ procs->glEnableVertexAttribArray = glEnableVertexAttribArray;
++ procs->glVertexAttribPointer = (FF_PFNGLVERTEXATTRIBPOINTERPROC) glVertexAttribPointer;
++#endif
+
+ return 0;
+
++#undef CAN_DYNAMIC_LOAD
+ #undef SelectedGetProcAddress
+ #undef LOAD_OPENGL_FUN
+ }
+--
+2.38.1
+
diff --git a/meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/2003-libavcodec-fix-v4l2_req_devscan.patch b/meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/2003-libavcodec-fix-v4l2_req_devscan.patch
new file mode 100644
index 0000000000..2232c48308
--- /dev/null
+++ b/meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/2003-libavcodec-fix-v4l2_req_devscan.patch
@@ -0,0 +1,45 @@
+From 62c2f041890a6e20770350721a0a2138d0b38634 Mon Sep 17 00:00:00 2001
+From: Vincent Davis Jr <vince@underview.tech>
+Date: Sat, 3 Dec 2022 23:35:51 -0600
+Subject: [PATCH] libavcodec: fix v4l2_req_devscan.h
+
+Upstream-Status: Inappropriate
+
+RPI-Distro repo clones original ffmpeg and applies patches to enable
+raspiberry pi support.
+
+Fixes minor differences between v4l2_req_devscan.c
+and v4l2_req_devscan.h after all patches have been
+applied.
+
+Signed-off-by: Vincent Davis Jr <vince@underview.tech>
+---
+ libavcodec/v4l2_req_devscan.h | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/libavcodec/v4l2_req_devscan.h b/libavcodec/v4l2_req_devscan.h
+index 0baef365..cd9c49ac 100644
+--- a/libavcodec/v4l2_req_devscan.h
++++ b/libavcodec/v4l2_req_devscan.h
+@@ -1,6 +1,8 @@
+ #ifndef _DEVSCAN_H_
+ #define _DEVSCAN_H_
+
++#include <stdint.h>
++
+ struct devscan;
+ struct decdev;
+ enum v4l2_buf_type;
+@@ -13,7 +15,8 @@ const char *decdev_video_path(const struct decdev *const dev);
+ enum v4l2_buf_type decdev_src_type(const struct decdev *const dev);
+ uint32_t decdev_src_pixelformat(const struct decdev *const dev);
+
+-const struct decdev *devscan_find(struct devscan *const scan, const uint32_t src_fmt_v4l2);
++const struct decdev *devscan_find(struct devscan *const scan,
++ const uint32_t src_fmt_v4l2);
+
+ int devscan_build(void * const dc, struct devscan **pscan);
+ void devscan_delete(struct devscan **const pScan);
+--
+2.38.1
+
diff --git a/meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/2004-libavcodec-omx-replace-opt-vc-path-with-usr-lib.patch b/meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/2004-libavcodec-omx-replace-opt-vc-path-with-usr-lib.patch
new file mode 100644
index 0000000000..02c07de2cc
--- /dev/null
+++ b/meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/files/2004-libavcodec-omx-replace-opt-vc-path-with-usr-lib.patch
@@ -0,0 +1,35 @@
+From 0dfb56e12fa709794525cda1471091f6699905d5 Mon Sep 17 00:00:00 2001
+From: Vincent Davis Jr <vince@underview.tech>
+Date: Thu, 8 Dec 2022 10:49:03 -0600
+Subject: [PATCH] libavcodec: omx replace /opt/vc path with /usr/lib
+
+Upstream-Status: Inappropriate
+
+RPI-Distro repo clones original ffmpeg and applies patches to enable
+raspiberry pi support.
+
+Configures omx.c for OE usages as libbcm_host.so
+and libopenmaxil.so are located in a different
+location.
+
+Signed-off-by: Vincent Davis Jr <vince@underview.tech>
+---
+ libavcodec/omx.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/libavcodec/omx.c b/libavcodec/omx.c
+index 0a6a3083..8c6e9193 100644
+--- a/libavcodec/omx.c
++++ b/libavcodec/omx.c
+@@ -141,7 +141,7 @@ static av_cold OMXContext *omx_init(void *logctx, const char *libname, const cha
+ {
+ static const char * const libnames[] = {
+ #if CONFIG_OMX_RPI
+- "/opt/vc/lib/libopenmaxil.so", "/opt/vc/lib/libbcm_host.so",
++ "/usr/lib/libopenmaxil.so", "/usr/lib/libbcm_host.so",
+ #else
+ "libOMX_Core.so", NULL,
+ "libOmxCore.so", NULL,
+--
+2.38.1
+
diff --git a/meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/rpidistro-ffmpeg_4.3.2.bb b/meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/rpidistro-ffmpeg_4.3.4.bb
index bf8d4b824c..30e7c575e3 100644
--- a/meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/rpidistro-ffmpeg_4.3.2.bb
+++ b/meta-raspberrypi/recipes-multimedia/rpidistro-ffmpeg/rpidistro-ffmpeg_4.3.4.bb
@@ -33,23 +33,27 @@ RPROVIDES:${PN} = "${PROVIDES}"
DEPENDS = "nasm-native"
inherit autotools pkgconfig
-PACKAGECONFIG ??= "avdevice avfilter avcodec avformat swresample swscale postproc avresample \
- opengl udev sdl2 ffplay alsa bzlib lzma pic pthreads shared theora zlib \
- libvorbis x264 gpl sand rpi vout-drm vout-egl \
- ${@bb.utils.contains('MACHINE_FEATURES', 'vc4graphics', '', 'mmal', d)} \
+PACKAGECONFIG ??= "avdevice avfilter avcodec avformat swresample swscale postproc avresample ffplay \
+ v4l2 drm udev alsa bzlib lzma pic pthreads shared theora zlib libvorbis x264 gpl \
+ ${@bb.utils.contains('MACHINE_FEATURES', 'vc4graphics', '', 'mmal rpi sand vout-drm', d)} \
${@bb.utils.contains('AVAILTUNES', 'mips32r2', 'mips32r2', '', d)} \
- ${@bb.utils.contains('DISTRO_FEATURES', 'x11', 'xv xcb', '', d)}"
+ ${@bb.utils.contains('DISTRO_FEATURES', 'opengl', 'opengl', '', d)} \
+ ${@bb.utils.contains('DISTRO_FEATURES', 'x11', 'xv xcb vout-egl epoxy', '', d)}"
SRC_URI = "\
git://git@github.com/RPi-Distro/ffmpeg;protocol=https;branch=pios/bullseye \
file://0001-avcodec-arm-sbcenc-avoid-callee-preserved-vfp-regist.patch \
file://0002-Fix-build-on-powerpc-and-ppc64.patch \
file://0003-avcodec-pngenc-remove-monowhite-from-apng-formats.patch \
- file://0004-ffmpeg-4.3.2-rpi_10.patch \
- file://0005-fix_flags.diff \
-"
+ file://0004-ffmpeg-4.3.4-rpi_14.patch \
+ file://0005-fix-flags.diff \
+ file://2001-configure-setup-for-OE-core-usage.patch \
+ file://2002-libavdevice-opengl_enc-update-dynamic-function-loader.patch \
+ file://2003-libavcodec-fix-v4l2_req_devscan.patch \
+ file://2004-libavcodec-omx-replace-opt-vc-path-with-usr-lib.patch \
+ "
-SRCREV = "ea72093f350f38edcd39c480b331c3219c377642"
+SRCREV = "246e1a55a0eca931537d8706acd8b133c07beb05"
S = "${WORKDIR}/git"
@@ -70,7 +74,7 @@ PACKAGECONFIG[altivec] = "--enable-altivec,--disable-altivec,"
PACKAGECONFIG[bzlib] = "--enable-bzlib,--disable-bzlib,bzip2"
PACKAGECONFIG[fdk-aac] = "--enable-libfdk-aac --enable-nonfree,--disable-libfdk-aac,fdk-aac"
PACKAGECONFIG[gpl] = "--enable-gpl,--disable-gpl"
-PACKAGECONFIG[opengl] = "--enable-opengl,--disable-opengl,virtual/libgl"
+PACKAGECONFIG[opengl] = "--enable-opengl,--disable-opengl,virtual/libgles2"
PACKAGECONFIG[gsm] = "--enable-libgsm,--disable-libgsm,libgsm"
PACKAGECONFIG[jack] = "--enable-indev=jack,--disable-indev=jack,jack"
PACKAGECONFIG[libvorbis] = "--enable-libvorbis,--disable-libvorbis,libvorbis"
@@ -90,9 +94,11 @@ PACKAGECONFIG[x264] = "--enable-libx264,--disable-libx264,x264"
PACKAGECONFIG[xcb] = "--enable-libxcb,--disable-libxcb,libxcb"
PACKAGECONFIG[xv] = "--enable-outdev=xv,--disable-outdev=xv,libxv"
PACKAGECONFIG[zlib] = "--enable-zlib,--disable-zlib,zlib"
-#PACKAGECONFIG[snappy] = "--enable-libsnappy,--enable-libsnappy,snappy"
+PACKAGECONFIG[snappy] = "--enable-libsnappy,--disable-libsnappy,snappy"
PACKAGECONFIG[udev] = "--enable-libudev,--disable-libudev,udev"
-PACKAGECONFIG[v4l2] = "--enable-libv4l2 --enable-v4l2-request --enable-libdrm,,v4l-utils"
+PACKAGECONFIG[drm] = "--enable-libdrm,--disable-libdrm,libdrm"
+PACKAGECONFIG[epoxy] = "--enable-epoxy,--disable-epoxy,libepoxy"
+PACKAGECONFIG[v4l2] = "--enable-libv4l2 --enable-v4l2-m2m,,v4l-utils"
PACKAGECONFIG[mmal] = "--enable-omx --enable-omx-rpi --enable-mmal,,userland"
PACKAGECONFIG[sand] = "--enable-sand,,"
PACKAGECONFIG[rpi] = "--enable-rpi,,"
@@ -138,11 +144,6 @@ EXTRA_OECONF = " \
"
EXTRA_OECONF:append:linux-gnux32 = " --disable-asm"
-# Directly specify the include directories the contain headers for
-# libdrm
-# openmaxil
-TARGET_CFLAGS:append = " -I${STAGING_INCDIR}/IL -I${STAGING_INCDIR}/drm"
-
# gold crashes on x86, another solution is to --disable-asm but thats more hacky
# ld.gold: internal error in relocate_section, at ../../gold/i386.cc:3684
LDFLAGS:append:x86 = "${@bb.utils.contains('DISTRO_FEATURES', 'ld-is-gold', ' -fuse-ld=bfd ', '', d)}"
@@ -190,5 +191,5 @@ INSANE_SKIP:${MLPREFIX}libpostproc = "textrel"
# Only enable it for rpi class of machines
COMPATIBLE_HOST = "null"
-COMPATIBLE_HOST:rpi = "'(.*)'"
+COMPATIBLE_HOST:rpi = "(.*)"