summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorboogie2023-01-30 10:37:31 +0100
committerboogie2023-01-30 10:37:31 +0100
commit4837da3395e945592cba7c795fa5bc17a8812a06 (patch)
tree89c9d22be4d35710d9f6a71ffa5d14cf4adc88a9
downloadaur-4837da3395e945592cba7c795fa5bc17a8812a06.tar.gz
initial
-rw-r--r--.SRCINFO96
-rw-r--r--PKGBUILD206
-rw-r--r--add-av_stream_get_first_dts-for-chromium.patch31
-rw-r--r--rkmpp-5.patch2768
4 files changed, 3101 insertions, 0 deletions
diff --git a/.SRCINFO b/.SRCINFO
new file mode 100644
index 000000000000..48fd8448e4af
--- /dev/null
+++ b/.SRCINFO
@@ -0,0 +1,96 @@
+pkgbase = ffmpeg-mpp
+ pkgdesc = Complete solution to record, convert and stream audio and video supporting rockchip MPP hardware decoder
+ pkgver = 5.1.2
+ pkgrel = 4
+ epoch = 2
+ url = https://ffmpeg.org/
+ arch = aarch64
+ arch = arm7f
+ license = GPL3
+ makedepends = amf-headers
+ makedepends = avisynthplus
+ makedepends = clang
+ makedepends = git
+ makedepends = ladspa
+ makedepends = mesa
+ makedepends = nasm
+ makedepends = opencl-headers
+ makedepends = vulkan-headers
+ depends = alsa-lib
+ depends = bzip2
+ depends = fontconfig
+ depends = fribidi
+ depends = gmp
+ depends = gnutls
+ depends = gsm
+ depends = jack
+ depends = lame
+ depends = libass.so
+ depends = libavc1394
+ depends = libbluray.so
+ depends = libbs2b.so
+ depends = libdav1d.so
+ depends = libdrm
+ depends = libfreetype.so
+ depends = libgl
+ depends = libiec61883
+ depends = libmodplug
+ depends = libpulse
+ depends = libraw1394
+ depends = librsvg-2.so
+ depends = libsoxr
+ depends = libssh
+ depends = libtheora
+ depends = libva.so
+ depends = libva-drm.so
+ depends = libva-x11.so
+ depends = libvdpau
+ depends = libvidstab.so
+ depends = libvorbisenc.so
+ depends = libvorbis.so
+ depends = libvpx.so
+ depends = libvulkan.so
+ depends = libwebp
+ depends = libx11
+ depends = libx264.so
+ depends = libx265.so
+ depends = libxcb
+ depends = libxext
+ depends = libxml2
+ depends = libxv
+ depends = libxvidcore.so
+ depends = libzimg.so
+ depends = ocl-icd
+ depends = opencore-amr
+ depends = openjpeg2
+ depends = opus
+ depends = sdl2
+ depends = speex
+ depends = srt
+ depends = v4l-utils
+ depends = xz
+ depends = zlib
+ depends = mpp-git
+ optdepends = avisynthplus: AviSynthPlus support
+ optdepends = ladspa: LADSPA filters
+ provides = libavcodec.so
+ provides = libavdevice.so
+ provides = libavfilter.so
+ provides = libavformat.so
+ provides = libavutil.so
+ provides = libpostproc.so
+ provides = libswresample.so
+ provides = libswscale.so
+ provides = ffmpeg-mpp
+ provides = ffmpeg
+ conflicts = ffmpeg-mpp
+ conflicts = ffmpeg
+ source = git+https://git.ffmpeg.org/ffmpeg.git?#tag=1326fe9d4c85cca1ee774b072ef4fa337694f2e7
+ source = add-av_stream_get_first_dts-for-chromium.patch
+ source = rkmpp-5.patch
+ validpgpkeys = DD1EC9E8DE085C629B3E1846B18E8928B3948D64
+ b2sums = SKIP
+ b2sums = 555274228e09a233d92beb365d413ff5c718a782008075552cafb2130a3783cf976b51dfe4513c15777fb6e8397a34122d475080f2c4483e8feea5c0d878e6de
+ b2sums = 7fff16d721cfc6dcbe5081a4250686dd4941e31a3f1b745485dfb72a599c3d147d35d8055070e9fefed0340efc0ce13a2f30eacae8b33331e7de1aa45baea46f
+
+pkgname = ffmpeg-mpp
diff --git a/PKGBUILD b/PKGBUILD
new file mode 100644
index 000000000000..bff4ee47ffda
--- /dev/null
+++ b/PKGBUILD
@@ -0,0 +1,206 @@
+# Maintainer: Mahmut Dikcizgi <boogiepop a~t gmx com>
+# Contributor: Maxime Gauduin <alucryd@archlinux.org>
+# Contributor: Bartłomiej Piotrowski <bpiotrowski@archlinux.org>
+# Contributor: Ionut Biru <ibiru@archlinux.org>
+# Contributor: Tom Newsom <Jeepster@gmx.co.uk>
+# Contributor: Paul Mattal <paul@archlinux.org>
+
+# ALARM: Kevin Mihelich <kevin@archlinuxarm.org>
+# - use -fPIC in host cflags for v7/v8 to fix print_options.c compile
+# - remove makedepends on ffnvcodec-headers, remove --enable-nvenc, --enable-nvdec
+# - remove depends on aom, remove --enable-libaom
+# - remove depends on intel-media-sdk, remove --enable-libmfx
+# - remove depends on vmaf, remove --enable-vmaf
+# - remove depends on rav1e, remove --enable-librav1e
+# - remove depends on svt-av1, remove --enable-libsvtav1
+# - remove --enable-lto
+# - enable rockchip decoders witht he highest priority
+# - interface rockchip rga from kernel to userspace directly
+# - hack around rockchips vp8&9 colorspace is not detected when used with Firefox
+
+pkgname=ffmpeg-mpp
+pkgver=5.1.2
+pkgrel=4
+epoch=2
+pkgdesc='Complete solution to record, convert and stream audio and video supporting rockchip MPP hardware decoder'
+arch=(aarch64 arm7f)
+url=https://ffmpeg.org/
+license=(GPL3)
+depends=(
+ alsa-lib
+ bzip2
+ fontconfig
+ fribidi
+ gmp
+ gnutls
+ gsm
+ jack
+ lame
+ libass.so
+ libavc1394
+ libbluray.so
+ libbs2b.so
+ libdav1d.so
+ libdrm
+ libfreetype.so
+ libgl
+ libiec61883
+ libmodplug
+ libpulse
+ libraw1394
+ librsvg-2.so
+ libsoxr
+ libssh
+ libtheora
+ libva.so
+ libva-drm.so
+ libva-x11.so
+ libvdpau
+ libvidstab.so
+ libvorbisenc.so
+ libvorbis.so
+ libvpx.so
+ libvulkan.so
+ libwebp
+ libx11
+ libx264.so
+ libx265.so
+ libxcb
+ libxext
+ libxml2
+ libxv
+ libxvidcore.so
+ libzimg.so
+ ocl-icd
+ opencore-amr
+ openjpeg2
+ opus
+ sdl2
+ speex
+ srt
+ v4l-utils
+ xz
+ zlib
+ mpp-git
+)
+makedepends=(
+ amf-headers
+ avisynthplus
+ clang
+ git
+ ladspa
+ mesa
+ nasm
+ opencl-headers
+ vulkan-headers
+)
+optdepends=(
+ 'avisynthplus: AviSynthPlus support'
+ 'ladspa: LADSPA filters'
+)
+provides=(
+ libavcodec.so
+ libavdevice.so
+ libavfilter.so
+ libavformat.so
+ libavutil.so
+ libpostproc.so
+ libswresample.so
+ libswscale.so
+ $pkgname
+ ffmpeg
+)
+conflicts=(
+ $pkgname
+ ffmpeg
+)
+_tag=1326fe9d4c85cca1ee774b072ef4fa337694f2e7
+source=(
+ git+https://git.ffmpeg.org/ffmpeg.git?#tag=${_tag}
+ add-av_stream_get_first_dts-for-chromium.patch
+ rkmpp-5.patch
+)
+b2sums=('SKIP'
+ '555274228e09a233d92beb365d413ff5c718a782008075552cafb2130a3783cf976b51dfe4513c15777fb6e8397a34122d475080f2c4483e8feea5c0d878e6de'
+ '7fff16d721cfc6dcbe5081a4250686dd4941e31a3f1b745485dfb72a599c3d147d35d8055070e9fefed0340efc0ce13a2f30eacae8b33331e7de1aa45baea46f')
+validpgpkeys=(DD1EC9E8DE085C629B3E1846B18E8928B3948D64) # Michael Niedermayer <michael@niedermayer.cc>
+
+prepare() {
+ cd ffmpeg
+ patch -Np1 -i ../add-av_stream_get_first_dts-for-chromium.patch # https://crbug.com/1251779
+ patch -Np1 -i ../rkmpp-5.patch
+}
+
+pkgver() {
+ cd ffmpeg
+ git describe --tags | sed 's/^n//'
+}
+
+build() {
+ cd ffmpeg
+ [[ $CARCH == "armv7h" || $CARCH == "aarch64" ]] && CONFIG='--host-cflags="-fPIC"'
+
+ ./configure \
+ --prefix=/usr \
+ --disable-debug \
+ --disable-static \
+ --disable-stripping \
+ --enable-amf \
+ --enable-avisynth \
+ --enable-cuda-llvm \
+ --enable-fontconfig \
+ --enable-gmp \
+ --enable-gnutls \
+ --enable-gpl \
+ --enable-ladspa \
+ --enable-libass \
+ --enable-libbluray \
+ --enable-libbs2b \
+ --enable-libdav1d \
+ --enable-libdrm \
+ --enable-libfreetype \
+ --enable-libfribidi \
+ --enable-libgsm \
+ --enable-libiec61883 \
+ --enable-libjack \
+ --enable-libmodplug \
+ --enable-libmp3lame \
+ --enable-libopencore_amrnb \
+ --enable-libopencore_amrwb \
+ --enable-libopenjpeg \
+ --enable-libopus \
+ --enable-libpulse \
+ --enable-librsvg \
+ --enable-libsoxr \
+ --enable-libspeex \
+ --enable-libsrt \
+ --enable-libssh \
+ --enable-libtheora \
+ --enable-libv4l2 \
+ --enable-libvidstab \
+ --enable-libvorbis \
+ --enable-libvpx \
+ --enable-libwebp \
+ --enable-libx264 \
+ --enable-libx265 \
+ --enable-libxcb \
+ --enable-libxml2 \
+ --enable-libxvid \
+ --enable-libzimg \
+ --enable-opencl \
+ --enable-opengl \
+ --enable-shared \
+ --enable-version3 \
+ --enable-rkmpp \
+ --enable-vulkan $CONFIG
+ make -j$(nproc)
+ make tools/qt-faststart
+ make doc/ff{mpeg,play}.1
+}
+
+package() {
+ make DESTDIR="${pkgdir}" -C ffmpeg install install-man
+ install -Dm 755 ffmpeg/tools/qt-faststart "${pkgdir}"/usr/bin/
+}
+
+# vim: ts=2 sw=2 et: \ No newline at end of file
diff --git a/add-av_stream_get_first_dts-for-chromium.patch b/add-av_stream_get_first_dts-for-chromium.patch
new file mode 100644
index 000000000000..20ea725dabf4
--- /dev/null
+++ b/add-av_stream_get_first_dts-for-chromium.patch
@@ -0,0 +1,31 @@
+diff '--color=auto' -rupN ffmpeg.orig/libavformat/avformat.h ffmpeg/libavformat/avformat.h
+--- ffmpeg.orig/libavformat/avformat.h 2022-08-19 17:42:47.323422603 +0200
++++ ffmpeg/libavformat/avformat.h 2022-08-19 17:42:51.347130436 +0200
+@@ -1128,6 +1128,10 @@ struct AVCodecParserContext *av_stream_g
+ */
+ int64_t av_stream_get_end_pts(const AVStream *st);
+
++// Chromium: We use the internal field first_dts vvv
++int64_t av_stream_get_first_dts(const AVStream *st);
++// Chromium: We use the internal field first_dts ^^^
++
+ #define AV_PROGRAM_RUNNING 1
+
+ /**
+diff '--color=auto' -rupN ffmpeg.orig/libavformat/mux_utils.c ffmpeg/libavformat/mux_utils.c
+--- ffmpeg.orig/libavformat/mux_utils.c 2022-08-19 17:42:47.346758108 +0200
++++ ffmpeg/libavformat/mux_utils.c 2022-08-19 17:47:28.549589002 +0200
+@@ -37,6 +37,13 @@ int64_t av_stream_get_end_pts(const AVSt
+ return AV_NOPTS_VALUE;
+ }
+
++// Chromium: We use the internal field first_dts vvv
++int64_t av_stream_get_first_dts(const AVStream *st)
++{
++ return cffstream(st)->first_dts;
++}
++// Chromium: We use the internal field first_dts ^^^
++
+ int avformat_query_codec(const AVOutputFormat *ofmt, enum AVCodecID codec_id,
+ int std_compliance)
+ {
diff --git a/rkmpp-5.patch b/rkmpp-5.patch
new file mode 100644
index 000000000000..c16a17236872
--- /dev/null
+++ b/rkmpp-5.patch
@@ -0,0 +1,2768 @@
+From 39e9a603be52a5ef2a791e0ea9287dde802f14e7 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/15] 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 d4f09f456d..d3f87975e4 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 bcc297fedd3a2a78e116241a3568a272d9ede3be 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/15] 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 d3f87975e4..fccaa6a0fd 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 7acd9d6b4715f64d21cc136d30420777c0e3b372 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/15] 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 fccaa6a0fd..0b845a118e 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 02eaaec51070c0b924ad0cb47a42f86127c11f95 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/15] 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 0b845a118e..e6508ddfbb 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 e4d5ce7e1e05aad8a800db1d94d905ab8339c26d 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/15] 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 e6508ddfbb..e5d565256c 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 f192efbf66c787c4dc51e965b03cb77601a24bea 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/15] 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 ba5793b2ff..cacd7fa4c4 100755
+--- a/configure
++++ b/configure
+@@ -348,6 +348,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]
+@@ -1904,6 +1905,7 @@ HWACCEL_AUTODETECT_LIBRARY_LIST="
+ videotoolbox
+ vulkan
+ v4l2_m2m
++ librga
+ "
+
+ # catchall list of things that require external libs to link
+@@ -6730,10 +6732,13 @@ enabled openssl && { { check_pkg_config openssl "openssl >= 3.0.0" ope
+ 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 e5d565256c..a10a1dc64e 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[] = {
+ .p.priv_class = &rkmpp_##NAME##_dec_class, \
+ .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, \
+ .p.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 19457080d4f6f758509b0f10921f75d794e3e422 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/15] 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 a10a1dc64e..20b5783db0 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 "codec_internal.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 773487e3632a25010691a95c23ad17ba768fc382 Mon Sep 17 00:00:00 2001
+From: boogie <boogiepop@gmx.com>
+Date: Sat, 7 Jan 2023 00:43:42 +0100
+Subject: [PATCH 08/15] HACK: libavcodec & rkmppdec: Add
+ FF_CODEC_CAP_CONTIGUOUS_BUFFERS
+
+Add FF_CODEC_CAP_CONTIGUOUS_BUFFERS to alloc contiguous buffers.
+Allow Probing
+
+Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
+---
+ libavcodec/codec_internal.h | 4 ++++
+ libavcodec/get_buffer.c | 24 ++++++++++++++++++++++++
+ libavcodec/rkmppdec.c | 19 +++++++++++--------
+ 3 files changed, 39 insertions(+), 8 deletions(-)
+
+diff --git a/libavcodec/codec_internal.h b/libavcodec/codec_internal.h
+index 5df286ce52..c4483f93be 100644
+--- a/libavcodec/codec_internal.h
++++ b/libavcodec/codec_internal.h
+@@ -78,6 +78,10 @@
+ * FFCodec.codec_tags termination value
+ */
+ #define FF_CODEC_TAGS_END -1
++/**
++ * The decoder requires contiguous buffers.
++ */
++#define FF_CODEC_CAP_CONTIGUOUS_BUFFERS (1 << 31)
+
+ typedef struct FFCodecDefault {
+ const char *key;
+diff --git a/libavcodec/get_buffer.c b/libavcodec/get_buffer.c
+index 3e45a0479f..dfffa530ab 100644
+--- a/libavcodec/get_buffer.c
++++ b/libavcodec/get_buffer.c
+@@ -31,6 +31,7 @@
+ #include "libavutil/version.h"
+
+ #include "avcodec.h"
++#include "codec_internal.h"
+ #include "internal.h"
+
+ typedef struct FramePool {
+@@ -147,6 +148,14 @@ FF_ENABLE_DEPRECATION_WARNINGS
+
+ for (i = 0; i < 4; i++) {
+ pool->linesize[i] = linesize[i];
++
++ if (avctx->codec->capabilities & 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);
+@@ -273,6 +282,21 @@ static int video_get_buffer(AVCodecContext *s, AVFrame *pic)
+
+ pic->data[i] = pic->buf[i]->data;
+ }
++
++ if (s->codec->capabilities & 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/rkmppdec.c b/libavcodec/rkmppdec.c
+index 20b5783db0..f0c4c5bb03 100644
+--- a/libavcodec/rkmppdec.c
++++ b/libavcodec/rkmppdec.c
+@@ -501,20 +501,18 @@ 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 +529,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);
+
+@@ -756,7 +759,7 @@ static const AVCodecHWConfigInternal *const rkmpp_hw_configs[] = {
+ FF_CODEC_RECEIVE_FRAME_CB(rkmpp_receive_frame), \
+ .flush = rkmpp_flush, \
+ .p.priv_class = &rkmpp_##NAME##_dec_class, \
+- .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, \
++ .p.capabilities = AV_CODEC_CAP_DELAY | FF_CODEC_CAP_CONTIGUOUS_BUFFERS | AV_CODEC_CAP_HARDWARE, \
+ .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_DRM_PRIME, \
+ AV_PIX_FMT_YUV420P, \
+ AV_PIX_FMT_NONE}, \
+--
+2.39.0
+
+
+From 38f3960fd42e4bdd7412d45ca795d09669835956 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/15] 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 f0c4c5bb03..295610a4ec 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 60755d6e5fe77bbdb73d6427e958ccdda508b229 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/15] 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 295610a4ec..1c09cdfbbc 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 23001dea7ece2affef0470d1dc51af8e8b5135ec 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/15] 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 1c09cdfbbc..edc05f5bd0 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;
+ }
+
+@@ -724,6 +733,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 18e847bcc7c79a46e511d01549a5479bdbfc31f1 Mon Sep 17 00:00:00 2001
+From: boogie <boogiepop@gmx.com>
+Date: Sun, 8 Jan 2023 01:32:15 +0100
+Subject: [PATCH 12/15] Add rkmpp H263 MPEG1 MPEG2 MPEG4 DECODERS Priotize
+ RKMPP decoders first Allow NV15
+
+---
+ configure | 4 ++++
+ libavcodec/Makefile | 5 +++++
+ libavcodec/allcodecs.c | 13 +++++++++----
+ libavcodec/rkmppdec.c | 11 ++++++++++-
+ 4 files changed, 28 insertions(+), 5 deletions(-)
+
+diff --git a/configure b/configure
+index cacd7fa4c4..663b3153f7 100755
+--- a/configure
++++ b/configure
+@@ -3168,6 +3168,7 @@ av1_cuvid_decoder_deps="cuvid CUVIDAV1PICPARAMS"
+ h263_v4l2m2m_decoder_deps="v4l2_m2m h263_v4l2_m2m"
+ h263_v4l2m2m_encoder_deps="v4l2_m2m h263_v4l2_m2m"
+ h264_amf_encoder_deps="amf"
++h263_rkmpp_decoder_deps="rkmpp"
+ h264_crystalhd_decoder_select="crystalhd h264_mp4toannexb_bsf h264_parser"
+ h264_cuvid_decoder_deps="cuvid"
+ h264_cuvid_decoder_select="h264_mp4toannexb_bsf"
+@@ -3212,6 +3213,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"
+@@ -3220,6 +3222,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"
+@@ -3227,6 +3230,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"
+ vc1_crystalhd_decoder_select="crystalhd"
+ vc1_cuvid_decoder_deps="cuvid"
+diff --git a/libavcodec/Makefile b/libavcodec/Makefile
+index 457ec58377..8d7ff5ed03 100644
+--- a/libavcodec/Makefile
++++ b/libavcodec/Makefile
+@@ -62,6 +62,11 @@ OBJS = ac3_parser.o \
+ xiph.o \
+
+ # subsystems
++OBJS-$(CONFIG_H263_RKMPP_DECODER) += rkmppdec.o
++OBJS-$(CONFIG_MPEG1_RKMPP_DECODER) += rkmppdec.o
++OBJS-$(CONFIG_MPEG2_RKMPP_DECODER) += rkmppdec.o
++OBJS-$(CONFIG_MPEG4_RKMPP_DECODER) += rkmppdec.o
++
+ OBJS-$(CONFIG_AANDCTTABLES) += aandcttab.o
+ OBJS-$(CONFIG_AC3DSP) += ac3dsp.o ac3.o ac3tab.o
+ OBJS-$(CONFIG_ADTS_HEADER) += adts_header.o mpeg4audio_sample_rates.o
+diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
+index bdfc2f6f45..bb09cf417a 100644
+--- a/libavcodec/allcodecs.c
++++ b/libavcodec/allcodecs.c
+@@ -34,6 +34,15 @@
+ #include "codec_id.h"
+ #include "codec_internal.h"
+
++extern const FFCodec ff_h263_rkmpp_decoder;
++extern const FFCodec ff_h264_rkmpp_decoder;
++extern const FFCodec ff_hevc_rkmpp_decoder;
++extern const FFCodec ff_mpeg4_rkmpp_decoder;
++extern const FFCodec ff_mpeg1_rkmpp_decoder;
++extern const FFCodec ff_mpeg2_rkmpp_decoder;
++extern const FFCodec ff_vp8_rkmpp_decoder;
++extern const FFCodec ff_vp9_rkmpp_decoder;
++
+ extern const FFCodec ff_a64multi_encoder;
+ extern const FFCodec ff_a64multi5_encoder;
+ extern const FFCodec ff_aasc_decoder;
+@@ -154,12 +163,10 @@ extern const FFCodec ff_h264_v4l2m2m_decoder;
+ extern const FFCodec ff_h264_mediacodec_decoder;
+ extern const FFCodec ff_h264_mmal_decoder;
+ extern const FFCodec ff_h264_qsv_decoder;
+-extern const FFCodec ff_h264_rkmpp_decoder;
+ extern const FFCodec ff_hap_encoder;
+ extern const FFCodec ff_hap_decoder;
+ extern const FFCodec ff_hevc_decoder;
+ extern const FFCodec ff_hevc_qsv_decoder;
+-extern const FFCodec ff_hevc_rkmpp_decoder;
+ extern const FFCodec ff_hevc_v4l2m2m_decoder;
+ extern const FFCodec ff_hnm4_video_decoder;
+ extern const FFCodec ff_hq_hqa_decoder;
+@@ -372,10 +379,8 @@ extern const FFCodec ff_vp6a_decoder;
+ extern const FFCodec ff_vp6f_decoder;
+ extern const FFCodec ff_vp7_decoder;
+ extern const FFCodec ff_vp8_decoder;
+-extern const FFCodec ff_vp8_rkmpp_decoder;
+ extern const FFCodec ff_vp8_v4l2m2m_decoder;
+ extern const FFCodec ff_vp9_decoder;
+-extern const FFCodec ff_vp9_rkmpp_decoder;
+ extern const FFCodec ff_vp9_v4l2m2m_decoder;
+ extern const FFCodec ff_vqa_decoder;
+ extern const FFCodec ff_webp_decoder;
+diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
+index edc05f5bd0..617a611af5 100644
+--- a/libavcodec/rkmppdec.c
++++ b/libavcodec/rkmppdec.c
+@@ -28,6 +28,7 @@
+ #include <sys/time.h>
+
+ #include "avcodec.h"
++#include "internal.h"
+ #include "codec_internal.h"
+ #include "decode.h"
+ #include "hwconfig.h"
+@@ -45,7 +46,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
+@@ -83,10 +84,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;
+ }
+ }
+@@ -794,7 +799,11 @@ static const AVCodecHWConfigInternal *const rkmpp_hw_configs[] = {
+ .p.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 313d65b370084d632c1370ac101152e1032dd082 Mon Sep 17 00:00:00 2001
+From: boogie <boogiepop@gmx.com>
+Date: Fri, 13 Jan 2023 22:27:01 +0100
+Subject: [PATCH 13/15] rkmpp: interface with kernel directly for rga and ditch
+ librga
+
+---
+ 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 617a611af5..6d55db7935 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 "internal.h"
+@@ -39,11 +46,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')
+@@ -51,11 +55,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;
+
+@@ -116,17 +125,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)
+ {
+@@ -139,6 +146,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;
+@@ -154,6 +163,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);
+
+@@ -251,13 +274,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);
+@@ -308,13 +345,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);
+@@ -322,29 +360,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 ||
+@@ -352,23 +402,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;
+@@ -424,6 +464,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;
+@@ -531,6 +715,8 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
+
+
+ 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 308f59115409ff79b9f8a3e013c052be36f2779a Mon Sep 17 00:00:00 2001
+From: boogie <boogiepop@gmx.com>
+Date: Tue, 17 Jan 2023 01:02:19 +0100
+Subject: [PATCH 14/15] 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 6d55db7935..8ca686cfd9 100644
+--- a/libavcodec/rkmppdec.c
++++ b/libavcodec/rkmppdec.c
+@@ -738,6 +738,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
+
+
+From 089687f525a0da46e3dc2f5c9e06e9c1cadf28f4 Mon Sep 17 00:00:00 2001
+From: Jeffy Chen <jeffy.chen@rock-chips.com>
+Date: Tue, 17 Jan 2023 18:31:57 +0800
+Subject: [PATCH 15/15] WIP: rkmppdec: For AV1
+
+---
+ configure | 1 +
+ libavcodec/Makefile | 1 +
+ libavcodec/allcodecs.c | 1 +
+ libavcodec/rkmppdec.c | 14 ++------------
+ 4 files changed, 5 insertions(+), 12 deletions(-)
+
+diff --git a/configure b/configure
+index 663b3153f7..1fb9bd201a 100755
+--- a/configure
++++ b/configure
+@@ -3165,6 +3165,7 @@ nvenc_deps_any="libdl LoadLibrary"
+ aac_mf_encoder_deps="mediafoundation"
+ ac3_mf_encoder_deps="mediafoundation"
+ av1_cuvid_decoder_deps="cuvid CUVIDAV1PICPARAMS"
++av1_rkmpp_decoder_deps="rkmpp"
+ h263_v4l2m2m_decoder_deps="v4l2_m2m h263_v4l2_m2m"
+ h263_v4l2m2m_encoder_deps="v4l2_m2m h263_v4l2_m2m"
+ h264_amf_encoder_deps="amf"
+diff --git a/libavcodec/Makefile b/libavcodec/Makefile
+index 8d7ff5ed03..4ee69fbeda 100644
+--- a/libavcodec/Makefile
++++ b/libavcodec/Makefile
+@@ -246,6 +246,7 @@ OBJS-$(CONFIG_AURA_DECODER) += cyuv.o
+ OBJS-$(CONFIG_AURA2_DECODER) += aura.o
+ OBJS-$(CONFIG_AV1_DECODER) += av1dec.o
+ OBJS-$(CONFIG_AV1_CUVID_DECODER) += cuviddec.o
++OBJS-$(CONFIG_AV1_RKMPP_DECODER) += rkmppdec.o
+ OBJS-$(CONFIG_AVRN_DECODER) += avrndec.o
+ OBJS-$(CONFIG_AVRP_DECODER) += r210dec.o
+ OBJS-$(CONFIG_AVRP_ENCODER) += r210enc.o
+diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
+index bb09cf417a..b638e77ccd 100644
+--- a/libavcodec/allcodecs.c
++++ b/libavcodec/allcodecs.c
+@@ -42,6 +42,7 @@ extern const FFCodec ff_mpeg1_rkmpp_decoder;
+ extern const FFCodec ff_mpeg2_rkmpp_decoder;
+ extern const FFCodec ff_vp8_rkmpp_decoder;
+ extern const FFCodec ff_vp9_rkmpp_decoder;
++extern const FFCodec ff_av1_rkmpp_decoder;
+
+ extern const FFCodec ff_a64multi_encoder;
+ extern const FFCodec ff_a64multi5_encoder;
+diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
+index 8ca686cfd9..ea96956fe3 100644
+--- a/libavcodec/rkmppdec.c
++++ b/libavcodec/rkmppdec.c
+@@ -96,6 +96,7 @@ static MppCodingType rkmpp_get_codingtype(AVCodecContext *avctx)
+ 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_AV1: return MPP_VIDEO_CodingAV1;
+ case AV_CODEC_ID_VP8: return MPP_VIDEO_CodingVP8;
+ case AV_CODEC_ID_VP9: return MPP_VIDEO_CodingVP9;
+ case AV_CODEC_ID_MPEG1VIDEO: /* fallthrough */
+@@ -187,20 +188,8 @@ 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;
+- }
+-
+ if (getenv("FFMPEG_RKMPP_SYNC")) {
+ // wait for decode result after feeding any packets
+ decoder->sync = 1;
+@@ -1003,6 +992,7 @@ static const AVCodecHWConfigInternal *const rkmpp_hw_configs[] = {
+ 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(av1, AV_CODEC_ID_AV1, NULL)
+ RKMPP_DEC(vp8, AV_CODEC_ID_VP8, NULL)
+ RKMPP_DEC(vp9, AV_CODEC_ID_VP9, NULL)
+ RKMPP_DEC(mpeg1, AV_CODEC_ID_MPEG1VIDEO, NULL)
+--
+2.39.0
+