summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorboogie2023-01-30 11:14:13 +0100
committerboogie2023-01-30 11:14:13 +0100
commitf4cc880714a8be1012e22dfcfbbc4d28ed127b86 (patch)
tree3a1e081c2b05e65e7b3099113bf3253c1e205c51
downloadaur-f4cc880714a8be1012e22dfcfbbc4d28ed127b86.tar.gz
initial
-rw-r--r--.SRCINFO183
-rw-r--r--0001-ffmpeg-buildsys.patch25
-rw-r--r--0002-rkmpp-4.patch2771
-rw-r--r--0003-ffmpegdirect-buildsys.patch12
-rw-r--r--PKGBUILD322
5 files changed, 3313 insertions, 0 deletions
diff --git a/.SRCINFO b/.SRCINFO
new file mode 100644
index 000000000000..dce669eb3cc4
--- /dev/null
+++ b/.SRCINFO
@@ -0,0 +1,183 @@
+pkgbase = kodi-nexus-mpp-git
+ pkgver = r62294.e75ba45eef3.457d9a5
+ pkgrel = 2
+ url = https://kodi.tv
+ arch = aarch64
+ arch = arm7f
+ license = GPL2
+ makedepends = afpfs-ng
+ makedepends = bluez-libs
+ makedepends = cmake
+ makedepends = curl
+ makedepends = dav1d
+ makedepends = doxygen
+ makedepends = git
+ makedepends = glew
+ makedepends = gperf
+ makedepends = hicolor-icon-theme
+ makedepends = java-runtime
+ makedepends = libaacs
+ makedepends = libass
+ makedepends = libbluray
+ makedepends = libcdio
+ makedepends = libcec
+ makedepends = libgl
+ makedepends = mariadb-libs
+ makedepends = libmicrohttpd
+ makedepends = libmodplug
+ makedepends = libmpeg2
+ makedepends = libnfs
+ makedepends = libplist
+ makedepends = libpulse
+ makedepends = libva
+ makedepends = libva-vdpau-driver
+ makedepends = libxrandr
+ makedepends = libxslt
+ makedepends = lirc
+ makedepends = lzo
+ makedepends = mesa
+ makedepends = nasm
+ makedepends = python-pycryptodomex
+ makedepends = python-pillow
+ makedepends = python-pybluez
+ makedepends = python-simplejson
+ makedepends = shairplay
+ makedepends = smbclient
+ makedepends = taglib
+ makedepends = tinyxml
+ makedepends = swig
+ makedepends = upower
+ makedepends = giflib
+ makedepends = ghostscript
+ makedepends = meson
+ makedepends = gtest
+ makedepends = graphviz
+ makedepends = wayland-protocols
+ makedepends = waylandpp
+ makedepends = libxkbcommon
+ makedepends = libinput
+ makedepends = mpp-git
+ noextract = libdvdcss-1.4.3-Next-Nexus-Alpha2-2.tar.gz
+ noextract = libdvdnav-6.1.1-Next-Nexus-Alpha2-2.tar.gz
+ noextract = libdvdread-6.1.3-Next-Nexus-Alpha2-2.tar.gz
+ noextract = ffmpeg-4.4.1-Nexus-Alpha1.tar.gz
+ noextract = fmt-9.1.0.tar.gz
+ noextract = spdlog-1.10.0.tar.gz
+ noextract = crossguid-ca1bf4b810e2d188d04cb6286f957008ee1b7681.tar.gz
+ noextract = fstrcmp-0.7.D001.tar.gz
+ noextract = flatbuffers-2.0.0.tar.gz
+ noextract = libudfread-1.1.2.tar.gz
+ options = !lto
+ options = debug
+ options = strip
+ source = git+https://github.com/xbmc/xbmc.git#branch=Nexus
+ source = git+https://github.com/xbmc/inputstream.ffmpegdirect.git#branch=Nexus
+ source = libdvdcss-1.4.3-Next-Nexus-Alpha2-2.tar.gz::https://github.com/xbmc/libdvdcss/archive/1.4.3-Next-Nexus-Alpha2-2.tar.gz
+ source = libdvdnav-6.1.1-Next-Nexus-Alpha2-2.tar.gz::https://github.com/xbmc/libdvdnav/archive/6.1.1-Next-Nexus-Alpha2-2.tar.gz
+ source = libdvdread-6.1.3-Next-Nexus-Alpha2-2.tar.gz::https://github.com/xbmc/libdvdread/archive/6.1.3-Next-Nexus-Alpha2-2.tar.gz
+ source = ffmpeg-4.4.1-Nexus-Alpha1.tar.gz::https://github.com/xbmc/FFmpeg/archive/4.4.1-Nexus-Alpha1.tar.gz
+ source = https://mirrors.kodi.tv/build-deps/sources/fmt-9.1.0.tar.gz
+ source = https://mirrors.kodi.tv/build-deps/sources/spdlog-1.10.0.tar.gz
+ source = https://mirrors.kodi.tv/build-deps/sources/crossguid-ca1bf4b810e2d188d04cb6286f957008ee1b7681.tar.gz
+ source = https://mirrors.kodi.tv/build-deps/sources/fstrcmp-0.7.D001.tar.gz
+ source = https://mirrors.kodi.tv/build-deps/sources/flatbuffers-2.0.0.tar.gz
+ source = https://mirrors.kodi.tv/build-deps/sources/libudfread-1.1.2.tar.gz
+ source = 0001-ffmpeg-buildsys.patch
+ source = 0002-rkmpp-4.patch
+ source = 0003-ffmpegdirect-buildsys.patch
+ b2sums = SKIP
+ b2sums = SKIP
+ b2sums = 2f503d3ab767094958f7ec10b4ad11ffd02665deee571c8f3c739bef5fc7e2ff84babc5a3fdee638dc095f896b72fe3ce65e6b688674cb5f7b7b77190992688c
+ b2sums = db4d05836d8fbb3637ae50bdbfc0e4b612ee6b3be24addfea94ce772c3bf28d58b63a3f252d6f9f016f72f8cbb841cc1820b091226b136f4c4664385a32da73c
+ b2sums = c94feb5a03a12efa5b7767965118d2500a088299ea36f3b82e46d157e45893e6b04503cb50f179ca681bac914457607fab26acfa6e304752b355c407578572d1
+ b2sums = 51d310e7000aeba657d55341c5fdb540474e197b85062228ab4b314c8309ec11985aa7f105193333fc6106529e8e58c86eafe268190894be8532d0e0b9065fa6
+ b2sums = ff1daa43140615b63aeb1ecd0aa1c32d24decfd5006805080293ef3db04d544c0445a30e8da0d985a6f5a25ad48ce4f6ae61e52da5ea4a4d3b031c212da38b18
+ b2sums = e40afa9fd1dd791e1f703392f0f54fc798ed70537a9f1ee9c8598dd449f4cd4dd03bc4ce95e416cbbe224711a17e70708a106f0432384542d6316cf232cf8757
+ b2sums = 0f78a8ab5a420297f666b3b8156d499a9141ec25c049d4d2bb2ba594dc585abe211a149b83c605cce4f5530207231a065d5f3a87a0c969781de8c6381afa2527
+ b2sums = a8b68fcb8613f0d30e5ff7b862b37408472162585ca71cdff328e3299ff50476fd265467bbd77b352b22bb88c590969044f74d91c5468475504568fd269fa69e
+ b2sums = ccd827a43da39cf831727b439beed0cea216cdf50dbfe70954854bbe388b2c47ed4e78cc87e3fc0d5568034b13baa2ea96480914cc8129747bccbf8ea928847c
+ b2sums = 1801d84a0ca38410a78f23e7d44f37e6d53346753c853df2e7380d259ce1ae7f0c712825b95a5753ad0bc6360cfffe1888b9e7bc30da8b84549e0f1198248f61
+ b2sums = a4c52a1efe8957c2d941a47caeb1b3ec86741d902ae2c58eff4aaba369475e72257bf63c43a1b5f55fc8d07bb2d0c5ea0b7717a028278eae6a34f5a91eb5047f
+ b2sums = 1a818e38b6f763d60ce50e4b0a5d26c86f833dd26dbcee352579d8395e6382b06ee816dad7938e3ea12a1e676251417ef4c090c21dca45f7decfba81694d3a2b
+ b2sums = 943d358b4c127b77a691886a48245604081e3fdb5f05cd9a9821b52acf46bc6736089348f3299e00f35bbc09ba501d136088d96c7f118b3f5f3fe1cb7d77c7fd
+
+pkgname = kodi-nexus-mpp-git
+ pkgdesc = A software media player and entertainment hub for digital media (Nexus branch) with Rockchip MPP hardware acceleration
+ depends = bluez-libs
+ depends = curl
+ depends = dav1d
+ depends = desktop-file-utils
+ depends = hicolor-icon-theme
+ depends = lcms2
+ depends = libass
+ depends = libbluray
+ depends = libcdio
+ depends = libcec
+ depends = libmicrohttpd
+ depends = libnfs
+ depends = libplist
+ depends = libpulse
+ depends = libva
+ depends = libvdpau
+ depends = libxslt
+ depends = lirc
+ depends = mariadb-libs
+ depends = mesa
+ depends = python-pillow
+ depends = python-pycryptodomex
+ depends = python-simplejson
+ depends = shairplay
+ depends = smbclient
+ depends = sqlite
+ depends = taglib
+ depends = tinyxml
+ depends = libxrandr
+ depends = libxkbcommon
+ depends = waylandpp
+ depends = libinput
+ depends = pcre
+ depends = mpp-git
+ optdepends = afpfs-ng: Apple shares support
+ optdepends = bluez: Blutooth support
+ optdepends = python-pybluez: Bluetooth support
+ optdepends = pulseaudio: PulseAudio support
+ optdepends = upower: Display battery level
+ provides = kodi=r62294.e75ba45eef3.457d9a5
+ provides = kodi-x11
+ provides = kodi-wayland
+ provides = kodi-gbm
+ conflicts = kodi
+ conflicts = kodi-x11
+ conflicts = kodi-wayland
+ conflicts = kodi-gbm
+
+pkgname = kodi-nexus-mpp-git-eventclients
+ pkgdesc = Kodi Event Clients (Nexus branch)
+ optdepends = kodi: local machine eventclient use
+ optdepends = python: most eventclients are implemented in python
+ provides = kodi-eventclients=r62294.e75ba45eef3.457d9a5
+ conflicts = kodi-eventclients
+
+pkgname = kodi-nexus-mpp-git-tools-texturepacker
+ pkgdesc = Kodi Texturepacker tool (Nexus branch)
+ depends = libpng
+ depends = giflib
+ depends = libjpeg-turbo
+ depends = lzo
+ provides = kodi-tools-texturepacker=r62294.e75ba45eef3.457d9a5
+ conflicts = kodi-tools-texturepacker
+
+pkgname = kodi-nexus-mpp-git-dev
+ pkgdesc = Kodi dev files (Nexus branch) with Rockchip MPP hardware acceleration
+ depends = kodi-nexus-mpp-git
+ provides = kodi-nexus-dev=r62294.e75ba45eef3.457d9a5
+ provides = kodi-dev=r62294.e75ba45eef3.457d9a5
+ conflicts = kodi-nexus-dev
+ conflicts = kodi-dev
+
+pkgname = kodi-nexus-mpp-git-ffmpegdirect
+ pkgdesc = Inputstream ffmpegdirect kodi binary addon (Nexus branch) supporting Rockchip MPP hardware acceleration
+ depends = kodi
+ depends = kodi-nexus-mpp-git
+ provides = kodi-addon-inputstream-ffmpegdirect
+ conflicts = kodi-addon-inputstream-ffmpegdirect
diff --git a/0001-ffmpeg-buildsys.patch b/0001-ffmpeg-buildsys.patch
new file mode 100644
index 000000000000..a5b1ab88eb37
--- /dev/null
+++ b/0001-ffmpeg-buildsys.patch
@@ -0,0 +1,25 @@
+unchanged:
+--- xbmc/cmake/modules/FindFFMPEG.cmake 2023-01-29 16:26:22.106190627 +0100
++++ xbmc/cmake/modules/FindFFMPEG.new 2023-01-29 04:10:14.260604086 +0100
+@@ -96,7 +96,7 @@
+ -DPKG_CONFIG_PATH=${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/lib/pkgconfig)
+ set(PATCH_COMMAND ${CMAKE_COMMAND} -E copy
+ ${CMAKE_SOURCE_DIR}/tools/depends/target/ffmpeg/CMakeLists.txt
+- <SOURCE_DIR>)
++ <SOURCE_DIR> && patch -p1 -N -i ${CMAKE_SOURCE_DIR}/tools/depends/target/ffmpeg/0002-rkmpp-4.patch)
+
+ if(CMAKE_GENERATOR STREQUAL Xcode)
+ set(FFMPEG_GENERATOR CMAKE_GENERATOR "Unix Makefiles")
+only in patch2:
+unchanged:
+--- xbmc/tools/depends/target/ffmpeg/CMakeLists.txt 2023-01-29 04:12:26.179949543 +0100
++++ xbmc/tools/depends/target/ffmpeg/CMakeLists.new 2023-01-29 04:10:14.270603769 +0100
+@@ -150,6 +150,9 @@
+ CONFIGURE_COMMAND ${pkgconf} ${pkgconf_path} <SOURCE_DIR>/configure
+ --prefix=${CMAKE_INSTALL_PREFIX}
+ --extra-version="kodi-${FFMPEG_VER}"
++ --enable-version3
++ --enable-rkmpp
++ --enable-libdrm
+ ${ffmpeg_conf}
+ BUILD_COMMAND ${MAKE_COMMAND})
diff --git a/0002-rkmpp-4.patch b/0002-rkmpp-4.patch
new file mode 100644
index 000000000000..5c8734c1535a
--- /dev/null
+++ b/0002-rkmpp-4.patch
@@ -0,0 +1,2771 @@
+From 9590c16111eb27ba8cb1b5c46ea57dc9052e82ed Mon Sep 17 00:00:00 2001
+From: Jeffy Chen <jeffy.chen@rock-chips.com>
+Date: Wed, 4 Sep 2019 17:24:37 +0800
+Subject: [PATCH 01/16] avcodec/rkmppdec: Clear eos flag after reset
+
+Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
+---
+ libavcodec/rkmppdec.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
+index a60962dc86..3654437268 100644
+--- a/libavcodec/rkmppdec.c
++++ b/libavcodec/rkmppdec.c
+@@ -544,6 +544,7 @@ static void rkmpp_flush(AVCodecContext *avctx)
+ ret = decoder->mpi->reset(decoder->ctx);
+ if (ret == MPP_OK) {
+ decoder->first_packet = 1;
++ decoder->eos_reached = 0;
+ } else
+ av_log(avctx, AV_LOG_ERROR, "Failed to reset MPI (code = %d)\n", ret);
+ }
+--
+2.39.0
+
+
+From 43fc7807c58999a57d4c407dcda0d3d2fac7405b Mon Sep 17 00:00:00 2001
+From: Jeffy Chen <jeffy.chen@rock-chips.com>
+Date: Wed, 4 Sep 2019 17:27:46 +0800
+Subject: [PATCH 02/16] avcodec/rkmppdec: Compatible with old reordered_opaque
+ and pkt_pts
+
+Some users might still using these deprecated APIs.
+
+Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
+---
+ libavcodec/rkmppdec.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
+index 3654437268..6256abe63c 100644
+--- a/libavcodec/rkmppdec.c
++++ b/libavcodec/rkmppdec.c
+@@ -93,6 +93,9 @@ static int rkmpp_write_data(AVCodecContext *avctx, uint8_t *buffer, int size, in
+ int ret;
+ MppPacket packet;
+
++ if (!pts || pts == AV_NOPTS_VALUE)
++ pts = avctx->reordered_opaque;
++
+ // create the MPP packet
+ ret = mpp_packet_init(&packet, buffer, size);
+ if (ret != MPP_OK) {
+@@ -398,6 +401,12 @@ static int rkmpp_retrieve_frame(AVCodecContext *avctx, AVFrame *frame)
+ frame->width = mpp_frame_get_width(mppframe);
+ frame->height = mpp_frame_get_height(mppframe);
+ frame->pts = mpp_frame_get_pts(mppframe);
++#if FF_API_PKT_PTS
++ FF_DISABLE_DEPRECATION_WARNINGS
++ frame->pkt_pts = frame->pts;
++ FF_ENABLE_DEPRECATION_WARNINGS
++#endif
++ frame->reordered_opaque = frame->pts;
+ frame->color_range = mpp_frame_get_color_range(mppframe);
+ frame->color_primaries = mpp_frame_get_color_primaries(mppframe);
+ frame->color_trc = mpp_frame_get_color_trc(mppframe);
+--
+2.39.0
+
+
+From 6b5e686cea5638fe6c2c92eeaaabe16d9a72121b Mon Sep 17 00:00:00 2001
+From: Jeffy Chen <jeffy.chen@rock-chips.com>
+Date: Wed, 19 May 2021 09:55:03 +0800
+Subject: [PATCH 03/16] rkmppdec: Remove frame buffer limit
+
+It would hang when reaching the limit.
+
+Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
+---
+ libavcodec/rkmppdec.c | 8 --------
+ 1 file changed, 8 deletions(-)
+
+diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
+index 6256abe63c..96696e84dc 100644
+--- a/libavcodec/rkmppdec.c
++++ b/libavcodec/rkmppdec.c
+@@ -39,7 +39,6 @@
+ #include "libavutil/log.h"
+
+ #define RECEIVE_FRAME_TIMEOUT 100
+-#define FRAMEGROUP_MAX_FRAMES 16
+ #define INPUT_MAX_PACKETS 4
+
+ typedef struct {
+@@ -241,13 +240,6 @@ static int rkmpp_init_decoder(AVCodecContext *avctx)
+ goto fail;
+ }
+
+- ret = mpp_buffer_group_limit_config(decoder->frame_group, 0, FRAMEGROUP_MAX_FRAMES);
+- if (ret) {
+- av_log(avctx, AV_LOG_ERROR, "Failed to set buffer group limit (code = %d)\n", ret);
+- ret = AVERROR_UNKNOWN;
+- goto fail;
+- }
+-
+ decoder->first_packet = 1;
+
+ av_log(avctx, AV_LOG_DEBUG, "RKMPP decoder initialized successfully.\n");
+--
+2.39.0
+
+
+From 668ec8c36d1112c5c4939ddc3d3b7cff487cedc1 Mon Sep 17 00:00:00 2001
+From: Jeffy Chen <jeffy.chen@rock-chips.com>
+Date: Thu, 20 May 2021 10:19:15 +0800
+Subject: [PATCH 04/16] avcodec/rkmppdec: Rework decoding flow
+
+Stop using the deprecated MPP_DEC_GET_STREAM_COUNT API.
+
+Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
+---
+ libavcodec/rkmppdec.c | 526 ++++++++++++++++++++++--------------------
+ 1 file changed, 270 insertions(+), 256 deletions(-)
+
+diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
+index 96696e84dc..7c28378120 100644
+--- a/libavcodec/rkmppdec.c
++++ b/libavcodec/rkmppdec.c
+@@ -38,17 +38,15 @@
+ #include "libavutil/imgutils.h"
+ #include "libavutil/log.h"
+
+-#define RECEIVE_FRAME_TIMEOUT 100
+-#define INPUT_MAX_PACKETS 4
+-
+ typedef struct {
+ MppCtx ctx;
+ MppApi *mpi;
+ MppBufferGroup frame_group;
+
+- char first_packet;
+- char eos_reached;
++ int8_t eos;
++ int8_t draining;
+
++ AVPacket packet;
+ AVBufferRef *frames_ref;
+ AVBufferRef *device_ref;
+ } RKMPPDecoder;
+@@ -85,47 +83,13 @@ static uint32_t rkmpp_get_frameformat(MppFrameFormat mppformat)
+ }
+ }
+
+-static int rkmpp_write_data(AVCodecContext *avctx, uint8_t *buffer, int size, int64_t pts)
++static int rkmpp_close_decoder(AVCodecContext *avctx)
+ {
+ RKMPPDecodeContext *rk_context = avctx->priv_data;
+ RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data;
+- int ret;
+- MppPacket packet;
+-
+- if (!pts || pts == AV_NOPTS_VALUE)
+- pts = avctx->reordered_opaque;
+-
+- // create the MPP packet
+- ret = mpp_packet_init(&packet, buffer, size);
+- if (ret != MPP_OK) {
+- av_log(avctx, AV_LOG_ERROR, "Failed to init MPP packet (code = %d)\n", ret);
+- return AVERROR_UNKNOWN;
+- }
+-
+- mpp_packet_set_pts(packet, pts);
+-
+- if (!buffer)
+- mpp_packet_set_eos(packet);
+
+- ret = decoder->mpi->decode_put_packet(decoder->ctx, packet);
+- if (ret != MPP_OK) {
+- if (ret == MPP_ERR_BUFFER_FULL) {
+- av_log(avctx, AV_LOG_DEBUG, "Buffer full writing %d bytes to decoder\n", size);
+- ret = AVERROR(EAGAIN);
+- } else
+- ret = AVERROR_UNKNOWN;
+- }
+- else
+- av_log(avctx, AV_LOG_DEBUG, "Wrote %d bytes to decoder\n", size);
++ av_packet_unref(&decoder->packet);
+
+- mpp_packet_deinit(&packet);
+-
+- return ret;
+-}
+-
+-static int rkmpp_close_decoder(AVCodecContext *avctx)
+-{
+- RKMPPDecodeContext *rk_context = avctx->priv_data;
+ av_buffer_unref(&rk_context->decoder_ref);
+ return 0;
+ }
+@@ -151,14 +115,32 @@ static void rkmpp_release_decoder(void *opaque, uint8_t *data)
+ av_free(decoder);
+ }
+
++static int rkmpp_prepare_decoder(AVCodecContext *avctx)
++{
++ RKMPPDecodeContext *rk_context = avctx->priv_data;
++ RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data;
++ MppPacket packet;
++ int ret;
++
++ // send extra data
++ if (avctx->extradata_size) {
++ ret = mpp_packet_init(&packet, avctx->extradata, avctx->extradata_size);
++ if (ret < 0)
++ return AVERROR_UNKNOWN;
++ ret = decoder->mpi->decode_put_packet(decoder->ctx, packet);
++ mpp_packet_deinit(&packet);
++ if (ret < 0)
++ return AVERROR_UNKNOWN;
++ }
++ return 0;
++}
++
+ static int rkmpp_init_decoder(AVCodecContext *avctx)
+ {
+ RKMPPDecodeContext *rk_context = avctx->priv_data;
+ RKMPPDecoder *decoder = NULL;
+ MppCodingType codectype = MPP_VIDEO_CodingUnused;
+ int ret;
+- RK_S64 paramS64;
+- RK_S32 paramS32;
+
+ avctx->pix_fmt = AV_PIX_FMT_DRM_PRIME;
+
+@@ -201,6 +183,9 @@ static int rkmpp_init_decoder(AVCodecContext *avctx)
+ goto fail;
+ }
+
++ ret = 1;
++ decoder->mpi->control(decoder->ctx, MPP_DEC_SET_PARSER_FAST_MODE, &ret);
++
+ // initialize mpp
+ ret = mpp_init(decoder->ctx, MPP_CTX_DEC, codectype);
+ if (ret != MPP_OK) {
+@@ -209,26 +194,9 @@ static int rkmpp_init_decoder(AVCodecContext *avctx)
+ goto fail;
+ }
+
+- // make decode calls blocking with a timeout
+- paramS32 = MPP_POLL_BLOCK;
+- ret = decoder->mpi->control(decoder->ctx, MPP_SET_OUTPUT_BLOCK, &paramS32);
+- if (ret != MPP_OK) {
+- av_log(avctx, AV_LOG_ERROR, "Failed to set blocking mode on MPI (code = %d).\n", ret);
+- ret = AVERROR_UNKNOWN;
+- goto fail;
+- }
+-
+- paramS64 = RECEIVE_FRAME_TIMEOUT;
+- ret = decoder->mpi->control(decoder->ctx, MPP_SET_OUTPUT_BLOCK_TIMEOUT, &paramS64);
+- if (ret != MPP_OK) {
+- av_log(avctx, AV_LOG_ERROR, "Failed to set block timeout on MPI (code = %d).\n", ret);
+- ret = AVERROR_UNKNOWN;
+- goto fail;
+- }
+-
+ ret = mpp_buffer_group_get_internal(&decoder->frame_group, MPP_BUFFER_TYPE_ION);
+ if (ret) {
+- av_log(avctx, AV_LOG_ERROR, "Failed to retrieve buffer group (code = %d)\n", ret);
++ av_log(avctx, AV_LOG_ERROR, "Failed to get buffer group (code = %d)\n", ret);
+ ret = AVERROR_UNKNOWN;
+ goto fail;
+ }
+@@ -240,7 +208,13 @@ static int rkmpp_init_decoder(AVCodecContext *avctx)
+ goto fail;
+ }
+
+- decoder->first_packet = 1;
++ decoder->mpi->control(decoder->ctx, MPP_DEC_SET_DISABLE_ERROR, NULL);
++
++ ret = rkmpp_prepare_decoder(avctx);
++ if (ret < 0) {
++ av_log(avctx, AV_LOG_ERROR, "Failed to prepare decoder (code = %d)\n", ret);
++ goto fail;
++ }
+
+ av_log(avctx, AV_LOG_DEBUG, "RKMPP decoder initialized successfully.\n");
+
+@@ -261,44 +235,6 @@ fail:
+ return ret;
+ }
+
+-static int rkmpp_send_packet(AVCodecContext *avctx, const AVPacket *avpkt)
+-{
+- RKMPPDecodeContext *rk_context = avctx->priv_data;
+- RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data;
+- int ret;
+-
+- // handle EOF
+- if (!avpkt->size) {
+- av_log(avctx, AV_LOG_DEBUG, "End of stream.\n");
+- decoder->eos_reached = 1;
+- ret = rkmpp_write_data(avctx, NULL, 0, 0);
+- if (ret)
+- av_log(avctx, AV_LOG_ERROR, "Failed to send EOS to decoder (code = %d)\n", ret);
+- return ret;
+- }
+-
+- // on first packet, send extradata
+- if (decoder->first_packet) {
+- if (avctx->extradata_size) {
+- ret = rkmpp_write_data(avctx, avctx->extradata,
+- avctx->extradata_size,
+- avpkt->pts);
+- if (ret) {
+- av_log(avctx, AV_LOG_ERROR, "Failed to write extradata to decoder (code = %d)\n", ret);
+- return ret;
+- }
+- }
+- decoder->first_packet = 0;
+- }
+-
+- // now send packet
+- ret = rkmpp_write_data(avctx, avpkt->data, avpkt->size, avpkt->pts);
+- if (ret && ret!=AVERROR(EAGAIN))
+- av_log(avctx, AV_LOG_ERROR, "Failed to write data to decoder (code = %d)\n", ret);
+-
+- return ret;
+-}
+-
+ static void rkmpp_release_frame(void *opaque, uint8_t *data)
+ {
+ AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor *)data;
+@@ -312,7 +248,7 @@ static void rkmpp_release_frame(void *opaque, uint8_t *data)
+ av_free(desc);
+ }
+
+-static int rkmpp_retrieve_frame(AVCodecContext *avctx, AVFrame *frame)
++static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
+ {
+ RKMPPDecodeContext *rk_context = avctx->priv_data;
+ RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data;
+@@ -327,156 +263,164 @@ static int rkmpp_retrieve_frame(AVCodecContext *avctx, AVFrame *frame)
+ MppFrameFormat mppformat;
+ uint32_t drmformat;
+
++ // should not provide any frame after EOS
++ if (decoder->eos)
++ return AVERROR_EOF;
++
++ decoder->mpi->control(decoder->ctx, MPP_SET_OUTPUT_TIMEOUT, (MppParam)&timeout);
++
+ ret = decoder->mpi->decode_get_frame(decoder->ctx, &mppframe);
+ if (ret != MPP_OK && ret != MPP_ERR_TIMEOUT) {
+- av_log(avctx, AV_LOG_ERROR, "Failed to get a frame from MPP (code = %d)\n", ret);
+- goto fail;
++ av_log(avctx, AV_LOG_ERROR, "Failed to get frame (code = %d)\n", ret);
++ return AVERROR_UNKNOWN;
+ }
+
+- if (mppframe) {
+- // Check whether we have a special frame or not
+- if (mpp_frame_get_info_change(mppframe)) {
+- AVHWFramesContext *hwframes;
++ if (!mppframe) {
++ av_log(avctx, AV_LOG_DEBUG, "Timeout getting decoded frame.\n");
++ return AVERROR(EAGAIN);
++ }
+
+- av_log(avctx, AV_LOG_INFO, "Decoder noticed an info change (%dx%d), format=%d\n",
+- (int)mpp_frame_get_width(mppframe), (int)mpp_frame_get_height(mppframe),
+- (int)mpp_frame_get_fmt(mppframe));
++ if (mpp_frame_get_eos(mppframe)) {
++ av_log(avctx, AV_LOG_DEBUG, "Received a EOS frame.\n");
++ decoder->eos = 1;
++ ret = AVERROR_EOF;
++ goto fail;
++ }
+
+- avctx->width = mpp_frame_get_width(mppframe);
+- avctx->height = mpp_frame_get_height(mppframe);
++ if (mpp_frame_get_discard(mppframe)) {
++ av_log(avctx, AV_LOG_DEBUG, "Received a discard frame.\n");
++ ret = AVERROR(EAGAIN);
++ goto fail;
++ }
+
+- decoder->mpi->control(decoder->ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL);
++ if (mpp_frame_get_errinfo(mppframe)) {
++ av_log(avctx, AV_LOG_ERROR, "Received a errinfo frame.\n");
++ ret = AVERROR_UNKNOWN;
++ goto fail;
++ }
+
+- av_buffer_unref(&decoder->frames_ref);
++ if (mpp_frame_get_info_change(mppframe)) {
++ AVHWFramesContext *hwframes;
+
+- decoder->frames_ref = av_hwframe_ctx_alloc(decoder->device_ref);
+- if (!decoder->frames_ref) {
+- ret = AVERROR(ENOMEM);
+- goto fail;
+- }
++ av_log(avctx, AV_LOG_INFO, "Decoder noticed an info change (%dx%d), format=%d\n",
++ (int)mpp_frame_get_width(mppframe), (int)mpp_frame_get_height(mppframe),
++ (int)mpp_frame_get_fmt(mppframe));
+
+- mppformat = mpp_frame_get_fmt(mppframe);
+- drmformat = rkmpp_get_frameformat(mppformat);
++ avctx->width = mpp_frame_get_width(mppframe);
++ avctx->height = mpp_frame_get_height(mppframe);
+
+- hwframes = (AVHWFramesContext*)decoder->frames_ref->data;
+- hwframes->format = AV_PIX_FMT_DRM_PRIME;
+- hwframes->sw_format = drmformat == DRM_FORMAT_NV12 ? AV_PIX_FMT_NV12 : AV_PIX_FMT_NONE;
+- hwframes->width = avctx->width;
+- hwframes->height = avctx->height;
+- ret = av_hwframe_ctx_init(decoder->frames_ref);
+- if (ret < 0)
+- goto fail;
++ decoder->mpi->control(decoder->ctx, MPP_DEC_SET_FRAME_INFO, (MppParam) mppframe);
++ decoder->mpi->control(decoder->ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL);
+
+- // here decoder is fully initialized, we need to feed it again with data
+- ret = AVERROR(EAGAIN);
+- goto fail;
+- } else if (mpp_frame_get_eos(mppframe)) {
+- av_log(avctx, AV_LOG_DEBUG, "Received a EOS frame.\n");
+- decoder->eos_reached = 1;
+- ret = AVERROR_EOF;
+- goto fail;
+- } else if (mpp_frame_get_discard(mppframe)) {
+- av_log(avctx, AV_LOG_DEBUG, "Received a discard frame.\n");
+- ret = AVERROR(EAGAIN);
+- goto fail;
+- } else if (mpp_frame_get_errinfo(mppframe)) {
+- av_log(avctx, AV_LOG_ERROR, "Received a errinfo frame.\n");
+- ret = AVERROR_UNKNOWN;
++ av_buffer_unref(&decoder->frames_ref);
++
++ decoder->frames_ref = av_hwframe_ctx_alloc(decoder->device_ref);
++ if (!decoder->frames_ref) {
++ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+- // here we should have a valid frame
+- av_log(avctx, AV_LOG_DEBUG, "Received a frame.\n");
++ mppformat = mpp_frame_get_fmt(mppframe);
++ drmformat = rkmpp_get_frameformat(mppformat);
++
++ hwframes = (AVHWFramesContext*)decoder->frames_ref->data;
++ hwframes->format = AV_PIX_FMT_DRM_PRIME;
++ hwframes->sw_format = drmformat == DRM_FORMAT_NV12 ? AV_PIX_FMT_NV12 : AV_PIX_FMT_NONE;
++ hwframes->width = avctx->width;
++ hwframes->height = avctx->height;
++ ret = av_hwframe_ctx_init(decoder->frames_ref);
++ if (!ret)
++ ret = AVERROR(EAGAIN);
++
++ goto fail;
++ }
+
+- // setup general frame fields
+- frame->format = AV_PIX_FMT_DRM_PRIME;
+- frame->width = mpp_frame_get_width(mppframe);
+- frame->height = mpp_frame_get_height(mppframe);
+- frame->pts = mpp_frame_get_pts(mppframe);
++ // here we should have a valid frame
++ av_log(avctx, AV_LOG_DEBUG, "Received a frame.\n");
++
++ // now setup the frame buffer info
++ buffer = mpp_frame_get_buffer(mppframe);
++ if (!buffer) {
++ av_log(avctx, AV_LOG_ERROR, "Failed to get the frame buffer, frame is dropped (code = %d)\n", ret);
++ ret = AVERROR(EAGAIN);
++ goto fail;
++ }
++
++ // setup general frame fields
++ frame->format = avctx->pix_fmt;
++ frame->width = mpp_frame_get_width(mppframe);
++ frame->height = mpp_frame_get_height(mppframe);
++ frame->pts = mpp_frame_get_pts(mppframe);
+ #if FF_API_PKT_PTS
+- FF_DISABLE_DEPRECATION_WARNINGS
+- frame->pkt_pts = frame->pts;
+- FF_ENABLE_DEPRECATION_WARNINGS
++ FF_DISABLE_DEPRECATION_WARNINGS;
++ frame->pkt_pts = frame->pts;
++ FF_ENABLE_DEPRECATION_WARNINGS;
+ #endif
+- frame->reordered_opaque = frame->pts;
+- frame->color_range = mpp_frame_get_color_range(mppframe);
+- frame->color_primaries = mpp_frame_get_color_primaries(mppframe);
+- frame->color_trc = mpp_frame_get_color_trc(mppframe);
+- frame->colorspace = mpp_frame_get_colorspace(mppframe);
++ frame->reordered_opaque = frame->pts;
++ frame->color_range = mpp_frame_get_color_range(mppframe);
++ frame->color_primaries = mpp_frame_get_color_primaries(mppframe);
++ frame->color_trc = mpp_frame_get_color_trc(mppframe);
++ frame->colorspace = mpp_frame_get_colorspace(mppframe);
+
+- mode = mpp_frame_get_mode(mppframe);
+- frame->interlaced_frame = ((mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK) == MPP_FRAME_FLAG_DEINTERLACED);
+- frame->top_field_first = ((mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK) == MPP_FRAME_FLAG_TOP_FIRST);
++ mode = mpp_frame_get_mode(mppframe);
++ frame->interlaced_frame = ((mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK) == MPP_FRAME_FLAG_DEINTERLACED);
++ frame->top_field_first = ((mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK) == MPP_FRAME_FLAG_TOP_FIRST);
+
+- mppformat = mpp_frame_get_fmt(mppframe);
+- drmformat = rkmpp_get_frameformat(mppformat);
++ mppformat = mpp_frame_get_fmt(mppframe);
++ drmformat = rkmpp_get_frameformat(mppformat);
+
+- // now setup the frame buffer info
+- buffer = mpp_frame_get_buffer(mppframe);
+- if (buffer) {
+- desc = av_mallocz(sizeof(AVDRMFrameDescriptor));
+- if (!desc) {
+- ret = AVERROR(ENOMEM);
+- goto fail;
+- }
++ desc = av_mallocz(sizeof(AVDRMFrameDescriptor));
++ if (!desc) {
++ ret = AVERROR(ENOMEM);
++ goto fail;
++ }
+
+- desc->nb_objects = 1;
+- desc->objects[0].fd = mpp_buffer_get_fd(buffer);
+- desc->objects[0].size = mpp_buffer_get_size(buffer);
+-
+- desc->nb_layers = 1;
+- layer = &desc->layers[0];
+- layer->format = drmformat;
+- layer->nb_planes = 2;
+-
+- layer->planes[0].object_index = 0;
+- layer->planes[0].offset = 0;
+- layer->planes[0].pitch = mpp_frame_get_hor_stride(mppframe);
+-
+- layer->planes[1].object_index = 0;
+- layer->planes[1].offset = layer->planes[0].pitch * mpp_frame_get_ver_stride(mppframe);
+- layer->planes[1].pitch = layer->planes[0].pitch;
+-
+- // we also allocate a struct in buf[0] that will allow to hold additionnal information
+- // for releasing properly MPP frames and decoder
+- framecontextref = av_buffer_allocz(sizeof(*framecontext));
+- if (!framecontextref) {
+- ret = AVERROR(ENOMEM);
+- goto fail;
+- }
++ desc->nb_objects = 1;
++ desc->objects[0].fd = mpp_buffer_get_fd(buffer);
++ desc->objects[0].size = mpp_buffer_get_size(buffer);
+
+- // MPP decoder needs to be closed only when all frames have been released.
+- framecontext = (RKMPPFrameContext *)framecontextref->data;
+- framecontext->decoder_ref = av_buffer_ref(rk_context->decoder_ref);
+- framecontext->frame = mppframe;
++ desc->nb_layers = 1;
++ layer = &desc->layers[0];
++ layer->format = drmformat;
++ layer->nb_planes = 2;
+
+- frame->data[0] = (uint8_t *)desc;
+- frame->buf[0] = av_buffer_create((uint8_t *)desc, sizeof(*desc), rkmpp_release_frame,
+- framecontextref, AV_BUFFER_FLAG_READONLY);
++ layer->planes[0].object_index = 0;
++ layer->planes[0].offset = 0;
++ layer->planes[0].pitch = mpp_frame_get_hor_stride(mppframe);
+
+- if (!frame->buf[0]) {
+- ret = AVERROR(ENOMEM);
+- goto fail;
+- }
++ layer->planes[1].object_index = 0;
++ layer->planes[1].offset = layer->planes[0].pitch * mpp_frame_get_ver_stride(mppframe);
++ layer->planes[1].pitch = layer->planes[0].pitch;
+
+- frame->hw_frames_ctx = av_buffer_ref(decoder->frames_ref);
+- if (!frame->hw_frames_ctx) {
+- ret = AVERROR(ENOMEM);
+- goto fail;
+- }
++ // we also allocate a struct in buf[0] that will allow to hold additionnal information
++ // for releasing properly MPP frames and decoder
++ framecontextref = av_buffer_allocz(sizeof(*framecontext));
++ if (!framecontextref) {
++ ret = AVERROR(ENOMEM);
++ goto fail;
++ }
+
+- return 0;
+- } else {
+- av_log(avctx, AV_LOG_ERROR, "Failed to retrieve the frame buffer, frame is dropped (code = %d)\n", ret);
+- mpp_frame_deinit(&mppframe);
+- }
+- } else if (decoder->eos_reached) {
+- return AVERROR_EOF;
+- } else if (ret == MPP_ERR_TIMEOUT) {
+- av_log(avctx, AV_LOG_DEBUG, "Timeout when trying to get a frame from MPP\n");
++ // MPP decoder needs to be closed only when all frames have been released.
++ framecontext = (RKMPPFrameContext *)framecontextref->data;
++ framecontext->decoder_ref = av_buffer_ref(rk_context->decoder_ref);
++ framecontext->frame = mppframe;
++
++ frame->data[0] = (uint8_t *)desc;
++ frame->buf[0] = av_buffer_create((uint8_t *)desc, sizeof(*desc), rkmpp_release_frame,
++ framecontextref, AV_BUFFER_FLAG_READONLY);
++
++ if (!frame->buf[0]) {
++ ret = AVERROR(ENOMEM);
++ goto fail;
+ }
+
+- return AVERROR(EAGAIN);
++ frame->hw_frames_ctx = av_buffer_ref(decoder->frames_ref);
++ if (!frame->hw_frames_ctx) {
++ ret = AVERROR(ENOMEM);
++ goto fail;
++ }
++
++ return 0;
+
+ fail:
+ if (mppframe)
+@@ -494,60 +438,130 @@ fail:
+ return ret;
+ }
+
++static int rkmpp_send_packet(AVCodecContext *avctx, AVPacket *packet)
++{
++ RKMPPDecodeContext *rk_context = avctx->priv_data;
++ RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data;
++ MppPacket mpkt;
++ int64_t pts = packet->pts;
++ int ret;
++
++ // avoid sending new data after EOS
++ if (decoder->draining)
++ return AVERROR_EOF;
++
++ if (!pts || pts == AV_NOPTS_VALUE)
++ pts = avctx->reordered_opaque;
++
++ ret = mpp_packet_init(&mpkt, packet->data, packet->size);
++ if (ret != MPP_OK) {
++ av_log(avctx, AV_LOG_ERROR, "Failed to init MPP packet (code = %d)\n", ret);
++ return AVERROR_UNKNOWN;
++ }
++
++ mpp_packet_set_pts(mpkt, pts);
++
++ ret = decoder->mpi->decode_put_packet(decoder->ctx, mpkt);
++ mpp_packet_deinit(&mpkt);
++
++ if (ret != MPP_OK) {
++ av_log(avctx, AV_LOG_DEBUG, "Buffer full\n");
++ return AVERROR(EAGAIN);
++ }
++
++ av_log(avctx, AV_LOG_DEBUG, "Wrote %d bytes to decoder\n", packet->size);
++ return 0;
++}
++
++static int rkmpp_send_eos(AVCodecContext *avctx)
++{
++ RKMPPDecodeContext *rk_context = avctx->priv_data;
++ RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data;
++ MppPacket mpkt;
++ int ret;
++
++ ret = mpp_packet_init(&mpkt, NULL, 0);
++ if (ret != MPP_OK) {
++ av_log(avctx, AV_LOG_ERROR, "Failed to init EOS packet (code = %d)\n", ret);
++ return AVERROR_UNKNOWN;
++ }
++
++ mpp_packet_set_eos(mpkt);
++
++ do {
++ ret = decoder->mpi->decode_put_packet(decoder->ctx, mpkt);
++ } while (ret != MPP_OK);
++ mpp_packet_deinit(&mpkt);
++
++ decoder->draining = 1;
++
++ return 0;
++}
++
+ static int rkmpp_receive_frame(AVCodecContext *avctx, AVFrame *frame)
+ {
+ RKMPPDecodeContext *rk_context = avctx->priv_data;
+ RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data;
+- int ret = MPP_NOK;
+- AVPacket pkt = {0};
+- RK_S32 usedslots, freeslots;
+-
+- if (!decoder->eos_reached) {
+- // we get the available slots in decoder
+- ret = decoder->mpi->control(decoder->ctx, MPP_DEC_GET_STREAM_COUNT, &usedslots);
+- if (ret != MPP_OK) {
+- av_log(avctx, AV_LOG_ERROR, "Failed to get decoder used slots (code = %d).\n", ret);
+- return ret;
+- }
++ AVPacket *packet = &decoder->packet;
++ int ret;
+
+- freeslots = INPUT_MAX_PACKETS - usedslots;
+- if (freeslots > 0) {
+- ret = ff_decode_get_packet(avctx, &pkt);
+- if (ret < 0 && ret != AVERROR_EOF) {
++ // no more frames after EOS
++ if (decoder->eos)
++ return AVERROR_EOF;
++
++ // draining remain frames
++ if (decoder->draining)
++ return rkmpp_get_frame(avctx, frame, MPP_TIMEOUT_BLOCK);
++
++ while (1) {
++ if (!packet->size) {
++ ret = ff_decode_get_packet(avctx, packet);
++ if (ret == AVERROR_EOF) {
++ av_log(avctx, AV_LOG_DEBUG, "End of stream.\n");
++ // send EOS and start draining
++ rkmpp_send_eos(avctx);
++ return rkmpp_get_frame(avctx, frame, MPP_TIMEOUT_BLOCK);
++ } else if (ret == AVERROR(EAGAIN)) {
++ // not blocking so that we can feed new data ASAP
++ return rkmpp_get_frame(avctx, frame, MPP_TIMEOUT_NON_BLOCK);
++ } else if (ret < 0) {
++ av_log(avctx, AV_LOG_ERROR, "Failed to get packet (code = %d)\n", ret);
+ return ret;
+ }
+-
+- ret = rkmpp_send_packet(avctx, &pkt);
+- av_packet_unref(&pkt);
+-
+- if (ret < 0) {
+- av_log(avctx, AV_LOG_ERROR, "Failed to send packet to decoder (code = %d)\n", ret);
++ } else {
++ // send pending data to decoder
++ ret = rkmpp_send_packet(avctx, packet);
++ if (ret == AVERROR(EAGAIN)) {
++ // some streams might need more packets to start returning frames
++ ret = rkmpp_get_frame(avctx, frame, 1);
++ if (ret != AVERROR(EAGAIN))
++ return ret;
++ } else if (ret < 0) {
++ av_log(avctx, AV_LOG_ERROR, "Failed to send data (code = %d)\n", ret);
+ return ret;
++ } else {
++ av_packet_unref(packet);
++ packet->size = 0;
+ }
+ }
+-
+- // make sure we keep decoder full
+- if (freeslots > 1)
+- return AVERROR(EAGAIN);
+ }
+-
+- return rkmpp_retrieve_frame(avctx, frame);
+ }
+
+ static void rkmpp_flush(AVCodecContext *avctx)
+ {
+ RKMPPDecodeContext *rk_context = avctx->priv_data;
+ RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data;
+- int ret = MPP_NOK;
+
+ av_log(avctx, AV_LOG_DEBUG, "Flush.\n");
+
+- ret = decoder->mpi->reset(decoder->ctx);
+- if (ret == MPP_OK) {
+- decoder->first_packet = 1;
+- decoder->eos_reached = 0;
+- } else
+- av_log(avctx, AV_LOG_ERROR, "Failed to reset MPI (code = %d)\n", ret);
++ decoder->mpi->reset(decoder->ctx);
++
++ rkmpp_prepare_decoder(avctx);
++
++ decoder->eos = 0;
++ decoder->draining = 0;
++
++ av_packet_unref(&decoder->packet);
+ }
+
+ static const AVCodecHWConfigInternal *const rkmpp_hw_configs[] = {
+--
+2.39.0
+
+
+From 3f94c029c3eeca764c63e32435e8ca8241a87dfc Mon Sep 17 00:00:00 2001
+From: Jeffy Chen <jeffy.chen@rock-chips.com>
+Date: Fri, 21 May 2021 04:23:36 +0800
+Subject: [PATCH 05/16] HACK: avcodec/rkmppdec: Force aligning coded width and
+ height to 64
+
+The chromium would try to align planes' width and height to 32, which
+might break the plane buffers' contiguous required by RGA.
+
+Passing a 64-aligned coded width and height to avoid that.
+
+Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
+---
+ libavcodec/rkmppdec.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
+index 7c28378120..bae3ca6cb5 100644
+--- a/libavcodec/rkmppdec.c
++++ b/libavcodec/rkmppdec.c
+@@ -309,6 +309,11 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
+ avctx->width = mpp_frame_get_width(mppframe);
+ avctx->height = mpp_frame_get_height(mppframe);
+
++ // chromium would align planes' width and height to 32, adding this
++ // hack to avoid breaking the plane buffers' contiguous.
++ avctx->coded_width = FFALIGN(avctx->width, 64);
++ avctx->coded_height = FFALIGN(avctx->height, 64);
++
+ decoder->mpi->control(decoder->ctx, MPP_DEC_SET_FRAME_INFO, (MppParam) mppframe);
+ decoder->mpi->control(decoder->ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL);
+
+--
+2.39.0
+
+
+From 804808de6c6af583b71526ff9e11196e1515e542 Mon Sep 17 00:00:00 2001
+From: Jeffy Chen <jeffy.chen@rock-chips.com>
+Date: Thu, 20 May 2021 10:20:17 +0800
+Subject: [PATCH 06/16] HACK: avcodec/rkmppdec: Support outputing YUV420P
+
+Lots of users support YUV420P format rather than DRM_PRIME.
+
+Support RGA accelerated format conversion.
+
+Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
+---
+ configure | 7 ++-
+ libavcodec/rkmppdec.c | 120 +++++++++++++++++++++++++++++++++++++++++-
+ 2 files changed, 125 insertions(+), 2 deletions(-)
+
+diff --git a/configure b/configure
+index 89af70d72f..9e08481e11 100755
+--- a/configure
++++ b/configure
+@@ -345,6 +345,7 @@ External library support:
+ --enable-omx enable OpenMAX IL code [no]
+ --enable-omx-rpi enable OpenMAX IL code for Raspberry Pi [no]
+ --enable-rkmpp enable Rockchip Media Process Platform code [no]
++ --enable-librga enable Rockchip RGA 2D accel via librga [autodetect]
+ --disable-v4l2-m2m disable V4L2 mem2mem code [autodetect]
+ --disable-vaapi disable Video Acceleration API (mainly Unix/Intel) code [autodetect]
+ --disable-vdpau disable Nvidia Video Decode and Presentation API for Unix code [autodetect]
+@@ -1848,6 +1849,7 @@ HWACCEL_AUTODETECT_LIBRARY_LIST="
+ videotoolbox
+ v4l2_m2m
+ xvmc
++ librga
+ "
+
+ # catchall list of things that require external libs to link
+@@ -6539,10 +6541,13 @@ enabled openssl && { check_pkg_config openssl openssl openssl/ssl.h OP
+ check_lib openssl openssl/ssl.h SSL_library_init -lssl -lcrypto -lws2_32 -lgdi32 ||
+ die "ERROR: openssl not found"; }
+ enabled pocketsphinx && require_pkg_config pocketsphinx pocketsphinx pocketsphinx/pocketsphinx.h ps_init
++enabled librga && check_lib librga rga/RgaApi.h c_RkRgaInit -lrga && prepend rkmpp_deps "librga"
+ enabled rkmpp && { require_pkg_config rkmpp rockchip_mpp rockchip/rk_mpi.h mpp_create &&
+ require_pkg_config rockchip_mpp "rockchip_mpp >= 1.3.7" rockchip/rk_mpi.h mpp_create &&
+ { enabled libdrm ||
+- die "ERROR: rkmpp requires --enable-libdrm"; }
++ die "ERROR: rkmpp requires --enable-libdrm"; } &&
++ { enabled librga ||
++ warn "using rkmpp without librga"; }
+ }
+ enabled vapoursynth && require_pkg_config vapoursynth "vapoursynth-script >= 42" VSScript.h vsscript_init
+
+diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
+index bae3ca6cb5..c621e687e0 100644
+--- a/libavcodec/rkmppdec.c
++++ b/libavcodec/rkmppdec.c
+@@ -38,6 +38,11 @@
+ #include "libavutil/imgutils.h"
+ #include "libavutil/log.h"
+
++#if CONFIG_LIBRGA
++#include <rga/rga.h>
++#include <rga/RgaApi.h>
++#endif
++
+ typedef struct {
+ MppCtx ctx;
+ MppApi *mpi;
+@@ -83,6 +88,17 @@ static uint32_t rkmpp_get_frameformat(MppFrameFormat mppformat)
+ }
+ }
+
++#if CONFIG_LIBRGA
++static uint32_t rkmpp_get_rgaformat(MppFrameFormat mppformat)
++{
++ switch (mppformat) {
++ case MPP_FMT_YUV420SP: return RK_FORMAT_YCbCr_420_SP;
++ case MPP_FMT_YUV420SP_10BIT: return RK_FORMAT_YCbCr_420_SP_10B;
++ default: return RK_FORMAT_UNKNOWN;
++ }
++}
++#endif
++
+ static int rkmpp_close_decoder(AVCodecContext *avctx)
+ {
+ RKMPPDecodeContext *rk_context = avctx->priv_data;
+@@ -142,7 +158,7 @@ static int rkmpp_init_decoder(AVCodecContext *avctx)
+ MppCodingType codectype = MPP_VIDEO_CodingUnused;
+ int ret;
+
+- avctx->pix_fmt = AV_PIX_FMT_DRM_PRIME;
++ avctx->pix_fmt = ff_get_format(avctx, avctx->codec->pix_fmts);
+
+ // create a decoder and a ref to it
+ decoder = av_mallocz(sizeof(RKMPPDecoder));
+@@ -248,6 +264,95 @@ static void rkmpp_release_frame(void *opaque, uint8_t *data)
+ av_free(desc);
+ }
+
++static int rkmpp_convert_frame(AVCodecContext *avctx, AVFrame *frame,
++ MppFrame mppframe, MppBuffer buffer)
++{
++ char *src = mpp_buffer_get_ptr(buffer);
++ char *dst_y = frame->data[0];
++ char *dst_u = frame->data[1];
++ char *dst_v = frame->data[2];
++#if CONFIG_LIBRGA
++ RgaSURF_FORMAT format = rkmpp_get_rgaformat(mpp_frame_get_fmt(mppframe));
++#endif
++ int width = mpp_frame_get_width(mppframe);
++ int height = mpp_frame_get_height(mppframe);
++ int hstride = mpp_frame_get_hor_stride(mppframe);
++ int vstride = mpp_frame_get_ver_stride(mppframe);
++ int y_pitch = frame->linesize[0];
++ int u_pitch = frame->linesize[1];
++ int v_pitch = frame->linesize[2];
++ int i, j;
++
++#if CONFIG_LIBRGA
++ rga_info_t src_info = {0};
++ rga_info_t dst_info = {0};
++ int dst_height = (dst_u - dst_y) / y_pitch;
++
++ static int rga_supported = 1;
++ static int rga_inited = 0;
++
++ if (!rga_supported)
++ goto bail;
++
++ if (!rga_inited) {
++ if (c_RkRgaInit() < 0) {
++ rga_supported = 0;
++ av_log(avctx, AV_LOG_WARNING, "RGA not available\n");
++ goto bail;
++ }
++ rga_inited = 1;
++ }
++
++ if (format == RK_FORMAT_UNKNOWN)
++ goto bail;
++
++ if (u_pitch != y_pitch / 2 || v_pitch != y_pitch / 2 ||
++ dst_u != dst_y + y_pitch * dst_height ||
++ dst_v != dst_u + u_pitch * dst_height / 2)
++ goto bail;
++
++ src_info.fd = mpp_buffer_get_fd(buffer);
++ src_info.mmuFlag = 1;
++ rga_set_rect(&src_info.rect, 0, 0, width, height, hstride, vstride,
++ format);
++
++ dst_info.virAddr = dst_y;
++ dst_info.mmuFlag = 1;
++ rga_set_rect(&dst_info.rect, 0, 0, frame->width, frame->height,
++ y_pitch, dst_height, RK_FORMAT_YCbCr_420_P);
++
++ if (c_RkRgaBlit(&src_info, &dst_info, NULL) < 0)
++ goto bail;
++
++ return 0;
++
++bail:
++#endif
++ if (mpp_frame_get_fmt(mppframe) != MPP_FMT_YUV420SP) {
++ av_log(avctx, AV_LOG_WARNING, "Unable to convert\n");
++ return -1;
++ }
++
++ av_log(avctx, AV_LOG_WARNING, "Doing slow software conversion\n");
++
++ for (i = 0; i < frame->height; i++)
++ memcpy(dst_y + i * y_pitch, src + i * hstride, frame->width);
++
++ src += hstride * vstride;
++
++ for (i = 0; i < frame->height / 2; i++) {
++ for (j = 0; j < frame->width; j++) {
++ dst_u[j] = src[2 * j + 0];
++ dst_v[j] = src[2 * j + 1];
++ }
++ dst_u += u_pitch;
++ dst_v += v_pitch;
++ src += hstride;
++ }
++
++ return 0;
++}
++
+ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
+ {
+ RKMPPDecodeContext *rk_context = avctx->priv_data;
+@@ -355,6 +460,16 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
+ frame->format = avctx->pix_fmt;
+ frame->width = mpp_frame_get_width(mppframe);
+ frame->height = mpp_frame_get_height(mppframe);
++
++ if (avctx->pix_fmt != AV_PIX_FMT_DRM_PRIME) {
++ ret = ff_get_buffer(avctx, frame, 0);
++ if (ret < 0)
++ goto out;
++
++ ret = rkmpp_convert_frame(avctx, frame, mppframe, buffer);
++ goto out;
++ }
++
+ frame->pts = mpp_frame_get_pts(mppframe);
+ #if FF_API_PKT_PTS
+ FF_DISABLE_DEPRECATION_WARNINGS;
+@@ -427,6 +542,7 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
+
+ return 0;
+
++out:
+ fail:
+ if (mppframe)
+ mpp_frame_deinit(&mppframe);
+@@ -571,6 +687,7 @@ static void rkmpp_flush(AVCodecContext *avctx)
+
+ static const AVCodecHWConfigInternal *const rkmpp_hw_configs[] = {
+ HW_CONFIG_INTERNAL(DRM_PRIME),
++ HW_CONFIG_INTERNAL(YUV420P),
+ NULL
+ };
+
+@@ -595,6 +712,7 @@ static const AVCodecHWConfigInternal *const rkmpp_hw_configs[] = {
+ .priv_class = &rkmpp_##NAME##_dec_class, \
+ .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, \
+ .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_DRM_PRIME, \
++ AV_PIX_FMT_YUV420P, \
+ AV_PIX_FMT_NONE}, \
+ .hw_configs = rkmpp_hw_configs, \
+ .bsfs = BSFS, \
+--
+2.39.0
+
+
+From ad6f4d3518eea4795f457b81d44d27da943be982 Mon Sep 17 00:00:00 2001
+From: Jeffy Chen <jeffy.chen@rock-chips.com>
+Date: Mon, 27 Sep 2021 10:20:54 +0800
+Subject: [PATCH 07/16] avcodec/rkmppdec: Support logging fps
+
+Set env FFMPEG_RKMPP_LOG_FPS=1 to enable it.
+
+Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
+---
+ libavcodec/rkmppdec.c | 46 +++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 46 insertions(+)
+
+diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
+index c621e687e0..82834c27a6 100644
+--- a/libavcodec/rkmppdec.c
++++ b/libavcodec/rkmppdec.c
+@@ -25,6 +25,7 @@
+ #include <rockchip/rk_mpi.h>
+ #include <time.h>
+ #include <unistd.h>
++#include <sys/time.h>
+
+ #include "avcodec.h"
+ #include "decode.h"
+@@ -43,6 +44,8 @@
+ #include <rga/RgaApi.h>
+ #endif
+
++#define FPS_UPDATE_INTERVAL 120
++
+ typedef struct {
+ MppCtx ctx;
+ MppApi *mpi;
+@@ -54,6 +57,11 @@ typedef struct {
+ AVPacket packet;
+ AVBufferRef *frames_ref;
+ AVBufferRef *device_ref;
++
++ char print_fps;
++
++ uint64_t last_fps_time;
++ uint64_t frames;
+ } RKMPPDecoder;
+
+ typedef struct {
+@@ -156,6 +164,7 @@ static int rkmpp_init_decoder(AVCodecContext *avctx)
+ RKMPPDecodeContext *rk_context = avctx->priv_data;
+ RKMPPDecoder *decoder = NULL;
+ MppCodingType codectype = MPP_VIDEO_CodingUnused;
++ char *env;
+ int ret;
+
+ avctx->pix_fmt = ff_get_format(avctx, avctx->codec->pix_fmts);
+@@ -167,6 +176,10 @@ static int rkmpp_init_decoder(AVCodecContext *avctx)
+ goto fail;
+ }
+
++ env = getenv("FFMPEG_RKMPP_LOG_FPS");
++ if (env != NULL)
++ decoder->print_fps = !!atoi(env);
++
+ rk_context->decoder_ref = av_buffer_create((uint8_t *)decoder, sizeof(*decoder), rkmpp_release_decoder,
+ NULL, AV_BUFFER_FLAG_READONLY);
+ if (!rk_context->decoder_ref) {
+@@ -353,6 +366,36 @@ bail:
+ return 0;
+ }
+
++static void rkmpp_update_fps(AVCodecContext *avctx)
++{
++ RKMPPDecodeContext *rk_context = avctx->priv_data;
++ RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data;
++ struct timeval tv;
++ uint64_t curr_time;
++ float fps;
++
++ if (!decoder->print_fps)
++ return;
++
++ if (!decoder->last_fps_time) {
++ gettimeofday(&tv, NULL);
++ decoder->last_fps_time = tv.tv_sec * 1000 + tv.tv_usec / 1000;
++ }
++
++ if (++decoder->frames % FPS_UPDATE_INTERVAL)
++ return;
++
++ gettimeofday(&tv, NULL);
++ curr_time = tv.tv_sec * 1000 + tv.tv_usec / 1000;
++
++ fps = 1000.0f * FPS_UPDATE_INTERVAL / (curr_time - decoder->last_fps_time);
++ decoder->last_fps_time = curr_time;
++
++ av_log(avctx, AV_LOG_INFO,
++ "[FFMPEG RKMPP] FPS: %6.1f || Frames: %" PRIu64 "\n",
++ fps, decoder->frames);
++}
++
+ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
+ {
+ RKMPPDecodeContext *rk_context = avctx->priv_data;
+@@ -456,6 +499,8 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
+ goto fail;
+ }
+
++ rkmpp_update_fps(avctx);
++
+ // setup general frame fields
+ frame->format = avctx->pix_fmt;
+ frame->width = mpp_frame_get_width(mppframe);
+@@ -681,6 +726,7 @@ static void rkmpp_flush(AVCodecContext *avctx)
+
+ decoder->eos = 0;
+ decoder->draining = 0;
++ decoder->last_fps_time = decoder->frames = 0;
+
+ av_packet_unref(&decoder->packet);
+ }
+--
+2.39.0
+
+
+From 8b7cfe72359520a7f1cae3b3ce935a2ea549f705 Mon Sep 17 00:00:00 2001
+From: boogie <boogiepop@gmx.com>
+Date: Thu, 5 Jan 2023 22:41:48 +0100
+Subject: [PATCH 08/16] HACK: libavcodec & rkmppdec: Add
+ FF_CODEC_CAP_CONTIGUOUS_BUFFERS
+
+Add FF_CODEC_CAP_CONTIGUOUS_BUFFERS to alloc contiguous buffers.
+
+Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
+---
+ libavcodec/decode.c | 23 +++++++++++++++++++++++
+ libavcodec/internal.h | 4 ++++
+ libavcodec/rkmppdec.c | 19 ++++++++++---------
+ 3 files changed, 37 insertions(+), 9 deletions(-)
+
+diff --git a/libavcodec/decode.c b/libavcodec/decode.c
+index 936e5d63da..dfd9ed656d 100644
+--- a/libavcodec/decode.c
++++ b/libavcodec/decode.c
+@@ -1549,6 +1549,14 @@ static int update_frame_pool(AVCodecContext *avctx, AVFrame *frame)
+
+ for (i = 0; i < 4; i++) {
+ pool->linesize[i] = linesize[i];
++
++ if (avctx->codec->caps_internal & FF_CODEC_CAP_CONTIGUOUS_BUFFERS) {
++ if (!i)
++ size[0] += size[1] + size[2] + size[3];
++ else
++ continue;
++ }
++
+ if (size[i]) {
+ if (size[i] > INT_MAX - (16 + STRIDE_ALIGN - 1)) {
+ ret = AVERROR(EINVAL);
+@@ -1675,6 +1683,21 @@ static int video_get_buffer(AVCodecContext *s, AVFrame *pic)
+
+ pic->data[i] = pic->buf[i]->data;
+ }
++
++ if (s->codec->caps_internal & FF_CODEC_CAP_CONTIGUOUS_BUFFERS) {
++ int size;
++
++ for (i = 1; i < 4; i++) {
++ pic->linesize[i] = pool->linesize[i];
++ av_buffer_unref(pic->buf[i]);
++ }
++
++ size = av_image_fill_pointers(pic->data, pic->format, pic->height,
++ pic->buf[0]->data, pic->linesize);
++ if (size < 0 || size > pic->buf[0]->size)
++ goto fail;
++ }
++
+ for (; i < AV_NUM_DATA_POINTERS; i++) {
+ pic->data[i] = NULL;
+ pic->linesize[i] = 0;
+diff --git a/libavcodec/internal.h b/libavcodec/internal.h
+index d889c1883e..47e6a1d13b 100644
+--- a/libavcodec/internal.h
++++ b/libavcodec/internal.h
+@@ -89,6 +89,10 @@
+ */
+ #define FF_CODEC_TAGS_END -1
+
++/**
++ * The decoder requires contiguous buffers.
++ */
++#define FF_CODEC_CAP_CONTIGUOUS_BUFFERS (1 << 31)
+
+ #ifdef TRACE
+ # define ff_tlog(ctx, ...) av_log(ctx, AV_LOG_TRACE, __VA_ARGS__)
+diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
+index 82834c27a6..a05c77977d 100644
+--- a/libavcodec/rkmppdec.c
++++ b/libavcodec/rkmppdec.c
+@@ -501,20 +501,15 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
+
+ rkmpp_update_fps(avctx);
+
+- // setup general frame fields
+- frame->format = avctx->pix_fmt;
+- frame->width = mpp_frame_get_width(mppframe);
+- frame->height = mpp_frame_get_height(mppframe);
+-
+ if (avctx->pix_fmt != AV_PIX_FMT_DRM_PRIME) {
+ ret = ff_get_buffer(avctx, frame, 0);
+ if (ret < 0)
+ goto out;
+-
+- ret = rkmpp_convert_frame(avctx, frame, mppframe, buffer);
+- goto out;
+ }
+-
++ // setup general frame fields
++ frame->format = avctx->pix_fmt;
++ frame->width = mpp_frame_get_width(mppframe);
++ frame->height = mpp_frame_get_height(mppframe);
+ frame->pts = mpp_frame_get_pts(mppframe);
+ #if FF_API_PKT_PTS
+ FF_DISABLE_DEPRECATION_WARNINGS;
+@@ -531,6 +526,11 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
+ frame->interlaced_frame = ((mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK) == MPP_FRAME_FLAG_DEINTERLACED);
+ frame->top_field_first = ((mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK) == MPP_FRAME_FLAG_TOP_FIRST);
+
++ if (avctx->pix_fmt != AV_PIX_FMT_DRM_PRIME) {
++ ret = rkmpp_convert_frame(avctx, frame, mppframe, buffer);
++ goto out;
++ }
++
+ mppformat = mpp_frame_get_fmt(mppframe);
+ drmformat = rkmpp_get_frameformat(mppformat);
+
+@@ -757,6 +757,7 @@ static const AVCodecHWConfigInternal *const rkmpp_hw_configs[] = {
+ .flush = rkmpp_flush, \
+ .priv_class = &rkmpp_##NAME##_dec_class, \
+ .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, \
++ .caps_internal = FF_CODEC_CAP_CONTIGUOUS_BUFFERS, \
+ .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_DRM_PRIME, \
+ AV_PIX_FMT_YUV420P, \
+ AV_PIX_FMT_NONE}, \
+--
+2.39.0
+
+
+From d1ab43ce9ccb0b832dc1bd620785a1a455e15bed Mon Sep 17 00:00:00 2001
+From: Jeffy Chen <jeffy.chen@rock-chips.com>
+Date: Mon, 13 Dec 2021 15:44:43 +0800
+Subject: [PATCH 09/16] HACK: avcodec/rkmppdec: Define DRM_FORMAT_NV12_10
+
+DRM_FORMAT_NV12_10 is a downstream custom format for Rockchip.
+
+Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
+---
+ libavcodec/rkmppdec.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
+index a05c77977d..2aa3ee2a30 100644
+--- a/libavcodec/rkmppdec.c
++++ b/libavcodec/rkmppdec.c
+@@ -44,6 +44,10 @@
+ #include <rga/RgaApi.h>
+ #endif
+
++#ifndef DRM_FORMAT_NV12_10
++#define DRM_FORMAT_NV12_10 fourcc_code('N', 'A', '1', '2')
++#endif
++
+ #define FPS_UPDATE_INTERVAL 120
+
+ typedef struct {
+@@ -89,9 +93,7 @@ static uint32_t rkmpp_get_frameformat(MppFrameFormat mppformat)
+ {
+ switch (mppformat) {
+ case MPP_FMT_YUV420SP: return DRM_FORMAT_NV12;
+-#ifdef DRM_FORMAT_NV12_10
+ case MPP_FMT_YUV420SP_10BIT: return DRM_FORMAT_NV12_10;
+-#endif
+ default: return 0;
+ }
+ }
+--
+2.39.0
+
+
+From 486ff6b9a813c48bca125b04a33088c5b3bf512d Mon Sep 17 00:00:00 2001
+From: Jeffy Chen <jeffy.chen@rock-chips.com>
+Date: Wed, 15 Dec 2021 15:34:48 +0800
+Subject: [PATCH 10/16] avcodec/rkmppdec: Support NV16
+
+The MPP might output NV16 format.
+
+Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
+---
+ libavcodec/rkmppdec.c | 15 +++++++++++++--
+ 1 file changed, 13 insertions(+), 2 deletions(-)
+
+diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
+index 2aa3ee2a30..82288cad03 100644
+--- a/libavcodec/rkmppdec.c
++++ b/libavcodec/rkmppdec.c
+@@ -94,6 +94,17 @@ static uint32_t rkmpp_get_frameformat(MppFrameFormat mppformat)
+ switch (mppformat) {
+ case MPP_FMT_YUV420SP: return DRM_FORMAT_NV12;
+ case MPP_FMT_YUV420SP_10BIT: return DRM_FORMAT_NV12_10;
++ case MPP_FMT_YUV422SP: return DRM_FORMAT_NV16;
++ default: return 0;
++ }
++}
++
++static uint32_t rkmpp_get_avformat(MppFrameFormat mppformat)
++{
++ switch (mppformat) {
++ case MPP_FMT_YUV420SP: return AV_PIX_FMT_NV12;
++ case MPP_FMT_YUV420SP_10BIT: return AV_PIX_FMT_NONE;
++ case MPP_FMT_YUV422SP: return AV_PIX_FMT_NV16;
+ default: return 0;
+ }
+ }
+@@ -104,6 +115,7 @@ static uint32_t rkmpp_get_rgaformat(MppFrameFormat mppformat)
+ switch (mppformat) {
+ case MPP_FMT_YUV420SP: return RK_FORMAT_YCbCr_420_SP;
+ case MPP_FMT_YUV420SP_10BIT: return RK_FORMAT_YCbCr_420_SP_10B;
++ case MPP_FMT_YUV422SP: return RK_FORMAT_YCbCr_422_SP;
+ default: return RK_FORMAT_UNKNOWN;
+ }
+ }
+@@ -476,11 +488,10 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
+ }
+
+ mppformat = mpp_frame_get_fmt(mppframe);
+- drmformat = rkmpp_get_frameformat(mppformat);
+
+ hwframes = (AVHWFramesContext*)decoder->frames_ref->data;
+ hwframes->format = AV_PIX_FMT_DRM_PRIME;
+- hwframes->sw_format = drmformat == DRM_FORMAT_NV12 ? AV_PIX_FMT_NV12 : AV_PIX_FMT_NONE;
++ hwframes->sw_format = rkmpp_get_avformat(mppformat);
+ hwframes->width = avctx->width;
+ hwframes->height = avctx->height;
+ ret = av_hwframe_ctx_init(decoder->frames_ref);
+--
+2.39.0
+
+
+From 7bf50d04f27c963a1bac402beb04f8f13a3773a4 Mon Sep 17 00:00:00 2001
+From: Jeffy Chen <jeffy.chen@rock-chips.com>
+Date: Wed, 23 Mar 2022 14:20:16 +0800
+Subject: [PATCH 11/16] avcodec/rkmppdec: Support sync mode
+
+Some people just don't know how to handle async APIs :(
+
+Support sync mode by waiting for decode result after feeding any packets.
+
+Set env "FFMPEG_RKMPP_SYNC" to enable it.
+
+Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
+---
+ libavcodec/rkmppdec.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
+index 82288cad03..c8b400e910 100644
+--- a/libavcodec/rkmppdec.c
++++ b/libavcodec/rkmppdec.c
+@@ -66,6 +66,8 @@ typedef struct {
+
+ uint64_t last_fps_time;
+ uint64_t frames;
++
++ char sync;
+ } RKMPPDecoder;
+
+ typedef struct {
+@@ -170,6 +172,13 @@ static int rkmpp_prepare_decoder(AVCodecContext *avctx)
+ if (ret < 0)
+ return AVERROR_UNKNOWN;
+ }
++
++ if (getenv("FFMPEG_RKMPP_SYNC")) {
++ // wait for decode result after feeding any packets
++ decoder->sync = 1;
++ ret = 1;
++ decoder->mpi->control(decoder->ctx, MPP_DEC_SET_IMMEDIATE_OUT, &ret);
++ }
+ return 0;
+ }
+
+@@ -721,6 +730,10 @@ static int rkmpp_receive_frame(AVCodecContext *avctx, AVFrame *frame)
+ } else {
+ av_packet_unref(packet);
+ packet->size = 0;
++
++ // blocked waiting for decode result
++ if (decoder->sync)
++ return rkmpp_get_frame(avctx, frame, MPP_TIMEOUT_BLOCK);
+ }
+ }
+ }
+--
+2.39.0
+
+
+From 8725010e4431bc5f8933e0389b195ba7f8a8fa46 Mon Sep 17 00:00:00 2001
+From: boogie <boogiepop@gmx.com>
+Date: Thu, 5 Jan 2023 23:04:45 +0100
+Subject: [PATCH 12/16] avcodec/rkmppdec: Add H263/MPEG1/MPEG2/MPEG4
+
+Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
+---
+ configure | 4 ++++
+ libavcodec/Makefile | 4 ++++
+ libavcodec/allcodecs.c | 4 ++++
+ libavcodec/rkmppdec.c | 8 ++++++++
+ 4 files changed, 20 insertions(+)
+
+diff --git a/configure b/configure
+index 9e08481e11..6e72375e09 100755
+--- a/configure
++++ b/configure
+@@ -3074,6 +3074,7 @@ ac3_mf_encoder_deps="mediafoundation"
+ av1_cuvid_decoder_deps="cuvid CUVIDAV1PICPARAMS"
+ h263_v4l2m2m_decoder_deps="v4l2_m2m h263_v4l2_m2m"
+ h263_v4l2m2m_encoder_deps="v4l2_m2m h263_v4l2_m2m"
++h263_rkmpp_decoder_deps="rkmpp"
+ h264_amf_encoder_deps="amf"
+ h264_crystalhd_decoder_select="crystalhd h264_mp4toannexb_bsf h264_parser"
+ h264_cuvid_decoder_deps="cuvid"
+@@ -3119,6 +3120,7 @@ mjpeg_vaapi_encoder_select="cbs_jpeg jpegtables vaapi_encode"
+ mp3_mf_encoder_deps="mediafoundation"
+ mpeg1_cuvid_decoder_deps="cuvid"
+ mpeg1_v4l2m2m_decoder_deps="v4l2_m2m mpeg1_v4l2_m2m"
++mpeg1_rkmpp_decoder_deps="rkmpp"
+ mpeg2_crystalhd_decoder_select="crystalhd"
+ mpeg2_cuvid_decoder_deps="cuvid"
+ mpeg2_mmal_decoder_deps="mmal"
+@@ -3127,6 +3129,7 @@ mpeg2_qsv_decoder_select="qsvdec"
+ mpeg2_qsv_encoder_select="qsvenc"
+ mpeg2_vaapi_encoder_select="cbs_mpeg2 vaapi_encode"
+ mpeg2_v4l2m2m_decoder_deps="v4l2_m2m mpeg2_v4l2_m2m"
++mpeg2_rkmpp_decoder_deps="rkmpp"
+ mpeg4_crystalhd_decoder_select="crystalhd"
+ mpeg4_cuvid_decoder_deps="cuvid"
+ mpeg4_mediacodec_decoder_deps="mediacodec"
+@@ -3134,6 +3137,7 @@ mpeg4_mmal_decoder_deps="mmal"
+ mpeg4_omx_encoder_deps="omx"
+ mpeg4_v4l2m2m_decoder_deps="v4l2_m2m mpeg4_v4l2_m2m"
+ mpeg4_v4l2m2m_encoder_deps="v4l2_m2m mpeg4_v4l2_m2m"
++mpeg4_rkmpp_decoder_deps="rkmpp"
+ msmpeg4_crystalhd_decoder_select="crystalhd"
+ nvenc_h264_encoder_select="h264_nvenc_encoder"
+ nvenc_hevc_encoder_select="hevc_nvenc_encoder"
+diff --git a/libavcodec/Makefile b/libavcodec/Makefile
+index b3d284d7d0..345b6a5816 100644
+--- a/libavcodec/Makefile
++++ b/libavcodec/Makefile
+@@ -364,6 +364,7 @@ OBJS-$(CONFIG_H263_ENCODER) += mpeg4video.o \
+ h263.o ituh263enc.o h263data.o
+ OBJS-$(CONFIG_H263_V4L2M2M_DECODER) += v4l2_m2m_dec.o
+ OBJS-$(CONFIG_H263_V4L2M2M_ENCODER) += v4l2_m2m_enc.o
++OBJS-$(CONFIG_H263_RKMPP_DECODER) += rkmppdec.o
+ OBJS-$(CONFIG_H264_DECODER) += h264dec.o h264_cabac.o h264_cavlc.o \
+ h264_direct.o h264_loopfilter.o \
+ h264_mb.o h264_picture.o \
+@@ -488,6 +489,7 @@ OBJS-$(CONFIG_MPEG1VIDEO_DECODER) += mpeg12dec.o mpeg12.o mpeg12data.o
+ OBJS-$(CONFIG_MPEG1VIDEO_ENCODER) += mpeg12enc.o mpeg12.o
+ OBJS-$(CONFIG_MPEG1_CUVID_DECODER) += cuviddec.o
+ OBJS-$(CONFIG_MPEG1_V4L2M2M_DECODER) += v4l2_m2m_dec.o
++OBJS-$(CONFIG_MPEG1_RKMPP_DECODER) += rkmppdec.o
+ OBJS-$(CONFIG_MPEG2_MMAL_DECODER) += mmaldec.o
+ OBJS-$(CONFIG_MPEG2_QSV_DECODER) += qsvdec.o
+ OBJS-$(CONFIG_MPEG2_QSV_ENCODER) += qsvenc_mpeg2.o
+@@ -497,6 +499,7 @@ OBJS-$(CONFIG_MPEG2_CUVID_DECODER) += cuviddec.o
+ OBJS-$(CONFIG_MPEG2_MEDIACODEC_DECODER) += mediacodecdec.o
+ OBJS-$(CONFIG_MPEG2_VAAPI_ENCODER) += vaapi_encode_mpeg2.o
+ OBJS-$(CONFIG_MPEG2_V4L2M2M_DECODER) += v4l2_m2m_dec.o
++OBJS-$(CONFIG_MPEG2_RKMPP_DECODER) += rkmppdec.o
+ OBJS-$(CONFIG_MPEG4_DECODER) += xvididct.o
+ OBJS-$(CONFIG_MPEG4_ENCODER) += mpeg4videoenc.o
+ OBJS-$(CONFIG_MPEG4_CUVID_DECODER) += cuviddec.o
+@@ -504,6 +507,7 @@ OBJS-$(CONFIG_MPEG4_MEDIACODEC_DECODER) += mediacodecdec.o
+ OBJS-$(CONFIG_MPEG4_OMX_ENCODER) += omx.o
+ OBJS-$(CONFIG_MPEG4_V4L2M2M_DECODER) += v4l2_m2m_dec.o
+ OBJS-$(CONFIG_MPEG4_V4L2M2M_ENCODER) += v4l2_m2m_enc.o
++OBJS-$(CONFIG_MPEG4_RKMPP_DECODER) += rkmppdec.o
+ OBJS-$(CONFIG_MPL2_DECODER) += mpl2dec.o ass.o
+ OBJS-$(CONFIG_MSA1_DECODER) += mss3.o
+ OBJS-$(CONFIG_MSCC_DECODER) += mscc.o
+diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
+index 2e9a3581de..5b2d8abe80 100644
+--- a/libavcodec/allcodecs.c
++++ b/libavcodec/allcodecs.c
+@@ -140,6 +140,7 @@ extern AVCodec ff_h263_decoder;
+ extern AVCodec ff_h263i_decoder;
+ extern AVCodec ff_h263p_encoder;
+ extern AVCodec ff_h263p_decoder;
++extern AVCodec ff_h263_rkmpp_decoder;
+ extern AVCodec ff_h263_v4l2m2m_decoder;
+ extern AVCodec ff_h264_decoder;
+ extern AVCodec ff_h264_crystalhd_decoder;
+@@ -199,11 +200,14 @@ extern AVCodec ff_mpeg2video_decoder;
+ extern AVCodec ff_mpeg4_encoder;
+ extern AVCodec ff_mpeg4_decoder;
+ extern AVCodec ff_mpeg4_crystalhd_decoder;
++extern AVCodec ff_mpeg4_rkmpp_decoder;
+ extern AVCodec ff_mpeg4_v4l2m2m_decoder;
+ extern AVCodec ff_mpeg4_mmal_decoder;
+ extern AVCodec ff_mpegvideo_decoder;
++extern AVCodec ff_mpeg1_rkmpp_decoder;
+ extern AVCodec ff_mpeg1_v4l2m2m_decoder;
+ extern AVCodec ff_mpeg2_mmal_decoder;
++extern AVCodec ff_mpeg2_rkmpp_decoder;
+ extern AVCodec ff_mpeg2_crystalhd_decoder;
+ extern AVCodec ff_mpeg2_v4l2m2m_decoder;
+ extern AVCodec ff_mpeg2_qsv_decoder;
+diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
+index c8b400e910..79baab932d 100644
+--- a/libavcodec/rkmppdec.c
++++ b/libavcodec/rkmppdec.c
+@@ -83,10 +83,14 @@ typedef struct {
+ static MppCodingType rkmpp_get_codingtype(AVCodecContext *avctx)
+ {
+ switch (avctx->codec_id) {
++ case AV_CODEC_ID_H263: return MPP_VIDEO_CodingH263;
+ case AV_CODEC_ID_H264: return MPP_VIDEO_CodingAVC;
+ case AV_CODEC_ID_HEVC: return MPP_VIDEO_CodingHEVC;
+ case AV_CODEC_ID_VP8: return MPP_VIDEO_CodingVP8;
+ case AV_CODEC_ID_VP9: return MPP_VIDEO_CodingVP9;
++ case AV_CODEC_ID_MPEG1VIDEO: /* fallthrough */
++ case AV_CODEC_ID_MPEG2VIDEO: return MPP_VIDEO_CodingMPEG2;
++ case AV_CODEC_ID_MPEG4: return MPP_VIDEO_CodingMPEG4;
+ default: return MPP_VIDEO_CodingUnused;
+ }
+ }
+@@ -792,7 +796,11 @@ static const AVCodecHWConfigInternal *const rkmpp_hw_configs[] = {
+ .wrapper_name = "rkmpp", \
+ };
+
++RKMPP_DEC(h263, AV_CODEC_ID_H263, NULL)
+ RKMPP_DEC(h264, AV_CODEC_ID_H264, "h264_mp4toannexb")
+ RKMPP_DEC(hevc, AV_CODEC_ID_HEVC, "hevc_mp4toannexb")
+ RKMPP_DEC(vp8, AV_CODEC_ID_VP8, NULL)
+ RKMPP_DEC(vp9, AV_CODEC_ID_VP9, NULL)
++RKMPP_DEC(mpeg1, AV_CODEC_ID_MPEG1VIDEO, NULL)
++RKMPP_DEC(mpeg2, AV_CODEC_ID_MPEG2VIDEO, NULL)
++RKMPP_DEC(mpeg4, AV_CODEC_ID_MPEG4, "mpeg4_unpack_bframes")
+--
+2.39.0
+
+
+From a1795f4a3ea85a4b499765a66427db8d39c844da Mon Sep 17 00:00:00 2001
+From: boogie <boogiepop@gmx.com>
+Date: Fri, 6 Jan 2023 20:39:23 +0100
+Subject: [PATCH 13/16] allow nv15 and allow probing
+
+---
+ libavcodec/rkmppdec.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
+index 79baab932d..93c426eeb3 100644
+--- a/libavcodec/rkmppdec.c
++++ b/libavcodec/rkmppdec.c
+@@ -45,7 +45,7 @@
+ #endif
+
+ #ifndef DRM_FORMAT_NV12_10
+-#define DRM_FORMAT_NV12_10 fourcc_code('N', 'A', '1', '2')
++#define DRM_FORMAT_NV12_10 fourcc_code('N', 'A', '1', '5')
+ #endif
+
+ #define FPS_UPDATE_INTERVAL 120
+@@ -786,7 +786,7 @@ static const AVCodecHWConfigInternal *const rkmpp_hw_configs[] = {
+ .receive_frame = rkmpp_receive_frame, \
+ .flush = rkmpp_flush, \
+ .priv_class = &rkmpp_##NAME##_dec_class, \
+- .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, \
++ .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, \
+ .caps_internal = FF_CODEC_CAP_CONTIGUOUS_BUFFERS, \
+ .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_DRM_PRIME, \
+ AV_PIX_FMT_YUV420P, \
+--
+2.39.0
+
+
+From 73f8dc251ae7111b2f8ce9c4084071e157765e33 Mon Sep 17 00:00:00 2001
+From: boogie <boogiepop@gmx.com>
+Date: Fri, 6 Jan 2023 21:36:04 +0100
+Subject: [PATCH 14/16] priotrize the rkmpp variants first
+
+---
+ libavcodec/allcodecs.c | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
+index 5b2d8abe80..409e7f33e4 100644
+--- a/libavcodec/allcodecs.c
++++ b/libavcodec/allcodecs.c
+@@ -135,25 +135,25 @@ extern AVCodec ff_gif_encoder;
+ extern AVCodec ff_gif_decoder;
+ extern AVCodec ff_h261_encoder;
+ extern AVCodec ff_h261_decoder;
++extern AVCodec ff_h263_rkmpp_decoder;
+ extern AVCodec ff_h263_encoder;
+ extern AVCodec ff_h263_decoder;
+ extern AVCodec ff_h263i_decoder;
+ extern AVCodec ff_h263p_encoder;
+ extern AVCodec ff_h263p_decoder;
+-extern AVCodec ff_h263_rkmpp_decoder;
+ extern AVCodec ff_h263_v4l2m2m_decoder;
++extern AVCodec ff_h264_rkmpp_decoder;
+ extern AVCodec ff_h264_decoder;
+ extern AVCodec ff_h264_crystalhd_decoder;
+ extern AVCodec ff_h264_v4l2m2m_decoder;
+ extern AVCodec ff_h264_mediacodec_decoder;
+ extern AVCodec ff_h264_mmal_decoder;
+ extern AVCodec ff_h264_qsv_decoder;
+-extern AVCodec ff_h264_rkmpp_decoder;
+ extern AVCodec ff_hap_encoder;
+ extern AVCodec ff_hap_decoder;
++extern AVCodec ff_hevc_rkmpp_decoder;
+ extern AVCodec ff_hevc_decoder;
+ extern AVCodec ff_hevc_qsv_decoder;
+-extern AVCodec ff_hevc_rkmpp_decoder;
+ extern AVCodec ff_hevc_v4l2m2m_decoder;
+ extern AVCodec ff_hnm4_video_decoder;
+ extern AVCodec ff_hq_hqa_decoder;
+@@ -193,21 +193,21 @@ extern AVCodec ff_mjpegb_decoder;
+ extern AVCodec ff_mmvideo_decoder;
+ extern AVCodec ff_mobiclip_decoder;
+ extern AVCodec ff_motionpixels_decoder;
++extern AVCodec ff_mpeg1_rkmpp_decoder;
+ extern AVCodec ff_mpeg1video_encoder;
+ extern AVCodec ff_mpeg1video_decoder;
+ extern AVCodec ff_mpeg2video_encoder;
+ extern AVCodec ff_mpeg2video_decoder;
++extern AVCodec ff_mpeg4_rkmpp_decoder;
+ extern AVCodec ff_mpeg4_encoder;
+ extern AVCodec ff_mpeg4_decoder;
+ extern AVCodec ff_mpeg4_crystalhd_decoder;
+-extern AVCodec ff_mpeg4_rkmpp_decoder;
+ extern AVCodec ff_mpeg4_v4l2m2m_decoder;
+ extern AVCodec ff_mpeg4_mmal_decoder;
+ extern AVCodec ff_mpegvideo_decoder;
+-extern AVCodec ff_mpeg1_rkmpp_decoder;
+ extern AVCodec ff_mpeg1_v4l2m2m_decoder;
+-extern AVCodec ff_mpeg2_mmal_decoder;
+ extern AVCodec ff_mpeg2_rkmpp_decoder;
++extern AVCodec ff_mpeg2_mmal_decoder;
+ extern AVCodec ff_mpeg2_crystalhd_decoder;
+ extern AVCodec ff_mpeg2_v4l2m2m_decoder;
+ extern AVCodec ff_mpeg2_qsv_decoder;
+@@ -360,11 +360,11 @@ extern AVCodec ff_vp6_decoder;
+ extern AVCodec ff_vp6a_decoder;
+ extern AVCodec ff_vp6f_decoder;
+ extern AVCodec ff_vp7_decoder;
+-extern AVCodec ff_vp8_decoder;
+ extern AVCodec ff_vp8_rkmpp_decoder;
++extern AVCodec ff_vp8_decoder;
+ extern AVCodec ff_vp8_v4l2m2m_decoder;
+-extern AVCodec ff_vp9_decoder;
+ extern AVCodec ff_vp9_rkmpp_decoder;
++extern AVCodec ff_vp9_decoder;
+ extern AVCodec ff_vp9_v4l2m2m_decoder;
+ extern AVCodec ff_vqa_decoder;
+ extern AVCodec ff_webp_decoder;
+--
+2.39.0
+
+
+From 15cc4a4c861e6c0cb527e023332d875a75b6b732 Mon Sep 17 00:00:00 2001
+From: boogie <boogiepop@gmx.com>
+Date: Fri, 13 Jan 2023 22:27:01 +0100
+Subject: [PATCH 15/16] rkmpp: interface with kernel directly for rga and ditch
+ librga
+
+credit goes to icecream95: https://gitlab.com/-/snippets/2460396
+---
+ libavcodec/rga.h | 574 ++++++++++++++++++++++++++++++++++++++++++
+ libavcodec/rkmppdec.c | 272 ++++++++++++++++----
+ 2 files changed, 803 insertions(+), 43 deletions(-)
+ create mode 100644 libavcodec/rga.h
+
+diff --git a/libavcodec/rga.h b/libavcodec/rga.h
+new file mode 100644
+index 0000000000..9595558de0
+--- /dev/null
++++ b/libavcodec/rga.h
+@@ -0,0 +1,574 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++#ifndef _RGA_DRIVER_H_
++#define _RGA_DRIVER_H_
++
++/* Use 'r' as magic number */
++#define RGA_IOC_MAGIC 'r'
++#define RGA_IOW(nr, type) _IOW(RGA_IOC_MAGIC, nr, type)
++#define RGA_IOR(nr, type) _IOR(RGA_IOC_MAGIC, nr, type)
++#define RGA_IOWR(nr, type) _IOWR(RGA_IOC_MAGIC, nr, type)
++
++#define RGA_IOC_GET_DRVIER_VERSION RGA_IOR(0x1, struct rga_version_t)
++#define RGA_IOC_GET_HW_VERSION RGA_IOR(0x2, struct rga_hw_versions_t)
++#define RGA_IOC_IMPORT_BUFFER RGA_IOWR(0x3, struct rga_buffer_pool)
++#define RGA_IOC_RELEASE_BUFFER RGA_IOW(0x4, struct rga_buffer_pool)
++#define RGA_IOC_REQUEST_CREATE RGA_IOR(0x5, uint32_t)
++#define RGA_IOC_REQUEST_SUBMIT RGA_IOWR(0x6, struct rga_user_request)
++#define RGA_IOC_REQUEST_CONFIG RGA_IOWR(0x7, struct rga_user_request)
++#define RGA_IOC_REQUEST_CANCEL RGA_IOWR(0x8, uint32_t)
++
++#define RGA_BLIT_SYNC 0x5017
++#define RGA_BLIT_ASYNC 0x5018
++#define RGA_FLUSH 0x5019
++#define RGA_GET_RESULT 0x501a
++#define RGA_GET_VERSION 0x501b
++#define RGA_CACHE_FLUSH 0x501c
++
++#define RGA2_GET_VERSION 0x601b
++#define RGA_IMPORT_DMA 0x601d
++#define RGA_RELEASE_DMA 0x601e
++
++#define RGA_TASK_NUM_MAX 50
++
++#define RGA_OUT_OF_RESOURCES -10
++#define RGA_MALLOC_ERROR -11
++
++#define SCALE_DOWN_LARGE 1
++#define SCALE_UP_LARGE 1
++
++#define RGA_BUFFER_POOL_SIZE_MAX 40
++
++#define RGA3_MAJOR_VERSION_MASK (0xF0000000)
++#define RGA3_MINOR_VERSION_MASK (0x0FF00000)
++#define RGA3_SVN_VERSION_MASK (0x000FFFFF)
++
++#define RGA2_MAJOR_VERSION_MASK (0xFF000000)
++#define RGA2_MINOR_VERSION_MASK (0x00F00000)
++#define RGA2_SVN_VERSION_MASK (0x000FFFFF)
++
++#define RGA_MODE_ROTATE_0 (1<<0)
++#define RGA_MODE_ROTATE_90 (1<<1)
++#define RGA_MODE_ROTATE_180 (1<<2)
++#define RGA_MODE_ROTATE_270 (1<<3)
++#define RGA_MODE_X_MIRROR (1<<4)
++#define RGA_MODE_Y_MIRROR (1<<5)
++
++#define RGA_MODE_CSC_BT601L (1<<0)
++#define RGA_MODE_CSC_BT601F (1<<1)
++#define RGA_MODE_CSC_BT709 (1<<2)
++#define RGA_MODE_CSC_BT2020 (1<<3)
++
++#define RGA_MODE_ROTATE_MASK (\
++ RGA_MODE_ROTATE_0 | \
++ RGA_MODE_ROTATE_90 | \
++ RGA_MODE_ROTATE_180 | \
++ RGA_MODE_ROTATE_270 | \
++ RGA_MODE_X_MIRROR | \
++ RGA_MODE_Y_MIRROR)
++
++enum rga_memory_type {
++ RGA_DMA_BUFFER = 0,
++ RGA_VIRTUAL_ADDRESS,
++ RGA_PHYSICAL_ADDRESS,
++ RGA_DMA_BUFFER_PTR,
++};
++
++enum rga_scale_up_mode {
++ RGA_SCALE_UP_NONE = 0x0,
++ RGA_SCALE_UP_BIC = 0x1,
++};
++
++enum rga_scale_down_mode {
++ RGA_SCALE_DOWN_NONE = 0x0,
++ RGA_SCALE_DOWN_AVG = 0x1,
++};
++
++/* RGA process mode enum */
++enum {
++ BITBLT_MODE = 0x0,
++ COLOR_PALETTE_MODE = 0x1,
++ COLOR_FILL_MODE = 0x2,
++ /* used by rga2 */
++ UPDATE_PALETTE_TABLE_MODE = 0x6,
++ UPDATE_PATTEN_BUF_MODE = 0x7,
++}; /*render mode*/
++
++/* RGA rd_mode */
++enum {
++ RGA_RASTER_MODE = 0x1 << 0,
++ RGA_FBC_MODE = 0x1 << 1,
++ RGA_TILE_MODE = 0x1 << 2,
++};
++
++enum {
++ RGA_CONTEXT_NONE = 0x0,
++ RGA_CONTEXT_SRC_FIX_ENABLE = 0x1 << 0,
++ RGA_CONTEXT_SRC_CACHE_INFO = 0x1 << 1,
++ RGA_CONTEXT_SRC_MASK = RGA_CONTEXT_SRC_FIX_ENABLE |
++ RGA_CONTEXT_SRC_CACHE_INFO,
++ RGA_CONTEXT_PAT_FIX_ENABLE = 0x1 << 2,
++ RGA_CONTEXT_PAT_CACHE_INFO = 0x1 << 3,
++ RGA_CONTEXT_PAT_MASK = RGA_CONTEXT_PAT_FIX_ENABLE |
++ RGA_CONTEXT_PAT_CACHE_INFO,
++ RGA_CONTEXT_DST_FIX_ENABLE = 0x1 << 4,
++ RGA_CONTEXT_DST_CACHE_INFO = 0x1 << 5,
++ RGA_CONTEXT_DST_MASK = RGA_CONTEXT_DST_FIX_ENABLE |
++ RGA_CONTEXT_DST_CACHE_INFO,
++};
++
++/* RGA feature */
++enum {
++ RGA_COLOR_FILL = 0x1 << 0,
++ RGA_COLOR_PALETTE = 0x1 << 1,
++ RGA_COLOR_KEY = 0x1 << 2,
++ RGA_ROP_CALCULATE = 0x1 << 3,
++ RGA_NN_QUANTIZE = 0x1 << 4,
++ RGA_OSD_BLEND = 0x1 << 5,
++ RGA_DITHER = 0x1 << 6,
++ RGA_MOSAIC = 0x1 << 7,
++ RGA_YIN_YOUT = 0x1 << 8,
++ RGA_YUV_HDS = 0x1 << 9,
++ RGA_YUV_VDS = 0x1 << 10,
++ RGA_OSD = 0x1 << 11,
++ RGA_PRE_INTR = 0x1 << 12,
++};
++
++enum rga_surf_format {
++ RGA_FORMAT_RGBA_8888 = 0x0,
++ RGA_FORMAT_RGBX_8888 = 0x1,
++ RGA_FORMAT_RGB_888 = 0x2,
++ RGA_FORMAT_BGRA_8888 = 0x3,
++ RGA_FORMAT_RGB_565 = 0x4,
++ RGA_FORMAT_RGBA_5551 = 0x5,
++ RGA_FORMAT_RGBA_4444 = 0x6,
++ RGA_FORMAT_BGR_888 = 0x7,
++
++ RGA_FORMAT_YCbCr_422_SP = 0x8,
++ RGA_FORMAT_YCbCr_422_P = 0x9,
++ RGA_FORMAT_YCbCr_420_SP = 0xa,
++ RGA_FORMAT_YCbCr_420_P = 0xb,
++
++ RGA_FORMAT_YCrCb_422_SP = 0xc,
++ RGA_FORMAT_YCrCb_422_P = 0xd,
++ RGA_FORMAT_YCrCb_420_SP = 0xe,
++ RGA_FORMAT_YCrCb_420_P = 0xf,
++
++ RGA_FORMAT_BPP1 = 0x10,
++ RGA_FORMAT_BPP2 = 0x11,
++ RGA_FORMAT_BPP4 = 0x12,
++ RGA_FORMAT_BPP8 = 0x13,
++
++ RGA_FORMAT_Y4 = 0x14,
++ RGA_FORMAT_YCbCr_400 = 0x15,
++
++ RGA_FORMAT_BGRX_8888 = 0x16,
++
++ RGA_FORMAT_YVYU_422 = 0x18,
++ RGA_FORMAT_YVYU_420 = 0x19,
++ RGA_FORMAT_VYUY_422 = 0x1a,
++ RGA_FORMAT_VYUY_420 = 0x1b,
++ RGA_FORMAT_YUYV_422 = 0x1c,
++ RGA_FORMAT_YUYV_420 = 0x1d,
++ RGA_FORMAT_UYVY_422 = 0x1e,
++ RGA_FORMAT_UYVY_420 = 0x1f,
++
++ RGA_FORMAT_YCbCr_420_SP_10B = 0x20,
++ RGA_FORMAT_YCrCb_420_SP_10B = 0x21,
++ RGA_FORMAT_YCbCr_422_SP_10B = 0x22,
++ RGA_FORMAT_YCrCb_422_SP_10B = 0x23,
++
++ RGA_FORMAT_BGR_565 = 0x24,
++ RGA_FORMAT_BGRA_5551 = 0x25,
++ RGA_FORMAT_BGRA_4444 = 0x26,
++
++ RGA_FORMAT_ARGB_8888 = 0x28,
++ RGA_FORMAT_XRGB_8888 = 0x29,
++ RGA_FORMAT_ARGB_5551 = 0x2a,
++ RGA_FORMAT_ARGB_4444 = 0x2b,
++ RGA_FORMAT_ABGR_8888 = 0x2c,
++ RGA_FORMAT_XBGR_8888 = 0x2d,
++ RGA_FORMAT_ABGR_5551 = 0x2e,
++ RGA_FORMAT_ABGR_4444 = 0x2f,
++
++ RGA_FORMAT_RGBA_2BPP = 0x30,
++
++ RGA_FORMAT_UNKNOWN = 0x100,
++};
++
++#define RGA_SCHED_PRIORITY_DEFAULT 0
++#define RGA_SCHED_PRIORITY_MAX 6
++
++#define RGA_VERSION_SIZE 16
++#define RGA_HW_SIZE 5
++
++struct rga_version_t {
++ uint32_t major;
++ uint32_t minor;
++ uint32_t revision;
++ uint8_t str[RGA_VERSION_SIZE];
++};
++
++struct rga_hw_versions_t {
++ struct rga_version_t version[RGA_HW_SIZE];
++ uint32_t size;
++};
++
++struct rga_memory_parm {
++ uint32_t width;
++ uint32_t height;
++ uint32_t format;
++
++ uint32_t size;
++};
++
++struct rga_external_buffer {
++ uint64_t memory;
++ uint32_t type;
++
++ uint32_t handle;
++ struct rga_memory_parm memory_parm;
++
++ uint8_t reserve[252];
++};
++
++struct rga_buffer_pool {
++ uint64_t buffers_ptr;
++ uint32_t size;
++};
++
++struct rga_color_fill_t {
++ int16_t gr_x_a;
++ int16_t gr_y_a;
++ int16_t gr_x_b;
++ int16_t gr_y_b;
++ int16_t gr_x_g;
++ int16_t gr_y_g;
++ int16_t gr_x_r;
++ int16_t gr_y_r;
++};
++
++/***************************************/
++/* porting from rga.h for msg convert */
++/***************************************/
++
++struct rga_fading_t {
++ uint8_t b;
++ uint8_t g;
++ uint8_t r;
++ uint8_t res;
++};
++
++struct rga_mmu_t {
++ uint8_t mmu_en;
++ uint64_t base_addr;
++ /*
++ * [0] mmu enable [1] src_flush [2] dst_flush
++ * [3] CMD_flush [4~5] page size
++ */
++ uint32_t mmu_flag;
++};
++
++struct rga_rect_t {
++ uint16_t xmin;
++ /* width - 1 */
++ uint16_t xmax;
++ uint16_t ymin;
++ /* height - 1 */
++ uint16_t ymax;
++};
++
++struct rga_point_t {
++ uint16_t x;
++ uint16_t y;
++};
++
++struct rga_line_draw_t {
++ /* LineDraw_start_point */
++ struct rga_point_t start_point;
++ /* LineDraw_end_point */
++ struct rga_point_t end_point;
++ /* LineDraw_color */
++ uint32_t color;
++ /* (enum) LineDrawing mode sel */
++ uint32_t flag;
++ /* range 1~16 */
++ uint32_t line_width;
++};
++
++/* color space convert coefficient. */
++struct rga_csc_coe {
++ int16_t r_v;
++ int16_t g_y;
++ int16_t b_u;
++ int32_t off;
++};
++
++struct rga_full_csc {
++ uint8_t flag;
++ struct rga_csc_coe coe_y;
++ struct rga_csc_coe coe_u;
++ struct rga_csc_coe coe_v;
++};
++
++struct rga_mosaic_info {
++ uint8_t enable;
++ uint8_t mode;
++};
++
++/* MAX(min, (max - channel_value)) */
++struct rga_osd_invert_factor {
++ uint8_t alpha_max;
++ uint8_t alpha_min;
++ uint8_t yg_max;
++ uint8_t yg_min;
++ uint8_t crb_max;
++ uint8_t crb_min;
++};
++
++struct rga_color {
++ union {
++ struct {
++ uint8_t red;
++ uint8_t green;
++ uint8_t blue;
++ uint8_t alpha;
++ };
++ uint32_t value;
++ };
++};
++
++struct rga_osd_bpp2 {
++ uint8_t ac_swap; // ac swap flag
++ // 0: CA
++ // 1: AC
++ uint8_t endian_swap; // rgba2bpp endian swap
++ // 0: Big endian
++ // 1: Little endian
++ struct rga_color color0;
++ struct rga_color color1;
++};
++
++struct rga_osd_mode_ctrl {
++ uint8_t mode; // OSD cal mode:
++ // 0b'1: statistics mode
++ // 1b'1: auto inversion overlap mode
++ uint8_t direction_mode; // horizontal or vertical
++ // 0: horizontal
++ // 1: vertical
++ uint8_t width_mode; // using @fix_width or LUT width
++ // 0: fix width
++ // 1: LUT width
++ uint16_t block_fix_width; // OSD block fixed width
++ // real width = (fix_width + 1) * 2
++ uint8_t block_num; // OSD block num
++ uint16_t flags_index; // auto invert flags index
++
++ /* invertion config */
++ uint8_t color_mode; // selete color
++ // 0: src1 color
++ // 1: config data color
++ uint8_t invert_flags_mode; // invert flag selete
++ // 0: use RAM flag
++ // 1: usr last result
++ uint8_t default_color_sel; // default color mode
++ // 0: default is bright
++ // 1: default is dark
++ uint8_t invert_enable; // invert channel enable
++ // 1 << 0: alpha enable
++ // 1 << 1: Y/G disable
++ // 1 << 3: C/RB disable
++ uint8_t invert_mode; // invert cal mode
++ // 0: normal(max-data)
++ // 1: swap
++ uint8_t invert_thresh; // if luma > thresh, osd_flag to be 1
++ uint8_t unfix_index; // OSD width config index
++};
++
++struct rga_osd_info {
++ uint8_t enable;
++
++ struct rga_osd_mode_ctrl mode_ctrl;
++ struct rga_osd_invert_factor cal_factor;
++ struct rga_osd_bpp2 bpp2_info;
++
++ union {
++ struct {
++ uint32_t last_flags0;
++ uint32_t last_flags1;
++ };
++ uint64_t last_flags;
++ };
++
++ union {
++ struct {
++ uint32_t cur_flags0;
++ uint32_t cur_flags1;
++ };
++ uint64_t cur_flags;
++ };
++};
++
++struct rga_pre_intr_info {
++ uint8_t enable;
++
++ uint8_t read_intr_en;
++ uint8_t write_intr_en;
++ uint8_t read_hold_en;
++ uint32_t read_threshold;
++ uint32_t write_start;
++ uint32_t write_step;
++};
++
++struct rga_img_info_t {
++ /* yrgb mem addr */
++ uint64_t yrgb_addr;
++ /* cb/cr mem addr */
++ uint64_t uv_addr;
++ /* cr mem addr */
++ uint64_t v_addr;
++ /* definition by RK_FORMAT */
++ uint32_t format;
++
++ uint16_t act_w;
++ uint16_t act_h;
++ uint16_t x_offset;
++ uint16_t y_offset;
++
++ uint16_t vir_w;
++ uint16_t vir_h;
++
++ uint16_t endian_mode;
++ /* useless */
++ uint16_t alpha_swap;
++
++ /* used by RGA3 */
++ uint16_t rotate_mode;
++ uint16_t rd_mode;
++
++ uint16_t is_10b_compact;
++ uint16_t is_10b_endian;
++
++ uint16_t enable;
++};
++
++struct rga_req {
++ /* (enum) process mode sel */
++ uint8_t render_mode;
++
++ struct rga_img_info_t src;
++ struct rga_img_info_t dst;
++ struct rga_img_info_t pat;
++
++ /* rop4 mask addr */
++ uint64_t rop_mask_addr;
++ /* LUT addr */
++ uint64_t LUT_addr;
++
++ /* dst clip window default value is dst_vir */
++ /* value from [0, w-1] / [0, h-1]*/
++ struct rga_rect_t clip;
++
++ /* dst angle default value 0 16.16 scan from table */
++ int32_t sina;
++ /* dst angle default value 0 16.16 scan from table */
++ int32_t cosa;
++
++ /* alpha rop process flag */
++ /* ([0] = 1 alpha_rop_enable) */
++ /* ([1] = 1 rop enable) */
++ /* ([2] = 1 fading_enable) */
++ /* ([3] = 1 PD_enable) */
++ /* ([4] = 1 alpha cal_mode_sel) */
++ /* ([5] = 1 dither_enable) */
++ /* ([6] = 1 gradient fill mode sel) */
++ /* ([7] = 1 AA_enable) */
++ uint16_t alpha_rop_flag;
++
++ /* 0 nearst / 1 bilnear / 2 bicubic */
++ uint8_t scale_mode;
++
++ /* color key max */
++ uint32_t color_key_max;
++ /* color key min */
++ uint32_t color_key_min;
++
++ /* foreground color */
++ uint32_t fg_color;
++ /* background color */
++ uint32_t bg_color;
++
++ /* color fill use gradient */
++ struct rga_color_fill_t gr_color;
++
++ struct rga_line_draw_t line_draw_info;
++
++ struct rga_fading_t fading;
++
++ /* porter duff alpha mode sel */
++ uint8_t PD_mode;
++
++ /* global alpha value */
++ uint8_t alpha_global_value;
++
++ /* rop2/3/4 code scan from rop code table*/
++ uint16_t rop_code;
++
++ /* [2] 0 blur 1 sharp / [1:0] filter_type*/
++ uint8_t bsfilter_flag;
++
++ /* (enum) color palette 0/1bpp, 1/2bpp 2/4bpp 3/8bpp*/
++ uint8_t palette_mode;
++
++ /* (enum) BT.601 MPEG / BT.601 JPEG / BT.709 */
++ uint8_t yuv2rgb_mode;
++
++ /* 0/big endian 1/little endian*/
++ uint8_t endian_mode;
++
++ /* (enum) rotate mode */
++ /* 0x0, no rotate */
++ /* 0x1, rotate */
++ /* 0x2, x_mirror */
++ /* 0x3, y_mirror */
++ uint8_t rotate_mode;
++
++ /* 0 solid color / 1 pattern color */
++ uint8_t color_fill_mode;
++
++ /* mmu information */
++ struct rga_mmu_t mmu_info;
++
++ /* ([0~1] alpha mode) */
++ /* ([2~3] rop mode) */
++ /* ([4] zero mode en) */
++ /* ([5] dst alpha mode) */
++ /* ([6] alpha output mode sel) 0 src / 1 dst*/
++ uint8_t alpha_rop_mode;
++
++ uint8_t src_trans_mode;
++
++ uint8_t dither_mode;
++
++ /* full color space convert */
++ struct rga_full_csc full_csc;
++
++ int32_t in_fence_fd;
++ uint8_t core;
++ uint8_t priority;
++ int32_t out_fence_fd;
++
++ uint8_t handle_flag;
++
++ /* RGA2 1106 add */
++ struct rga_mosaic_info mosaic_info;
++
++ uint8_t uvhds_mode;
++ uint8_t uvvds_mode;
++
++ struct rga_osd_info osd_info;
++
++ struct rga_pre_intr_info pre_intr_info;
++
++ uint8_t reservr[59];
++};
++#endif /*_RGA_DRIVER_H_*/
+diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
+index 93c426eeb3..325150f483 100644
+--- a/libavcodec/rkmppdec.c
++++ b/libavcodec/rkmppdec.c
+@@ -18,6 +18,10 @@
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
++#ifdef _POSIX_C_SOURCE
++#undef _POSIX_C_SOURCE
++#endif
++#define _POSIX_C_SOURCE 200809L /* for O_CLOEXEC */
+
+ #include <drm_fourcc.h>
+ #include <pthread.h>
+@@ -26,6 +30,9 @@
+ #include <time.h>
+ #include <unistd.h>
+ #include <sys/time.h>
++#include <sys/mman.h>
++#include <linux/dma-heap.h>
++#include <fcntl.h>
+
+ #include "avcodec.h"
+ #include "decode.h"
+@@ -38,11 +45,8 @@
+ #include "libavutil/hwcontext_drm.h"
+ #include "libavutil/imgutils.h"
+ #include "libavutil/log.h"
++#include "rga.h"
+
+-#if CONFIG_LIBRGA
+-#include <rga/rga.h>
+-#include <rga/RgaApi.h>
+-#endif
+
+ #ifndef DRM_FORMAT_NV12_10
+ #define DRM_FORMAT_NV12_10 fourcc_code('N', 'A', '1', '5')
+@@ -50,11 +54,16 @@
+
+ #define FPS_UPDATE_INTERVAL 120
+
++struct rkmpp_dma_buffer;
+ typedef struct {
+ MppCtx ctx;
+ MppApi *mpi;
+ MppBufferGroup frame_group;
+
++ int dma_fd;
++ struct rkmpp_dma_buffer *dma_cache;
++ int rga_fd;
++
+ int8_t eos;
+ int8_t draining;
+
+@@ -115,17 +124,15 @@ static uint32_t rkmpp_get_avformat(MppFrameFormat mppformat)
+ }
+ }
+
+-#if CONFIG_LIBRGA
+ static uint32_t rkmpp_get_rgaformat(MppFrameFormat mppformat)
+ {
+ switch (mppformat) {
+- case MPP_FMT_YUV420SP: return RK_FORMAT_YCbCr_420_SP;
+- case MPP_FMT_YUV420SP_10BIT: return RK_FORMAT_YCbCr_420_SP_10B;
+- case MPP_FMT_YUV422SP: return RK_FORMAT_YCbCr_422_SP;
+- default: return RK_FORMAT_UNKNOWN;
++ case MPP_FMT_YUV420SP: return RGA_FORMAT_YCbCr_420_SP;
++ case MPP_FMT_YUV420SP_10BIT: return RGA_FORMAT_YCbCr_420_SP_10B;
++ case MPP_FMT_YUV422SP: return RGA_FORMAT_YCbCr_422_SP;
++ default: return RGA_FORMAT_UNKNOWN;
+ }
+ }
+-#endif
+
+ static int rkmpp_close_decoder(AVCodecContext *avctx)
+ {
+@@ -138,6 +145,8 @@ static int rkmpp_close_decoder(AVCodecContext *avctx)
+ return 0;
+ }
+
++static void rkmpp_buffer_free(struct rkmpp_dma_buffer *buffer);
++
+ static void rkmpp_release_decoder(void *opaque, uint8_t *data)
+ {
+ RKMPPDecoder *decoder = (RKMPPDecoder *)data;
+@@ -153,6 +162,20 @@ static void rkmpp_release_decoder(void *opaque, uint8_t *data)
+ decoder->frame_group = NULL;
+ }
+
++ rkmpp_buffer_free(decoder->dma_cache);
++ decoder->dma_cache = NULL;
++
++ if (decoder->dma_fd) {
++ close(decoder->dma_fd);
++ decoder->dma_fd = 0;
++ }
++
++ if (decoder->rga_fd) {
++ close(decoder->rga_fd);
++ decoder->rga_fd = 0;
++ }
++
++
+ av_buffer_unref(&decoder->frames_ref);
+ av_buffer_unref(&decoder->device_ref);
+
+@@ -250,13 +273,27 @@ static int rkmpp_init_decoder(AVCodecContext *avctx)
+ goto fail;
+ }
+
+- ret = mpp_buffer_group_get_internal(&decoder->frame_group, MPP_BUFFER_TYPE_ION);
++ ret = mpp_buffer_group_get_internal(&decoder->frame_group,
++ MPP_BUFFER_TYPE_DMA_HEAP);
++
+ if (ret) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to get buffer group (code = %d)\n", ret);
+ ret = AVERROR_UNKNOWN;
+ goto fail;
+ }
+
++ decoder->dma_fd = open("/dev/dma_heap/system-dma32", O_RDWR);
++ if (decoder->dma_fd < 0) {
++ av_log(avctx, AV_LOG_ERROR, "Failed to open system-dma32 heap\n");
++ ret = AVERROR_UNKNOWN;
++ goto fail;
++ }
++
++ decoder->rga_fd = open("/dev/rga", O_RDWR);
++ if (decoder->dma_fd < 0) {
++ av_log(avctx, AV_LOG_WARNING, "Failed to open RGA\n");
++ }
++
+ ret = decoder->mpi->control(decoder->ctx, MPP_DEC_SET_EXT_BUF_GROUP, decoder->frame_group);
+ if (ret) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to assign buffer group (code = %d)\n", ret);
+@@ -307,13 +344,14 @@ static void rkmpp_release_frame(void *opaque, uint8_t *data)
+ static int rkmpp_convert_frame(AVCodecContext *avctx, AVFrame *frame,
+ MppFrame mppframe, MppBuffer buffer)
+ {
++ RKMPPDecodeContext *rk_context = avctx->priv_data;
++ RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data;
++
+ char *src = mpp_buffer_get_ptr(buffer);
+ char *dst_y = frame->data[0];
+ char *dst_u = frame->data[1];
+ char *dst_v = frame->data[2];
+-#if CONFIG_LIBRGA
+- RgaSURF_FORMAT format = rkmpp_get_rgaformat(mpp_frame_get_fmt(mppframe));
+-#endif
++ enum rga_surf_format format = rkmpp_get_rgaformat(mpp_frame_get_fmt(mppframe));
+ int width = mpp_frame_get_width(mppframe);
+ int height = mpp_frame_get_height(mppframe);
+ int hstride = mpp_frame_get_hor_stride(mppframe);
+@@ -321,29 +359,41 @@ static int rkmpp_convert_frame(AVCodecContext *avctx, AVFrame *frame,
+ int y_pitch = frame->linesize[0];
+ int u_pitch = frame->linesize[1];
+ int v_pitch = frame->linesize[2];
+- int i, j;
++ int i, j, ret;
+
+-#if CONFIG_LIBRGA
+- rga_info_t src_info = {0};
+- rga_info_t dst_info = {0};
+ int dst_height = (dst_u - dst_y) / y_pitch;
+
+- static int rga_supported = 1;
+- static int rga_inited = 0;
++ struct rga_req req = {
++ .src = {
++ .yrgb_addr = mpp_buffer_get_fd(buffer),
++ .v_addr = hstride * vstride,
++ .format = format,
++ .act_w = width,
++ .act_h = height,
++ .vir_w = hstride,
++ .vir_h = vstride,
++ .rd_mode = RGA_RASTER_MODE,
++ },
++ .dst = {
++ .uv_addr = (uintptr_t) dst_y,
++ .v_addr = (uintptr_t) dst_u,
++ .format = RGA_FORMAT_YCbCr_420_P,
++ .act_w = width,
++ .act_h = height,
++ .vir_w = y_pitch,
++ .vir_h = dst_height,
++ .rd_mode = RGA_RASTER_MODE,
++ },
++ .mmu_info = {
++ .mmu_en = 1,
++ .mmu_flag = 0x80000521,
++ },
++ };
+
+- if (!rga_supported)
++ if (decoder->rga_fd < 0)
+ goto bail;
+
+- if (!rga_inited) {
+- if (c_RkRgaInit() < 0) {
+- rga_supported = 0;
+- av_log(avctx, AV_LOG_WARNING, "RGA not available\n");
+- goto bail;
+- }
+- rga_inited = 1;
+- }
+-
+- if (format == RK_FORMAT_UNKNOWN)
++ if (format == RGA_FORMAT_UNKNOWN)
+ goto bail;
+
+ if (u_pitch != y_pitch / 2 || v_pitch != y_pitch / 2 ||
+@@ -351,23 +401,13 @@ static int rkmpp_convert_frame(AVCodecContext *avctx, AVFrame *frame,
+ dst_v != dst_u + u_pitch * dst_height / 2)
+ goto bail;
+
+- src_info.fd = mpp_buffer_get_fd(buffer);
+- src_info.mmuFlag = 1;
+- rga_set_rect(&src_info.rect, 0, 0, width, height, hstride, vstride,
+- format);
+-
+- dst_info.virAddr = dst_y;
+- dst_info.mmuFlag = 1;
+- rga_set_rect(&dst_info.rect, 0, 0, frame->width, frame->height,
+- y_pitch, dst_height, RK_FORMAT_YCbCr_420_P);
+-
+- if (c_RkRgaBlit(&src_info, &dst_info, NULL) < 0)
++ ret = ioctl(decoder->rga_fd, RGA_BLIT_SYNC, &req);
++ if (ret < 0)
+ goto bail;
+
+ return 0;
+
+ bail:
+-#endif
+ if (mpp_frame_get_fmt(mppframe) != MPP_FMT_YUV420SP) {
+ av_log(avctx, AV_LOG_WARNING, "Unable to convert\n");
+ return -1;
+@@ -423,6 +463,150 @@ static void rkmpp_update_fps(AVCodecContext *avctx)
+ fps, decoder->frames);
+ }
+
++struct rkmpp_dma_buffer {
++ int fd;
++ void *cpu;
++ size_t size;
++ struct rkmpp_dma_buffer **cache;
++};
++
++static void rkmpp_buffer_free(struct rkmpp_dma_buffer *buffer)
++{
++ if (!buffer)
++ return;
++
++ munmap(buffer->cpu, buffer->size);
++ close(buffer->fd);
++ av_free(buffer);
++}
++
++static void rkmpp_buffer_cache(void *opaque, uint8_t *data)
++{
++ struct rkmpp_dma_buffer *buffer = opaque;
++
++ if (!buffer)
++ return;
++
++ if (*buffer->cache)
++ rkmpp_buffer_free(buffer);
++ else
++ *buffer->cache = buffer;
++}
++
++static struct rkmpp_dma_buffer *rkmpp_buffer_alloc(RKMPPDecoder *decoder, size_t size)
++{
++ struct rkmpp_dma_buffer *buffer;
++ int ret;
++
++ struct dma_heap_allocation_data alloc = {
++ .len = size,
++ .fd_flags = O_CLOEXEC | O_RDWR,
++ };
++
++ if (decoder->dma_cache) {
++ struct rkmpp_dma_buffer *cached = decoder->dma_cache;
++ decoder->dma_cache = NULL;
++
++ if (cached->size == size) {
++ return cached;
++ }
++
++ rkmpp_buffer_free(cached);
++ }
++
++ ret = ioctl(decoder->dma_fd, DMA_HEAP_IOCTL_ALLOC, &alloc);
++ if (ret == -1)
++ return NULL;
++
++ buffer = av_mallocz(sizeof(*buffer));
++ buffer->fd = alloc.fd;
++ buffer->size = alloc.len;
++ buffer->cpu = mmap(NULL, buffer->size, PROT_READ | PROT_WRITE,
++ MAP_SHARED, buffer->fd, 0);
++ buffer->cache = &decoder->dma_cache;
++
++ return buffer;
++}
++
++static int rkmpp_get_buffer2(AVCodecContext *avctx, AVFrame *pic, int flags)
++{
++ RKMPPDecodeContext *rk_context = avctx->priv_data;
++ RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data;
++
++ int ret;
++
++ int linesize[4];
++ int stride_align[AV_NUM_DATA_POINTERS];
++ int w = pic->width;
++ int h = pic->height;
++ int unaligned;
++ ptrdiff_t linesize1[4];
++ size_t size[4];
++
++ struct rkmpp_dma_buffer *buffer;
++
++ int total;
++
++ avcodec_align_dimensions2(avctx, &w, &h, stride_align);
++
++ do {
++ // NOTE: do not align linesizes individually, this breaks e.g. assumptions
++ // that linesize[0] == 2*linesize[1] in the MPEG-encoder for 4:2:2
++ ret = av_image_fill_linesizes(linesize, avctx->pix_fmt, w);
++ if (ret < 0)
++ goto fail;
++ // increase alignment of w for next try (rhs gives the lowest bit set in w)
++ w += w & ~(w - 1);
++
++ unaligned = 0;
++ for (int i = 0; i < 4; i++)
++ unaligned |= linesize[i] % stride_align[i];
++ } while (unaligned);
++
++ for (int i = 0; i < 4; i++)
++ linesize1[i] = linesize[i];
++ ret = av_image_fill_plane_sizes(size, avctx->pix_fmt, h, linesize1);
++ if (ret < 0)
++ goto fail;
++
++ size[0] += size[1] + size[2] + size[3];
++ size[0] += 16 + STRIDE_ALIGN - 1;
++
++ buffer = rkmpp_buffer_alloc(decoder, size[0]);
++ if (!buffer)
++ goto fail;
++
++ av_log(avctx, AV_LOG_DEBUG, "Allocated buffer of size %zi -> %p (CPU %p)\n", size[0], buffer, buffer->cpu);
++
++ memset(pic->data, 0, sizeof(pic->data));
++ pic->extended_data = pic->data;
++
++ pic->linesize[0] = linesize[0];
++ pic->buf[0] = av_buffer_create(buffer->cpu, size[0],
++ rkmpp_buffer_cache, buffer, 0);
++ pic->data[0] = pic->buf[0]->data;
++
++ for (int i = 1; i < 4; i++)
++ pic->linesize[i] = linesize[i];
++
++ total = av_image_fill_pointers(pic->data, pic->format, pic->height,
++ pic->buf[0]->data, pic->linesize);
++ if (total < 0 || total > pic->buf[0]->size)
++ goto fail;
++
++ for (int i = 4; i < AV_NUM_DATA_POINTERS; i++) {
++ pic->data[i] = NULL;
++ pic->linesize[i] = 0;
++ }
++
++ return 0;
++
++fail:
++ av_frame_unref(pic);
++ return AVERROR(ENOMEM);
++}
++
++
+ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
+ {
+ RKMPPDecodeContext *rk_context = avctx->priv_data;
+@@ -528,6 +712,8 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
+ rkmpp_update_fps(avctx);
+
+ if (avctx->pix_fmt != AV_PIX_FMT_DRM_PRIME) {
++ avctx->get_buffer2 = rkmpp_get_buffer2;
++
+ ret = ff_get_buffer(avctx, frame, 0);
+ if (ret < 0)
+ goto out;
+--
+2.39.0
+
+
+From 44ccb8a4f398dbb05c2bd2fd9a0dcd56ca8ceb54 Mon Sep 17 00:00:00 2001
+From: boogie <boogiepop@gmx.com>
+Date: Tue, 17 Jan 2023 01:02:19 +0100
+Subject: [PATCH 16/16] ugliest hack: vp8&9 color space workaround
+
+---
+ libavcodec/rkmppdec.c | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
+index 325150f483..ad9208f0e6 100644
+--- a/libavcodec/rkmppdec.c
++++ b/libavcodec/rkmppdec.c
+@@ -734,6 +734,21 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
+ frame->color_trc = mpp_frame_get_color_trc(mppframe);
+ frame->colorspace = mpp_frame_get_colorspace(mppframe);
+
++ /* ugliest hack in the world: firefox does not probe with avformat, so it does not
++ * have any idea about the frame format, instead tries to guess with decoder profile
++ * matches. Since this decoder does not provide any profile, it just sets color pro-
++ * file to 0 which RGB. This causes funny coloring on video decode.
++ * I set this manually to most popular BT709 colorspace for VP8&9. This worksaround
++ * youtube problems, but does not work always. At least there is no need to run this
++ * on each frame... But yeah it is too late and i dont care.
++ */
++ if ((avctx->codec_id == AV_CODEC_ID_VP8 || avctx->codec_id == AV_CODEC_ID_VP9 ) \
++ && avctx->profile == FF_PROFILE_UNKNOWN && !frame->colorspace){
++ frame->color_primaries = AVCOL_PRI_BT709;
++ frame->color_trc = AVCOL_TRC_BT709;
++ frame->colorspace = AVCOL_SPC_BT709;
++ }
++
+ mode = mpp_frame_get_mode(mppframe);
+ frame->interlaced_frame = ((mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK) == MPP_FRAME_FLAG_DEINTERLACED);
+ frame->top_field_first = ((mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK) == MPP_FRAME_FLAG_TOP_FIRST);
+--
+2.39.0
+
diff --git a/0003-ffmpegdirect-buildsys.patch b/0003-ffmpegdirect-buildsys.patch
new file mode 100644
index 000000000000..debc79057a26
--- /dev/null
+++ b/0003-ffmpegdirect-buildsys.patch
@@ -0,0 +1,12 @@
+--- inputstream.ffmpegdirect/FindFFMPEG.cmake 2023-01-29 22:25:24.115814241 +0100
++++ inputstream.ffmpegdirect/FindFFMPEG.new 2023-01-29 22:14:38.239471283 +0100
+@@ -31,7 +31,7 @@
+ # ffmpeg - The FFmpeg libraries
+ # --------
+ #
+-
++set(FFMPEG_PATH $ENV{FFMPEG_PATH})
+ # required ffmpeg library versions
+ set(REQUIRED_FFMPEG_VERSION 4.0)
+ set(_avcodec_ver ">=58.18.100")
+ \ No newline at end of file
diff --git a/PKGBUILD b/PKGBUILD
new file mode 100644
index 000000000000..d13b3c528ec6
--- /dev/null
+++ b/PKGBUILD
@@ -0,0 +1,322 @@
+# vim:set ts=2 sw=2 et:
+# Maintainer: Faruk Dikcizgi <boogiepop@gmx.de>
+# Contributor: graysky <therealgraysky AT protonmail DOT com>
+# Contributor: BlackIkeEagle < ike DOT devolder AT gmail DOT com >
+# Contributor: Sergej Pupykin <pupykin.s+arch@gmail.com>
+# Contributor: DonVla <donvla@users.sourceforge.net>
+# Contributor: Ulf Winkelvos <ulf [at] winkelvos [dot] de>
+# Contributor: Ralf Barth <archlinux dot org at haggy dot org>
+# Contributor: B & monty - Thanks for your hints :)
+# Contributor: marzoul
+# Contributor: Sergej Pupykin <pupykin.s+arch@gmail.com>
+# Contributor: Brad Fanella <bradfanella@archlinux.us>
+# Contributor: [vEX] <niechift.dot.vex.at.gmail.dot.com>
+# Contributor: Zeqadious <zeqadious.at.gmail.dot.com>
+# Contributor: Bartłomiej Piotrowski <bpiotrowski@archlinux.org>
+# Contributor: Maxime Gauduin <alucryd@gmail.com>
+#
+# Original credits go to Edgar Hucek <gimli at dark-green dot com>
+# for his xbmc-vdpau-vdr PKGBUILD at https://archvdr.svn.sourceforge.net/svnroot/archvdr/trunk/archvdr/xbmc-vdpau-vdr/PKGBUILD
+
+# set this to anything to build with clang rather than with gcc
+_clangbuild=
+
+pkgbase=kodi-nexus-mpp-git
+pkgname=("$pkgbase" "$pkgbase-eventclients" "$pkgbase-tools-texturepacker" "$pkgbase-dev" "$pkgbase-ffmpegdirect")
+pkgver=r62294.e75ba45eef3.457d9a5
+pkgrel=2
+arch=('aarch64' 'arm7f')
+url="https://kodi.tv"
+license=('GPL2')
+makedepends=(
+ 'afpfs-ng' 'bluez-libs' 'cmake' 'curl' 'dav1d' 'doxygen' 'git' 'glew'
+ 'gperf' 'hicolor-icon-theme' 'java-runtime' 'libaacs' 'libass'
+ 'libbluray' 'libcdio' 'libcec' 'libgl' 'mariadb-libs' 'libmicrohttpd'
+ 'libmodplug' 'libmpeg2' 'libnfs' 'libplist' 'libpulse' 'libva'
+ 'libva-vdpau-driver' 'libxrandr' 'libxslt' 'lirc' 'lzo' 'mesa' 'nasm'
+ 'python-pycryptodomex' 'python-pillow' 'python-pybluez'
+ 'python-simplejson' 'shairplay' 'smbclient' 'taglib' 'tinyxml' 'swig'
+ 'upower' 'giflib' 'ghostscript' 'meson' 'gtest' 'graphviz'
+ # wayland
+ 'wayland-protocols' 'waylandpp' 'libxkbcommon'
+ # gbm
+ 'libinput' 'mpp-git'
+)
+options=(!lto debug strip)
+
+[[ -n "$_clangbuild" ]] && makedepends+=('clang' 'lld' 'llvm')
+
+_gitname=xbmc
+_gitnameff='inputstream.ffmpegdirect'
+_codename=Nexus
+
+# Found on their respective github release pages. One can check them against
+# what is pulled down when not specifying them in the cmake step.
+# $CHROOT/build/kodi-git/src/kodi-build/build/download
+#
+# https://github.com/xbmc/FFmpeg/tags
+# https://github.com/xbmc/libdvdcss/tags
+# https://github.com/xbmc/libdvdnav/tags
+# https://github.com/xbmc/libdvdread/tags
+#
+# fmt and crossguid can be found https://mirrors.kodi.tv/build-deps/sources/
+#
+_libdvdcss_version="1.4.3-Next-Nexus-Alpha2-2"
+_libdvdnav_version="6.1.1-Next-Nexus-Alpha2-2"
+_libdvdread_version="6.1.3-Next-Nexus-Alpha2-2"
+_ffmpeg_version="4.4.1-Nexus-Alpha1"
+_fmt_version="9.1.0"
+_spdlog_version="1.10.0"
+_crossguid_version="ca1bf4b810e2d188d04cb6286f957008ee1b7681"
+_fstrcmp_version="0.7.D001"
+_flatbuffers_version="2.0.0"
+_libudfread_version="1.1.2"
+source=(
+ "git+https://github.com/xbmc/xbmc.git#branch=$_codename"
+ "git+https://github.com/xbmc/inputstream.ffmpegdirect.git#branch=$_codename"
+ "libdvdcss-$_libdvdcss_version.tar.gz::https://github.com/xbmc/libdvdcss/archive/$_libdvdcss_version.tar.gz"
+ "libdvdnav-$_libdvdnav_version.tar.gz::https://github.com/xbmc/libdvdnav/archive/$_libdvdnav_version.tar.gz"
+ "libdvdread-$_libdvdread_version.tar.gz::https://github.com/xbmc/libdvdread/archive/$_libdvdread_version.tar.gz"
+ "ffmpeg-$_ffmpeg_version.tar.gz::https://github.com/xbmc/FFmpeg/archive/$_ffmpeg_version.tar.gz"
+ "https://mirrors.kodi.tv/build-deps/sources/fmt-$_fmt_version.tar.gz"
+ "https://mirrors.kodi.tv/build-deps/sources/spdlog-$_spdlog_version.tar.gz"
+ "https://mirrors.kodi.tv/build-deps/sources/crossguid-$_crossguid_version.tar.gz"
+ "https://mirrors.kodi.tv/build-deps/sources/fstrcmp-$_fstrcmp_version.tar.gz"
+ "https://mirrors.kodi.tv/build-deps/sources/flatbuffers-$_flatbuffers_version.tar.gz"
+ "https://mirrors.kodi.tv/build-deps/sources/libudfread-$_libudfread_version.tar.gz"
+ 0001-ffmpeg-buildsys.patch
+ 0002-rkmpp-4.patch
+ 0003-ffmpegdirect-buildsys.patch
+)
+
+noextract=(
+ "libdvdcss-$_libdvdcss_version.tar.gz"
+ "libdvdnav-$_libdvdnav_version.tar.gz"
+ "libdvdread-$_libdvdread_version.tar.gz"
+ "ffmpeg-$_ffmpeg_version.tar.gz"
+ "fmt-$_fmt_version.tar.gz"
+ "spdlog-$_spdlog_version.tar.gz"
+ "crossguid-$_crossguid_version.tar.gz"
+ "fstrcmp-$_fstrcmp_version.tar.gz"
+ "flatbuffers-$_flatbuffers_version.tar.gz"
+ "libudfread-$_libudfread_version.tar.gz"
+)
+
+b2sums=('SKIP'
+ 'SKIP'
+ '2f503d3ab767094958f7ec10b4ad11ffd02665deee571c8f3c739bef5fc7e2ff84babc5a3fdee638dc095f896b72fe3ce65e6b688674cb5f7b7b77190992688c'
+ 'db4d05836d8fbb3637ae50bdbfc0e4b612ee6b3be24addfea94ce772c3bf28d58b63a3f252d6f9f016f72f8cbb841cc1820b091226b136f4c4664385a32da73c'
+ 'c94feb5a03a12efa5b7767965118d2500a088299ea36f3b82e46d157e45893e6b04503cb50f179ca681bac914457607fab26acfa6e304752b355c407578572d1'
+ '51d310e7000aeba657d55341c5fdb540474e197b85062228ab4b314c8309ec11985aa7f105193333fc6106529e8e58c86eafe268190894be8532d0e0b9065fa6'
+ 'ff1daa43140615b63aeb1ecd0aa1c32d24decfd5006805080293ef3db04d544c0445a30e8da0d985a6f5a25ad48ce4f6ae61e52da5ea4a4d3b031c212da38b18'
+ 'e40afa9fd1dd791e1f703392f0f54fc798ed70537a9f1ee9c8598dd449f4cd4dd03bc4ce95e416cbbe224711a17e70708a106f0432384542d6316cf232cf8757'
+ '0f78a8ab5a420297f666b3b8156d499a9141ec25c049d4d2bb2ba594dc585abe211a149b83c605cce4f5530207231a065d5f3a87a0c969781de8c6381afa2527'
+ 'a8b68fcb8613f0d30e5ff7b862b37408472162585ca71cdff328e3299ff50476fd265467bbd77b352b22bb88c590969044f74d91c5468475504568fd269fa69e'
+ 'ccd827a43da39cf831727b439beed0cea216cdf50dbfe70954854bbe388b2c47ed4e78cc87e3fc0d5568034b13baa2ea96480914cc8129747bccbf8ea928847c'
+ '1801d84a0ca38410a78f23e7d44f37e6d53346753c853df2e7380d259ce1ae7f0c712825b95a5753ad0bc6360cfffe1888b9e7bc30da8b84549e0f1198248f61'
+ 'a4c52a1efe8957c2d941a47caeb1b3ec86741d902ae2c58eff4aaba369475e72257bf63c43a1b5f55fc8d07bb2d0c5ea0b7717a028278eae6a34f5a91eb5047f'
+ '1a818e38b6f763d60ce50e4b0a5d26c86f833dd26dbcee352579d8395e6382b06ee816dad7938e3ea12a1e676251417ef4c090c21dca45f7decfba81694d3a2b'
+ '943d358b4c127b77a691886a48245604081e3fdb5f05cd9a9821b52acf46bc6736089348f3299e00f35bbc09ba501d136088d96c7f118b3f5f3fe1cb7d77c7fd')
+
+pkgver() {
+ cd "$_gitname"
+ local _kcommits="$(git rev-list --count HEAD)"
+ local _kcommit="$(git rev-parse --short HEAD)"
+ cd "../$_gitnameff"
+ local _ffcommits="$(git rev-list --count HEAD)"
+ local _ffcommit="$(git rev-parse --short HEAD)"
+ local _revnum=$(($_kcommits + $_ffcommits))
+ printf "r${_revnum}.${_kcommit}.${_ffcommit}"
+}
+
+prepare() {
+ mkdir -p "$srcdir/kodi-build"
+ mkdir -p "$srcdir/ffdirect-build"
+ # when built with debug enabled LTO needs more than 2gb size which larger than /tmp ond efault arch
+ # we are creating a temporary tmp folder to satisfy LTO, otherwise linking stage will fail
+ mkdir -p "$srcdir/tmp"
+
+ cd "$_gitname"
+ patch -p1 -N -i ../0001-ffmpeg-buildsys.patch
+ cp ../0002-rkmpp-4.patch tools/depends/target/ffmpeg
+
+ cd ../"$_gitnameff"
+ patch -p1 -N -i ../0003-ffmpegdirect-buildsys.patch
+ rm -rf depends/common/ffmpeg
+
+ if [[ -n "$_clangbuild" ]]; then
+ msg "Building with clang"
+ export CC=clang CXX=clang++
+ fi
+}
+
+build() {
+ cd "$srcdir/kodi-build"
+
+ _args=(
+ -DCMAKE_BUILD_TYPE=Release
+ -DCMAKE_INSTALL_PREFIX=/usr
+ -DCMAKE_INSTALL_LIBDIR=/usr/lib
+ -DUSE_LTO=$(nproc)
+ -DVERBOSE=ON
+ -DENABLE_LDGOLD=OFF
+ -DENABLE_EVENTCLIENTS=ON
+ -DENABLE_INTERNAL_FFMPEG=ON
+ -DENABLE_INTERNAL_FMT=ON
+ -DENABLE_INTERNAL_SPDLOG=ON
+ -DENABLE_INTERNAL_CROSSGUID=ON
+ -DENABLE_INTERNAL_FSTRCMP=ON
+ -DENABLE_INTERNAL_FLATBUFFERS=ON
+ -DENABLE_INTERNAL_UDFREAD=ON
+ -DENABLE_MYSQLCLIENT=ON
+ -DENABLE_VAAPI=ON
+ -DENABLE_VDPAU=ON
+ -Dlibdvdcss_URL="$srcdir/libdvdcss-$_libdvdcss_version.tar.gz"
+ -Dlibdvdnav_URL="$srcdir/libdvdnav-$_libdvdnav_version.tar.gz"
+ -Dlibdvdread_URL="$srcdir/libdvdread-$_libdvdread_version.tar.gz"
+ -DFFMPEG_URL="$srcdir/ffmpeg-$_ffmpeg_version.tar.gz"
+ -DFMT_URL="$srcdir/fmt-$_fmt_version.tar.gz"
+ -DSPDLOG_URL="$srcdir/spdlog-$_spdlog_version.tar.gz"
+ -DCROSSGUID_URL="$srcdir/crossguid-$_crossguid_version.tar.gz"
+ -DFSTRCMP_URL="$srcdir/fstrcmp-$_fstrcmp_version.tar.gz"
+ -DFLATBUFFERS_URL="$srcdir/flatbuffers-$_flatbuffers_version.tar.gz"
+ -DUDFREAD_URL="$srcdir/libudfread-$_libudfread_version.tar.gz"
+ -DAPP_RENDER_SYSTEM=gl
+ )
+
+ # https://github.com/google/flatbuffers/issues/7404
+ CXXFLAGS+=' -Wno-error=restrict'
+
+ echo "building kodi"
+ cmake "${_args[@]}" ../"$_gitname"
+ TMPDIR="$srcdir/tmp" make -j$(nproc)
+
+ cd "$srcdir/ffdirect-build"
+ echo "building ffmpeg-direct"
+ cmake -DCMAKE_INSTALL_PREFIX=/usr \
+ -DCMAKE_INSTALL_LIBDIR=/usr/lib/kodi \
+ -DCMAKE_BUILD_TYPE=Release \
+ -DADDONS_TO_BUILD=$_gitnameff \
+ -DADDON_SRC_PREFIX="../$_gitnameff/.." \
+ "../$_gitname/cmake/addons"
+ FFMPEG_PATH=$srcdir/kodi-build/build make -j$(nproc)
+}
+
+# kodi
+# components: kodi
+package_kodi-nexus-mpp-git() {
+ pkgdesc="A software media player and entertainment hub for digital media (Nexus branch) with Rockchip MPP hardware acceleration"
+ depends=(
+ 'bluez-libs' 'curl' 'dav1d' 'desktop-file-utils' 'hicolor-icon-theme'
+ 'lcms2' 'libass' 'libbluray' 'libcdio' 'libcec' 'libmicrohttpd' 'libnfs'
+ 'libplist' 'libpulse' 'libva' 'libvdpau' 'libxslt' 'lirc' 'mariadb-libs'
+ 'mesa' 'python-pillow' 'python-pycryptodomex' 'python-simplejson'
+ 'shairplay' 'smbclient' 'sqlite' 'taglib' 'tinyxml'
+ 'libxrandr' 'libxkbcommon' 'waylandpp' 'libinput'
+ 'pcre' 'mpp-git'
+ )
+ [[ -n "$_clangbuild" ]] && depends+=('glu')
+
+ optdepends=(
+ 'afpfs-ng: Apple shares support'
+ 'bluez: Blutooth support'
+ 'python-pybluez: Bluetooth support'
+ 'pulseaudio: PulseAudio support'
+ 'upower: Display battery level'
+ )
+ provides=("kodi=${pkgver}" 'kodi-x11' 'kodi-wayland' 'kodi-gbm')
+ conflicts=('kodi' 'kodi-x11' 'kodi-wayland' 'kodi-gbm')
+
+ _components=(
+ 'kodi'
+ 'kodi-bin'
+ )
+
+ cd kodi-build
+ for _cmp in ${_components[@]}; do
+ DESTDIR="$pkgdir" /usr/bin/cmake \
+ -DCMAKE_INSTALL_COMPONENT="$_cmp" \
+ -P cmake_install.cmake
+ done
+
+ # avoid error <general>: GetDirectory - Error getting /usr/lib/kodi/addons
+ mkdir -p "$pkgdir"/usr/lib/kodi/addons
+}
+
+# kodi-eventclients
+# components: kodi-eventclients-common kodi-eventclients-ps3 kodi-eventclients-kodi-send
+package_kodi-nexus-mpp-git-eventclients() {
+ pkgdesc="Kodi Event Clients (Nexus branch)"
+ provides=("kodi-eventclients=${pkgver}")
+ conflicts=('kodi-eventclients')
+ optdepends=(
+ 'kodi: local machine eventclient use'
+ 'python: most eventclients are implemented in python'
+ )
+
+ _components=(
+ 'kodi-eventclients-common'
+ 'kodi-eventclients-ps3'
+ 'kodi-eventclients-kodi-send'
+ )
+
+ cd kodi-build
+ for _cmp in ${_components[@]}; do
+ DESTDIR="$pkgdir" /usr/bin/cmake \
+ -DCMAKE_INSTALL_COMPONENT="$_cmp" \
+ -P cmake_install.cmake
+ done
+}
+
+# kodi-tools-texturepacker
+# components: kodi-tools-texturepacker
+package_kodi-nexus-mpp-git-tools-texturepacker() {
+ pkgdesc="Kodi Texturepacker tool (Nexus branch)"
+ provides=("kodi-tools-texturepacker=${pkgver}")
+ conflicts=('kodi-tools-texturepacker')
+ depends=('libpng' 'giflib' 'libjpeg-turbo' 'lzo')
+
+ _components=(
+ 'kodi-tools-texturepacker'
+ )
+
+ cd kodi-build
+ for _cmp in ${_components[@]}; do
+ DESTDIR="$pkgdir" /usr/bin/cmake \
+ -DCMAKE_INSTALL_COMPONENT="$_cmp" \
+ -P cmake_install.cmake
+ done
+}
+
+package_kodi-nexus-mpp-git-ffmpegdirect() {
+ pkgdesc="Inputstream ffmpegdirect kodi binary addon (Nexus branch) supporting Rockchip MPP hardware acceleration"
+ provides=('kodi-addon-inputstream-ffmpegdirect')
+ conflicts=('kodi-addon-inputstream-ffmpegdirect')
+ depends=('kodi' 'kodi-nexus-mpp-git')
+
+ cd "$srcdir/ffdirect-build"
+ install -d "${pkgdir}/usr"
+ mv .install/lib "${pkgdir}/usr/"
+ mv .install/share "${pkgdir}/usr/"
+}
+
+# kodi-dev
+# components: kodi-addon-dev kodi-eventclients-dev
+package_kodi-nexus-mpp-git-dev() {
+ pkgdesc="Kodi dev files (Nexus branch) with Rockchip MPP hardware acceleration"
+ depends=('kodi-nexus-mpp-git')
+ provides=("kodi-nexus-dev=${pkgver}" "kodi-dev=${pkgver}")
+ conflicts=('kodi-nexus-dev' "kodi-dev")
+
+ _components=(
+ 'kodi-addon-dev'
+ 'kodi-eventclients-dev'
+ )
+
+ cd kodi-build
+ for _cmp in ${_components[@]}; do
+ DESTDIR="$pkgdir" /usr/bin/cmake \
+ -DCMAKE_INSTALL_COMPONENT="$_cmp" \
+ -P cmake_install.cmake
+ done
+} \ No newline at end of file