summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorboogie2023-08-02 08:57:04 +0200
committerboogie2023-08-02 08:57:04 +0200
commit01276b4cdf1b6467b7a8ec227f88e8a86060506f (patch)
tree36f29b28c5bb574af1b67de35ce1e29df37e865c
parentec884a607381e2a8f638428b47e7309994b58927 (diff)
downloadaur-01276b4cdf1b6467b7a8ec227f88e8a86060506f.tar.gz
encoder support, fix lots of stuff
-rw-r--r--.SRCINFO22
-rw-r--r--PKGBUILD50
-rw-r--r--rkmpp-6.patch7044
3 files changed, 3682 insertions, 3434 deletions
diff --git a/.SRCINFO b/.SRCINFO
index bb5eea410750..caf42de44027 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -1,9 +1,9 @@
pkgbase = ffmpeg-mpp
pkgdesc = Complete solution to record, convert and stream audio and video supporting rockchip MPP hardware decoder
pkgver = 6.0
- pkgrel = 6
+ pkgrel = 7
epoch = 2
- url = https://ffmpeg.org/
+ url = https://github.com/hbiyik/ffmpeg/
arch = aarch64
arch = arm7f
license = GPL3
@@ -17,7 +17,10 @@ pkgbase = ffmpeg-mpp
makedepends = opencl-headers
makedepends = mpp-git
makedepends = libyuv
+ makedepends = perl
+ depends = aom
depends = alsa-lib
+ depends = cairo
depends = bzip2
depends = fontconfig
depends = fribidi
@@ -35,6 +38,7 @@ pkgbase = ffmpeg-mpp
depends = libfreetype.so
depends = libgl
depends = libiec61883
+ depends = libjxl
depends = libmodplug
depends = libopenmpt.so
depends = libpulse
@@ -62,9 +66,11 @@ pkgbase = ffmpeg-mpp
depends = libxvidcore.so
depends = libzimg.so
depends = ocl-icd
+ depends = onevpl
depends = opencore-amr
depends = openjpeg2
depends = opus
+ depends = rav1e
depends = sdl2
depends = speex
depends = srt
@@ -73,6 +79,8 @@ pkgbase = ffmpeg-mpp
depends = zlib
depends = mpp-git
depends = libyuv
+ depends = librist
+ depends = librga-multi
optdepends = avisynthplus: AviSynthPlus support
optdepends = ladspa: LADSPA filters
provides = libavcodec.so
@@ -83,19 +91,21 @@ pkgbase = ffmpeg-mpp
provides = libpostproc.so
provides = libswresample.so
provides = libswscale.so
- provides = ffmpeg-mpp
- provides = ffmpeg
- conflicts = ffmpeg-mpp
+ provides = ffmpeg=6.0-7
+ provides = ffmpeg-obs=6.0-7
conflicts = ffmpeg
+ conflicts = ffmpeg-mpp
options = !lto
options = debug
options = strip
source = git+https://git.ffmpeg.org/ffmpeg.git?#tag=3949db4d261748a9f34358a388ee255ad1a7f0c0
+ source = obs-deps::git+https://github.com/obsproject/obs-deps.git#tag=2023-04-03
source = add-av_stream_get_first_dts-for-chromium.patch
source = rkmpp-6.patch
validpgpkeys = DD1EC9E8DE085C629B3E1846B18E8928B3948D64
b2sums = SKIP
+ b2sums = SKIP
b2sums = 555274228e09a233d92beb365d413ff5c718a782008075552cafb2130a3783cf976b51dfe4513c15777fb6e8397a34122d475080f2c4483e8feea5c0d878e6de
- b2sums = 4d62f7a21cf6bdb9177f931b72a8a30b9a75c0bcef84eb500feb6820e60fd95507b4d92efba5f224fb992e5170d0d8cef388c9f6326f046c1d85eacd22e50a89
+ b2sums = 0109ab217541a5120588315bac4378795f7678dcde8468a408eac89523e46dcd5da903a2a28cd9da065a8f09e37e803ade9f8a0f75983dcdd92ecb83825b4081
pkgname = ffmpeg-mpp
diff --git a/PKGBUILD b/PKGBUILD
index 44208753ded1..472c5d7bf874 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -20,15 +20,18 @@
pkgname=ffmpeg-mpp
pkgver=6.0
-pkgrel=6
+pkgrel=7
epoch=2
+_obs_deps_tag=2023-04-03
pkgdesc='Complete solution to record, convert and stream audio and video supporting rockchip MPP hardware decoder'
arch=(aarch64 arm7f)
-url=https://ffmpeg.org/
+url=https://github.com/hbiyik/ffmpeg/
license=(GPL3)
options=(!lto debug strip)
depends=(
+ aom
alsa-lib
+ cairo
bzip2
fontconfig
fribidi
@@ -46,6 +49,7 @@ depends=(
libfreetype.so
libgl
libiec61883
+ libjxl
libmodplug
libopenmpt.so
libpulse
@@ -73,9 +77,11 @@ depends=(
libxvidcore.so
libzimg.so
ocl-icd
+ onevpl
opencore-amr
openjpeg2
opus
+ rav1e
sdl2
speex
srt
@@ -84,6 +90,8 @@ depends=(
zlib
mpp-git
libyuv
+ librist
+ librga-multi
)
makedepends=(
amf-headers
@@ -96,6 +104,7 @@ makedepends=(
opencl-headers
mpp-git
libyuv
+ perl
)
optdepends=(
'avisynthplus: AviSynthPlus support'
@@ -110,30 +119,46 @@ provides=(
libpostproc.so
libswresample.so
libswscale.so
- $pkgname
- ffmpeg
+ "ffmpeg=${pkgver}-${pkgrel}"
+ "ffmpeg-obs=${pkgver}-${pkgrel}"
)
conflicts=(
- $pkgname
ffmpeg
+ $pkgname
)
_tag=3949db4d261748a9f34358a388ee255ad1a7f0c0
source=(
git+https://git.ffmpeg.org/ffmpeg.git?#tag=${_tag}
+ "obs-deps::git+https://github.com/obsproject/obs-deps.git#tag=${_obs_deps_tag}"
add-av_stream_get_first_dts-for-chromium.patch
rkmpp-6.patch
)
b2sums=('SKIP'
+ 'SKIP'
'555274228e09a233d92beb365d413ff5c718a782008075552cafb2130a3783cf976b51dfe4513c15777fb6e8397a34122d475080f2c4483e8feea5c0d878e6de'
- '4d62f7a21cf6bdb9177f931b72a8a30b9a75c0bcef84eb500feb6820e60fd95507b4d92efba5f224fb992e5170d0d8cef388c9f6326f046c1d85eacd22e50a89')
+ '0109ab217541a5120588315bac4378795f7678dcde8468a408eac89523e46dcd5da903a2a28cd9da065a8f09e37e803ade9f8a0f75983dcdd92ecb83825b4081')
validpgpkeys=(DD1EC9E8DE085C629B3E1846B18E8928B3948D64) # Michael Niedermayer <michael@niedermayer.cc>
prepare() {
cd ffmpeg
+ # delete the newly created files after patching, so that patching can work next time
+ rm libavcodec/rkmpp.h || true
+ rm libavcodec/rkmpp.c || true
+ rm libavcodec/rkmppenc.c || true
+ rm libavcodec/rkplane.c || true
+ rm libavcodec/rkplane.h || true
+ ## Fix segfault with avisynthplus
+ sed -i 's/RTLD_LOCAL/RTLD_DEEPBIND/g' libavformat/avisynth.c
patch -Np1 -i ../add-av_stream_get_first_dts-for-chromium.patch # https://crbug.com/1251779
patch -Np1 -i ../rkmpp-6.patch
+
+ # This patch applies:
+ # - Fix decoding of certain malformed FLV files
+ # - Add additional CPU levels for libaom
+ patch -Np1 -i ../obs-deps/deps.ffmpeg/patches/FFmpeg/0001-flvdec-handle-unknown.patch
+ patch -Np1 -i ../obs-deps/deps.ffmpeg/patches/FFmpeg/0002-libaomenc-presets.patch
}
pkgver() {
@@ -157,6 +182,7 @@ build() {
--enable-gnutls \
--enable-gpl \
--enable-ladspa \
+ --enable-libaom \
--enable-libass \
--enable-libbluray \
--enable-libbs2b \
@@ -167,6 +193,7 @@ build() {
--enable-libgsm \
--enable-libiec61883 \
--enable-libjack \
+ --enable-libjxl \
--enable-libmodplug \
--enable-libmp3lame \
--enable-libopencore_amrnb \
@@ -175,6 +202,7 @@ build() {
--enable-libopenmpt \
--enable-libopus \
--enable-libpulse \
+ --enable-librav1e \
--enable-librsvg \
--enable-libsoxr \
--enable-libspeex \
@@ -184,6 +212,7 @@ build() {
--enable-libv4l2 \
--enable-libvidstab \
--enable-libvorbis \
+ --enable-libvpl \
--enable-libvpx \
--enable-libwebp \
--enable-libx264 \
@@ -196,15 +225,16 @@ build() {
--enable-opengl \
--enable-shared \
--enable-version3 \
+ --enable-librist \
--disable-vulkan \
--enable-rkmpp $CONFIG
- make -j$(nproc)
- make tools/qt-faststart
- make doc/ff{mpeg,play}.1
+ make ${MAKEFLAGS}
+ make ${MAKEFLAGS} tools/qt-faststart
+ make ${MAKEFLAGS} doc/ff{mpeg,play}.1
}
package() {
- make DESTDIR="${pkgdir}" -C ffmpeg install install-man
+ make ${MAKEFLAGS} DESTDIR="${pkgdir}" -C ffmpeg install install-man
install -Dm 755 ffmpeg/tools/qt-faststart "${pkgdir}"/usr/bin/
}
diff --git a/rkmpp-6.patch b/rkmpp-6.patch
index 4b906b28d652..905ec3867c77 100644
--- a/rkmpp-6.patch
+++ b/rkmpp-6.patch
@@ -1,161 +1,639 @@
-From e13ddabb7694f8332d95ddc4bc00e37b1f7e2a76 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/24] avcodec/rkmppdec: Clear eos flag after reset
+From 3262b03e2a59ec36b3c69fc3fed6f1aa931cf69d Mon Sep 17 00:00:00 2001
+From: rigaya <rigaya34589@live.jp>
+Date: Fri, 7 Apr 2023 22:45:51 +0900
+Subject: [PATCH 01/13] avdevice/v4l2: add v4l2 multi-planar API support
-Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
---
- libavcodec/rkmppdec.c | 1 +
- 1 file changed, 1 insertion(+)
+ libavdevice/v4l2.c | 173 ++++++++++++++++++++++++++++++++-------------
+ 1 file changed, 124 insertions(+), 49 deletions(-)
-diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
-index 8bf7c6ed16..e31e0c44dc 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;
+diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c
+index 5e85d1a2b3..249bedfaaa 100644
+--- a/libavdevice/v4l2.c
++++ b/libavdevice/v4l2.c
+@@ -87,14 +87,16 @@ struct video_data {
+ int frame_size;
+ int interlaced;
+ int top_field_first;
++ int multi_planer;
+ int ts_mode;
+ TimeFilter *timefilter;
+ int64_t last_time_m;
+
+ int buffers;
+ atomic_int buffers_queued;
+- void **buf_start;
+- unsigned int *buf_len;
++ int plane_count;
++ void ***buf_start;
++ unsigned int **buf_len;
+ char *standard;
+ v4l2_std_id std_id;
+ int channel;
+@@ -181,11 +183,12 @@ static int device_open(AVFormatContext *ctx, const char* device_path)
+ av_log(ctx, AV_LOG_VERBOSE, "fd:%d capabilities:%x\n",
+ fd, cap.capabilities);
+
+- if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
++ if (!(cap.capabilities & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_CAPTURE_MPLANE))) {
+ av_log(ctx, AV_LOG_ERROR, "Not a video capture device.\n");
+ err = AVERROR(ENODEV);
+ goto fail;
+ }
++ s->multi_planer = ((cap.capabilities & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_CAPTURE_MPLANE)) == V4L2_CAP_VIDEO_CAPTURE_MPLANE) ? 1 : 0;
+
+ if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
+ av_log(ctx, AV_LOG_ERROR,
+@@ -205,7 +208,7 @@ static int device_init(AVFormatContext *ctx, int *width, int *height,
+ uint32_t pixelformat)
+ {
+ struct video_data *s = ctx->priv_data;
+- struct v4l2_format fmt = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };
++ struct v4l2_format fmt = { .type = (s->multi_planer) ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : V4L2_BUF_TYPE_VIDEO_CAPTURE };
+ int res = 0;
+
+ fmt.fmt.pix.width = *width;
+@@ -287,7 +290,7 @@ static void list_framesizes(AVFormatContext *ctx, uint32_t pixelformat)
+ static void list_formats(AVFormatContext *ctx, int type)
+ {
+ const struct video_data *s = ctx->priv_data;
+- struct v4l2_fmtdesc vfd = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };
++ struct v4l2_fmtdesc vfd = { .type = (s->multi_planer) ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : V4L2_BUF_TYPE_VIDEO_CAPTURE };
+
+ while(!v4l2_ioctl(s->fd, VIDIOC_ENUM_FMT, &vfd)) {
+ enum AVCodecID codec_id = ff_fmt_v4l2codec(vfd.pixelformat);
+@@ -351,7 +354,7 @@ static int mmap_init(AVFormatContext *ctx)
+ int i, res;
+ struct video_data *s = ctx->priv_data;
+ struct v4l2_requestbuffers req = {
+- .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
++ .type = (s->multi_planer) ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ .count = desired_video_buffers,
+ .memory = V4L2_MEMORY_MMAP
+ };
+@@ -367,45 +370,71 @@ static int mmap_init(AVFormatContext *ctx)
+ return AVERROR(ENOMEM);
+ }
+ s->buffers = req.count;
+- s->buf_start = av_malloc_array(s->buffers, sizeof(void *));
++ s->buf_start = av_malloc_array(s->buffers, sizeof(void **));
+ if (!s->buf_start) {
+ av_log(ctx, AV_LOG_ERROR, "Cannot allocate buffer pointers\n");
+ return AVERROR(ENOMEM);
+ }
+- s->buf_len = av_malloc_array(s->buffers, sizeof(unsigned int));
++ s->buf_len = av_malloc_array(s->buffers, sizeof(unsigned int*));
+ if (!s->buf_len) {
+ av_log(ctx, AV_LOG_ERROR, "Cannot allocate buffer sizes\n");
+ av_freep(&s->buf_start);
+ return AVERROR(ENOMEM);
+ }
+
++ s->plane_count = 0;
+ for (i = 0; i < req.count; i++) {
++ int total_frame_size = 0;
++ int plane_count = 0;
++ struct v4l2_plane planes[VIDEO_MAX_PLANES];
+ struct v4l2_buffer buf = {
+- .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+- .index = i,
+- .memory = V4L2_MEMORY_MMAP
++ .type = (s->multi_planer) ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : V4L2_BUF_TYPE_VIDEO_CAPTURE,
++ .index = i,
++ .memory = V4L2_MEMORY_MMAP,
++ .m.planes = (s->multi_planer) ? planes : 0,
++ .length = (s->multi_planer) ? VIDEO_MAX_PLANES : 0
+ };
+ if (v4l2_ioctl(s->fd, VIDIOC_QUERYBUF, &buf) < 0) {
+ res = AVERROR(errno);
+ av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYBUF): %s\n", av_err2str(res));
+ return res;
+ }
+-
+- s->buf_len[i] = buf.length;
+- if (s->frame_size > 0 && s->buf_len[i] < s->frame_size) {
+- av_log(ctx, AV_LOG_ERROR,
+- "buf_len[%d] = %d < expected frame size %d\n",
+- i, s->buf_len[i], s->frame_size);
++ plane_count = (s->multi_planer) ? buf.length : 1;
++ if (s->plane_count > 0 && s->plane_count != plane_count) {
++ av_log(ctx, AV_LOG_ERROR, "Plane count differed between buffers\n");
++ return AVERROR(EINVAL);
++ }
++ s->plane_count = plane_count;
++ s->buf_start[i] = av_malloc_array(s->plane_count, sizeof(void *));
++ if (!s->buf_start[i]) {
++ av_log(ctx, AV_LOG_ERROR, "Cannot allocate buffer pointers\n");
+ return AVERROR(ENOMEM);
+ }
+- s->buf_start[i] = v4l2_mmap(NULL, buf.length,
+- PROT_READ | PROT_WRITE, MAP_SHARED,
+- s->fd, buf.m.offset);
++ s->buf_len[i] = av_malloc_array(s->plane_count, sizeof(unsigned int*));
++ if (!s->buf_len[i]) {
++ av_log(ctx, AV_LOG_ERROR, "Cannot allocate buffer sizes\n");
++ av_freep(&s->buf_start);
++ return AVERROR(ENOMEM);
++ }
++ for (int iplane = 0; iplane < s->plane_count; iplane++) {
++ s->buf_len[i][iplane] = (s->multi_planer) ? buf.m.planes[iplane].length : buf.length;
++ total_frame_size += s->buf_len[i][iplane];
++ s->buf_start[i][iplane] = v4l2_mmap(NULL, s->buf_len[i][iplane],
++ PROT_READ | PROT_WRITE, MAP_SHARED,
++ s->fd, (s->multi_planer) ? buf.m.planes[iplane].m.mem_offset : buf.m.offset);
++
++ if (s->buf_start[i] == MAP_FAILED) {
++ res = AVERROR(errno);
++ av_log(ctx, AV_LOG_ERROR, "mmap: %s\n", av_err2str(res));
++ return res;
++ }
++ }
+
+- if (s->buf_start[i] == MAP_FAILED) {
+- res = AVERROR(errno);
+- av_log(ctx, AV_LOG_ERROR, "mmap: %s\n", av_err2str(res));
+- return res;
++ if (s->frame_size > 0 && total_frame_size < s->frame_size) {
++ av_log(ctx, AV_LOG_ERROR,
++ "buf_len[%d] = %d < expected frame size %d\n",
++ i, total_frame_size, s->frame_size);
++ return AVERROR(ENOMEM);
+ }
+ }
+
+@@ -432,9 +461,9 @@ static void mmap_release_buffer(void *opaque, uint8_t *data)
+ struct buff_data *buf_descriptor = opaque;
+ struct video_data *s = buf_descriptor->s;
+
+- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++ buf.type = (s->multi_planer) ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_MMAP;
+- buf.index = buf_descriptor->index;
++ buf.index = buf_descriptor->index;
+ av_free(buf_descriptor);
+
+ enqueue_buffer(s, &buf);
+@@ -504,9 +533,12 @@ static int convert_timestamp(AVFormatContext *ctx, int64_t *ts)
+ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt)
+ {
+ struct video_data *s = ctx->priv_data;
++ struct v4l2_plane planes[VIDEO_MAX_PLANES];
+ struct v4l2_buffer buf = {
+- .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+- .memory = V4L2_MEMORY_MMAP
++ .type = (s->multi_planer) ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : V4L2_BUF_TYPE_VIDEO_CAPTURE,
++ .memory = V4L2_MEMORY_MMAP,
++ .m.planes = (s->multi_planer) ? planes : 0,
++ .length = (s->multi_planer) ? VIDEO_MAX_PLANES : 0
+ };
+ struct timeval buf_ts;
+ int res;
+@@ -544,29 +576,63 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt)
} else
- av_log(avctx, AV_LOG_ERROR, "Failed to reset MPI (code = %d)\n", ret);
- }
+ #endif
+ {
++ int total_frame_size = 0;
++
+ /* CPIA is a compressed format and we don't know the exact number of bytes
+ * used by a frame, so set it here as the driver announces it. */
+ if (ctx->video_codec_id == AV_CODEC_ID_CPIA)
+ s->frame_size = buf.bytesused;
+
+- if (s->frame_size > 0 && buf.bytesused != s->frame_size) {
++ if (V4L2_TYPE_IS_MULTIPLANAR(buf.type)) {
++ for (int iplane = 0; iplane < buf.length; iplane++) {
++ total_frame_size += buf.m.planes[iplane].bytesused;
++ }
++ } else {
++ total_frame_size = buf.bytesused;
++ }
++ if (s->frame_size > 0 && total_frame_size != s->frame_size) {
+ av_log(ctx, AV_LOG_WARNING,
+ "Dequeued v4l2 buffer contains %d bytes, but %d were expected. Flags: 0x%08X.\n",
+- buf.bytesused, s->frame_size, buf.flags);
+- buf.bytesused = 0;
++ total_frame_size, s->frame_size, buf.flags);
++ if (V4L2_TYPE_IS_MULTIPLANAR(buf.type)) {
++ for (int iplane = 0; iplane < buf.length; iplane++) {
++ buf.m.planes[iplane].bytesused = 0;
++ }
++ } else {
++ buf.bytesused = 0;
++ }
+ }
+ }
+
+- /* Image is at s->buff_start[buf.index] */
+- if (atomic_load(&s->buffers_queued) == FFMAX(s->buffers / 8, 1)) {
+- /* when we start getting low on queued buffers, fall back on copying data */
+- res = av_new_packet(pkt, buf.bytesused);
+- if (res < 0) {
+- av_log(ctx, AV_LOG_ERROR, "Error allocating a packet.\n");
+- enqueue_buffer(s, &buf);
+- return res;
++ if (atomic_load(&s->buffers_queued) == FFMAX(s->buffers / 8, 1) || V4L2_TYPE_IS_MULTIPLANAR(buf.type)) {
++ if (V4L2_TYPE_IS_MULTIPLANAR(buf.type)) {
++ int totalbytes = 0;
++ for (int iplane = 0; iplane < buf.length; iplane++) {
++ totalbytes += buf.m.planes[iplane].bytesused;
++ }
++ res = av_new_packet(pkt, totalbytes);
++ if (res < 0) {
++ av_log(ctx, AV_LOG_ERROR, "Error allocating a packet.\n");
++ enqueue_buffer(s, &buf);
++ return res;
++ }
++ totalbytes = 0;
++ for (int iplane = 0; iplane < buf.length; iplane++) {
++ struct v4l2_plane *plane = &buf.m.planes[iplane];
++ memcpy(pkt->data + totalbytes, s->buf_start[buf.index][plane->data_offset], plane->bytesused);
++ totalbytes += plane->bytesused;
++ }
++ } else {
++ /* Image is at s->buff_start[buf.index] */
++ /* when we start getting low on queued buffers, fall back on copying data */
++ res = av_new_packet(pkt, buf.bytesused);
++ if (res < 0) {
++ av_log(ctx, AV_LOG_ERROR, "Error allocating a packet.\n");
++ enqueue_buffer(s, &buf);
++ return res;
++ }
++ memcpy(pkt->data, s->buf_start[buf.index][0], buf.bytesused);
+ }
+- memcpy(pkt->data, s->buf_start[buf.index], buf.bytesused);
+
+ res = enqueue_buffer(s, &buf);
+ if (res) {
+@@ -576,7 +642,7 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt)
+ } else {
+ struct buff_data *buf_descriptor;
+
+- pkt->data = s->buf_start[buf.index];
++ pkt->data = s->buf_start[buf.index][0];
+ pkt->size = buf.bytesused;
+
+ buf_descriptor = av_malloc(sizeof(struct buff_data));
+@@ -614,10 +680,13 @@ static int mmap_start(AVFormatContext *ctx)
+ int i, res;
+
+ for (i = 0; i < s->buffers; i++) {
++ struct v4l2_plane planes[VIDEO_MAX_PLANES];
+ struct v4l2_buffer buf = {
+- .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+- .index = i,
+- .memory = V4L2_MEMORY_MMAP
++ .type = (s->multi_planer) ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : V4L2_BUF_TYPE_VIDEO_CAPTURE,
++ .index = i,
++ .memory = V4L2_MEMORY_MMAP,
++ .m.planes = (s->multi_planer) ? planes : 0,
++ .length = (s->multi_planer) ? VIDEO_MAX_PLANES : 0
+ };
+
+ if (v4l2_ioctl(s->fd, VIDIOC_QBUF, &buf) < 0) {
+@@ -629,7 +698,7 @@ static int mmap_start(AVFormatContext *ctx)
+ }
+ atomic_store(&s->buffers_queued, s->buffers);
+
+- type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++ type = (s->multi_planer) ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ if (v4l2_ioctl(s->fd, VIDIOC_STREAMON, &type) < 0) {
+ res = AVERROR(errno);
+ av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_STREAMON): %s\n",
+@@ -645,13 +714,19 @@ static void mmap_close(struct video_data *s)
+ enum v4l2_buf_type type;
+ int i;
+
+- type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++ type = (s->multi_planer) ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ /* We do not check for the result, because we could
+ * not do anything about it anyway...
+ */
+ v4l2_ioctl(s->fd, VIDIOC_STREAMOFF, &type);
+ for (i = 0; i < s->buffers; i++) {
+- v4l2_munmap(s->buf_start[i], s->buf_len[i]);
++ for (int iplane = 0; iplane < s->plane_count; iplane++) {
++ v4l2_munmap(s->buf_start[i][iplane], s->buf_len[i][iplane]);
++ }
++ }
++ for (int iplane = 0; iplane < s->plane_count; iplane++) {
++ av_freep(&s->buf_start[iplane]);
++ av_freep(&s->buf_len[iplane]);
+ }
+ av_freep(&s->buf_start);
+ av_freep(&s->buf_len);
+@@ -732,7 +807,7 @@ static int v4l2_set_parameters(AVFormatContext *ctx)
+ tpf = &streamparm.parm.capture.timeperframe;
+ }
+
+- streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++ streamparm.type = (s->multi_planer) ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ if (v4l2_ioctl(s->fd, VIDIOC_G_PARM, &streamparm) < 0) {
+ ret = AVERROR(errno);
+ av_log(ctx, AV_LOG_WARNING, "ioctl(VIDIOC_G_PARM): %s\n", av_err2str(ret));
+@@ -920,7 +995,7 @@ static int v4l2_read_header(AVFormatContext *ctx)
+ }
+
+ if (!s->width && !s->height) {
+- struct v4l2_format fmt = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };
++ struct v4l2_format fmt = { .type = (s->multi_planer) ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : V4L2_BUF_TYPE_VIDEO_CAPTURE };
+
+ av_log(ctx, AV_LOG_VERBOSE,
+ "Querying the device for the current frame size\n");
--
-2.40.0
+2.41.0
+
+
+From 16f078866ae21f5a0c34897b14af1d975f1ae203 Mon Sep 17 00:00:00 2001
+From: rigaya <rigaya34589@live.jp>
+Date: Fri, 7 Apr 2023 22:47:10 +0900
+Subject: [PATCH 02/13] avdevice/v4l2: add nv16, nv24 support
+
+---
+ libavdevice/v4l2-common.c | 2 ++
+ 1 file changed, 2 insertions(+)
+diff --git a/libavdevice/v4l2-common.c b/libavdevice/v4l2-common.c
+index b5b4448a31..1926179fdc 100644
+--- a/libavdevice/v4l2-common.c
++++ b/libavdevice/v4l2-common.c
+@@ -49,6 +49,8 @@ const struct fmt_map ff_fmt_conversion_table[] = {
+ #ifdef V4L2_PIX_FMT_Z16
+ { AV_PIX_FMT_GRAY16LE,AV_CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_Z16 },
+ #endif
++ { AV_PIX_FMT_NV24, AV_CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_NV24 },
++ { AV_PIX_FMT_NV16, AV_CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_NV16 },
+ { AV_PIX_FMT_NV12, AV_CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_NV12 },
+ { AV_PIX_FMT_NONE, AV_CODEC_ID_MJPEG, V4L2_PIX_FMT_MJPEG },
+ { AV_PIX_FMT_NONE, AV_CODEC_ID_MJPEG, V4L2_PIX_FMT_JPEG },
+--
+2.41.0
-From 32c3c2a06887dce24c73a8fb65fd90f0d47dc53f 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/24] avcodec/rkmppdec: Compatible with old reordered_opaque
- and pkt_pts
-Some users might still using these deprecated APIs.
+From 7e3c98159375a5466c03b1853daaca212bf2008b Mon Sep 17 00:00:00 2001
+From: rigaya <rigaya34589@live.jp>
+Date: Sat, 8 Apr 2023 09:48:45 +0900
+Subject: [PATCH 03/13] avdevice/v4l2: add option to ignore input error
+ (-ignore_input_error).
-Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
+Some device returns error with VIDIOC_S_INPUT, VIDIOC_G_INPUT.
---
- libavcodec/rkmppdec.c | 4 ++++
- 1 file changed, 4 insertions(+)
+ libavdevice/v4l2.c | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
-diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
-index e31e0c44dc..4b4b17c342 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,7 @@ 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);
-+ 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);
+diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c
+index 249bedfaaa..9bdcc324ae 100644
+--- a/libavdevice/v4l2.c
++++ b/libavdevice/v4l2.c
+@@ -89,6 +89,7 @@ struct video_data {
+ int top_field_first;
+ int multi_planer;
+ int ts_mode;
++ int ignore_input_error;
+ TimeFilter *timefilter;
+ int64_t last_time_m;
+
+@@ -810,7 +811,7 @@ static int v4l2_set_parameters(AVFormatContext *ctx)
+ streamparm.type = (s->multi_planer) ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ if (v4l2_ioctl(s->fd, VIDIOC_G_PARM, &streamparm) < 0) {
+ ret = AVERROR(errno);
+- av_log(ctx, AV_LOG_WARNING, "ioctl(VIDIOC_G_PARM): %s\n", av_err2str(ret));
++ av_log(ctx, AV_LOG_WARNING, "ioctl(VIDIOC_G_PARM): %s\n", av_err2str(ret));
+ } else if (framerate_q.num && framerate_q.den) {
+ if (streamparm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) {
+ tpf = &streamparm.parm.capture.timeperframe;
+@@ -940,8 +941,10 @@ static int v4l2_read_header(AVFormatContext *ctx)
+ av_log(ctx, AV_LOG_DEBUG, "Selecting input_channel: %d\n", s->channel);
+ if (v4l2_ioctl(s->fd, VIDIOC_S_INPUT, &s->channel) < 0) {
+ res = AVERROR(errno);
+- av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_S_INPUT): %s\n", av_err2str(res));
+- goto fail;
++ av_log(ctx, (s->ignore_input_error) ? AV_LOG_WARNING : AV_LOG_ERROR, "ioctl(VIDIOC_S_INPUT): %s\n", av_err2str(res));
++ if (!s->ignore_input_error) {
++ goto fail;
++ }
+ }
+ } else {
+ /* get current video input */
+@@ -1183,6 +1186,7 @@ static const AVOption options[] = {
+ { "pixel_format", "set preferred pixel format", OFFSET(pixel_format), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
+ { "input_format", "set preferred pixel format (for raw video) or codec name", OFFSET(pixel_format), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
+ { "framerate", "set frame rate", OFFSET(framerate), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
++ { "ignore_input_error", "ignore input error", OFFSET(ignore_input_error), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, DEC },
+
+ { "list_formats", "list available formats and exit", OFFSET(list_format), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, DEC, "list_formats" },
+ { "all", "show all available formats", OFFSET(list_format), AV_OPT_TYPE_CONST, {.i64 = V4L_ALLFORMATS }, 0, INT_MAX, DEC, "list_formats" },
--
-2.40.0
+2.41.0
+
+
+From 6dfc851fa786023ba4d036f4b0a699dc2599d804 Mon Sep 17 00:00:00 2001
+From: rigaya <rigaya34589@live.jp>
+Date: Sat, 8 Apr 2023 09:49:05 +0900
+Subject: [PATCH 04/13] avdevice/v4l2: estimate framerate from dv-timings when
+ VIDIOC_G_PARM returns error.
+---
+ libavdevice/v4l2.c | 30 ++++++++++++++++++++++++++++++
+ 1 file changed, 30 insertions(+)
+
+diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c
+index 9bdcc324ae..2146c6cd57 100644
+--- a/libavdevice/v4l2.c
++++ b/libavdevice/v4l2.c
+@@ -810,8 +810,38 @@ static int v4l2_set_parameters(AVFormatContext *ctx)
+
+ streamparm.type = (s->multi_planer) ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ if (v4l2_ioctl(s->fd, VIDIOC_G_PARM, &streamparm) < 0) {
++ // for error cases, try to get frame rate from VIDIOC_G_DV_TIMINGS
++ struct v4l2_dv_timings timings;
+ ret = AVERROR(errno);
++ if (v4l2_ioctl(s->fd, VIDIOC_G_DV_TIMINGS, &timings) == 0) {
++ const int total_width = timings.bt.width + timings.bt.hfrontporch + timings.bt.hsync + timings.bt.hbackporch;
++ const int total_height = timings.bt.height + timings.bt.vfrontporch + timings.bt.vsync + timings.bt.vbackporch;
++ int64_t framerate_den = 1001;
++ int64_t framerate_num = av_rescale(timings.bt.pixelclock, framerate_den, (int64_t)total_width * total_height);
++ framerate_num = ((framerate_num + 5) / 10) * 10; // round by 10
++ if (framerate_num % 1000 == 0) {
++ tpf->numerator = framerate_den;
++ tpf->denominator = framerate_num;
++ } else {
++ int framerate_num_dst = 0, framerate_den_dst = 0;
++ framerate_den = 1000;
++ framerate_num = av_rescale(timings.bt.pixelclock, framerate_den, (int64_t)total_width * total_height);
++ framerate_num = ((framerate_num + 5) / 10) * 10; // round by 10
++ av_reduce(&framerate_num_dst, &framerate_den_dst, framerate_num, framerate_den, INT_MAX);
++ tpf->numerator = framerate_den_dst;
++ tpf->denominator = framerate_num_dst;
++ }
++ av_log(ctx, AV_LOG_WARNING, "ioctl(VIDIOC_G_PARM): %s, estimated framerate %d/%d from dv timings.\n",
++ av_err2str(ret), tpf->denominator, tpf->numerator);
++ } else if (framerate_q.num && framerate_q.den) {
++ // use user defined framerate for further error cases.
++ tpf->numerator = framerate_q.num;
++ tpf->denominator = framerate_q.den;
++ av_log(ctx, AV_LOG_WARNING, "ioctl(VIDIOC_G_PARM): %s, using framerate %d/%d\n",
++ av_err2str(ret), framerate_q.num, framerate_q.den);
++ } else {
+ av_log(ctx, AV_LOG_WARNING, "ioctl(VIDIOC_G_PARM): %s\n", av_err2str(ret));
++ }
+ } else if (framerate_q.num && framerate_q.den) {
+ if (streamparm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) {
+ tpf = &streamparm.parm.capture.timeperframe;
+--
+2.41.0
-From 1839dfc7860999826e5152c0b96938d8772a4739 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/24] rkmppdec: Remove frame buffer limit
-It would hang when reaching the limit.
+From 6b8f166c76fe3e7cdb57811d09a64162169a2ff1 Mon Sep 17 00:00:00 2001
+From: boogie <boogiepop@gmx.com>
+Date: Sat, 17 Jun 2023 18:56:02 +0200
+Subject: [PATCH 05/13] v4l2: use always channel 0 if driver does not return
+ it. Always ignore device select / set errors
-Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
---
- libavcodec/rkmppdec.c | 8 --------
- 1 file changed, 8 deletions(-)
+ libavdevice/v4l2.c | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
-diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
-index 4b4b17c342..d8f48f36b9 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;
+diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c
+index 2146c6cd57..6b7c5dbc20 100644
+--- a/libavdevice/v4l2.c
++++ b/libavdevice/v4l2.c
+@@ -980,8 +980,11 @@ static int v4l2_read_header(AVFormatContext *ctx)
+ /* get current video input */
+ if (v4l2_ioctl(s->fd, VIDIOC_G_INPUT, &s->channel) < 0) {
+ res = AVERROR(errno);
+- av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_G_INPUT): %s\n", av_err2str(res));
+- goto fail;
++ av_log(ctx, (s->ignore_input_error) ? AV_LOG_WARNING : AV_LOG_ERROR, "ioctl(VIDIOC_G_INPUT): %s\n", av_err2str(res));
++ if (!s->ignore_input_error)
++ goto fail;
++ else
++ s->channel = 0;
+ }
}
-- 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;
+@@ -1216,7 +1219,7 @@ static const AVOption options[] = {
+ { "pixel_format", "set preferred pixel format", OFFSET(pixel_format), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
+ { "input_format", "set preferred pixel format (for raw video) or codec name", OFFSET(pixel_format), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
+ { "framerate", "set frame rate", OFFSET(framerate), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
+- { "ignore_input_error", "ignore input error", OFFSET(ignore_input_error), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, DEC },
++ { "ignore_input_error", "ignore input error", OFFSET(ignore_input_error), AV_OPT_TYPE_BOOL, {.i64 = 1 }, 0, 1, DEC },
- av_log(avctx, AV_LOG_DEBUG, "RKMPP decoder initialized successfully.\n");
+ { "list_formats", "list available formats and exit", OFFSET(list_format), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, DEC, "list_formats" },
+ { "all", "show all available formats", OFFSET(list_format), AV_OPT_TYPE_CONST, {.i64 = V4L_ALLFORMATS }, 0, INT_MAX, DEC, "list_formats" },
--
-2.40.0
-
+2.41.0
-From 076cca4ad14ac04297aa2cf9786cb7b9b80be07b 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/24] avcodec/rkmppdec: Rework decoding flow
-Stop using the deprecated MPP_DEC_GET_STREAM_COUNT API.
+From 0f71b074a151ae47006a40ae4a2c8c8a434c3d94 Mon Sep 17 00:00:00 2001
+From: boogie <boogiepop@gmx.com>
+Date: Mon, 24 Jul 2023 16:05:01 +0200
+Subject: [PATCH 06/13] remove old rkmpp
-Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
---
- libavcodec/rkmppdec.c | 520 ++++++++++++++++++++++--------------------
- 1 file changed, 267 insertions(+), 253 deletions(-)
+ libavcodec/rkmppdec.c | 587 ------------------------------------------
+ 1 file changed, 587 deletions(-)
+ delete mode 100644 libavcodec/rkmppdec.c
diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
-index d8f48f36b9..d3c13297d2 100644
+deleted file mode 100644
+index 8bf7c6ed16..0000000000
--- a/libavcodec/rkmppdec.c
-+++ b/libavcodec/rkmppdec.c
-@@ -38,17 +38,15 @@
- #include "libavutil/imgutils.h"
- #include "libavutil/log.h"
-
++++ /dev/null
+@@ -1,587 +0,0 @@
+-/*
+- * RockChip MPP Video Decoder
+- * Copyright (c) 2017 Lionel CHAZALLON
+- *
+- * This file is part of FFmpeg.
+- *
+- * FFmpeg is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2.1 of the License, or (at your option) any later version.
+- *
+- * FFmpeg is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with FFmpeg; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+- */
+-
+-#include <drm_fourcc.h>
+-#include <pthread.h>
+-#include <rockchip/mpp_buffer.h>
+-#include <rockchip/rk_mpi.h>
+-#include <time.h>
+-#include <unistd.h>
+-
+-#include "avcodec.h"
+-#include "codec_internal.h"
+-#include "decode.h"
+-#include "hwconfig.h"
+-#include "libavutil/buffer.h"
+-#include "libavutil/common.h"
+-#include "libavutil/frame.h"
+-#include "libavutil/hwcontext.h"
+-#include "libavutil/hwcontext_drm.h"
+-#include "libavutil/imgutils.h"
+-#include "libavutil/log.h"
+-
-#define RECEIVE_FRAME_TIMEOUT 100
+-#define FRAMEGROUP_MAX_FRAMES 16
-#define INPUT_MAX_PACKETS 4
-
- typedef struct {
- MppCtx ctx;
- MppApi *mpi;
- MppBufferGroup frame_group;
-
+-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)
- }
- }
-
+-
+- AVBufferRef *frames_ref;
+- AVBufferRef *device_ref;
+-} RKMPPDecoder;
+-
+-typedef struct {
+- AVClass *av_class;
+- AVBufferRef *decoder_ref;
+-} RKMPPDecodeContext;
+-
+-typedef struct {
+- MppFrame frame;
+- AVBufferRef *decoder_ref;
+-} RKMPPFrameContext;
+-
+-static MppCodingType rkmpp_get_codingtype(AVCodecContext *avctx)
+-{
+- switch (avctx->codec_id) {
+- 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;
+- default: return MPP_VIDEO_CodingUnused;
+- }
+-}
+-
+-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;
+- }
+-}
+-
-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;
+-{
+- 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);
@@ -184,63 +662,93 @@ index d8f48f36b9..d3c13297d2 100644
-
- return ret;
-}
-+ av_packet_unref(&decoder->packet);
-
+-
-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;
+- av_buffer_unref(&rk_context->decoder_ref);
+- return 0;
+-}
+-
+-static void rkmpp_release_decoder(void *opaque, uint8_t *data)
+-{
+- RKMPPDecoder *decoder = (RKMPPDecoder *)data;
+-
+- if (decoder->mpi) {
+- decoder->mpi->reset(decoder->ctx);
+- mpp_destroy(decoder->ctx);
+- decoder->ctx = NULL;
+- }
+-
+- if (decoder->frame_group) {
+- mpp_buffer_group_put(decoder->frame_group);
+- decoder->frame_group = NULL;
+- }
+-
+- av_buffer_unref(&decoder->frames_ref);
+- av_buffer_unref(&decoder->device_ref);
+-
+- av_free(decoder);
+-}
+-
+-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;
- }
-
+-
+- avctx->pix_fmt = AV_PIX_FMT_DRM_PRIME;
+-
+- // create a decoder and a ref to it
+- decoder = av_mallocz(sizeof(RKMPPDecoder));
+- if (!decoder) {
+- ret = AVERROR(ENOMEM);
+- goto fail;
+- }
+-
+- 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) {
+- av_free(decoder);
+- ret = AVERROR(ENOMEM);
+- goto fail;
+- }
+-
+- av_log(avctx, AV_LOG_DEBUG, "Initializing RKMPP decoder.\n");
+-
+- codectype = rkmpp_get_codingtype(avctx);
+- if (codectype == MPP_VIDEO_CodingUnused) {
+- av_log(avctx, AV_LOG_ERROR, "Unknown codec type (%d).\n", avctx->codec_id);
+- ret = AVERROR_UNKNOWN;
+- goto fail;
+- }
+-
+- ret = mpp_check_support_format(MPP_CTX_DEC, codectype);
+- if (ret != MPP_OK) {
+- av_log(avctx, AV_LOG_ERROR, "Codec type (%d) unsupported by MPP\n", avctx->codec_id);
+- ret = AVERROR_UNKNOWN;
+- goto fail;
+- }
+-
+- // Create the MPP context
+- ret = mpp_create(&decoder->ctx, &decoder->mpi);
+- if (ret != MPP_OK) {
+- av_log(avctx, AV_LOG_ERROR, "Failed to create MPP context (code = %d).\n", ret);
+- ret = AVERROR_UNKNOWN;
+- goto fail;
+- }
+-
+- // initialize mpp
+- ret = mpp_init(decoder->ctx, MPP_CTX_DEC, codectype);
+- if (ret != MPP_OK) {
+- av_log(avctx, AV_LOG_ERROR, "Failed to initialize MPP context (code = %d).\n", ret);
+- ret = AVERROR_UNKNOWN;
+- goto fail;
+- }
+-
- // make decode calls blocking with a timeout
- paramS32 = MPP_POLL_BLOCK;
- ret = decoder->mpi->control(decoder->ctx, MPP_SET_OUTPUT_BLOCK, &paramS32);
@@ -258,32 +766,48 @@ index d8f48f36b9..d3c13297d2 100644
- goto fail;
- }
-
- ret = mpp_buffer_group_get_internal(&decoder->frame_group, MPP_BUFFER_TYPE_ION);
- if (ret) {
+- 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;
- }
-
+- ret = AVERROR_UNKNOWN;
+- goto fail;
+- }
+-
+- 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);
+- ret = AVERROR_UNKNOWN;
+- 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;
-+ 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;
- }
-
+-
+- av_log(avctx, AV_LOG_DEBUG, "RKMPP decoder initialized successfully.\n");
+-
+- decoder->device_ref = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_DRM);
+- if (!decoder->device_ref) {
+- ret = AVERROR(ENOMEM);
+- goto fail;
+- }
+- ret = av_hwdevice_ctx_init(decoder->device_ref);
+- if (ret < 0)
+- goto fail;
+-
+- return 0;
+-
+-fail:
+- av_log(avctx, AV_LOG_ERROR, "Failed to initialize RKMPP decoder.\n");
+- rkmpp_close_decoder(avctx);
+- return ret;
+-}
+-
-static int rkmpp_send_packet(AVCodecContext *avctx, const AVPacket *avpkt)
-{
- RKMPPDecodeContext *rk_context = avctx->priv_data;
@@ -322,88 +846,65 @@ index d8f48f36b9..d3c13297d2 100644
- 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 void rkmpp_release_frame(void *opaque, uint8_t *data)
+-{
+- AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor *)data;
+- AVBufferRef *framecontextref = (AVBufferRef *)opaque;
+- RKMPPFrameContext *framecontext = (RKMPPFrameContext *)framecontextref->data;
+-
+- mpp_frame_deinit(&framecontext->frame);
+- av_buffer_unref(&framecontext->decoder_ref);
+- av_buffer_unref(&framecontextref);
+-
+- 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,151 +263,159 @@ 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) {
+-{
+- RKMPPDecodeContext *rk_context = avctx->priv_data;
+- RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data;
+- RKMPPFrameContext *framecontext = NULL;
+- AVBufferRef *framecontextref = NULL;
+- int ret;
+- MppFrame mppframe = NULL;
+- MppBuffer buffer = NULL;
+- AVDRMFrameDescriptor *desc = NULL;
+- AVDRMLayerDescriptor *layer = NULL;
+- int mode;
+- MppFrameFormat mppformat;
+- uint32_t drmformat;
+-
+- 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;
@@ -412,9 +913,7 @@ index d8f48f36b9..d3c13297d2 100644
- 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;
@@ -430,49 +929,29 @@ index d8f48f36b9..d3c13297d2 100644
- } 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;
- }
-
+- 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);
-
+-
- // 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);
-- 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);
-+ 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);
-
+-
- 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);
-+ goto fail;
-+ }
-
+-
- mppformat = mpp_frame_get_fmt(mppframe);
- drmformat = rkmpp_get_frameformat(mppformat);
-+ // 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) {
@@ -481,14 +960,7 @@ index d8f48f36b9..d3c13297d2 100644
- ret = AVERROR(ENOMEM);
- goto fail;
- }
-+ // 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;
-+ }
-
+-
- desc->nb_objects = 1;
- desc->objects[0].fd = mpp_buffer_get_fd(buffer);
- desc->objects[0].size = mpp_buffer_get_size(buffer);
@@ -513,63 +985,27 @@ index d8f48f36b9..d3c13297d2 100644
- ret = AVERROR(ENOMEM);
- 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);
-+ 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);
-+
-+ mppformat = mpp_frame_get_fmt(mppframe);
-+ drmformat = rkmpp_get_frameformat(mppformat);
-+
-+ desc = av_mallocz(sizeof(AVDRMFrameDescriptor));
-+ if (!desc) {
-+ ret = AVERROR(ENOMEM);
-+ goto fail;
-+ }
-
+-
- // 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_objects = 1;
-+ desc->objects[0].fd = mpp_buffer_get_fd(buffer);
-+ desc->objects[0].size = mpp_buffer_get_size(buffer);
-
+-
- 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);
-+ desc->nb_layers = 1;
-+ layer = &desc->layers[0];
-+ layer->format = drmformat;
-+ layer->nb_planes = 2;
-
+-
- if (!frame->buf[0]) {
- ret = AVERROR(ENOMEM);
- goto fail;
- }
-+ layer->planes[0].object_index = 0;
-+ layer->planes[0].offset = 0;
-+ layer->planes[0].pitch = mpp_frame_get_hor_stride(mppframe);
-
+-
- frame->hw_frames_ctx = av_buffer_ref(decoder->frames_ref);
- if (!frame->hw_frames_ctx) {
- 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;
-
+-
- return 0;
- } else {
- av_log(avctx, AV_LOG_ERROR, "Failed to retrieve the frame buffer, frame is dropped (code = %d)\n", ret);
@@ -579,107 +1015,30 @@ index d8f48f36b9..d3c13297d2 100644
- 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");
-+ // 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 AVERROR(EAGAIN);
-+ // 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;
-+ }
-+
-+ 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)
-@@ -489,60 +433,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;
+-
+-fail:
+- if (mppframe)
+- mpp_frame_deinit(&mppframe);
+-
+- if (framecontext)
+- av_buffer_unref(&framecontext->decoder_ref);
+-
+- if (framecontextref)
+- av_buffer_unref(&framecontextref);
+-
+- if (desc)
+- av_free(desc);
+-
+- return ret;
+-}
+-
+-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;
@@ -691,817 +1050,131 @@ index d8f48f36b9..d3c13297d2 100644
- 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;
- }
+- 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;
- }
- }
+- return ret;
+- }
+- }
-
- // 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;
+-}
+-
+-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");
-
+-
+- 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.40.0
-
-
-From 3f3e229c729d779ff1b4bc6ec8abc11e2b2b078b 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/24] 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 d3c13297d2..c767fc8f1b 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.40.0
-
-
-From fdf094ef3e983706e28f7f77d96284de554612d9 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/24] 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 | 121 +++++++++++++++++++++++++++++++++++++++++-
- 2 files changed, 126 insertions(+), 2 deletions(-)
-
-diff --git a/configure b/configure
-index b6616f00b6..b2b6d45e78 100755
---- a/configure
-+++ b/configure
-@@ -349,6 +349,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]
-@@ -1892,6 +1893,7 @@ HWACCEL_AUTODETECT_LIBRARY_LIST="
- videotoolbox
- vulkan
- v4l2_m2m
-+ librga
- "
-
- # catchall list of things that require external libs to link
-@@ -6789,10 +6791,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 c767fc8f1b..2bcc357c36 100644
---- a/libavcodec/rkmppdec.c
-+++ b/libavcodec/rkmppdec.c
-@@ -28,6 +28,7 @@
-
- #include "avcodec.h"
- #include "codec_internal.h"
-+#include "internal.h"
- #include "decode.h"
- #include "hwconfig.h"
- #include "libavutil/buffer.h"
-@@ -38,6 +39,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 +89,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 +159,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 +265,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 +461,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);
- frame->reordered_opaque = frame->pts;
- frame->color_range = mpp_frame_get_color_range(mppframe);
-@@ -422,6 +538,7 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
-
- return 0;
-
-+out:
- fail:
- if (mppframe)
- mpp_frame_deinit(&mppframe);
-@@ -566,6 +683,7 @@ static void rkmpp_flush(AVCodecContext *avctx)
-
- static const AVCodecHWConfigInternal *const rkmpp_hw_configs[] = {
- HW_CONFIG_INTERNAL(DRM_PRIME),
-+ HW_CONFIG_INTERNAL(YUV420P),
- NULL
- };
-
-@@ -590,6 +708,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.40.0
-
-
-From 6f54c9ff2d603000d3ee112c584b4d76a23bfd5f 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/24] 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 2bcc357c36..41e17422a0 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"
-@@ -44,6 +45,8 @@
- #include <rga/RgaApi.h>
- #endif
-
-+#define FPS_UPDATE_INTERVAL 120
-+
- typedef struct {
- MppCtx ctx;
- MppApi *mpi;
-@@ -55,6 +58,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 {
-@@ -157,6 +165,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);
-@@ -168,6 +177,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) {
-@@ -354,6 +367,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;
-@@ -457,6 +500,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);
-@@ -677,6 +722,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.40.0
-
-
-From 8b3fb18571d3dcf1f561f413c07aec7412046ea7 Mon Sep 17 00:00:00 2001
-From: Jeffy Chen <jeffy.chen@rock-chips.com>
-Date: Mon, 27 Sep 2021 11:06:11 +0800
-Subject: [PATCH 08/24] 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/codec_internal.h | 4 ++++
- libavcodec/get_buffer.c | 24 ++++++++++++++++++++++++
- libavcodec/rkmppdec.c | 19 ++++++++++---------
- 3 files changed, 38 insertions(+), 9 deletions(-)
-
-diff --git a/libavcodec/codec_internal.h b/libavcodec/codec_internal.h
-index 130a7dc3cd..ed0dea86de 100644
---- a/libavcodec/codec_internal.h
-+++ b/libavcodec/codec_internal.h
-@@ -80,6 +80,10 @@
- * Codec supports embedded ICC profiles (AV_FRAME_DATA_ICC_PROFILE).
- */
- #define FF_CODEC_CAP_ICC_PROFILES (1 << 9)
-+/**
-+ * The decoder requires contiguous buffers.
-+ */
-+#define FF_CODEC_CAP_CONTIGUOUS_BUFFERS (1 << 28)
- /**
- * The encoder has AV_CODEC_CAP_DELAY set, but does not actually have delay - it
- * only wants to be flushed at the end to update some context variables (e.g.
-diff --git a/libavcodec/get_buffer.c b/libavcodec/get_buffer.c
-index a04fd878de..c6a1983f7e 100644
---- a/libavcodec/get_buffer.c
-+++ b/libavcodec/get_buffer.c
-@@ -32,6 +32,7 @@
-
- #include "avcodec.h"
- #include "internal.h"
-+#include "codec_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 (ffcodec(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);
-@@ -265,6 +274,21 @@ static int video_get_buffer(AVCodecContext *s, AVFrame *pic)
-
- pic->data[i] = pic->buf[i]->data;
- }
-+
-+ if (ffcodec(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/rkmppdec.c b/libavcodec/rkmppdec.c
-index 41e17422a0..01ab7e5492 100644
---- a/libavcodec/rkmppdec.c
-+++ b/libavcodec/rkmppdec.c
-@@ -502,20 +502,16 @@ 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);
- frame->reordered_opaque = frame->pts;
- frame->color_range = mpp_frame_get_color_range(mppframe);
-@@ -527,6 +523,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);
-
-@@ -759,7 +760,7 @@ static const AVCodecHWConfigInternal *const rkmpp_hw_configs[] = {
- .hw_configs = rkmpp_hw_configs, \
- .bsfs = BSFS, \
- .p.wrapper_name = "rkmpp", \
+-}
+-
+-static const AVCodecHWConfigInternal *const rkmpp_hw_configs[] = {
+- HW_CONFIG_INTERNAL(DRM_PRIME),
+- NULL
+-};
+-
+-#define RKMPP_DEC_CLASS(NAME) \
+- static const AVClass rkmpp_##NAME##_dec_class = { \
+- .class_name = "rkmpp_" #NAME "_dec", \
+- .version = LIBAVUTIL_VERSION_INT, \
+- };
+-
+-#define RKMPP_DEC(NAME, ID, BSFS) \
+- RKMPP_DEC_CLASS(NAME) \
+- const FFCodec ff_##NAME##_rkmpp_decoder = { \
+- .p.name = #NAME "_rkmpp", \
+- CODEC_LONG_NAME(#NAME " (rkmpp)"), \
+- .p.type = AVMEDIA_TYPE_VIDEO, \
+- .p.id = ID, \
+- .priv_data_size = sizeof(RKMPPDecodeContext), \
+- .init = rkmpp_init_decoder, \
+- .close = rkmpp_close_decoder, \
+- 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.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_DRM_PRIME, \
+- AV_PIX_FMT_NONE}, \
+- .hw_configs = rkmpp_hw_configs, \
+- .bsfs = BSFS, \
+- .p.wrapper_name = "rkmpp", \
- .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE, \
-+ .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | FF_CODEC_CAP_CONTIGUOUS_BUFFERS \
- };
-
- RKMPP_DEC(h264, AV_CODEC_ID_H264, "h264_mp4toannexb")
---
-2.40.0
-
-
-From 8e916a6896d847d4cda4d455ad47e188c1825337 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/24] HACK: avcodec/rkmppdec: Support NV15
-
-NV15 is the official DRM fourcc for Arm's NV12 10LE40 format.
-
-Fallback to NA12 for older Rockchip BSP kernel.
-
-Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
----
- libavcodec/rkmppdec.c | 9 ++++++---
- 1 file changed, 6 insertions(+), 3 deletions(-)
-
-diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
-index 01ab7e5492..403f5339a9 100644
---- a/libavcodec/rkmppdec.c
-+++ b/libavcodec/rkmppdec.c
-@@ -45,6 +45,11 @@
- #include <rga/RgaApi.h>
- #endif
-
-+// HACK: Older BSP kernel use NA12 for NV15.
-+#ifndef DRM_FORMAT_NV15 // fourcc_code('N', 'V', '1', '5')
-+#define DRM_FORMAT_NV15 fourcc_code('N', 'A', '1', '2')
-+#endif
-+
- #define FPS_UPDATE_INTERVAL 120
-
- typedef struct {
-@@ -90,9 +95,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
-+ case MPP_FMT_YUV420SP_10BIT: return DRM_FORMAT_NV15;
- default: return 0;
- }
- }
---
-2.40.0
-
-
-From c9d8ec349c5b766dffafbddbe3b1ef0e57b24456 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/24] 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 403f5339a9..770c4ef71c 100644
---- a/libavcodec/rkmppdec.c
-+++ b/libavcodec/rkmppdec.c
-@@ -96,6 +96,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_NV15;
-+ 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;
- }
- }
-@@ -106,6 +117,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;
- }
- }
-@@ -478,11 +490,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.40.0
-
-
-From 06e79e58f08c7426681497aa1f653ba1cc116947 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/24] 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 770c4ef71c..9539a48817 100644
---- a/libavcodec/rkmppdec.c
-+++ b/libavcodec/rkmppdec.c
-@@ -68,6 +68,8 @@ typedef struct {
-
- uint64_t last_fps_time;
- uint64_t frames;
-+
-+ char sync;
- } RKMPPDecoder;
-
- typedef struct {
-@@ -172,6 +174,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;
- }
-
-@@ -719,6 +728,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);
- }
- }
- }
+- };
+-
+-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)
--
-2.40.0
+2.41.0
-From ba5c782b923192e820b5c08aff61da5133b2dd1a Mon Sep 17 00:00:00 2001
-From: Jeffy Chen <jeffy.chen@rock-chips.com>
-Date: Wed, 25 May 2022 12:35:53 +0800
-Subject: [PATCH 12/24] avcodec/rkmppdec: Add H263/MPEG1/MPEG2/MPEG4
+From d0260e7573b9695e738e4b9a3ae02616fbeaacf0 Mon Sep 17 00:00:00 2001
+From: boogie <boogiepop@gmx.com>
+Date: Mon, 24 Jul 2023 16:01:21 +0200
+Subject: [PATCH 07/13] prepare buildsystem for rkmpp
-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(+)
+ configure | 18 +++++++++++++++++-
+ libavcodec/Makefile | 16 ++++++++++++----
+ 2 files changed, 29 insertions(+), 5 deletions(-)
diff --git a/configure b/configure
-index b2b6d45e78..8dd4294f28 100755
+index b6616f00b6..9bbf39b9ce 100755
--- a/configure
+++ b/configure
-@@ -3165,6 +3165,7 @@ av1_nvenc_encoder_deps="nvenc NV_ENC_PIC_PARAMS_AV1"
+@@ -3161,8 +3161,10 @@ av1_mediacodec_decoder_deps="mediacodec"
+ av1_mediacodec_decoder_extralibs="-landroid"
+ av1_nvenc_encoder_deps="nvenc NV_ENC_PIC_PARAMS_AV1"
av1_nvenc_encoder_select="atsc_a53"
++av1_rkmpp_decoder_deps="rkmpp"
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"
-@@ -3218,6 +3219,7 @@ mjpeg_vaapi_encoder_select="cbs_jpeg jpegtables vaapi_encode"
+@@ -3182,6 +3184,8 @@ h264_qsv_decoder_select="h264_mp4toannexb_bsf qsvdec"
+ h264_qsv_encoder_select="atsc_a53 qsvenc"
+ h264_rkmpp_decoder_deps="rkmpp"
+ h264_rkmpp_decoder_select="h264_mp4toannexb_bsf"
++h264_rkmpp_encoder_deps="rkmpp"
++h264_rkmpp_encoder_select="h264_mp4toannexb_bsf"
+ h264_vaapi_encoder_select="atsc_a53 cbs_h264 vaapi_encode"
+ h264_v4l2m2m_decoder_deps="v4l2_m2m h264_v4l2_m2m"
+ h264_v4l2m2m_decoder_select="h264_mp4toannexb_bsf"
+@@ -3202,6 +3206,8 @@ hevc_qsv_decoder_select="hevc_mp4toannexb_bsf qsvdec"
+ hevc_qsv_encoder_select="hevcparse qsvenc"
+ hevc_rkmpp_decoder_deps="rkmpp"
+ hevc_rkmpp_decoder_select="hevc_mp4toannexb_bsf"
++hevc_rkmpp_encoder_deps="rkmpp"
++hevc_rkmpp_encoder_select="hevc_mp4toannexb_bsf"
+ hevc_vaapi_encoder_deps="VAEncPictureParameterBufferHEVC"
+ hevc_vaapi_encoder_select="atsc_a53 cbs_h265 vaapi_encode"
+ hevc_v4l2m2m_decoder_deps="v4l2_m2m hevc_v4l2_m2m"
+@@ -3216,6 +3222,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"
@@ -1509,7 +1182,7 @@ index b2b6d45e78..8dd4294f28 100755
mpeg2_crystalhd_decoder_select="crystalhd"
mpeg2_cuvid_decoder_deps="cuvid"
mpeg2_mmal_decoder_deps="mmal"
-@@ -3226,6 +3228,7 @@ mpeg2_qsv_decoder_select="qsvdec"
+@@ -3224,6 +3231,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"
@@ -1517,7 +1190,7 @@ index b2b6d45e78..8dd4294f28 100755
mpeg4_crystalhd_decoder_select="crystalhd"
mpeg4_cuvid_decoder_deps="cuvid"
mpeg4_mediacodec_decoder_deps="mediacodec"
-@@ -3233,6 +3236,7 @@ mpeg4_mmal_decoder_deps="mmal"
+@@ -3231,6 +3239,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"
@@ -1525,252 +1198,130 @@ index b2b6d45e78..8dd4294f28 100755
msmpeg4_crystalhd_decoder_select="crystalhd"
vc1_crystalhd_decoder_select="crystalhd"
vc1_cuvid_decoder_deps="cuvid"
+@@ -3241,6 +3250,7 @@ vp8_cuvid_decoder_deps="cuvid"
+ vp8_mediacodec_decoder_deps="mediacodec"
+ vp8_qsv_decoder_select="qsvdec"
+ vp8_rkmpp_decoder_deps="rkmpp"
++vp8_rkmpp_encoder_deps="rkmpp"
+ vp8_vaapi_encoder_deps="VAEncPictureParameterBufferVP8"
+ vp8_vaapi_encoder_select="vaapi_encode"
+ vp8_v4l2m2m_decoder_deps="v4l2_m2m vp8_v4l2_m2m"
+@@ -6791,8 +6801,14 @@ enabled openssl && { { check_pkg_config openssl "openssl >= 3.0.0" ope
+ enabled pocketsphinx && require_pkg_config pocketsphinx pocketsphinx pocketsphinx/pocketsphinx.h ps_init
+ 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 &&
++ { check_lib librga rga/RgaApi.h c_RkRgaInit -lrga ||
++ die "ERROR: librga is necessary for rkmpp"; } &&
++ prepend rkmpp_deps "librga" &&
++ { check_lib libyuv libyuv/planar_functions.h SplitUVPlane -lyuv ||
++ die "ERROR: libyuv is necessary for rkmpp"; } &&
++ prepend rkmpp_deps "libyuv" &&
+ { enabled libdrm ||
+- die "ERROR: rkmpp requires --enable-libdrm"; }
++ die "ERROR: rkmpp requires --enable-libdrm"; }
+ }
+ enabled vapoursynth && require_pkg_config vapoursynth "vapoursynth-script >= 42" VSScript.h vsscript_init
+
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
-index 389253f5d0..504a31e83e 100644
+index 389253f5d0..5462385307 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
-@@ -397,6 +397,7 @@ OBJS-$(CONFIG_H263_ENCODER) += mpeg4video.o \
+@@ -255,6 +255,7 @@ OBJS-$(CONFIG_AV1_CUVID_DECODER) += cuviddec.o
+ OBJS-$(CONFIG_AV1_MEDIACODEC_DECODER) += mediacodecdec.o
+ OBJS-$(CONFIG_AV1_NVENC_ENCODER) += nvenc_av1.o nvenc.o
+ OBJS-$(CONFIG_AV1_QSV_ENCODER) += qsvenc_av1.o
++OBJS-$(CONFIG_AV1_RKMPP_DECODER) += rkmpp.o rkplane.o rkmppdec.o
+ OBJS-$(CONFIG_AVRN_DECODER) += avrndec.o
+ OBJS-$(CONFIG_AVRP_DECODER) += r210dec.o
+ OBJS-$(CONFIG_AVRP_ENCODER) += r210enc.o
+@@ -397,6 +398,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_H263_RKMPP_DECODER) += rkmpp.o rkplane.o 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 \
-@@ -529,6 +530,7 @@ OBJS-$(CONFIG_MPEG1VIDEO_DECODER) += mpeg12dec.o mpeg12.o mpeg12data.o
+@@ -412,7 +414,8 @@ OBJS-$(CONFIG_H264_NVENC_ENCODER) += nvenc_h264.o nvenc.o
+ OBJS-$(CONFIG_H264_OMX_ENCODER) += omx.o
+ OBJS-$(CONFIG_H264_QSV_DECODER) += qsvdec.o
+ OBJS-$(CONFIG_H264_QSV_ENCODER) += qsvenc_h264.o
+-OBJS-$(CONFIG_H264_RKMPP_DECODER) += rkmppdec.o
++OBJS-$(CONFIG_H264_RKMPP_DECODER) += rkmpp.o rkplane.o rkmppdec.o
++OBJS-$(CONFIG_H264_RKMPP_ENCODER) += rkmpp.o rkplane.o rkmppenc.o
+ OBJS-$(CONFIG_H264_VAAPI_ENCODER) += vaapi_encode_h264.o h264_levels.o \
+ h2645data.o
+ OBJS-$(CONFIG_H264_VIDEOTOOLBOX_ENCODER) += videotoolboxenc.o
+@@ -437,7 +440,8 @@ OBJS-$(CONFIG_HEVC_NVENC_ENCODER) += nvenc_hevc.o nvenc.o
+ OBJS-$(CONFIG_HEVC_QSV_DECODER) += qsvdec.o
+ OBJS-$(CONFIG_HEVC_QSV_ENCODER) += qsvenc_hevc.o hevc_ps_enc.o \
+ hevc_data.o
+-OBJS-$(CONFIG_HEVC_RKMPP_DECODER) += rkmppdec.o
++OBJS-$(CONFIG_HEVC_RKMPP_DECODER) += rkmpp.o rkplane.o rkmppdec.o
++OBJS-$(CONFIG_HEVC_RKMPP_ENCODER) += rkmpp.o rkplane.o rkmppenc.o
+ OBJS-$(CONFIG_HEVC_VAAPI_ENCODER) += vaapi_encode_h265.o h265_profile_level.o \
+ h2645data.o
+ OBJS-$(CONFIG_HEVC_V4L2M2M_DECODER) += v4l2_m2m_dec.o
+@@ -529,6 +533,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_MPEG1_RKMPP_DECODER) += rkmpp.o rkplane.o rkmppdec.o
OBJS-$(CONFIG_MPEG2_MMAL_DECODER) += mmaldec.o
OBJS-$(CONFIG_MPEG2_QSV_DECODER) += qsvdec.o
OBJS-$(CONFIG_MPEG2_QSV_ENCODER) += qsvenc_mpeg2.o
-@@ -539,12 +541,14 @@ OBJS-$(CONFIG_MPEG2_MEDIACODEC_DECODER) += mediacodecdec.o
+@@ -539,12 +544,14 @@ 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_MPEG4_DECODER) += mpeg4videodsp.o xvididct.o
-+OBJS-$(CONFIG_MPEG2_RKMPP_DECODER) += rkmppdec.o
++OBJS-$(CONFIG_MPEG2_RKMPP_DECODER) += rkmpp.o rkplane.o rkmppdec.o
OBJS-$(CONFIG_MPEG4_ENCODER) += mpeg4videoenc.o
OBJS-$(CONFIG_MPEG4_CUVID_DECODER) += cuviddec.o
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_MPEG4_RKMPP_DECODER) += rkmpp.o rkplane.o 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 e593ad19af..84e57b3e1b 100644
---- a/libavcodec/allcodecs.c
-+++ b/libavcodec/allcodecs.c
-@@ -150,6 +150,7 @@ extern const FFCodec ff_h263i_decoder;
- extern const FFCodec ff_h263p_encoder;
- extern const FFCodec ff_h263p_decoder;
- extern const FFCodec ff_h263_v4l2m2m_decoder;
-+extern const FFCodec ff_h263_rkmpp_decoder;
- extern const FFCodec ff_h264_decoder;
- extern const FFCodec ff_h264_crystalhd_decoder;
- extern const FFCodec ff_h264_v4l2m2m_decoder;
-@@ -212,13 +213,16 @@ extern const FFCodec ff_mpeg4_decoder;
- extern const FFCodec ff_mpeg4_crystalhd_decoder;
- extern const FFCodec ff_mpeg4_v4l2m2m_decoder;
- extern const FFCodec ff_mpeg4_mmal_decoder;
-+extern const AVCodec ff_mpeg4_rkmpp_decoder;
- extern const FFCodec ff_mpegvideo_decoder;
- extern const FFCodec ff_mpeg1_v4l2m2m_decoder;
-+extern const AVCodec ff_mpeg1_rkmpp_decoder;
- extern const FFCodec ff_mpeg2_mmal_decoder;
- extern const FFCodec ff_mpeg2_crystalhd_decoder;
- extern const FFCodec ff_mpeg2_v4l2m2m_decoder;
- extern const FFCodec ff_mpeg2_qsv_decoder;
- extern const FFCodec ff_mpeg2_mediacodec_decoder;
-+extern const AVCodec ff_mpeg2_rkmpp_decoder;
- extern const FFCodec ff_msa1_decoder;
- extern const FFCodec ff_mscc_decoder;
- extern const FFCodec ff_msmpeg4v1_decoder;
-diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
-index 9539a48817..cd03174ee2 100644
---- a/libavcodec/rkmppdec.c
-+++ b/libavcodec/rkmppdec.c
-@@ -85,10 +85,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;
- }
- }
-@@ -790,7 +794,11 @@ static const AVCodecHWConfigInternal *const rkmpp_hw_configs[] = {
- .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | FF_CODEC_CAP_CONTIGUOUS_BUFFERS \
- };
-
-+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.40.0
-
-
-From 27822b4269a2f5b7062c50b4ce4363a4f52f6cc6 Mon Sep 17 00:00:00 2001
-From: Jeffy Chen <jeffy.chen@rock-chips.com>
-Date: Sun, 29 Jan 2023 17:50:14 +0800
-Subject: [PATCH 13/24] avcodec/rkmppdec: Add AV1
-
-Note: For new chips like rk3588.
-
-Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
----
- configure | 1 +
- libavcodec/Makefile | 1 +
- libavcodec/allcodecs.c | 1 +
- libavcodec/rkmppdec.c | 6 ++++--
- 4 files changed, 7 insertions(+), 2 deletions(-)
-
-diff --git a/configure b/configure
-index 8dd4294f28..3804f193a5 100755
---- a/configure
-+++ b/configure
-@@ -3163,6 +3163,7 @@ av1_mediacodec_decoder_deps="mediacodec"
- av1_mediacodec_decoder_extralibs="-landroid"
- av1_nvenc_encoder_deps="nvenc NV_ENC_PIC_PARAMS_AV1"
- av1_nvenc_encoder_select="atsc_a53"
-+av1_rkmpp_decoder_deps="rkmpp"
- h263_v4l2m2m_decoder_deps="v4l2_m2m h263_v4l2_m2m"
- h263_v4l2m2m_encoder_deps="v4l2_m2m h263_v4l2_m2m"
- h263_rkmpp_decoder_deps="rkmpp"
-diff --git a/libavcodec/Makefile b/libavcodec/Makefile
-index 504a31e83e..af0cbbbfe1 100644
---- a/libavcodec/Makefile
-+++ b/libavcodec/Makefile
-@@ -255,6 +255,7 @@ OBJS-$(CONFIG_AV1_CUVID_DECODER) += cuviddec.o
- OBJS-$(CONFIG_AV1_MEDIACODEC_DECODER) += mediacodecdec.o
- OBJS-$(CONFIG_AV1_NVENC_ENCODER) += nvenc_av1.o nvenc.o
- OBJS-$(CONFIG_AV1_QSV_ENCODER) += qsvenc_av1.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 84e57b3e1b..dd8164d2b1 100644
---- a/libavcodec/allcodecs.c
-+++ b/libavcodec/allcodecs.c
-@@ -842,6 +842,7 @@ extern const FFCodec ff_av1_nvenc_encoder;
- extern const FFCodec ff_av1_qsv_decoder;
- extern const FFCodec ff_av1_qsv_encoder;
- extern const FFCodec ff_av1_amf_encoder;
-+extern const FFCodec ff_av1_rkmpp_decoder;
- extern const FFCodec ff_libopenh264_encoder;
- extern const FFCodec ff_libopenh264_decoder;
- extern const FFCodec ff_h264_amf_encoder;
-diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
-index cd03174ee2..32fe1ede6a 100644
---- a/libavcodec/rkmppdec.c
-+++ b/libavcodec/rkmppdec.c
-@@ -88,6 +88,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 */
-@@ -168,8 +169,8 @@ static int rkmpp_prepare_decoder(AVCodecContext *avctx)
- MppPacket packet;
- int ret;
-
-- // send extra data
-- if (avctx->extradata_size) {
-+ // HACK: somehow MPP cannot handle extra data for AV1
-+ if (avctx->extradata_size && avctx->codec_id != AV_CODEC_ID_AV1) {
- ret = mpp_packet_init(&packet, avctx->extradata, avctx->extradata_size);
- if (ret < 0)
- return AVERROR_UNKNOWN;
-@@ -797,6 +798,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.40.0
-
-
-From 07bad22a207711d9860d5d66191a865f32d59881 Mon Sep 17 00:00:00 2001
-From: Jeffy Chen <jeffy.chen@rock-chips.com>
-Date: Mon, 27 Mar 2023 17:44:09 +0800
-Subject: [PATCH 14/24] rkmppdec: Ignore special MPP format masks
-
-We should use the basic format in format conversion.
-
-Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
----
- libavcodec/rkmppdec.c | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
-index 32fe1ede6a..dcaea9d435 100644
---- a/libavcodec/rkmppdec.c
-+++ b/libavcodec/rkmppdec.c
-@@ -100,7 +100,7 @@ static MppCodingType rkmpp_get_codingtype(AVCodecContext *avctx)
-
- static uint32_t rkmpp_get_frameformat(MppFrameFormat mppformat)
- {
-- switch (mppformat) {
-+ switch (mppformat & MPP_FRAME_FMT_MASK) {
- case MPP_FMT_YUV420SP: return DRM_FORMAT_NV12;
- case MPP_FMT_YUV420SP_10BIT: return DRM_FORMAT_NV15;
- case MPP_FMT_YUV422SP: return DRM_FORMAT_NV16;
-@@ -110,7 +110,7 @@ static uint32_t rkmpp_get_frameformat(MppFrameFormat mppformat)
-
- static uint32_t rkmpp_get_avformat(MppFrameFormat mppformat)
- {
-- switch (mppformat) {
-+ switch (mppformat & MPP_FRAME_FMT_MASK) {
- 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;
-@@ -121,7 +121,7 @@ static uint32_t rkmpp_get_avformat(MppFrameFormat mppformat)
- #if CONFIG_LIBRGA
- static uint32_t rkmpp_get_rgaformat(MppFrameFormat mppformat)
- {
-- switch (mppformat) {
-+ switch (mppformat & MPP_FRAME_FMT_MASK) {
- 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;
+@@ -765,7 +772,8 @@ OBJS-$(CONFIG_VP8_DECODER) += vp8.o vpx_rac.o
+ OBJS-$(CONFIG_VP8_CUVID_DECODER) += cuviddec.o
+ OBJS-$(CONFIG_VP8_MEDIACODEC_DECODER) += mediacodecdec.o
+ OBJS-$(CONFIG_VP8_QSV_DECODER) += qsvdec.o
+-OBJS-$(CONFIG_VP8_RKMPP_DECODER) += rkmppdec.o
++OBJS-$(CONFIG_VP8_RKMPP_DECODER) += rkmpp.o rkplane.o rkmppdec.o
++OBJS-$(CONFIG_VP8_RKMPP_ENCODER) += rkmpp.o rkplane.o rkmppenc.o
+ OBJS-$(CONFIG_VP8_VAAPI_ENCODER) += vaapi_encode_vp8.o
+ OBJS-$(CONFIG_VP8_V4L2M2M_DECODER) += v4l2_m2m_dec.o
+ OBJS-$(CONFIG_VP8_V4L2M2M_ENCODER) += v4l2_m2m_enc.o
+@@ -774,7 +782,7 @@ OBJS-$(CONFIG_VP9_DECODER) += vp9.o vp9data.o vp9dsp.o vp9lpf.o vp9r
+ vp9dsp_8bpp.o vp9dsp_10bpp.o vp9dsp_12bpp.o
+ OBJS-$(CONFIG_VP9_CUVID_DECODER) += cuviddec.o
+ OBJS-$(CONFIG_VP9_MEDIACODEC_DECODER) += mediacodecdec.o
+-OBJS-$(CONFIG_VP9_RKMPP_DECODER) += rkmppdec.o
++OBJS-$(CONFIG_VP9_RKMPP_DECODER) += rkmpp.o rkplane.o rkmppdec.o
+ OBJS-$(CONFIG_VP9_VAAPI_ENCODER) += vaapi_encode_vp9.o
+ OBJS-$(CONFIG_VP9_QSV_ENCODER) += qsvenc_vp9.o
+ OBJS-$(CONFIG_VPLAYER_DECODER) += textdec.o ass.o
--
-2.40.0
+2.41.0
-From 5910b3c4944c51a762175c461eec4f4781a3234f Mon Sep 17 00:00:00 2001
+From ebd97550cf3a9a1902b5a58566caa846f9ad2114 Mon Sep 17 00:00:00 2001
From: boogie <boogiepop@gmx.com>
-Date: Thu, 20 Apr 2023 15:23:26 +0200
-Subject: [PATCH 15/24] Prioritize RKMPP decoders first
+Date: Mon, 24 Jul 2023 16:14:02 +0200
+Subject: [PATCH 08/13] register all codec as highest prio
---
- libavcodec/allcodecs.c | 19 ++++++++++---------
- 1 file changed, 10 insertions(+), 9 deletions(-)
+ libavcodec/allcodecs.c | 18 ++++++++++++++----
+ 1 file changed, 14 insertions(+), 4 deletions(-)
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
-index dd8164d2b1..ba08c937d2 100644
+index e593ad19af..082c4b8e29 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
-@@ -34,6 +34,16 @@
+@@ -34,6 +34,20 @@
#include "codec_id.h"
#include "codec_internal.h"
@@ -1784,18 +1335,14 @@ index dd8164d2b1..ba08c937d2 100644
+extern const FFCodec ff_vp8_rkmpp_decoder;
+extern const FFCodec ff_vp9_rkmpp_decoder;
+
++extern const FFCodec ff_vp8_rkmpp_encoder;
++extern const FFCodec ff_h264_rkmpp_encoder;
++extern const FFCodec ff_hevc_rkmpp_encoder;
++
extern const FFCodec ff_a64multi_encoder;
extern const FFCodec ff_a64multi5_encoder;
extern const FFCodec ff_aasc_decoder;
-@@ -150,7 +160,6 @@ extern const FFCodec ff_h263i_decoder;
- extern const FFCodec ff_h263p_encoder;
- extern const FFCodec ff_h263p_decoder;
- extern const FFCodec ff_h263_v4l2m2m_decoder;
--extern const FFCodec ff_h263_rkmpp_decoder;
- extern const FFCodec ff_h264_decoder;
- extern const FFCodec ff_h264_crystalhd_decoder;
- extern const FFCodec ff_h264_v4l2m2m_decoder;
-@@ -158,12 +167,10 @@ extern const FFCodec ff_h264_mediacodec_decoder;
+@@ -157,12 +171,10 @@ extern const FFCodec ff_h264_mediacodec_decoder;
extern const FFCodec ff_h264_mediacodec_encoder;
extern const FFCodec ff_h264_mmal_decoder;
extern const FFCodec ff_h264_qsv_decoder;
@@ -1808,24 +1355,7 @@ index dd8164d2b1..ba08c937d2 100644
extern const FFCodec ff_hevc_v4l2m2m_decoder;
extern const FFCodec ff_hnm4_video_decoder;
extern const FFCodec ff_hq_hqa_decoder;
-@@ -213,16 +220,13 @@ extern const FFCodec ff_mpeg4_decoder;
- extern const FFCodec ff_mpeg4_crystalhd_decoder;
- extern const FFCodec ff_mpeg4_v4l2m2m_decoder;
- extern const FFCodec ff_mpeg4_mmal_decoder;
--extern const AVCodec ff_mpeg4_rkmpp_decoder;
- extern const FFCodec ff_mpegvideo_decoder;
- extern const FFCodec ff_mpeg1_v4l2m2m_decoder;
--extern const AVCodec ff_mpeg1_rkmpp_decoder;
- extern const FFCodec ff_mpeg2_mmal_decoder;
- extern const FFCodec ff_mpeg2_crystalhd_decoder;
- extern const FFCodec ff_mpeg2_v4l2m2m_decoder;
- extern const FFCodec ff_mpeg2_qsv_decoder;
- extern const FFCodec ff_mpeg2_mediacodec_decoder;
--extern const AVCodec ff_mpeg2_rkmpp_decoder;
- extern const FFCodec ff_msa1_decoder;
- extern const FFCodec ff_mscc_decoder;
- extern const FFCodec ff_msmpeg4v1_decoder;
-@@ -381,10 +385,8 @@ extern const FFCodec ff_vp6a_decoder;
+@@ -377,10 +389,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;
@@ -1836,1643 +1366,2270 @@ index dd8164d2b1..ba08c937d2 100644
extern const FFCodec ff_vp9_v4l2m2m_decoder;
extern const FFCodec ff_vqa_decoder;
extern const FFCodec ff_vqc_decoder;
-@@ -842,7 +844,6 @@ extern const FFCodec ff_av1_nvenc_encoder;
- extern const FFCodec ff_av1_qsv_decoder;
- extern const FFCodec ff_av1_qsv_encoder;
- extern const FFCodec ff_av1_amf_encoder;
--extern const FFCodec ff_av1_rkmpp_decoder;
- extern const FFCodec ff_libopenh264_encoder;
- extern const FFCodec ff_libopenh264_decoder;
- extern const FFCodec ff_h264_amf_encoder;
--
-2.40.0
+2.41.0
-From 035feef7fdc3ed1378b13ce8d28ad4237cac48b2 Mon Sep 17 00:00:00 2001
+From a82dd80d7c3f267cef6ef88bd0b6852fe73bcdea Mon Sep 17 00:00:00 2001
From: boogie <boogiepop@gmx.com>
-Date: Fri, 7 Apr 2023 16:20:13 +0200
-Subject: [PATCH 16/24] Remove librga
+Date: Mon, 24 Jul 2023 16:10:39 +0200
+Subject: [PATCH 09/13] intiial up to: eb34616ece746ae58030fd4601e802dacb0d3ee2
---
- configure | 7 +----
- libavcodec/rkmppdec.c | 68 +------------------------------------------
- 2 files changed, 2 insertions(+), 73 deletions(-)
+ libavcodec/codec_internal.h | 4 +
+ libavcodec/get_buffer.c | 24 ++
+ libavcodec/rkmpp.c | 272 +++++++++++++++
+ libavcodec/rkmpp.h | 281 +++++++++++++++
+ libavcodec/rkmppdec.c | 335 ++++++++++++++++++
+ libavcodec/rkmppenc.c | 628 +++++++++++++++++++++++++++++++++
+ libavcodec/rkplane.c | 676 ++++++++++++++++++++++++++++++++++++
+ libavcodec/rkplane.h | 17 +
+ 8 files changed, 2237 insertions(+)
+ create mode 100644 libavcodec/rkmpp.c
+ create mode 100644 libavcodec/rkmpp.h
+ create mode 100644 libavcodec/rkmppdec.c
+ create mode 100644 libavcodec/rkmppenc.c
+ create mode 100644 libavcodec/rkplane.c
+ create mode 100644 libavcodec/rkplane.h
-diff --git a/configure b/configure
-index 3804f193a5..84c6850fca 100755
---- a/configure
-+++ b/configure
-@@ -349,7 +349,6 @@ 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]
-@@ -1893,7 +1892,6 @@ HWACCEL_AUTODETECT_LIBRARY_LIST="
- videotoolbox
- vulkan
- v4l2_m2m
-- librga
- "
-
- # catchall list of things that require external libs to link
-@@ -6796,13 +6794,10 @@ 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"; } &&
-- { enabled librga ||
-- warn "using rkmpp without librga"; }
-+ die "ERROR: rkmpp requires --enable-libdrm"; }
- }
- enabled vapoursynth && require_pkg_config vapoursynth "vapoursynth-script >= 42" VSScript.h vsscript_init
-
-diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
-index dcaea9d435..908ab3963b 100644
---- a/libavcodec/rkmppdec.c
-+++ b/libavcodec/rkmppdec.c
-@@ -40,11 +40,6 @@
- #include "libavutil/imgutils.h"
- #include "libavutil/log.h"
-
--#if CONFIG_LIBRGA
--#include <rga/rga.h>
--#include <rga/RgaApi.h>
--#endif
--
- // HACK: Older BSP kernel use NA12 for NV15.
- #ifndef DRM_FORMAT_NV15 // fourcc_code('N', 'V', '1', '5')
- #define DRM_FORMAT_NV15 fourcc_code('N', 'A', '1', '2')
-@@ -118,18 +113,6 @@ static uint32_t rkmpp_get_avformat(MppFrameFormat mppformat)
- }
- }
-
--#if CONFIG_LIBRGA
--static uint32_t rkmpp_get_rgaformat(MppFrameFormat mppformat)
--{
-- switch (mppformat & MPP_FRAME_FMT_MASK) {
-- 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;
-- }
--}
--#endif
--
- static int rkmpp_close_decoder(AVCodecContext *avctx)
- {
- RKMPPDecodeContext *rk_context = avctx->priv_data;
-@@ -314,9 +297,6 @@ static int rkmpp_convert_frame(AVCodecContext *avctx, AVFrame *frame,
- 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);
-@@ -326,51 +306,6 @@ static int rkmpp_convert_frame(AVCodecContext *avctx, AVFrame *frame,
- 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;
-@@ -533,7 +468,7 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
- if (avctx->pix_fmt != AV_PIX_FMT_DRM_PRIME) {
- ret = ff_get_buffer(avctx, frame, 0);
- if (ret < 0)
-- goto out;
-+ goto fail;
- }
-
- // setup general frame fields
-@@ -612,7 +547,6 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
-
- return 0;
+diff --git a/libavcodec/codec_internal.h b/libavcodec/codec_internal.h
+index 130a7dc3cd..ed0dea86de 100644
+--- a/libavcodec/codec_internal.h
++++ b/libavcodec/codec_internal.h
+@@ -80,6 +80,10 @@
+ * Codec supports embedded ICC profiles (AV_FRAME_DATA_ICC_PROFILE).
+ */
+ #define FF_CODEC_CAP_ICC_PROFILES (1 << 9)
++/**
++ * The decoder requires contiguous buffers.
++ */
++#define FF_CODEC_CAP_CONTIGUOUS_BUFFERS (1 << 28)
+ /**
+ * The encoder has AV_CODEC_CAP_DELAY set, but does not actually have delay - it
+ * only wants to be flushed at the end to update some context variables (e.g.
+diff --git a/libavcodec/get_buffer.c b/libavcodec/get_buffer.c
+index a04fd878de..c6a1983f7e 100644
+--- a/libavcodec/get_buffer.c
++++ b/libavcodec/get_buffer.c
+@@ -32,6 +32,7 @@
--out:
- fail:
- if (mppframe)
- mpp_frame_deinit(&mppframe);
---
-2.40.0
-
-
-From 3a656a5cf3545ebcfec88ca9b2ca4fad2ff3f286 Mon Sep 17 00:00:00 2001
-From: boogie <boogiepop@gmx.com>
-Date: Sun, 16 Apr 2023 19:17:44 +0200
-Subject: [PATCH 17/24] Faster sw conversion with libyuv using SIMD
-
----
- configure | 3 +++
- libavcodec/rkmppdec.c | 47 ++++++++++++++++++++-----------------------
- 2 files changed, 25 insertions(+), 25 deletions(-)
-
-diff --git a/configure b/configure
-index 84c6850fca..7b7c4c0872 100755
---- a/configure
-+++ b/configure
-@@ -6796,6 +6796,9 @@ enabled openssl && { { check_pkg_config openssl "openssl >= 3.0.0" ope
- enabled pocketsphinx && require_pkg_config pocketsphinx pocketsphinx pocketsphinx/pocketsphinx.h ps_init
- 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 &&
-+ { check_lib libyuv libyuv/planar_functions.h SplitUVPlane -lyuv ||
-+ die "ERROR: libyuv is necessary for rkmpp"; } &&
-+ prepend rkmpp_deps "libyuv" &&
- { enabled libdrm ||
- die "ERROR: rkmpp requires --enable-libdrm"; }
- }
-diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
-index 908ab3963b..1cca4b6e7d 100644
---- a/libavcodec/rkmppdec.c
-+++ b/libavcodec/rkmppdec.c
-@@ -39,6 +39,7 @@
- #include "libavutil/hwcontext_drm.h"
- #include "libavutil/imgutils.h"
- #include "libavutil/log.h"
-+#include "libyuv/planar_functions.h"
+ #include "avcodec.h"
+ #include "internal.h"
++#include "codec_internal.h"
- // HACK: Older BSP kernel use NA12 for NV15.
- #ifndef DRM_FORMAT_NV15 // fourcc_code('N', 'V', '1', '5')
-@@ -290,44 +291,41 @@ static void rkmpp_release_frame(void *opaque, uint8_t *data)
- av_free(desc);
- }
+ typedef struct FramePool {
+ /**
+@@ -147,6 +148,14 @@ FF_ENABLE_DEPRECATION_WARNINGS
-+static void rkmpp_release_buffer(void *opaque, uint8_t *data)
-+{
-+ MppFrame mppframe = opaque;
-+ mpp_frame_deinit(&mppframe);
-+}
+ for (i = 0; i < 4; i++) {
+ pool->linesize[i] = linesize[i];
+
- 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];
-- 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 (mpp_frame_get_fmt(mppframe) != MPP_FMT_YUV420SP) {
-- av_log(avctx, AV_LOG_WARNING, "Unable to convert\n");
-- return -1;
-+ //data[0] points to buf[1] where the mppbuffer is referenced for y plane
-+ //so that we can still use y plane without extra copies
-+ //data[1,2] points to allready allocated AVBuffer Pool (buf[0]), we will convert to
-+ //that buffer only u+v planes, which is half the size operation
-+ frame->data[0] = mpp_buffer_get_ptr(buffer);
-+ frame->buf[1] = av_buffer_create(frame->data[0], mpp_buffer_get_size(buffer),
-+ rkmpp_release_buffer, mppframe,
-+ AV_BUFFER_FLAG_READONLY);
-+ if (!frame->buf[1]) {
-+ return AVERROR(ENOMEM);
- }
--
-- 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);
-+ frame->linesize[0] = hstride;
-+ av_log(avctx, AV_LOG_WARNING, "Doing software conversion for uv planes\n");
-
- 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;
-- }
--
-+ SplitUVPlane(src, hstride, dst_u, u_pitch, dst_v, v_pitch,
-+ (frame->width + 1) >> 1, (frame->height + 1) >> 1);
- return 0;
- }
-
-@@ -487,8 +485,7 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
- frame->top_field_first = ((mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK) == MPP_FRAME_FLAG_TOP_FIRST);
++ if (ffcodec(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);
+@@ -265,6 +274,21 @@ static int video_get_buffer(AVCodecContext *s, AVFrame *pic)
- if (avctx->pix_fmt != AV_PIX_FMT_DRM_PRIME) {
-- ret = rkmpp_convert_frame(avctx, frame, mppframe, buffer);
-- goto out;
-+ return rkmpp_convert_frame(avctx, frame, mppframe, buffer);
+ pic->data[i] = pic->buf[i]->data;
}
-
- mppformat = mpp_frame_get_fmt(mppframe);
---
-2.40.0
-
-
-From ebe5776cef27e618ac8b75450f43ead8b0cb6b13 Mon Sep 17 00:00:00 2001
-From: boogie <boogiepop@gmx.com>
-Date: Tue, 18 Apr 2023 19:05:56 +0200
-Subject: [PATCH 18/24] Use internal rga to convert from mppbuffer to avbuffer
-
----
- libavcodec/rga.h | 574 ++++++++++++++++++++++++++++++++++++++++++
- libavcodec/rkmppdec.c | 80 +++++-
- 2 files changed, 653 insertions(+), 1 deletion(-)
- create mode 100644 libavcodec/rga.h
-
-diff --git a/libavcodec/rga.h b/libavcodec/rga.h
++
++ if (ffcodec(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/rkmpp.c b/libavcodec/rkmpp.c
new file mode 100644
-index 0000000000..9595558de0
+index 0000000000..b76dc1a868
--- /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,
++++ b/libavcodec/rkmpp.c
+@@ -0,0 +1,272 @@
++/*
++ * RockChip MPP Video Codec
++ * Copyright (c) 2023 Huseyin BIYIK
++ *
++ * This file is part of FFmpeg.
++ *
++ * FFmpeg is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * FFmpeg is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++#include <fcntl.h>
++#include <time.h>
++#include "rkmpp.h"
++
++static rkformat rkformats[13] = {
++ { .av = AV_PIX_FMT_YUV420P, .mpp = MPP_FMT_YUV420P, .drm = DRM_FORMAT_YUV420, .rga = RK_FORMAT_YCbCr_420_P},
++ { .av = AV_PIX_FMT_YUV422P, .mpp = MPP_FMT_YUV422P, .drm = DRM_FORMAT_YUV422, .rga = RK_FORMAT_YCbCr_422_P},
++ { .av = AV_PIX_FMT_NV12, .mpp = MPP_FMT_YUV420SP, .drm = DRM_FORMAT_NV12, .rga = RK_FORMAT_YCbCr_420_SP},
++ { .av = AV_PIX_FMT_NV16, .mpp = MPP_FMT_YUV422SP, .drm = DRM_FORMAT_NV16, .rga = RK_FORMAT_YCbCr_422_SP},
++ { .av = AV_PIX_FMT_NONE, .mpp = MPP_FMT_YUV420SP_10BIT, .drm = DRM_FORMAT_NV15, .rga = RK_FORMAT_YCbCr_420_SP_10B},
++ { .av = AV_PIX_FMT_BGR24, .mpp = MPP_FMT_BGR888, .drm = DRM_FORMAT_BGR888, .rga = RK_FORMAT_BGR_888},
++ { .av = AV_PIX_FMT_BGR0, .mpp = MPP_FMT_BGRA8888, .drm = DRM_FORMAT_XRGB8888, .rga = RK_FORMAT_BGRX_8888},
++ { .av = AV_PIX_FMT_BGRA, .mpp = MPP_FMT_BGRA8888, .drm = DRM_FORMAT_ARGB8888, .rga = RK_FORMAT_BGRA_8888},
++ { .av = AV_PIX_FMT_BGR565, .mpp = MPP_FMT_BGR565, .drm = DRM_FORMAT_BGR565, .rga = RK_FORMAT_BGR_565},
++ { .av = AV_PIX_FMT_YUYV422, .mpp = MPP_FMT_YUV422_YUYV, .drm = DRM_FORMAT_YUYV, .rga = RK_FORMAT_YUYV_422},
++ { .av = AV_PIX_FMT_UYVY422, .mpp = MPP_FMT_YUV422_UYVY, .drm = DRM_FORMAT_UYVY, .rga = RK_FORMAT_UYVY_422},
++ { .av = AV_PIX_FMT_NV24, .mpp = MPP_FMT_YUV444SP, .drm = DRM_FORMAT_NV24, .rga = RK_FORMAT_UNKNOWN},
++ { .av = AV_PIX_FMT_YUV444P, .mpp = MPP_FMT_YUV444P, .drm = DRM_FORMAT_YUV444, .rga = RK_FORMAT_UNKNOWN},
+};
+
-+enum rga_scale_up_mode {
-+ RGA_SCALE_UP_NONE = 0x0,
-+ RGA_SCALE_UP_BIC = 0x1,
-+};
++#define GETFORMAT(NAME, TYPE)\
++int rkmpp_get_##NAME##_format(rkformat *format, TYPE informat){ \
++ for(int i=0; i < 13; i++){ \
++ if(rkformats[i].NAME == informat){ \
++ format->av = rkformats[i].av;\
++ format->mpp = rkformats[i].mpp;\
++ format->drm = rkformats[i].drm;\
++ format->rga = rkformats[i].rga;\
++ return 0;\
++ }\
++ }\
++ return -1;\
++}
+
-+enum rga_scale_down_mode {
-+ RGA_SCALE_DOWN_NONE = 0x0,
-+ RGA_SCALE_DOWN_AVG = 0x1,
-+};
++GETFORMAT(drm, uint32_t)
++GETFORMAT(mpp, MppFrameFormat)
++GETFORMAT(rga, enum _Rga_SURF_FORMAT)
++GETFORMAT(av, enum AVPixelFormat)
+
-+/* 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,
-+};
++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_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 */
++ case AV_CODEC_ID_MPEG2VIDEO: return MPP_VIDEO_CodingMPEG2;
++ case AV_CODEC_ID_MPEG4: return MPP_VIDEO_CodingMPEG4;
++ default: return MPP_VIDEO_CodingUnused;
++ }
++}
+
-+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,
-+};
++int rkmpp_close_codec(AVCodecContext *avctx)
++{
++ RKMPPCodecContext *rk_context = avctx->priv_data;
++ RKMPPCodec *codec = (RKMPPCodec *)rk_context->codec_ref->data;
+
-+/* 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,
-+};
++ av_packet_unref(&codec->lastpacket);
++ av_frame_unref(&codec->lastframe);
+
-+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,
-+};
++ av_buffer_unref(&rk_context->codec_ref);
++ return 0;
++}
+
-+#define RGA_SCHED_PRIORITY_DEFAULT 0
-+#define RGA_SCHED_PRIORITY_MAX 6
++void rkmpp_release_codec(void *opaque, uint8_t *data)
++{
++ RKMPPCodec *codec = (RKMPPCodec *)data;
+
-+#define RGA_VERSION_SIZE 16
-+#define RGA_HW_SIZE 5
++ if (codec->mpi) {
++ codec->mpi->reset(codec->ctx);
++ mpp_destroy(codec->ctx);
++ codec->ctx = NULL;
++ }
+
-+struct rga_version_t {
-+ uint32_t major;
-+ uint32_t minor;
-+ uint32_t revision;
-+ uint8_t str[RGA_VERSION_SIZE];
-+};
++ if (codec->buffer_group) {
++ mpp_buffer_group_put(codec->buffer_group);
++ codec->buffer_group = NULL;
++ }
+
-+struct rga_hw_versions_t {
-+ struct rga_version_t version[RGA_HW_SIZE];
-+ uint32_t size;
-+};
++ if(codec->hwframes_ref)
++ av_buffer_unref(&codec->hwframes_ref);
++ if(codec->hwdevice_ref)
++ av_buffer_unref(&codec->hwdevice_ref);
+
-+struct rga_memory_parm {
-+ uint32_t width;
-+ uint32_t height;
-+ uint32_t format;
++ av_free(codec);
++}
+
-+ uint32_t size;
-+};
++int rkmpp_init_codec(AVCodecContext *avctx)
++{
++ RKMPPCodecContext *rk_context = avctx->priv_data;
++ RKMPPCodec *codec = NULL;
++ MppCodingType codectype = MPP_VIDEO_CodingUnused;
++ char *env;
++ int ret;
+
-+struct rga_external_buffer {
-+ uint64_t memory;
-+ uint32_t type;
++ // create a codec and a ref to it
++ codec = av_mallocz(sizeof(RKMPPCodec));
++ if (!codec) {
++ ret = AVERROR(ENOMEM);
++ goto fail;
++ }
+
-+ uint32_t handle;
-+ struct rga_memory_parm memory_parm;
++ rk_context->codec_ref = av_buffer_create((uint8_t *)codec, sizeof(*codec), rkmpp_release_codec,
++ NULL, AV_BUFFER_FLAG_READONLY);
++ if (!rk_context->codec_ref) {
++ av_free(codec);
++ ret = AVERROR(ENOMEM);
++ goto fail;
++ }
+
-+ uint8_t reserve[252];
-+};
++ env = getenv("FFMPEG_RKMPP_LOG_FPS");
++ if (env != NULL)
++ codec->print_fps = !!atoi(env);
+
-+struct rga_buffer_pool {
-+ uint64_t buffers_ptr;
-+ uint32_t size;
-+};
++ av_log(avctx, AV_LOG_DEBUG, "Initializing RKMPP Codec.\n");
+
-+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;
-+};
++ codectype = rkmpp_get_codingtype(avctx);
++ if (codectype == MPP_VIDEO_CodingUnused) {
++ av_log(avctx, AV_LOG_ERROR, "Unknown codec type (%d).\n", avctx->codec_id);
++ ret = AVERROR_UNKNOWN;
++ goto fail;
++ }
+
-+/***************************************/
-+/* porting from rga.h for msg convert */
-+/***************************************/
++ ret = mpp_check_support_format(codec->mppctxtype, codectype);
++ if (ret != MPP_OK) {
++ av_log(avctx, AV_LOG_ERROR, "Codec type (%d) unsupported by MPP\n", avctx->codec_id);
++ ret = AVERROR_UNKNOWN;
++ goto fail;
++ }
+
-+struct rga_fading_t {
-+ uint8_t b;
-+ uint8_t g;
-+ uint8_t r;
-+ uint8_t res;
-+};
++ // Create the MPP context
++ ret = mpp_create(&codec->ctx, &codec->mpi);
++ if (ret != MPP_OK) {
++ av_log(avctx, AV_LOG_ERROR, "Failed to create MPP context (code = %d).\n", ret);
++ ret = AVERROR_UNKNOWN;
++ goto fail;
++ }
+
-+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;
-+};
++ if(ffcodec(avctx->codec)->cb_type == FF_CODEC_CB_TYPE_RECEIVE_FRAME){
++ codec->init_callback = rkmpp_init_decoder;
++ codec->mppctxtype = MPP_CTX_DEC;
+
-+struct rga_rect_t {
-+ uint16_t xmin;
-+ /* width - 1 */
-+ uint16_t xmax;
-+ uint16_t ymin;
-+ /* height - 1 */
-+ uint16_t ymax;
-+};
++ ret = 1;
++ codec->mpi->control(codec->ctx, MPP_DEC_SET_PARSER_FAST_MODE, &ret);
++
++ avctx->pix_fmt = ff_get_format(avctx, avctx->codec->pix_fmts);
++
++ // override the the pixfmt according env variable
++ env = getenv("FFMPEG_RKMPP_PIXFMT");
++ if(env != NULL){
++ if(!strcmp(env, "YUV420P"))
++ avctx->pix_fmt = AV_PIX_FMT_YUV420P;
++ else if (!strcmp(env, "NV12"))
++ avctx->pix_fmt = AV_PIX_FMT_NV12;
++ else if(!strcmp(env, "DRMPRIME"))
++ avctx->pix_fmt = AV_PIX_FMT_DRM_PRIME;
++ }
++ } else if ((ffcodec(avctx->codec)->cb_type == FF_CODEC_CB_TYPE_ENCODE)){
++ codec->mppctxtype = MPP_CTX_ENC;
++ codec->init_callback = rkmpp_init_encoder;
++ } else {
++ ret = AVERROR(ENOMEM);
++ av_log(avctx, AV_LOG_DEBUG, "RKMPP Codec can not determine if the mode is decoder or encoder\n");
++ goto fail;
++ }
+
-+struct rga_point_t {
-+ uint16_t x;
-+ uint16_t y;
-+};
++ av_log(avctx, AV_LOG_INFO, "Picture format is %s.\n", av_get_pix_fmt_name(avctx->pix_fmt));
+
-+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;
-+};
++ // initialize mpp
++ ret = mpp_init(codec->ctx, codec->mppctxtype, codectype);
++ if (ret != MPP_OK) {
++ av_log(avctx, AV_LOG_ERROR, "Failed to initialize MPP context (code = %d).\n", ret);
++ ret = AVERROR_UNKNOWN;
++ goto fail;
++ }
+
-+/* color space convert coefficient. */
-+struct rga_csc_coe {
-+ int16_t r_v;
-+ int16_t g_y;
-+ int16_t b_u;
-+ int32_t off;
-+};
++ env = getenv("FFMPEG_RKMPP_NORGA");
++ if(env != NULL){
++ codec->norga = 1;
++ av_log(avctx, AV_LOG_INFO, "Bypassing RGA and using libyuv soft conversion\n");
++ }
+
-+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;
-+};
++ ret = mpp_buffer_group_get_internal(&codec->buffer_group, MPP_BUFFER_TYPE_DRM | MPP_BUFFER_FLAGS_DMA32);
++ if (ret) {
++ av_log(avctx, AV_LOG_ERROR, "Failed to get buffer group (code = %d)\n", ret);
++ ret = AVERROR_UNKNOWN;
++ goto fail;
++ }
++
++ ret = codec->init_callback(avctx);
++ if(ret){
++ av_log(avctx, AV_LOG_ERROR, "Failed to init Codec (code = %d).\n", ret);
++ goto fail;
++ }
++
++ return 0;
+
-+struct rga_mosaic_info {
-+ uint8_t enable;
-+ uint8_t mode;
++fail:
++ av_log(avctx, AV_LOG_ERROR, "Failed to initialize RKMPP Codec.\n");
++ rkmpp_close_codec(avctx);
++ return ret;
++}
++
++void rkmpp_flush(AVCodecContext *avctx)
++{
++ RKMPPCodecContext *rk_context = avctx->priv_data;
++ RKMPPCodec *codec = (RKMPPCodec *)rk_context->codec_ref->data;
++
++ av_log(avctx, AV_LOG_DEBUG, "Flush.\n");
++
++ codec->mpi->reset(codec->ctx);
++ codec->norga = codec->last_frame_time = codec->frames = codec->hascfg = 0;
++
++ av_packet_unref(&codec->lastpacket);
++ av_frame_unref(&codec->lastframe);
++}
++
++uint64_t rkmpp_update_latency(AVCodecContext *avctx, int latency)
++{
++ RKMPPCodecContext *rk_context = avctx->priv_data;
++ RKMPPCodec *codec = (RKMPPCodec *)rk_context->codec_ref->data;
++ struct timespec tv;
++ uint64_t curr_time;
++ float fps = 0.0f;
++
++ if (!codec->print_fps)
++ return 0;
++
++ clock_gettime(CLOCK_MONOTONIC, &tv);
++ curr_time = tv.tv_sec * 10e5 + tv.tv_nsec / 10e2;
++ if (latency == -1){
++ latency = codec->last_frame_time ? curr_time - codec->last_frame_time : 0;
++ codec->last_frame_time = curr_time;
++ codec->latencies[codec->frames % RKMPP_FPS_FRAME_MACD] = latency;
++ return latency;
++ } else if (latency == 0 || codec->frames < RKMPP_FPS_FRAME_MACD) {
++ fps = -1.0f;
++ } else {
++ for(int i = 0; i < RKMPP_FPS_FRAME_MACD; i++) {
++ fps += codec->latencies[i];
++ }
++ fps = RKMPP_FPS_FRAME_MACD * 1000000.0f / fps;
++ }
++ av_log(avctx, AV_LOG_INFO,
++ "[FFMPEG RKMPP] FPS(MACD%d): %6.1f || Frames: %" PRIu64 " || Latency: %d us || Buffer Delay %" PRIu64 "us\n",
++ RKMPP_FPS_FRAME_MACD, fps, codec->frames, latency, (uint64_t)(curr_time - codec->last_frame_time));
++
++ return 0;
++}
+diff --git a/libavcodec/rkmpp.h b/libavcodec/rkmpp.h
+new file mode 100644
+index 0000000000..c09ef5b564
+--- /dev/null
++++ b/libavcodec/rkmpp.h
+@@ -0,0 +1,281 @@
++#include <drm_fourcc.h>
++#include <rockchip/rk_mpi.h>
++#include <unistd.h>
++#include <stdint.h>
++
++#include "internal.h"
++#include "codec_internal.h"
++#include "avcodec.h"
++#include "hwconfig.h"
++#include "decode.h"
++#include "encode.h"
++#include "rga/RgaApi.h"
++#include "libavutil/macros.h"
++#include "libavutil/log.h"
++#include "libavutil/opt.h"
++#include "libavutil/buffer.h"
++#include "libavutil/pixfmt.h"
++#include "libavutil/pixdesc.h"
++#include "libavutil/hwcontext_drm.h"
++
++// HACK: Older BSP kernel use NA12 for NV15.
++#ifndef DRM_FORMAT_NV15 // fourcc_code('N', 'V', '1', '5')
++#define DRM_FORMAT_NV15 fourcc_code('N', 'A', '1', '2')
++#endif
++
++#define RKMPP_FPS_FRAME_MACD 30
++#define RKMPP_STRIDE_ALIGN 16
++#define RKMPP_RGA_MIN_SIZE 128
++#define RKMPP_RGA_MAX_SIZE 4096
++#define RKMPP_MPPFRAME_BUFINDEX 7
++#define HDR_SIZE 1024
++#define QMAX_H26x 51
++#define QMIN_H26x 10
++#define QMAX_VPx 127
++#define QMIN_VPx 40
++#define QMAX_JPEG 99
++#define QMIN_JPEG 1
++
++
++#define DRMFORMATNAME(buf, format) \
++ buf[0] = format & 0xff; \
++ buf[1] = (format >> 8) & 0xff; \
++ buf[2] = (format >> 16) & 0xff; \
++ buf[3] = (format >> 24) & 0x7f; \
++
++typedef struct {
++ AVClass *av_class;
++ AVBufferRef *codec_ref;
++ int rc_mode;
++ int profile;
++ int qmin;
++ int qmax;
++ int level;
++ int coder;
++ int dct8x8;
++ enum AVPixelFormat postrga_format;
++ int postrga_width;
++ int postrga_height;
++} RKMPPCodecContext;
++
++typedef struct {
++ MppCtx ctx;
++ MppApi *mpi;
++ MppBufferGroup buffer_group;
++ MppCtxType mppctxtype;
++ MppEncCfg enccfg;
++ int hascfg;
++ int64_t ptsstep;
++ int64_t pts;
++
++ AVPacket lastpacket;
++ AVFrame lastframe;
++ AVBufferRef *hwframes_ref;
++ AVBufferRef *hwdevice_ref;
++
++ char print_fps;
++ uint64_t last_frame_time;
++ uint64_t frames;
++ uint64_t latencies[RKMPP_FPS_FRAME_MACD];
++
++ int8_t norga;
++ int (*init_callback)(struct AVCodecContext *avctx);
++} RKMPPCodec;
++
++typedef struct {
++ enum AVPixelFormat av;
++ MppFrameFormat mpp;
++ uint32_t drm;
++ enum _Rga_SURF_FORMAT rga;
++} rkformat;
++
++MppCodingType rkmpp_get_codingtype(AVCodecContext *avctx);
++int rkmpp_get_drm_format(rkformat *format, uint32_t informat);
++int rkmpp_get_mpp_format(rkformat *format, MppFrameFormat informat);
++int rkmpp_get_rga_format(rkformat *format, enum _Rga_SURF_FORMAT informat);
++int rkmpp_get_av_format(rkformat *format, enum AVPixelFormat informat);
++int rkmpp_init_encoder(AVCodecContext *avctx);
++int rkmpp_encode(AVCodecContext *avctx, AVPacket *packet, const AVFrame *frame, int *got_packet);
++int rkmpp_init_decoder(AVCodecContext *avctx);
++int rkmpp_receive_frame(AVCodecContext *avctx, AVFrame *frame);
++int rkmpp_init_codec(AVCodecContext *avctx);
++int rkmpp_close_codec(AVCodecContext *avctx);
++void rkmpp_release_codec(void *opaque, uint8_t *data);
++void rkmpp_flush(AVCodecContext *avctx);
++uint64_t rkmpp_update_latency(AVCodecContext *avctx, int latency);
++
++#define OFFSET(x) offsetof(RKMPPCodecContext, x)
++#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
++
++#define ENCODEROPTS() \
++ { "rc_mode", "Set rate control mode", OFFSET(rc_mode), AV_OPT_TYPE_INT, \
++ { .i64 = MPP_ENC_RC_MODE_CBR }, MPP_ENC_RC_MODE_VBR, MPP_ENC_RC_MODE_BUTT, VE, "rc_mode"}, \
++ {"VBR", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MPP_ENC_RC_MODE_VBR }, 0, 0, VE, "rc_mode" }, \
++ {"CBR", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MPP_ENC_RC_MODE_CBR }, 0, 0, VE, "rc_mode" }, \
++ {"CQP", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MPP_ENC_RC_MODE_FIXQP }, 0, 0, VE, "rc_mode" }, \
++ {"AVBR", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MPP_ENC_RC_MODE_AVBR }, 0, 0, VE, "rc_mode" }, \
++ { "quality_min", "Minimum Quality", OFFSET(qmin), AV_OPT_TYPE_INT, \
++ { .i64=50 }, 0, 100, VE, "qmin"}, \
++ { "quality_max", "Maximum Quality", OFFSET(qmax), AV_OPT_TYPE_INT, \
++ { .i64=100 }, 0, 100, VE, "qmax"}, \
++ { "width", "scale to Width", OFFSET(postrga_width), AV_OPT_TYPE_INT, \
++ { .i64=0 }, 0, RKMPP_RGA_MAX_SIZE, VE, "width"}, \
++ { "height", "scale to Height", OFFSET(postrga_height), AV_OPT_TYPE_INT, \
++ { .i64=0 }, 0, RKMPP_RGA_MAX_SIZE, VE, "height"},
++
++static const AVOption options_h264_encoder[] = {
++ ENCODEROPTS()
++ { "profile", "Set profile restrictions", OFFSET(profile), AV_OPT_TYPE_INT,
++ { .i64=FF_PROFILE_H264_HIGH }, -1, FF_PROFILE_H264_HIGH, VE, "profile"},
++ { "baseline", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_H264_BASELINE}, INT_MIN, INT_MAX, VE, "profile" },
++ { "main", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_H264_MAIN}, INT_MIN, INT_MAX, VE, "profile" },
++ { "high", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_H264_HIGH}, INT_MIN, INT_MAX, VE, "profile" },
++ { "level", "Compression Level", OFFSET(level), AV_OPT_TYPE_INT,
++ { .i64 = 0 }, FF_LEVEL_UNKNOWN, 0xff, VE, "level"},
++ { "1", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 10 }, 0, 0, VE, "level"},
++ { "1.1", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 11 }, 0, 0, VE, "level"},
++ { "1.2", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 12 }, 0, 0, VE, "level"},
++ { "1.3", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 13 }, 0, 0, VE, "level"},
++ { "2", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 20 }, 0, 0, VE, "level"},
++ { "2.1", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 21 }, 0, 0, VE, "level"},
++ { "2.2", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 22 }, 0, 0, VE, "level"},
++ { "3", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 30 }, 0, 0, VE, "level"},
++ { "3.1", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 31 }, 0, 0, VE, "level"},
++ { "3.2", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 32 }, 0, 0, VE, "level"},
++ { "4", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 40 }, 0, 0, VE, "level"},
++ { "4.1", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 41 }, 0, 0, VE, "level"},
++ { "4.2", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 42 }, 0, 0, VE, "level"},
++ { "5", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 50 }, 0, 0, VE, "level"},
++ { "5.1", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 51 }, 0, 0, VE, "level"},
++ { "5.2", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 52 }, 0, 0, VE, "level"},
++ { "6", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 60 }, 0, 0, VE, "level"},
++ { "6.1", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 61 }, 0, 0, VE, "level"},
++ { "6.2", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 62 }, 0, 0, VE, "level"},
++ { "coder", "Entropy coder type (from 0 to 1) (default cabac)", OFFSET(coder), AV_OPT_TYPE_INT,
++ { .i64 = 1 }, 0, 1, VE, "coder"},
++ { "cavlc", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, VE, "coder" },
++ { "cabac", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, VE, "coder" },
++ { "8x8dct", "High profile 8x8 transform.", OFFSET(dct8x8), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE},
++ { NULL }
+};
+
-+/* 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;
++static const AVOption options_hevc_encoder[] = {
++ ENCODEROPTS()
++ { "level", "Compression Level", OFFSET(level), AV_OPT_TYPE_INT,
++ { .i64 = 0 }, FF_LEVEL_UNKNOWN, 0xff, VE, "level"},
++ { "1", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 30 }, 0, 0, VE, "level"},
++ { "2", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 60 }, 0, 0, VE, "level"},
++ { "2.1", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 63 }, 0, 0, VE, "level"},
++ { "3", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 90 }, 0, 0, VE, "level"},
++ { "3.1", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 93 }, 0, 0, VE, "level"},
++ { "4", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 120 }, 0, 0, VE, "level"},
++ { "4.1", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 123 }, 0, 0, VE, "level"},
++ { "5", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 150 }, 0, 0, VE, "level"},
++ { "5.1", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 153 }, 0, 0, VE, "level"},
++ { "5.2", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 156 }, 0, 0, VE, "level"},
++ { "6", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 180 }, 0, 0, VE, "level"},
++ { "6.1", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 183 }, 0, 0, VE, "level"},
++ { "6.2", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 186 }, 0, 0, VE, "level"},
++ { "8.5", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 255 }, 0, 0, VE, "level"},
++ { NULL }
+};
+
-+struct rga_color {
-+ union {
-+ struct {
-+ uint8_t red;
-+ uint8_t green;
-+ uint8_t blue;
-+ uint8_t alpha;
-+ };
-+ uint32_t value;
-+ };
++static const AVOption options_vp8_encoder[] = {
++ ENCODEROPTS()
++ { NULL }
+};
+
-+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;
++#define DECODEROPTIONS(NAME, TYPE) \
++static const AVOption options_##NAME##_##TYPE[] = { \
++ { NULL } \
++ };
++
++DECODEROPTIONS(h263, decoder);
++DECODEROPTIONS(h264, decoder);
++DECODEROPTIONS(hevc, decoder);
++DECODEROPTIONS(av1, decoder);
++DECODEROPTIONS(vp8, decoder);
++DECODEROPTIONS(vp9, decoder);
++DECODEROPTIONS(mpeg1, decoder);
++DECODEROPTIONS(mpeg2, decoder);
++DECODEROPTIONS(mpeg4, decoder);
++
++static const FFCodecDefault rkmpp_enc_defaults[] = {
++ { "b", "6M" },
++ { "g", "60" },
++ { NULL }
+};
+
-+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
++static const enum AVPixelFormat rkmppvepu1formats[] = {
++ AV_PIX_FMT_NV16,
++ AV_PIX_FMT_YUV422P,
++ AV_PIX_FMT_YUYV422,
++ AV_PIX_FMT_UYVY422,
++ AV_PIX_FMT_BGRA,
++ AV_PIX_FMT_BGR0,
++ AV_PIX_FMT_NV12,
++ AV_PIX_FMT_YUV420P,
++ AV_PIX_FMT_DRM_PRIME,
++ AV_PIX_FMT_NONE,
+};
+
-+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;
-+ };
++static const enum AVPixelFormat rkmppvepu5formats[] = {
++ AV_PIX_FMT_NV24,
++ AV_PIX_FMT_YUV444P,
++ AV_PIX_FMT_NV16,
++ AV_PIX_FMT_YUV422P,
++ AV_PIX_FMT_BGR24,
++ AV_PIX_FMT_YUYV422,
++ AV_PIX_FMT_UYVY422,
++ AV_PIX_FMT_BGRA,
++ AV_PIX_FMT_BGR0,
++ AV_PIX_FMT_NV12,
++ AV_PIX_FMT_YUV420P,
++ AV_PIX_FMT_DRM_PRIME,
++ AV_PIX_FMT_NONE,
+};
+
-+struct rga_pre_intr_info {
-+ uint8_t enable;
++#define RKMPP_CODEC(NAME, ID, BSFS, TYPE) \
++ static const AVClass rkmpp_##NAME##_##TYPE##_class = { \
++ .class_name = "rkmpp_" #NAME "_" #TYPE, \
++ .item_name = av_default_item_name,\
++ .option = options_##NAME##_##TYPE, \
++ .version = LIBAVUTIL_VERSION_INT, \
++ }; \
++ const FFCodec ff_##NAME##_rkmpp_##TYPE = { \
++ .p.name = #NAME "_rkmpp_" #TYPE, \
++ CODEC_LONG_NAME(#NAME " (rkmpp " #TYPE " )"), \
++ .p.type = AVMEDIA_TYPE_VIDEO, \
++ .p.id = ID, \
++ .priv_data_size = sizeof(RKMPPCodecContext), \
++ .init = rkmpp_init_codec, \
++ .close = rkmpp_close_codec, \
++ .flush = rkmpp_flush, \
++ .p.priv_class = &rkmpp_##NAME##_##TYPE##_class, \
++ .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | FF_CODEC_CAP_CONTIGUOUS_BUFFERS, \
++ .bsfs = BSFS, \
++ .p.wrapper_name = "rkmpp",
++
++
++#define RKMPP_DEC(NAME, ID, BSFS) \
++ RKMPP_CODEC(NAME, ID, BSFS, decoder) \
++ FF_CODEC_RECEIVE_FRAME_CB(rkmpp_receive_frame), \
++ .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_NV12, \
++ AV_PIX_FMT_YUV420P, \
++ AV_PIX_FMT_NONE}, \
++ .hw_configs = (const AVCodecHWConfigInternal *const []) { HW_CONFIG_INTERNAL(DRM_PRIME), \
++ HW_CONFIG_INTERNAL(NV12), \
++ NULL}, \
++ };
+
-+ 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;
-+};
++#define RKMPP_ENC(NAME, ID, VEPU) \
++ RKMPP_CODEC(NAME, ID, NULL, encoder) \
++ FF_CODEC_ENCODE_CB(rkmpp_encode), \
++ .p.capabilities = AV_CODEC_CAP_HARDWARE, \
++ .defaults = rkmpp_enc_defaults, \
++ .p.pix_fmts = rkmpp##VEPU##formats, \
++ .hw_configs = (const AVCodecHWConfigInternal *const []) { HW_CONFIG_INTERNAL(NV12), \
++ NULL}, \
++ };
+diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
+new file mode 100644
+index 0000000000..acec713140
+--- /dev/null
++++ b/libavcodec/rkmppdec.c
+@@ -0,0 +1,335 @@
++/*
++ * RockChip MPP Video Decoder
++ * Copyright (c) 2017 Lionel CHAZALLON
++ *
++ * This file is part of FFmpeg.
++ *
++ * FFmpeg is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * FFmpeg is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++#include "rkmpp.h"
++#include "rkplane.h"
+
-+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;
++int rkmpp_init_decoder(AVCodecContext *avctx){
++ RKMPPCodecContext *rk_context = avctx->priv_data;
++ RKMPPCodec *codec = (RKMPPCodec *)rk_context->codec_ref->data;
+
-+ uint16_t vir_w;
-+ uint16_t vir_h;
++ int ret;
+
-+ uint16_t endian_mode;
-+ /* useless */
-+ uint16_t alpha_swap;
++ ret = codec->mpi->control(codec->ctx, MPP_DEC_SET_EXT_BUF_GROUP, codec->buffer_group);
++ if (ret) {
++ av_log(avctx, AV_LOG_ERROR, "Failed to assign buffer group (code = %d)\n", ret);
++ return AVERROR_UNKNOWN;
++ }
+
-+ /* used by RGA3 */
-+ uint16_t rotate_mode;
-+ uint16_t rd_mode;
++ codec->mpi->control(codec->ctx, MPP_DEC_SET_DISABLE_ERROR, NULL);
++ if (ret < 0) {
++ av_log(avctx, AV_LOG_ERROR, "Failed to prepare Codec (code = %d)\n", ret);
++ return AVERROR_UNKNOWN;
++ }
+
-+ uint16_t is_10b_compact;
-+ uint16_t is_10b_endian;
++ avctx->coded_width = FFALIGN(avctx->width, 64);
++ avctx->coded_height = FFALIGN(avctx->height, 64);
+
-+ uint16_t enable;
-+};
++ codec->hwdevice_ref = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_DRM);
++ if (!codec->hwdevice_ref) {
++ return AVERROR(ENOMEM);
++ }
+
-+struct rga_req {
-+ /* (enum) process mode sel */
-+ uint8_t render_mode;
++ ret = av_hwdevice_ctx_init(codec->hwdevice_ref);
++ if (ret < 0)
++ return ret;
+
-+ struct rga_img_info_t src;
-+ struct rga_img_info_t dst;
-+ struct rga_img_info_t pat;
++ av_buffer_unref(&codec->hwframes_ref);
++ codec->hwframes_ref = av_hwframe_ctx_alloc(codec->hwdevice_ref);
++ if (!codec->hwframes_ref) {
++ return AVERROR(ENOMEM);
++ }
+
-+ /* rop4 mask addr */
-+ uint64_t rop_mask_addr;
-+ /* LUT addr */
-+ uint64_t LUT_addr;
++ return 0;
++}
+
-+ /* dst clip window default value is dst_vir */
-+ /* value from [0, w-1] / [0, h-1]*/
-+ struct rga_rect_t clip;
++static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
++{
++ RKMPPCodecContext *rk_context = avctx->priv_data;
++ RKMPPCodec *codec = (RKMPPCodec *)rk_context->codec_ref->data;
++ MppFrameFormat mpp_format;
++ MppFrame mppframe = NULL;
++ MppBuffer buffer = NULL;
++ rkformat format;
++ int ret, latency;
++ int mpp_width, mpp_height, mpp_mode;
++ enum AVColorRange mpp_color_range;
++ enum AVColorPrimaries mpp_color_primaries;
++ enum AVColorTransferCharacteristic mpp_color_trc;
++ enum AVColorSpace mpp_color_space;
++ int64_t mpp_pts;
++
++ codec->mpi->control(codec->ctx, MPP_SET_OUTPUT_TIMEOUT, (MppParam)&timeout);
++
++ ret = codec->mpi->decode_get_frame(codec->ctx, &mppframe);
++ if (ret != MPP_OK && ret != MPP_ERR_TIMEOUT) {
++ av_log(avctx, AV_LOG_ERROR, "Failed to get frame (code = %d)\n", ret);
++ return AVERROR_UNKNOWN;
++ }
+
-+ /* 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;
++ if (!mppframe) {
++ av_log(avctx, AV_LOG_DEBUG, "Timeout getting decoded frame.\n");
++ return AVERROR(EAGAIN);
++ }
+
-+ /* 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;
++ if (mpp_frame_get_eos(mppframe)) {
++ av_log(avctx, AV_LOG_DEBUG, "Received a EOS frame.\n");
++ ret = AVERROR_EOF;
++ goto clean;
++ }
+
-+ /* 0 nearst / 1 bilnear / 2 bicubic */
-+ uint8_t scale_mode;
++ if (mpp_frame_get_discard(mppframe)) {
++ av_log(avctx, AV_LOG_DEBUG, "Received a discard frame.\n");
++ ret = AVERROR(EAGAIN);
++ goto clean;
++ }
+
-+ /* color key max */
-+ uint32_t color_key_max;
-+ /* color key min */
-+ uint32_t color_key_min;
++ if (mpp_frame_get_errinfo(mppframe)) {
++ av_log(avctx, AV_LOG_ERROR, "Received a errinfo frame.\n");
++ ret = AVERROR_UNKNOWN;
++ goto clean;
++ }
+
-+ /* foreground color */
-+ uint32_t fg_color;
-+ /* background color */
-+ uint32_t bg_color;
++ mpp_format = mpp_frame_get_fmt(mppframe) & MPP_FRAME_FMT_MASK;
+
-+ /* color fill use gradient */
-+ struct rga_color_fill_t gr_color;
++ if (mpp_frame_get_info_change(mppframe)) {
++ if(codec->hascfg)
++ ret = AVERROR(EAGAIN);
++ else{
++ if (avctx->pix_fmt == AV_PIX_FMT_DRM_PRIME){
++ char drmname[4];
++ AVHWFramesContext *hwframes;
++ rkmpp_get_mpp_format(&format, mpp_format);
++ DRMFORMATNAME(drmname, format.drm)
++
++ hwframes = (AVHWFramesContext*)codec->hwframes_ref->data;
++ hwframes->format = AV_PIX_FMT_DRM_PRIME;
++ hwframes->sw_format = format.av;
++ hwframes->width = avctx->width;
++ hwframes->height = avctx->height;
++ ret = av_hwframe_ctx_init(codec->hwframes_ref);
++ // FIXME: handle error
++ av_log(avctx, AV_LOG_INFO, "Decoder is set to DRM Prime with format %s.\n", drmname);
++ } else if (mpp_format == MPP_FMT_YUV420SP_10BIT)
++ av_log(avctx, AV_LOG_WARNING, "10bit NV15 plane will be downgraded to 8bit %s.\n", av_get_pix_fmt_name(avctx->pix_fmt));
++ codec->hascfg = 1;
++ }
+
-+ struct rga_line_draw_t line_draw_info;
++ av_log(avctx, AV_LOG_INFO, "Decoder noticed an info change\n");
++ codec->mpi->control(codec->ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL);
++ goto clean;
++ }
+
-+ struct rga_fading_t fading;
++ // here we should have a valid frame
++ av_log(avctx, AV_LOG_DEBUG, "Received a frame.\n");
+
-+ /* porter duff alpha mode sel */
-+ uint8_t PD_mode;
++ // 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 clean;
++ }
+
-+ /* global alpha value */
-+ uint8_t alpha_global_value;
++ latency = rkmpp_update_latency(avctx, -1);
++ mpp_pts = mpp_frame_get_pts(mppframe);
++ mpp_width = mpp_frame_get_width(mppframe);
++ mpp_height = mpp_frame_get_height(mppframe);
++ mpp_color_range = mpp_frame_get_color_range(mppframe);
++ mpp_color_primaries = mpp_frame_get_color_primaries(mppframe);
++ mpp_color_trc = mpp_frame_get_color_trc(mppframe);
++ mpp_color_space = mpp_frame_get_colorspace(mppframe);
++ mpp_mode = mpp_frame_get_mode(mppframe);
+
-+ /* rop2/3/4 code scan from rop code table*/
-+ uint16_t rop_code;
++ if (avctx->pix_fmt == AV_PIX_FMT_DRM_PRIME){
++ ret = import_mpp_to_drm(avctx, mppframe, frame);
++ } else if (mpp_format == MPP_FMT_YUV420SP_10BIT && avctx->pix_fmt == AV_PIX_FMT_NV12){
++ ret = mpp_nv15_av_nv12(avctx, mppframe, frame);
++ } else if (mpp_format == MPP_FMT_YUV420SP_10BIT && avctx->pix_fmt == AV_PIX_FMT_YUV420P){
++ ret = mpp_nv15_av_yuv420p(avctx, mppframe, frame);
++ } else if (mpp_format == MPP_FMT_YUV420SP && avctx->pix_fmt == AV_PIX_FMT_NV12){
++ ret = mpp_nv12_av_nv12(avctx, mppframe, frame);
++ } else {
++ rkmpp_get_mpp_format(&format, mpp_format);
++ ret = convert_mpp_to_av(avctx, mppframe, frame, format.av, avctx->pix_fmt);
++ }
+
-+ /* [2] 0 blur 1 sharp / [1:0] filter_type*/
-+ uint8_t bsfilter_flag;
++ if(ret < 0){
++ av_log(avctx, AV_LOG_ERROR, "Failed set frame buffer (code = %d)\n", ret);
++ return ret;
++ }
+
-+ /* (enum) color palette 0/1bpp, 1/2bpp 2/4bpp 3/8bpp*/
-+ uint8_t palette_mode;
++ // setup general frame fields
++ frame->format = avctx->pix_fmt;
++ frame->width = mpp_width;
++ frame->height = mpp_height;
++ frame->color_range = mpp_color_range;
++ frame->color_primaries = mpp_color_primaries;
++ frame->color_trc = mpp_color_trc;
++ frame->colorspace = mpp_color_space;
++ frame->pts = mpp_pts;
+
-+ /* (enum) BT.601 MPEG / BT.601 JPEG / BT.709 */
-+ uint8_t yuv2rgb_mode;
++ // when mpp can not determine the color space, it returns reserved (0) value
++ // firefox does not understand this and instead expect unspecified (2) values
++ frame->color_primaries = frame->color_primaries == AVCOL_PRI_RESERVED0 ? AVCOL_PRI_UNSPECIFIED : frame->color_primaries;
++ frame->color_trc = frame->color_trc == AVCOL_TRC_RESERVED0 ? AVCOL_TRC_UNSPECIFIED : frame->color_trc;
++ frame->colorspace = frame->colorspace == AVCOL_SPC_RGB ? AVCOL_SPC_UNSPECIFIED: frame->color_trc;
+
-+ /* 0/big endian 1/little endian*/
-+ uint8_t endian_mode;
++ frame->interlaced_frame = ((mpp_mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK) == MPP_FRAME_FLAG_DEINTERLACED);
++ frame->top_field_first = ((mpp_mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK) == MPP_FRAME_FLAG_TOP_FIRST);
+
-+ /* (enum) rotate mode */
-+ /* 0x0, no rotate */
-+ /* 0x1, rotate */
-+ /* 0x2, x_mirror */
-+ /* 0x3, y_mirror */
-+ uint8_t rotate_mode;
++ codec->frames++;
++ rkmpp_update_latency(avctx, latency);
++ return 0;
+
-+ /* 0 solid color / 1 pattern color */
-+ uint8_t color_fill_mode;
++clean:
++ if (mppframe)
++ mpp_frame_deinit(&mppframe);
++ return ret;
++}
+
-+ /* mmu information */
-+ struct rga_mmu_t mmu_info;
++static int rkmpp_send_packet(AVCodecContext *avctx, AVPacket *packet)
++{
++ RKMPPCodecContext *rk_context = avctx->priv_data;
++ RKMPPCodec *codec = (RKMPPCodec *)rk_context->codec_ref->data;
++ MppPacket mpkt;
++ int64_t pts = packet->pts;
++ int ret;
+
-+ /* ([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;
++ if(pts == AV_NOPTS_VALUE || pts < 0){
++ if(!codec->ptsstep && avctx->framerate.den && avctx->framerate.num){
++ int64_t x = avctx->pkt_timebase.den * (int64_t)avctx->framerate.den;
++ int64_t y = avctx->pkt_timebase.num * (int64_t)avctx->framerate.num;
++ codec->ptsstep = x / y;
++ }
++ if(codec->ptsstep && (packet->dts == AV_NOPTS_VALUE || packet->dts < 0)){
++ pts = codec->pts;
++ codec->pts += codec->ptsstep;
++ } else {
++ codec->pts = packet->dts;
++ pts = packet->dts;
++ }
++ }
+
-+ uint8_t src_trans_mode;
++ 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;
++ }
+
-+ uint8_t dither_mode;
++ mpp_packet_set_pts(mpkt, pts);
+
-+ /* full color space convert */
-+ struct rga_full_csc full_csc;
++ ret = codec->mpi->decode_put_packet(codec->ctx, mpkt);
++ mpp_packet_deinit(&mpkt);
+
-+ int32_t in_fence_fd;
-+ uint8_t core;
-+ uint8_t priority;
-+ int32_t out_fence_fd;
++ if (ret != MPP_OK) {
++ av_log(avctx, AV_LOG_TRACE, "Decoder buffer full\n");
++ return AVERROR(EAGAIN);
++ }
+
-+ uint8_t handle_flag;
++ av_log(avctx, AV_LOG_DEBUG, "Wrote %d bytes to decoder\n", packet->size);
++ return 0;
++}
+
-+ /* RGA2 1106 add */
-+ struct rga_mosaic_info mosaic_info;
++static int rkmpp_send_eos(AVCodecContext *avctx)
++{
++ RKMPPCodecContext *rk_context = avctx->priv_data;
++ RKMPPCodec *codec = (RKMPPCodec *)rk_context->codec_ref->data;
++ MppPacket mpkt;
++ int ret;
+
-+ uint8_t uvhds_mode;
-+ uint8_t uvvds_mode;
++ 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;
++ }
+
-+ struct rga_osd_info osd_info;
++ mpp_packet_set_eos(mpkt);
+
-+ struct rga_pre_intr_info pre_intr_info;
++ do {
++ ret = codec->mpi->decode_put_packet(codec->ctx, mpkt);
++ } while (ret != MPP_OK);
++ mpp_packet_deinit(&mpkt);
+
-+ uint8_t reservr[59];
-+};
-+#endif /*_RGA_DRIVER_H_*/
-diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
-index 1cca4b6e7d..e3e51d9973 100644
---- a/libavcodec/rkmppdec.c
-+++ b/libavcodec/rkmppdec.c
-@@ -26,6 +26,7 @@
- #include <time.h>
- #include <unistd.h>
- #include <sys/time.h>
-+#include <fcntl.h>
-
- #include "avcodec.h"
- #include "codec_internal.h"
-@@ -40,6 +41,7 @@
- #include "libavutil/imgutils.h"
- #include "libavutil/log.h"
- #include "libyuv/planar_functions.h"
-+#include "rga.h"
-
- // HACK: Older BSP kernel use NA12 for NV15.
- #ifndef DRM_FORMAT_NV15 // fourcc_code('N', 'V', '1', '5')
-@@ -55,6 +57,7 @@ typedef struct {
-
- int8_t eos;
- int8_t draining;
-+ int8_t softconvert;
-
- AVPacket packet;
- AVBufferRef *frames_ref;
-@@ -66,6 +69,8 @@ typedef struct {
- uint64_t frames;
-
- char sync;
++ return 0;
++}
+
-+ int rga_fd;
- } RKMPPDecoder;
-
- typedef struct {
-@@ -114,6 +119,16 @@ static uint32_t rkmpp_get_avformat(MppFrameFormat mppformat)
- }
- }
-
-+static uint32_t rkmpp_get_rgaformat(MppFrameFormat mppformat)
++int rkmpp_receive_frame(AVCodecContext *avctx, AVFrame *frame)
+{
-+ switch (mppformat & MPP_FRAME_FMT_MASK) {
-+ 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;
++ AVCodecInternal *avci = avctx->internal;
++ RKMPPCodecContext *rk_context = avctx->priv_data;
++ RKMPPCodec *codec = (RKMPPCodec *)rk_context->codec_ref->data;
++ AVPacket *packet = &codec->lastpacket;
++ int ret_send, ret_get;
++
++ // get packet if not already available from previous iteration
++ if (!avci->draining){
++ if(!packet->size){
++ switch(ff_decode_get_packet(avctx, packet)){
++ case AVERROR_EOF:
++ av_log(avctx, AV_LOG_DEBUG, "Decoder Draining.\n");
++ return rkmpp_send_eos(avctx);
++ case AVERROR(EAGAIN):
++ av_log(avctx, AV_LOG_TRACE, "Decoder Can't get packet retrying.\n");
++ return AVERROR(EAGAIN);
++ }
++ }
++
++sendpacket:
++ // there is definitely a packet to send to decoder here
++ ret_send = rkmpp_send_packet(avctx, packet);
++ if (ret_send == 0){
++ // send successful, continue until decoder input buffer is full
++ av_packet_unref(packet);
++ return AVERROR(EAGAIN);
++ } else if (ret_send < 0 && ret_send != AVERROR(EAGAIN)) {
++ // something went wrong, raise error
++ av_log(avctx, AV_LOG_ERROR, "Decoder Failed to send data (code = %d)\n", ret_send);
++ return ret_send;
++ }
+ }
++
++ // were here only when draining and buffer is full
++ ret_get = rkmpp_get_frame(avctx, frame, MPP_TIMEOUT_BLOCK);
++
++ if (ret_get == AVERROR_EOF){
++ av_log(avctx, AV_LOG_DEBUG, "Decoder is at EOS.\n");
++ // this is not likely but lets handle it in case synchronization issues of mpp
++ } else if (ret_get == AVERROR(EAGAIN) && ret_send == AVERROR(EAGAIN))
++ goto sendpacket;
++ // only for logging
++ else if (ret_get < 0 && ret_get != AVERROR(EAGAIN)) // FIXME
++ av_log(avctx, AV_LOG_ERROR, "Decoder Failed to get frame (code = %d)\n", ret_get);
++
++ return ret_get;
+}
+
- static int rkmpp_close_decoder(AVCodecContext *avctx)
- {
- RKMPPDecodeContext *rk_context = avctx->priv_data;
-@@ -140,6 +155,11 @@ static void rkmpp_release_decoder(void *opaque, uint8_t *data)
- decoder->frame_group = NULL;
- }
-
-+ if (decoder->rga_fd) {
-+ close(decoder->rga_fd);
-+ decoder->rga_fd = 0;
++
++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)
++RKMPP_DEC(mpeg2, AV_CODEC_ID_MPEG2VIDEO, NULL)
++RKMPP_DEC(mpeg4,AV_CODEC_ID_MPEG4, "mpeg4_unpack_bframes")
++
+diff --git a/libavcodec/rkmppenc.c b/libavcodec/rkmppenc.c
+new file mode 100644
+index 0000000000..b611e9451b
+--- /dev/null
++++ b/libavcodec/rkmppenc.c
+@@ -0,0 +1,628 @@
++/*
++ * RockChip MPP Video Decoder
++ * Copyright (c) 2023 Huseyin BIYIK
++ *
++ * This file is part of FFmpeg.
++ *
++ * FFmpeg is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * FFmpeg is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++#include "rkmpp.h"
++#include "rkplane.h"
++
++static int rkmpp_config_withframe(AVCodecContext *avctx, MppFrame mppframe, AVFrame *frame){
++ RKMPPCodecContext *rk_context = avctx->priv_data;
++ RKMPPCodec *codec = (RKMPPCodec *)rk_context->codec_ref->data;
++ MppEncCfg cfg = codec->enccfg;
++
++ if(codec->hascfg == 0){
++ rkformat format;
++
++ int ret;
++ if(frame->time_base.num && frame->time_base.den){
++ avctx->time_base.num = frame->time_base.num;
++ avctx->time_base.den = frame->time_base.den;
++ } else {
++ avctx->time_base.num = avctx->framerate.den;
++ avctx->time_base.den = avctx->framerate.num;
++ }
++
++ mpp_enc_cfg_set_s32(cfg, "prep:width", mpp_frame_get_width(mppframe));
++ mpp_enc_cfg_set_s32(cfg, "prep:height", mpp_frame_get_height(mppframe));
++ mpp_enc_cfg_set_s32(cfg, "prep:hor_stride", mpp_frame_get_hor_stride(mppframe));
++ mpp_enc_cfg_set_s32(cfg, "prep:ver_stride", mpp_frame_get_ver_stride(mppframe));
++ mpp_enc_cfg_set_s32(cfg, "prep:format", mpp_frame_get_fmt(mppframe) & MPP_FRAME_FMT_MASK);
++ ret = codec->mpi->control(codec->ctx, MPP_ENC_SET_CFG, cfg);
++ if (ret != MPP_OK) {
++ av_log(avctx, AV_LOG_ERROR, "Failed to config with frame (code = %d).\n", ret);
++ return AVERROR_UNKNOWN;
++ }
++ codec->hascfg = 1;
++ rkmpp_get_mpp_format(&format, mpp_frame_get_fmt(mppframe));
++ av_log(avctx, AV_LOG_INFO, "Reconfigured with w=%d, h=%d, format=%s.\n", mpp_frame_get_width(mppframe),
++ mpp_frame_get_height(mppframe), av_get_pix_fmt_name(format.av));
++ return 0;
+ }
++ return 0;
++}
+
- av_buffer_unref(&decoder->frames_ref);
- av_buffer_unref(&decoder->device_ref);
-
-@@ -244,6 +264,11 @@ static int rkmpp_init_decoder(AVCodecContext *avctx)
- goto fail;
- }
-
-+ decoder->rga_fd = open("/dev/rga", O_RDWR);
-+ if (decoder->rga_fd < 0) {
-+ av_log(avctx, AV_LOG_WARNING, "Failed to open RGA, Falling back to libyuv\n");
++static int rkmpp_config(AVCodecContext *avctx){
++ RKMPPCodecContext *rk_context = avctx->priv_data;
++ RKMPPCodec *codec = (RKMPPCodec *)rk_context->codec_ref->data;
++ MppEncCfg cfg = codec->enccfg;
++ RK_U32 rc_mode, split_mode, split_arg, split_out, fps_num, fps_den;
++ MppCodingType coding_type = rkmpp_get_codingtype(avctx);
++ MppEncHeaderMode header_mode;
++ MppEncSeiMode sei_mode;
++ int ret, max_bps, min_bps, qmin, qmax;
++
++ //prep config
++ mpp_enc_cfg_set_s32(cfg, "prep:width", avctx->width);
++ mpp_enc_cfg_set_s32(cfg, "prep:height", avctx->height);
++ mpp_enc_cfg_set_s32(cfg, "prep:hor_stride", FFALIGN(avctx->width, RKMPP_STRIDE_ALIGN));
++ mpp_enc_cfg_set_s32(cfg, "prep:ver_stride", FFALIGN(avctx->height, RKMPP_STRIDE_ALIGN));
++ // later to be reconfigured with the first frame received
++ mpp_enc_cfg_set_s32(cfg, "prep:format", MPP_FMT_YUV420SP);
++ mpp_enc_cfg_set_s32(cfg, "prep:mirroring", 0);
++ mpp_enc_cfg_set_s32(cfg, "prep:rotation", 0);
++ mpp_enc_cfg_set_s32(cfg, "prep:flip", 0);
++
++ //rc config
++ // make sure time base of avctx is synced to input frames
++ av_reduce(&fps_num, &fps_den, avctx->time_base.den, avctx->time_base.num, 65535);
++
++ /* fix input / output frame rate */
++ mpp_enc_cfg_set_s32(cfg, "rc:fps_in_flex", 0);
++ mpp_enc_cfg_set_s32(cfg, "rc:fps_in_num", fps_num);
++ mpp_enc_cfg_set_s32(cfg, "rc:fps_in_denorm", fps_den);
++ mpp_enc_cfg_set_s32(cfg, "rc:fps_out_flex", 0);
++ mpp_enc_cfg_set_s32(cfg, "rc:fps_out_num",fps_num);
++ mpp_enc_cfg_set_s32(cfg, "rc:fps_out_denorm", fps_den);
++
++ mpp_enc_cfg_set_s32(cfg, "rc:gop", FFMAX(avctx->gop_size, 1));
++
++ // config rc: mode
++ rc_mode = rk_context->rc_mode;
++ if(rc_mode == MPP_ENC_RC_MODE_BUTT)
++ rc_mode = MPP_ENC_RC_MODE_CBR;
++
++ switch(rc_mode){
++ case MPP_ENC_RC_MODE_VBR:
++ av_log(avctx, AV_LOG_INFO, "Rate Control mode is set to VBR\n"); break;
++ case MPP_ENC_RC_MODE_CBR:
++ av_log(avctx, AV_LOG_INFO, "Rate Control mode is set to CBR\n"); break;
++ case MPP_ENC_RC_MODE_FIXQP:
++ av_log(avctx, AV_LOG_INFO, "Rate Control mode is set to CQP\n"); break;
++ case MPP_ENC_RC_MODE_AVBR:
++ av_log(avctx, AV_LOG_INFO, "Rate Control mode is set to AVBR\n"); break;
+ }
+
- 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);
-@@ -300,14 +325,67 @@ static void rkmpp_release_buffer(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];
-+ enum rga_surf_format rgaformat = 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);
- 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];
-
++ mpp_enc_cfg_set_u32(cfg, "rc:mode", rc_mode);
++
++ // config rc: bps
++ mpp_enc_cfg_set_u32(cfg, "rc:bps_target", avctx->bit_rate);
++
++ switch (rc_mode) {
++ case MPP_ENC_RC_MODE_FIXQP : {
++ /* do not setup bitrate on FIXQP mode */
++ min_bps = max_bps = avctx->bit_rate;
++ break;
++ }
++ case MPP_ENC_RC_MODE_CBR : {
++ /* CBR mode has narrow bound */
++ max_bps = avctx->bit_rate * 17 / 16;
++ min_bps = avctx->bit_rate * 15 / 16;
++ break;
++ }
++ case MPP_ENC_RC_MODE_VBR :
++ case MPP_ENC_RC_MODE_AVBR : {
++ /* VBR mode has wide bound */
++ max_bps = avctx->bit_rate * 17 / 16;
++ min_bps = avctx->bit_rate * 1 / 16;
++ break;
++ }
++ default : {
++ /* default use CBR mode */
++ max_bps = avctx->bit_rate * 17 / 16;
++ min_bps = avctx->bit_rate * 15 / 16;
++ break;
++ }
++ }
++
++ mpp_enc_cfg_set_s32(cfg, "rc:bps_max", max_bps);
++ mpp_enc_cfg_set_s32(cfg, "rc:bps_min", min_bps);
++
++ av_log(avctx, AV_LOG_INFO, "Bitrate Target/Min/Max is set to %ld/%d/%d\n", avctx->bit_rate, min_bps, max_bps);
++
++ // config rc: drop behaviour
++ mpp_enc_cfg_set_u32(cfg, "rc:drop_mode", MPP_ENC_RC_DROP_FRM_DISABLED);
++ mpp_enc_cfg_set_u32(cfg, "rc:drop_thd", 20); // 20% of max bps
++ mpp_enc_cfg_set_u32(cfg, "rc:drop_gap", 1); // Do not continuous drop frame
++
++ // config rc: qp
++ switch (coding_type) {
++ case MPP_VIDEO_CodingAVC :
++ case MPP_VIDEO_CodingHEVC : {
++ qmax = QMIN_H26x + (100 - rk_context->qmin) * (QMAX_H26x - QMIN_H26x) / 100;
++ qmin = QMIN_H26x + (100 - rk_context->qmax) * (QMAX_H26x - QMIN_H26x) / 100;
++ switch (rc_mode) {
++ case MPP_ENC_RC_MODE_FIXQP : {
++ mpp_enc_cfg_set_s32(cfg, "rc:qp_init", qmin);
++ mpp_enc_cfg_set_s32(cfg, "rc:qp_max", qmin);
++ mpp_enc_cfg_set_s32(cfg, "rc:qp_min", qmin);
++ mpp_enc_cfg_set_s32(cfg, "rc:qp_max_i", qmin);
++ mpp_enc_cfg_set_s32(cfg, "rc:qp_min_i", qmin);
++ mpp_enc_cfg_set_s32(cfg, "rc:qp_ip", 0);
++ break;
++ }
++ case MPP_ENC_RC_MODE_CBR :
++ case MPP_ENC_RC_MODE_VBR :
++ case MPP_ENC_RC_MODE_AVBR : {
++ mpp_enc_cfg_set_s32(cfg, "rc:qp_init", qmin);
++ mpp_enc_cfg_set_s32(cfg, "rc:qp_max", qmax);
++ mpp_enc_cfg_set_s32(cfg, "rc:qp_min", qmin);
++ mpp_enc_cfg_set_s32(cfg, "rc:qp_max_i",qmax);
++ mpp_enc_cfg_set_s32(cfg, "rc:qp_min_i", qmin);
++ mpp_enc_cfg_set_s32(cfg, "rc:qp_ip", 2);
++ break;
++ }
++ default : {
++ av_log(avctx, AV_LOG_ERROR, "Unsupported Encoder Mode %d.\n", rc_mode);
++ break;
++ }
++ }
++ break;
++ }
++ case MPP_VIDEO_CodingVP8 : {
++ // vp8 only setup base qp range
++ qmax = QMIN_VPx + (100 - rk_context->qmin) * (QMAX_VPx - QMIN_VPx) / 100;
++ qmin = QMIN_VPx + (100 - rk_context->qmax) * (QMAX_VPx - QMIN_VPx) / 100;
++ mpp_enc_cfg_set_s32(cfg, "rc:qp_init", qmin);
++ mpp_enc_cfg_set_s32(cfg, "rc:qp_max", qmax);
++ mpp_enc_cfg_set_s32(cfg, "rc:qp_min", qmin);
++ mpp_enc_cfg_set_s32(cfg, "rc:qp_max_i", qmax);
++ mpp_enc_cfg_set_s32(cfg, "rc:qp_min_i", qmin);
++ mpp_enc_cfg_set_s32(cfg, "rc:qp_ip", 6);
++ break;
++ }
++ case MPP_VIDEO_CodingMJPEG : {
++ qmax = QMIN_JPEG + (100 - rk_context->qmin) * (QMAX_JPEG - QMIN_JPEG) / 100;
++ qmin = QMIN_JPEG + (100 - rk_context->qmax) * (QMAX_JPEG- QMIN_JPEG) / 100;
++ // jpeg use special codec config to control qtable
++ mpp_enc_cfg_set_s32(cfg, "jpeg:q_factor", 80);
++ mpp_enc_cfg_set_s32(cfg, "jpeg:qf_max", qmax);
++ mpp_enc_cfg_set_s32(cfg, "jpeg:qf_min", qmin);
++ break;
++ }
++ default : {
++ break;
++ }
++ }
++
++ // setup codec
++ mpp_enc_cfg_set_s32(cfg, "codec:type", coding_type);
++ switch (coding_type) {
++ case MPP_VIDEO_CodingAVC : {
++ avctx->profile = rk_context->profile;
++ avctx->level = rk_context->level;
++ mpp_enc_cfg_set_s32(cfg, "h264:profile", avctx->profile);
++ mpp_enc_cfg_set_s32(cfg, "h264:level", avctx->level);
++ mpp_enc_cfg_set_s32(cfg, "h264:cabac_en", rk_context->coder);
++ mpp_enc_cfg_set_s32(cfg, "h264:cabac_idc", 0);
++ mpp_enc_cfg_set_s32(cfg, "h264:trans8x8", rk_context->dct8x8 && avctx->profile == FF_PROFILE_H264_HIGH ? 1 : 0);
++ switch(avctx->profile){
++ case FF_PROFILE_H264_BASELINE: av_log(avctx, AV_LOG_INFO, "Profile is set to BASELINE\n"); break;
++ case FF_PROFILE_H264_MAIN: av_log(avctx, AV_LOG_INFO, "Profile is set to MAIN\n"); break;
++ case FF_PROFILE_H264_HIGH:
++ av_log(avctx, AV_LOG_INFO, "Profile is set to HIGH\n");
++ if(rk_context->dct8x8)
++ av_log(avctx, AV_LOG_INFO, "8x8 Transform is enabled\n");
++ break;
++ }
++ av_log(avctx, AV_LOG_INFO, "Level is set to %d\n", avctx->level);
++ if(rk_context->coder)
++ av_log(avctx, AV_LOG_INFO, "Coder is set to CABAC\n");
++ else
++ av_log(avctx, AV_LOG_INFO, "Coder is set to CAVLC\n");
++ break;
++ }
++ case MPP_VIDEO_CodingHEVC : {
++ avctx->profile = FF_PROFILE_HEVC_MAIN;
++ avctx->level = rk_context->level;
++ mpp_enc_cfg_set_s32(cfg, "h265:profile", avctx->profile);
++ mpp_enc_cfg_set_s32(cfg, "h265:level", avctx->level);
++ switch(avctx->profile){
++ case FF_PROFILE_HEVC_MAIN: av_log(avctx, AV_LOG_INFO, "Profile is set to MAIN\n"); break;
++ case FF_PROFILE_HEVC_MAIN_10: av_log(avctx, AV_LOG_INFO, "Profile is set to MAIN 10\n"); break;
++ }
++ av_log(avctx, AV_LOG_INFO, "Level is set to %d\n", avctx->level == 255 ? 85 : avctx->level / 3);
++ break;
++ }
++ case MPP_VIDEO_CodingMJPEG :
++ case MPP_VIDEO_CodingVP8 :
++ mpp_enc_cfg_set_s32(cfg, "vp8:disable_ivf", 1);
++ break;
++ default : {
++ av_log(avctx, AV_LOG_ERROR, "Unsupported coding type for config (code = %d).\n", coding_type);
++ break;
++ }
++ }
++
++ av_log(avctx, AV_LOG_INFO, "Quality Min/Max is set to %d%%(Quant=%d) / %d%%(Quant=%d)\n",
++ rk_context->qmin, qmax, rk_context->qmax, qmin);
++
++ split_mode = 0;
++ split_arg = 0;
++ split_out = 0;
++
++ if (split_mode) {
++ mpp_enc_cfg_set_s32(cfg, "split:mode", split_mode);
++ mpp_enc_cfg_set_s32(cfg, "split:arg", split_arg);
++ mpp_enc_cfg_set_s32(cfg, "split:out", split_out);
++ }
++
++ ret = codec->mpi->control(codec->ctx, MPP_ENC_SET_CFG, cfg);
++ if (ret != MPP_OK) {
++ av_log(avctx, AV_LOG_ERROR, "Failed to set cfg on MPI (code = %d).\n", ret);
++ return AVERROR_UNKNOWN;
++ }
++
++ sei_mode = MPP_ENC_SEI_MODE_DISABLE;
++ ret = codec->mpi->control(codec->ctx, MPP_ENC_SET_SEI_CFG, &sei_mode);
++ if (ret != MPP_OK) {
++ av_log(avctx, AV_LOG_ERROR, "Failed to set sei cfg on MPI (code = %d).\n", ret);
++ return AVERROR_UNKNOWN;
++ }
++
++ header_mode = MPP_ENC_HEADER_MODE_EACH_IDR;
++ if (coding_type == MPP_VIDEO_CodingAVC || coding_type == MPP_VIDEO_CodingHEVC) {
++ ret = codec->mpi->control(codec->ctx, MPP_ENC_SET_HEADER_MODE, &header_mode);
++ if (ret) {
++ av_log(avctx, AV_LOG_ERROR, "Failed header mode on MPI (code = %d).\n", ret);
++ return ret;
++ }
++ }
++
++ return 0;
++}
++
++//https://github.com/rockchip-linux/mpp/issues/417
++//Encoder does not support 422 planes, but we can do this with rga
++//FIX-ME: NV12/YUV422P do not have libyuv fallbacks when encoding vp8
++static int check_vp8_planes(AVCodecContext *avctx, enum AVPixelFormat pix_fmt){
++ MppCodingType coding_type = rkmpp_get_codingtype(avctx);
++ RKMPPCodecContext *rk_context = avctx->priv_data;
++
++ if(coding_type == MPP_VIDEO_CodingVP8 &&
++ (pix_fmt == AV_PIX_FMT_NV16 ||
++ pix_fmt == AV_PIX_FMT_YUV422P)){
++ rk_context->postrga_format = AV_PIX_FMT_NV12;
++
++ if (avctx->width < RKMPP_RGA_MIN_SIZE || avctx->width > RKMPP_RGA_MAX_SIZE){
++ av_log(avctx, AV_LOG_ERROR, "Frame width (%d) not in rga scalable range (%d - %d)\n",
++ avctx->width, RKMPP_RGA_MIN_SIZE, RKMPP_RGA_MAX_SIZE);
++ return -1;
++ } else
++ rk_context->postrga_width = avctx->width;
++
++ if (avctx->height < RKMPP_RGA_MIN_SIZE || avctx->height > RKMPP_RGA_MAX_SIZE){
++ av_log(avctx, AV_LOG_ERROR, "Frame height (%d) not in rga scalable range (%d - %d)\n",
++ avctx->height, RKMPP_RGA_MIN_SIZE, RKMPP_RGA_MAX_SIZE);
++ return -1;
++ } else
++ rk_context->postrga_height = avctx->height;
++ } else
++ rk_context->postrga_format = AV_PIX_FMT_NONE;
++ return 0;
++}
++
++static int check_scaling(AVCodecContext *avctx, enum AVPixelFormat pix_fmt){
++ RKMPPCodecContext *rk_context = avctx->priv_data;
++
++ if(rk_context->postrga_width || rk_context->postrga_height){
++ if(pix_fmt != AV_PIX_FMT_NV16 && pix_fmt != AV_PIX_FMT_NV12 &&
++ pix_fmt != AV_PIX_FMT_YUV422P && pix_fmt != AV_PIX_FMT_YUV420P){
++ av_log(avctx, AV_LOG_ERROR, "Scaling is only supported for NV12,NV16,YUV420P,YUV422P. %s requested\n",
++ av_get_pix_fmt_name(pix_fmt));
++ return -1;
++ }
++ // align it to accepted RGA range
++ rk_context->postrga_width = FFMAX(rk_context->postrga_width, RKMPP_RGA_MIN_SIZE);
++ rk_context->postrga_height = FFMAX(rk_context->postrga_height, RKMPP_RGA_MIN_SIZE);
++ rk_context->postrga_width = FFMIN(rk_context->postrga_width, RKMPP_RGA_MAX_SIZE);
++ rk_context->postrga_height = FFMIN(rk_context->postrga_height, RKMPP_RGA_MAX_SIZE);
++ avctx->width = rk_context->postrga_width;
++ avctx->height = rk_context->postrga_height;
++ if(rk_context->postrga_format == AV_PIX_FMT_NONE)
++ rk_context->postrga_format = pix_fmt;
++ }
++ return 0;
++}
++
++int rkmpp_init_encoder(AVCodecContext *avctx){
++ RKMPPCodecContext *rk_context = avctx->priv_data;
++ RKMPPCodec *codec = (RKMPPCodec *)rk_context->codec_ref->data;
++ MppCodingType coding_type = rkmpp_get_codingtype(avctx);
++ RK_U8 enc_hdr_buf[HDR_SIZE];
++ MppPacket packet = NULL;
++ size_t packetlen;
++ void *packetpos;
+ int ret;
++ int input_timeout = 500;
+
-+ int dst_height = (dst_u - dst_y) / y_pitch;
-+
-+ if (decoder->softconvert || decoder->rga_fd < 0)
-+ goto softconvert;
-+
-+ struct rga_req req = {
-+ .src = {
-+ .yrgb_addr = mpp_buffer_get_fd(buffer),
-+ .v_addr = hstride * vstride,
-+ .format = rgaformat,
-+ .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,
-+ },
-+ };
++ // ENCODER SETUP
++ ret = mpp_enc_cfg_init(&codec->enccfg);
++ if (ret) {
++ av_log(avctx, AV_LOG_ERROR, "Codec failed to initialize encoder config (code = %d)\n", ret);
++ ret = AVERROR_UNKNOWN;
++ goto fail;
++ }
++
++ ret = codec->mpi->control(codec->ctx, MPP_ENC_GET_CFG, codec->enccfg);
++ if (ret) {
++ av_log(avctx, AV_LOG_ERROR, "Codec failed to get encoder config (code = %d)\n", ret);
++ ret = AVERROR_UNKNOWN;
++ goto fail;
++ }
++
++ if(avctx->pix_fmt != AV_PIX_FMT_DRM_PRIME){
++ if(check_vp8_planes(avctx, avctx->pix_fmt)){
++ ret = AVERROR_UNKNOWN;
++ goto fail;
++ }
++ if(check_scaling(avctx, avctx->pix_fmt)){
++ ret = AVERROR_UNKNOWN;
++ goto fail;
++ }
++ }
++
++ if(rkmpp_config(avctx)){
++ ret = AVERROR_UNKNOWN;
++ goto fail;
++ }
++
++ // copy sps/pps/vps to extradata for h26x
++ if(coding_type == MPP_VIDEO_CodingAVC || coding_type == MPP_VIDEO_CodingHEVC){
++ memset(enc_hdr_buf, 0 , HDR_SIZE);
+
-+ ret = ioctl(decoder->rga_fd, RGA_BLIT_SYNC, &req);
-+ if (ret < 0){
-+ decoder->softconvert = 1;
-+ av_log(avctx, AV_LOG_WARNING, "RGA failed with code %d, falling back to soft conversion of uv planes\n");
-+ goto softconvert;
++ ret = mpp_packet_init(&packet, (void *)enc_hdr_buf, HDR_SIZE);
++ if (!packet) {
++ av_log(avctx, AV_LOG_ERROR, "Failed to init extra info packet (code = %d).\n", ret);
++ ret = AVERROR_UNKNOWN;
++ goto fail;
++ }
++
++ mpp_packet_set_length(packet, 0);
++ ret = codec->mpi->control(codec->ctx, MPP_ENC_GET_HDR_SYNC, packet);
++ if (ret != MPP_OK) {
++ av_log(avctx, AV_LOG_ERROR, "Failed to get extra info on MPI (code = %d).\n", ret);
++ ret = AVERROR_UNKNOWN;
++ goto fail;
++ }
++
++ /* get and write sps/pps for H.264/H.265 */
++ packetpos = mpp_packet_get_pos(packet);
++ packetlen = mpp_packet_get_length(packet);
++
++ if (avctx->extradata != NULL) {
++ av_free(avctx->extradata);
++ avctx->extradata = NULL;
++ }
++ avctx->extradata = av_malloc(packetlen + AV_INPUT_BUFFER_PADDING_SIZE);
++ if (avctx->extradata == NULL) {
++ ret = AVERROR(ENOMEM);
++ goto fail;
++ }
++ avctx->extradata_size = packetlen + AV_INPUT_BUFFER_PADDING_SIZE;
++ memcpy(avctx->extradata, packetpos, packetlen);
++ memset(avctx->extradata + packetlen, 0, AV_INPUT_BUFFER_PADDING_SIZE);
++ mpp_packet_deinit(&packet);
+ }
+
-+ rkmpp_release_buffer(mppframe, NULL);
++ codec->mpi->control(codec->ctx, MPP_SET_INPUT_TIMEOUT, &input_timeout);
+ return 0;
+
-+softconvert:
- //data[0] points to buf[1] where the mppbuffer is referenced for y plane
- //so that we can still use y plane without extra copies
- //data[1,2] points to allready allocated AVBuffer Pool (buf[0]), we will convert to
-@@ -320,7 +398,6 @@ static int rkmpp_convert_frame(AVCodecContext *avctx, AVFrame *frame,
- return AVERROR(ENOMEM);
- }
- frame->linesize[0] = hstride;
-- av_log(avctx, AV_LOG_WARNING, "Doing software conversion for uv planes\n");
-
- src += hstride * vstride;
-
-@@ -686,6 +763,7 @@ static void rkmpp_flush(AVCodecContext *avctx)
-
- decoder->eos = 0;
- decoder->draining = 0;
-+ decoder->softconvert = 0;
- decoder->last_fps_time = decoder->frames = 0;
-
- av_packet_unref(&decoder->packet);
---
-2.40.0
-
-
-From 21644b8342b95bc75b2b2b4e1cddd37ab8668283 Mon Sep 17 00:00:00 2001
-From: boogie <boogiepop@gmx.com>
-Date: Tue, 18 Apr 2023 23:20:13 +0200
-Subject: [PATCH 19/24] rework receive frame without any loop and more
- statefull flow remove draining flags which is no more necessary with the new
- flow remove sync mode, this is useless
-
----
- libavcodec/rkmppdec.c | 114 +++++++++++++-----------------------------
- 1 file changed, 36 insertions(+), 78 deletions(-)
-
-diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
-index e3e51d9973..bd87d74e39 100644
---- a/libavcodec/rkmppdec.c
-+++ b/libavcodec/rkmppdec.c
-@@ -56,7 +56,6 @@ typedef struct {
- MppBufferGroup frame_group;
-
- int8_t eos;
-- int8_t draining;
- int8_t softconvert;
-
- AVPacket packet;
-@@ -68,8 +67,6 @@ typedef struct {
- uint64_t last_fps_time;
- uint64_t frames;
-
-- char sync;
--
- int rga_fd;
- } RKMPPDecoder;
-
-@@ -166,33 +163,6 @@ 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;
--
-- // HACK: somehow MPP cannot handle extra data for AV1
-- if (avctx->extradata_size && avctx->codec_id != AV_CODEC_ID_AV1) {
-- 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;
-- ret = 1;
-- decoder->mpi->control(decoder->ctx, MPP_DEC_SET_IMMEDIATE_OUT, &ret);
-- }
-- return 0;
--}
--
- static int rkmpp_init_decoder(AVCodecContext *avctx)
- {
- RKMPPDecodeContext *rk_context = avctx->priv_data;
-@@ -278,7 +248,6 @@ static int rkmpp_init_decoder(AVCodecContext *avctx)
-
- 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;
-@@ -378,7 +347,7 @@ static int rkmpp_convert_frame(AVCodecContext *avctx, AVFrame *frame,
- ret = ioctl(decoder->rga_fd, RGA_BLIT_SYNC, &req);
- if (ret < 0){
- decoder->softconvert = 1;
-- av_log(avctx, AV_LOG_WARNING, "RGA failed with code %d, falling back to soft conversion of uv planes\n");
-+ av_log(avctx, AV_LOG_WARNING, "RGA failed with code %d, falling back to soft conversion of uv planes\n", ret);
- goto softconvert;
- }
-
-@@ -645,10 +614,6 @@ static int rkmpp_send_packet(AVCodecContext *avctx, AVPacket *packet)
- 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;
-
-@@ -692,8 +657,6 @@ static int rkmpp_send_eos(AVCodecContext *avctx)
- } while (ret != MPP_OK);
- mpp_packet_deinit(&mpkt);
-
-- decoder->draining = 1;
--
- return 0;
- }
-
-@@ -703,51 +666,48 @@ static int rkmpp_receive_frame(AVCodecContext *avctx, AVFrame *frame)
- RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data;
- AVPacket *packet = &decoder->packet;
- int ret;
-+ int gettimeout = MPP_TIMEOUT_NON_BLOCK;;
-
-- // 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);
-+ // get packet if not already available from previous iteration
-+ if (!packet->size){
-+ ret = ff_decode_get_packet(avctx, packet);
-+ if (ret == AVERROR_EOF) {
-+ av_log(avctx, AV_LOG_DEBUG, "Draining.\n");
-+ // send EOS and start draining
-+ rkmpp_send_eos(avctx);
-+ // we can get all the decoder backlog blocking here
-+ gettimeout = MPP_TIMEOUT_BLOCK;
++fail:
++ av_log(avctx, AV_LOG_ERROR, "Failed to initialize RKMPP Codec.\n");
++ if(packet)
++ mpp_packet_deinit(&packet);
++ return ret;
++}
++
++static void rkmpp_release_packet_buf(void *opaque, uint8_t *data){
++ MppPacket mpppacket = opaque;
++ mpp_packet_deinit(&mpppacket);
++}
++
++static int rkmpp_send_frame(AVCodecContext *avctx, AVFrame *frame){
++ RKMPPCodecContext *rk_context = avctx->priv_data;
++ RKMPPCodec *codec = (RKMPPCodec *)rk_context->codec_ref->data;
++ MppFrame mppframe = NULL;
++ rkformat format;
++ int ret=0, keepframe=0;
++
++ // EOS frame, avframe=NULL
++ if (!frame) {
++ av_log(avctx, AV_LOG_DEBUG, "End of stream.\n");
++ mpp_frame_init(&mppframe);
++ mpp_frame_set_eos(mppframe, 1);
++ } else {
++ if (avctx->pix_fmt == AV_PIX_FMT_DRM_PRIME){
++ // the frame is coming from a DRMPRIME enabled decoder, no copy necessary
++ // just import existing fd and buffer to mmpp
++ mppframe = import_drm_to_mpp(avctx, frame);
++ } else {
++ // the frame is coming from a RKMPP decoder, no copy necessary
++ // use existing mppframe which is atatched to
++ // RKMPP_MPPFRAME_BUFINDEX of the frame buffers
++ // those frames need to be cleaned by the decoder itself therefore dont clean them
++ mppframe = get_mppframe_from_av(frame);
++ if(mppframe)
++ keepframe = 1;
++ else
++ // soft frames needs to be copied to a buffer region where mpp supports.
++ // a copy is necessary here
++ mppframe = create_mpp_frame(frame->width, frame->height, avctx->pix_fmt, codec->buffer_group, NULL, frame);
++ }
++
++ if(!mppframe){
++ ret = AVERROR_UNKNOWN;
++ goto clean;
++ }
++
++ rkmpp_get_mpp_format(&format, mpp_frame_get_fmt(mppframe));
++
++ if(check_vp8_planes(avctx, format.av)){
++ ret = AVERROR_UNKNOWN;
++ goto clean;
++ }
++ if(check_scaling(avctx, format.av)){
++ ret = AVERROR_UNKNOWN;
++ goto clean;
++ }
++
++ if(rk_context->postrga_format != AV_PIX_FMT_NONE || rk_context->postrga_width || rk_context->postrga_height){
++ MppFrame postmppframe = NULL;
++
++ postmppframe = create_mpp_frame(rk_context->postrga_width , rk_context->postrga_height, rk_context->postrga_format,
++ codec->buffer_group, NULL, NULL);
++
++ if(!postmppframe){
++ ret = AVERROR_UNKNOWN;
++ av_log(avctx, AV_LOG_ERROR, "Error creating post mpp frame\n");
++ goto clean;
++ }
++
++ ret = rga_convert_mpp_mpp(avctx, mppframe, postmppframe);
++ if(ret){
++ mpp_frame_deinit(&postmppframe);
++ av_log(avctx, AV_LOG_ERROR, "Error applying Post RGA\n");
++ goto clean;
++ }
++
++ if(!keepframe)
++ mpp_frame_deinit(&mppframe);
++ else
++ keepframe = 0;
++
++ mppframe = postmppframe;
+ }
++
++ mpp_frame_set_pts(mppframe, frame->pts);
+ }
-
-- 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;
-- }
-+ // when there are packets available to push to decoder
-+ if (packet->size) {
-+ ret = rkmpp_send_packet(avctx, packet);
-+ if (ret == AVERROR(EAGAIN)) {
-+ // decoder input buffer is full, no need to poll packets unless we receive a frame
-+ gettimeout = MPP_TIMEOUT_BLOCK;
-+ } else if (ret < 0) {
-+ // error handling
-+ av_log(avctx, AV_LOG_ERROR, "Failed to send data (code = %d)\n", ret);
-+ return 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;
--
-- // blocked waiting for decode result
-- if (decoder->sync)
-- return rkmpp_get_frame(avctx, frame, MPP_TIMEOUT_BLOCK);
-- }
-+ // successful decoder write
-+ av_packet_unref(packet);
- }
- }
+
-+ // always try to consume decoder because it is more likely to be full rather than the packet inputs
-+ // decoder is the bottleneck here
-+ ret = rkmpp_get_frame(avctx, frame, gettimeout);
-+ if (ret == AVERROR_EOF) {
-+ av_log(avctx, AV_LOG_DEBUG, "End of Stream.\n");
-+ return rkmpp_get_frame(avctx, frame, MPP_TIMEOUT_BLOCK);
++ ret = rkmpp_config_withframe(avctx, mppframe, frame);
++ if(ret){
++ ret = AVERROR_UNKNOWN;
++ goto clean;
+ }
+
++ // put the frame in encoder
++ ret = codec->mpi->encode_put_frame(codec->ctx, mppframe);
++
++ if (ret != MPP_OK) {
++ av_log(avctx, AV_LOG_DEBUG, "Encoder buffer full\n");
++ ret = AVERROR(EAGAIN);
++ } else
++ av_log(avctx, AV_LOG_DEBUG, "Wrote %ld bytes to encoder\n", mpp_frame_get_buf_size(mppframe));
++
++clean:
++ if(!keepframe)
++ mpp_frame_deinit(&mppframe);
+ return ret;
- }
-
- static void rkmpp_flush(AVCodecContext *avctx)
-@@ -759,11 +719,9 @@ static void rkmpp_flush(AVCodecContext *avctx)
-
- decoder->mpi->reset(decoder->ctx);
-
-- rkmpp_prepare_decoder(avctx);
--
- decoder->eos = 0;
-- decoder->draining = 0;
- decoder->softconvert = 0;
++}
+
- decoder->last_fps_time = decoder->frames = 0;
-
- av_packet_unref(&decoder->packet);
---
-2.40.0
-
-
-From f46c90307798f98cdf2b0d15d5b8905e4db83cf6 Mon Sep 17 00:00:00 2001
-From: boogie <boogiepop@gmx.com>
-Date: Fri, 28 Apr 2023 23:28:14 +0200
-Subject: [PATCH 20/24] rework on flow nv12 output support without rga hdr to
- sdr conversion support with rga3
-
----
- libavcodec/rkmppdec.c | 541 ++++++++++++++++++++++++------------------
- 1 file changed, 314 insertions(+), 227 deletions(-)
-
-diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
-index bd87d74e39..f71511d0d0 100644
---- a/libavcodec/rkmppdec.c
-+++ b/libavcodec/rkmppdec.c
-@@ -41,6 +41,8 @@
- #include "libavutil/imgutils.h"
- #include "libavutil/log.h"
- #include "libyuv/planar_functions.h"
-+#include "libyuv/scale_uv.h"
-+#include "libyuv/scale.h"
- #include "rga.h"
-
- // HACK: Older BSP kernel use NA12 for NV15.
-@@ -48,7 +50,7 @@
- #define DRM_FORMAT_NV15 fourcc_code('N', 'A', '1', '2')
- #endif
-
--#define FPS_UPDATE_INTERVAL 120
-+#define FPS_UPDATE_INTERVAL 60
-
- typedef struct {
- MppCtx ctx;
-@@ -56,7 +58,6 @@ typedef struct {
- MppBufferGroup frame_group;
-
- int8_t eos;
-- int8_t softconvert;
-
- AVPacket packet;
- AVBufferRef *frames_ref;
-@@ -67,7 +68,16 @@ typedef struct {
- uint64_t last_fps_time;
- uint64_t frames;
-
-+ uint32_t mpp_format;
-+ uint32_t rga_informat;
-+ uint32_t rga_outformat;
-+ uint32_t drm_format;
-+ uint32_t sw_format;
- int rga_fd;
-+ int8_t rgafbc;
-+ int8_t norga;
-+ int (*buffer_callback)(struct AVCodecContext *avctx, struct AVFrame *frame, MppFrame mppframe);
+
- } RKMPPDecoder;
-
- typedef struct {
-@@ -96,36 +106,6 @@ static MppCodingType rkmpp_get_codingtype(AVCodecContext *avctx)
- }
- }
-
--static uint32_t rkmpp_get_frameformat(MppFrameFormat mppformat)
--{
-- switch (mppformat & MPP_FRAME_FMT_MASK) {
-- case MPP_FMT_YUV420SP: return DRM_FORMAT_NV12;
-- case MPP_FMT_YUV420SP_10BIT: return DRM_FORMAT_NV15;
-- case MPP_FMT_YUV422SP: return DRM_FORMAT_NV16;
-- default: return 0;
-- }
--}
--
--static uint32_t rkmpp_get_avformat(MppFrameFormat mppformat)
--{
-- switch (mppformat & MPP_FRAME_FMT_MASK) {
-- 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;
-- }
--}
--
--static uint32_t rkmpp_get_rgaformat(MppFrameFormat mppformat)
--{
-- switch (mppformat & MPP_FRAME_FMT_MASK) {
-- 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;
-- }
--}
--
- static int rkmpp_close_decoder(AVCodecContext *avctx)
- {
- RKMPPDecodeContext *rk_context = avctx->priv_data;
-@@ -163,6 +143,141 @@ static void rkmpp_release_decoder(void *opaque, uint8_t *data)
- av_free(decoder);
- }
-
-+static void rkmpp_release_drmbuf(void *opaque, uint8_t *data)
-+{
-+ AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor *)data;
-+ AVBufferRef *framecontextref = (AVBufferRef *)opaque;
-+ RKMPPFrameContext *framecontext = (RKMPPFrameContext *)framecontextref->data;
++static int rkmpp_get_packet(AVCodecContext *avctx, AVPacket *packet, int timeout){
++ RKMPPCodecContext *rk_context = avctx->priv_data;
++ RKMPPCodec *codec = (RKMPPCodec *)rk_context->codec_ref->data;
++ MppPacket mpppacket = NULL;
++ MppMeta meta = NULL;
++ int ret, keyframe=0;
+
-+ mpp_frame_deinit(&framecontext->frame);
-+ av_buffer_unref(&framecontext->decoder_ref);
-+ av_buffer_unref(&framecontextref);
++ codec->mpi->control(codec->ctx, MPP_SET_OUTPUT_TIMEOUT, (MppParam)&timeout);
+
-+ av_free(desc);
++ ret = codec->mpi->encode_get_packet(codec->ctx, &mpppacket);
++
++ // rest of above code is never tested most likely broken
++ if (ret != MPP_OK && ret != MPP_ERR_TIMEOUT) {
++ av_log(avctx, AV_LOG_ERROR, "Failed to get packet (code = %d)\n", ret);
++ return AVERROR(EAGAIN);
++ }
++
++ if (!mpppacket) {
++ av_log(avctx, AV_LOG_DEBUG, "Timeout getting encoded packet.\n");
++ return AVERROR(EAGAIN);
++ }
++
++ // TO-DO: Handle EOS
++ if (mpp_packet_get_eos(mpppacket)) {
++ av_log(avctx, AV_LOG_DEBUG, "Received an EOS packet.\n");
++ ret = AVERROR_EOF;
++ goto fail;
++ }
++
++ av_log(avctx, AV_LOG_DEBUG, "Received a packet.\n");
++
++ packet->data = mpp_packet_get_data(mpppacket);
++ packet->size = mpp_packet_get_length(mpppacket);
++ packet->buf = av_buffer_create(packet->data, packet->size, rkmpp_release_packet_buf,
++ mpppacket, AV_BUFFER_FLAG_READONLY);
++ if (!packet->buf) {
++ ret = AVERROR(ENOMEM);
++ goto fail;
++ }
++
++ //FIXME: This is low-res and does not cover b-frames.
++ packet->time_base.num = avctx->time_base.num;
++ packet->time_base.den = avctx->time_base.den;
++ packet->pts = mpp_packet_get_pts(mpppacket);
++ packet->dts = mpp_packet_get_pts(mpppacket);
++ codec->frames++;
++
++ meta = mpp_packet_get_meta(mpppacket);
++ if (meta)
++ mpp_meta_get_s32(meta, KEY_OUTPUT_INTRA, &keyframe);
++ if (keyframe)
++ packet->flags |= AV_PKT_FLAG_KEY;
++
++ return 0;
++fail:
++ if (mpppacket)
++ mpp_packet_deinit(&mpppacket);
++ return ret;
++}
++
++
++int rkmpp_encode(AVCodecContext *avctx, AVPacket *packet, const AVFrame *frame, int *got_packet){
++ int ret;
++
++ ret = rkmpp_send_frame(avctx, (AVFrame *)frame);
++ if (ret)
++ return ret;
++
++ ret = rkmpp_get_packet(avctx, packet, MPP_TIMEOUT_BLOCK);
++ if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
++ *got_packet = 0;
++ } else if (ret) {
++ return ret;
++ } else {
++ *got_packet = 1;
++ }
++ return 0;
+}
+
-+static void rkmpp_release_buf(void *opaque, uint8_t *data)
++RKMPP_ENC(h264, AV_CODEC_ID_H264, vepu5)
++RKMPP_ENC(hevc, AV_CODEC_ID_HEVC, vepu5)
++RKMPP_ENC(vp8, AV_CODEC_ID_VP8, vepu1)
+diff --git a/libavcodec/rkplane.c b/libavcodec/rkplane.c
+new file mode 100644
+index 0000000000..e8063d8a6c
+--- /dev/null
++++ b/libavcodec/rkplane.c
+@@ -0,0 +1,676 @@
++/*
++ * RockChip MPP Plane Conversions
++ * Copyright (c) 2023 Huseyin BYIIK
++ *
++ * This file is part of FFmpeg.
++ *
++ * FFmpeg is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * FFmpeg is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++
++/*
++ * Mpp decoder/encoder outputs & inputs generally semi-planar pictures
++ * FFmpeg on the other hand uses planar pictures. Normally libavfilter has
++ * several filters to handle this conversion however it is not cpu affective
++ * This file handles several plane conversion with hardware accelerated RGA chip in
++ * rockchip socs, whenever there is a failure it falls back to libyuv which is SIMD
++ * optimized plane conversion library. Failure is expected time to time, because
++ * RGA is not always consistent in between kernel versions of rockchips downstream
++ *
++ * Normally both RGA and enhancements in libyuv should be a part or libavfilter, but
++ * currently this is easier. May be in future someone take this up and move to avfilter.
++ */
++
++#include <fcntl.h>
++#include "rkmpp.h"
++#include "rkplane.h"
++#include "libyuv/planar_functions.h"
++#include "libyuv/scale_uv.h"
++#include "libyuv/scale.h"
++
++
++#define AV_VSTRIDE(AVFRAME) (FFALIGN(AVFRAME->buf[0] && AVFRAME->buf[1] ? AVFRAME->buf[0]->size / AVFRAME->linesize[0] : (AVFRAME->data[1] - AVFRAME->data[0]) / AVFRAME->linesize[0], 16))
++
++static void rkmpp_release_mppframe(void *opaque, uint8_t *data)
+{
+ MppFrame mppframe = opaque;
+ mpp_frame_deinit(&mppframe);
+}
+
-+static int rkmpp_set_nv12_buf(AVCodecContext *avctx, AVFrame *frame, MppFrame mppframe)
++static void rkmpp_release_drm_desc(void *opaque, uint8_t *data)
+{
-+ RKMPPDecodeContext *rk_context = avctx->priv_data;
-+ RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data;
++ AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor *)opaque;
++ av_free(desc);
++}
++
++
++static int set_mppframe_to_avbuff(MppFrame mppframe, AVFrame * frame){
++ int i;
++
++ for(i=0; i<5; i++){
++ if(i > 3)
++ return -1;
++ else if(!frame->buf[i])
++ break;
++ }
++
++ frame->buf[i] = av_buffer_create(mppframe, mpp_frame_get_buf_size(mppframe),
++ rkmpp_release_mppframe, mppframe, AV_BUFFER_FLAG_READONLY);
++
++ return i;
++}
++
++static int set_drmdesc_to_avbuff(AVDRMFrameDescriptor *desc, AVFrame *frame){
++ int i;
++
++ for(i=0; i<5; i++){
++ if(i > 3)
++ return -1;
++ else if(!frame->buf[i])
++ break;
++ }
++
++ frame->buf[i] = av_buffer_create((unsigned char *) desc, sizeof(AVDRMFrameDescriptor),
++ rkmpp_release_drm_desc, desc, AV_BUFFER_FLAG_READONLY);
++
++ return i;
++}
++
++static int rga_scale(uint64_t src_fd, uint64_t src_y, uint16_t src_width, uint16_t src_height, uint16_t src_hstride, uint16_t src_vstride,
++ uint64_t dst_fd, uint64_t dst_y, uint16_t dst_width, uint16_t dst_height, uint16_t dst_hstride, uint16_t dst_vstride,
++ enum _Rga_SURF_FORMAT informat, enum _Rga_SURF_FORMAT outformat){
++ rga_info_t src = {0};
++ rga_info_t dst = {0};
++
++ if(dst_hstride < dst_width)
++ dst_width = FFALIGN(dst_width, RKMPP_STRIDE_ALIGN);
++ if(dst_vstride < dst_height)
++ dst_height = FFALIGN(dst_height, RKMPP_STRIDE_ALIGN);
++ if(src_hstride < src_width)
++ src_width = FFALIGN(src_width, RKMPP_STRIDE_ALIGN);
++ if(src_vstride < src_height)
++ src_height = FFALIGN(src_height, RKMPP_STRIDE_ALIGN);
++
++ src.fd = src_fd;
++ src.virAddr = (void *)src_y;
++ src.mmuFlag = 1;
++ src.format = informat;
++ rga_set_rect(&src.rect, 0, 0,
++ src_width, src_height, src_hstride, src_vstride, informat);
++
++ dst.fd = dst_fd;
++ dst.virAddr = (void *)dst_y;
++ dst.mmuFlag = 1;
++ dst.format = outformat;
++ rga_set_rect(&dst.rect, 0, 0,
++ dst_width, dst_height, dst_hstride, dst_vstride, outformat);
++
++ return c_RkRgaBlit(&src, &dst, NULL);
++}
++
++int rga_convert_mpp_mpp(AVCodecContext *avctx, MppFrame in_mppframe, MppFrame out_mppframe){
++ RKMPPCodecContext *rk_context = avctx->priv_data;
++ RKMPPCodec *codec = (RKMPPCodec *)rk_context->codec_ref->data;
++ rkformat informat, outformat;
++
++ if (!codec->norga){
++ if(!out_mppframe)
++ return -1;
++ rkmpp_get_mpp_format(&informat, mpp_frame_get_fmt(in_mppframe) & MPP_FRAME_FMT_MASK);
++ rkmpp_get_mpp_format(&outformat, mpp_frame_get_fmt(out_mppframe) & MPP_FRAME_FMT_MASK);
++ if(rga_scale(mpp_buffer_get_fd(mpp_frame_get_buffer(in_mppframe)), 0,
++ mpp_frame_get_width(in_mppframe), mpp_frame_get_height(in_mppframe),
++ mpp_frame_get_hor_stride(in_mppframe), mpp_frame_get_ver_stride(in_mppframe),
++ mpp_buffer_get_fd(mpp_frame_get_buffer(out_mppframe)), 0,
++ mpp_frame_get_width(out_mppframe), mpp_frame_get_height(out_mppframe),
++ mpp_frame_get_hor_stride(out_mppframe), mpp_frame_get_ver_stride(out_mppframe),
++ informat.rga,
++ outformat.rga)){
++ av_log(avctx, AV_LOG_WARNING, "RGA failed falling back to soft conversion\n");
++ codec->norga = 1; // fallback to soft conversion
++ return -1;
++ } else
++ return 0;
++ }
++
++ return -1;
++}
++
++static int rga_convert_mpp_av(AVCodecContext *avctx, MppFrame mppframe, AVFrame *frame,
++ enum AVPixelFormat informat, enum AVPixelFormat outformat){
++ RKMPPCodecContext *rk_context = avctx->priv_data;
++ RKMPPCodec *codec = (RKMPPCodec *)rk_context->codec_ref->data;
++ MppBuffer buffer = mpp_frame_get_buffer(mppframe);
++ rkformat inrkformat, outrkformat;
++
++ rkmpp_get_av_format(&inrkformat, informat);
++ rkmpp_get_av_format(&outrkformat, outformat);
++
++ if (!codec->norga){
++ if(rga_scale(mpp_buffer_get_fd(buffer), 0,
++ mpp_frame_get_width(mppframe), mpp_frame_get_height(mppframe),
++ mpp_frame_get_hor_stride(mppframe), mpp_frame_get_ver_stride(mppframe),
++ 0, (uint64_t) frame->data[0],
++ frame->width, frame->height,
++ frame->linesize[0], AV_VSTRIDE(frame),
++ inrkformat.rga, outrkformat.rga)){
++ av_log(avctx, AV_LOG_WARNING, "RGA failed falling back to soft conversion\n");
++ codec->norga = 1; // fallback to soft conversion
++ return -1;
++ }
++ } else
++ return -1;
+
++ return 0;
++}
++
++static int mpp_nv12_av_yuv420p_soft(MppFrame mppframe, AVFrame *frame){
++ // warning: mpp frame must not be released until displayed
+ MppBuffer buffer = mpp_frame_get_buffer(mppframe);
-+ int width = mpp_frame_get_width(mppframe);
+ int hstride = mpp_frame_get_hor_stride(mppframe);
+ int vstride = mpp_frame_get_ver_stride(mppframe);
++ int ret;
+
-+ frame->data[0] = mpp_buffer_get_ptr(buffer); // y
-+ frame->data[1] = frame->data[0] + hstride * vstride; // u + v
-+ frame->extended_data = frame->data;
++ frame->data[0] = mpp_buffer_get_ptr(buffer); // use existing y plane
++ frame->linesize[0] = hstride;
+
-+ frame->linesize[0] = hstride;
-+ frame->linesize[1] = hstride;
++ // convert only uv plane from semi-planar to planar
++ SplitUVPlane(frame->data[0] + hstride * vstride, hstride,
++ frame->data[1], frame->linesize[1], frame->data[2], frame->linesize[2],
++ (frame->width + 1) >> 1, (frame->height + 1) >> 1);
+
-+ frame->buf[0] = av_buffer_create(frame->data[0], mpp_buffer_get_size(buffer),
-+ rkmpp_release_buf, mppframe,
-+ AV_BUFFER_FLAG_READONLY);
-+ if (!frame->buf[0]) {
-+ return AVERROR(ENOMEM);
++ ret = set_mppframe_to_avbuff(mppframe, frame);
++ if(ret >= 0)
++ frame->data[RKMPP_MPPFRAME_BUFINDEX] = frame->buf[ret]->data;
++ return ret;
++}
++
++static int mpp_nv16_av_yuv420p_soft(MppFrame mppframe, AVFrame *frame){
++ // warning: mpp frame must not be released until displayed
++ MppBuffer buffer = mpp_frame_get_buffer(mppframe);
++ int hstride = mpp_frame_get_hor_stride(mppframe);
++ int vstride = mpp_frame_get_ver_stride(mppframe);
++ char *src = (char *)mpp_buffer_get_ptr(buffer) + hstride * vstride;
++ int ret;
++
++ // scale down uv plane by 2 and write it to y plane of avbuffer temporarily
++ UVScale(src, hstride, frame->width, frame->height,
++ frame->data[0], frame->linesize[0],
++ (frame->width + 1) >> 1, (frame->height + 1) >> 1, kFilterNone);
++
++ // convert uv plane from semi-planar to planar
++ SplitUVPlane(frame->data[0], frame->linesize[0],
++ frame->data[1], frame->linesize[1], frame->data[2], frame->linesize[2],
++ (frame->width + 1) >> 1, (frame->height + 1) >> 1);
++
++ // use existing y plane from mppbuffer
++ frame->data[0] = mpp_buffer_get_ptr(buffer);
++ frame->linesize[0] = hstride;
++
++ ret = set_mppframe_to_avbuff(mppframe, frame);
++ if(ret >= 0)
++ frame->data[RKMPP_MPPFRAME_BUFINDEX] = frame->buf[ret]->data;
++ return ret;
++}
++
++static int mpp_nv16_av_nv12_soft(MppFrame mppframe, AVFrame *frame){
++ // warning: mpp frame must not be released until displayed
++ MppBuffer buffer = mpp_frame_get_buffer(mppframe);
++ int hstride = mpp_frame_get_hor_stride(mppframe);
++ int vstride = mpp_frame_get_ver_stride(mppframe);
++ char *src = (char *)mpp_buffer_get_ptr(buffer) + hstride * vstride;
++ int ret;
++
++ // scale down uv plane by 2 and write it to uv plane of avbuffer
++ UVScale(src, hstride, frame->width, frame->height,
++ frame->data[1], frame->linesize[0],
++ (frame->width + 1) >> 1, (frame->height + 1) >> 1, kFilterNone);
++
++ // use existing y plane from mppbuffer
++ frame->data[0] = mpp_buffer_get_ptr(buffer);
++ frame->linesize[0] = hstride;
++
++ ret = set_mppframe_to_avbuff(mppframe, frame);
++ if(ret >= 0)
++ frame->data[RKMPP_MPPFRAME_BUFINDEX] = frame->buf[ret]->data;
++ return ret;
++}
++
++MppFrame create_mpp_frame(int width, int height, enum AVPixelFormat avformat, MppBufferGroup buffer_group, AVDRMFrameDescriptor *desc, AVFrame *frame){
++ MppFrame mppframe = NULL;
++ MppBuffer mppbuffer = NULL;
++ rkformat format;
++ int avmap[3][4]; //offset, dststride, width, height of max 3 planes
++ int size, ret, hstride, vstride;
++ int hstride_mult = 1;
++ int planes = 2;
++ int haspitch = 0;
++ int overshoot = 1024;
++
++ ret = mpp_frame_init(&mppframe);
++
++ if (ret) {
++ goto clean;
++ }
++
++ vstride = FFALIGN(height, RKMPP_STRIDE_ALIGN);
++
++ switch(avformat){
++ case AV_PIX_FMT_NV12:
++ planes = 2;
++ hstride = FFALIGN(width, RKMPP_STRIDE_ALIGN);
++ // y plane
++ avmap[0][0] = 0;
++ avmap[0][1] = hstride;
++ avmap[0][2] = width,
++ avmap[0][3] = height;
++ // uv plane
++ avmap[1][0] = hstride * vstride; // uv offset = y plane size
++ avmap[1][1] = hstride; // uv stride = hstride
++ avmap[1][2] = width; // uv width = width
++ avmap[1][3] = (height + 1)>> 1; // uv height = height / 2
++ size = avmap[1][0] + ((avmap[1][0] + 1) >> 1) + overshoot; // total size = y+uv planesize
++ break;
++ case AV_PIX_FMT_YUV420P:
++ planes = 3;
++ hstride = FFALIGN(width, RKMPP_STRIDE_ALIGN);
++ // y plane
++ avmap[0][0] = 0;
++ avmap[0][1] = hstride;
++ avmap[0][2] = width,
++ avmap[0][3] = height;
++ // u plane
++ avmap[1][0] = hstride * vstride; // u offset = y plane size
++ avmap[1][1] = (hstride + 1)>> 1; // u stride = hstride / 2
++ avmap[1][2] = (width + 1)>> 1; // u width = width / 2
++ avmap[1][3] = (height + 1)>> 1; // u height = height / 2
++ // v plane
++ avmap[2][0] = avmap[1][0] + ((avmap[1][0] + 1) >> 2); // v offset = y+u plane size
++ avmap[2][1] = avmap[1][1]; // v stride = hstride / 2
++ avmap[2][2] = avmap[1][2]; // v width = width / 2
++ avmap[2][3] = avmap[1][3]; // v height = height / 2
++ size = avmap[2][0] + ((avmap[1][0] + 1) >> 2) + overshoot; // total size = y+u+v planesize
++ break;
++ case AV_PIX_FMT_NV16:
++ planes = 2;
++ hstride = FFALIGN(width, RKMPP_STRIDE_ALIGN);
++ // y plane
++ avmap[0][0] = 0;
++ avmap[0][1] = hstride;
++ avmap[0][2] = width,
++ avmap[0][3] = height;
++ // uv plane
++ avmap[1][0] = hstride * vstride; // uv offset = y plane size
++ avmap[1][1] = hstride; // uv stride = hstride
++ avmap[1][2] = width; // uv width = width
++ avmap[1][3] = height; // uv height = height
++ size = avmap[1][0] * 2 + overshoot; // total size = y+uv planesize
++ break;
++ case AV_PIX_FMT_YUV422P:
++ planes = 3;
++ hstride = FFALIGN(width, RKMPP_STRIDE_ALIGN);
++ //y plane
++ avmap[0][0] = 0;
++ avmap[0][1] = hstride;
++ avmap[0][2] = width,
++ avmap[0][3] = height;
++ //u plane
++ avmap[1][0] = hstride * vstride; // u offset = y plane size
++ avmap[1][1] = (hstride + 1)>> 1; // u stride = hstride / 2
++ avmap[1][2] = width; // u width = width
++ avmap[1][3] = height; // u height = height
++ //v plane
++ avmap[2][0] = avmap[1][0] + ((avmap[1][0] + 1) >> 1); // v offset = y+u plane size
++ avmap[2][1] = avmap[1][1]; // v stride = hstride
++ avmap[2][2] = avmap[1][2]; // v width = width
++ avmap[2][3] = avmap[1][3]; // v height = height / 2
++ size = avmap[1][0] * 2 + overshoot; // total size = y+u+v planesize
++ break;
++ case AV_PIX_FMT_NV24:
++ planes = 2;
++ hstride = FFALIGN(width, RKMPP_STRIDE_ALIGN);
++ // y plane
++ avmap[0][0] = 0;
++ avmap[0][1] = hstride;
++ avmap[0][2] = width,
++ avmap[0][3] = height;
++ // uv plane
++ avmap[1][0] = hstride * vstride; // uv offset = y plane size
++ avmap[1][1] = hstride << 1; // uv stride = hstride * 2
++ avmap[1][2] = width << 1; // uv width = width * 2
++ avmap[1][3] = height; // uv height = height
++ size = avmap[1][0] * 3 + overshoot; // total size = y+u+v planesize
++ break;
++ case AV_PIX_FMT_YUV444P:
++ planes = 3;
++ hstride = FFALIGN(width, RKMPP_STRIDE_ALIGN);
++ //y plane
++ avmap[0][0] = 0;
++ avmap[0][1] = hstride;
++ avmap[0][2] = width,
++ avmap[0][3] = height;
++ //u plane
++ avmap[1][0] = hstride * vstride; // u offset = y plane size
++ avmap[1][1] = hstride; // u stride = hstride
++ avmap[1][2] = width; // u width = width
++ avmap[1][3] = height; // u height = height
++ //v plane
++ avmap[2][0] = avmap[1][0] * 2; // v offset = y+u plane size
++ avmap[2][1] = avmap[1][1]; // v stride = hstride
++ avmap[2][2] = avmap[1][2]; // v width = width
++ avmap[2][3] = avmap[1][3]; // v height = height
++ size = avmap[1][0] * 3 + overshoot; // total size = y+u+v planesize
++ break;
++ case AV_PIX_FMT_YUYV422:
++ case AV_PIX_FMT_UYVY422:
++ planes = 1;
++ haspitch = 1;
++ hstride_mult = 2;
++ hstride = FFALIGN(width * hstride_mult, RKMPP_STRIDE_ALIGN);
++ avmap[0][0] = 0;
++ avmap[0][1] = hstride;
++ avmap[0][2] = width << 1,
++ avmap[0][3] = height;
++ size = hstride * vstride;
++ break;
++ case AV_PIX_FMT_RGB24:
++ case AV_PIX_FMT_BGR24:
++ haspitch = 1;
++ hstride_mult = 3;
++ hstride = FFALIGN(width * hstride_mult, RKMPP_STRIDE_ALIGN);
++ avmap[0][0] = 0;
++ avmap[0][1] = hstride;
++ avmap[0][2] = width * 3,
++ avmap[0][3] = height;
++ size = hstride * vstride;
++ planes = 1;
++ break;
++ case AV_PIX_FMT_0RGB:
++ case AV_PIX_FMT_0BGR:
++ case AV_PIX_FMT_BGR0:
++ case AV_PIX_FMT_RGB0:
++ case AV_PIX_FMT_ARGB:
++ case AV_PIX_FMT_ABGR:
++ case AV_PIX_FMT_BGRA:
++ case AV_PIX_FMT_RGBA:
++ haspitch = 1;
++ hstride_mult = 4;
++ hstride = FFALIGN(width * hstride_mult, RKMPP_STRIDE_ALIGN);
++ avmap[0][0] = 0;
++ avmap[0][1] = hstride;
++ avmap[0][2] = width << 2,
++ avmap[0][3] = height;
++ size = hstride * vstride;
++ planes = 1;
++ break;
+ }
+
-+ return 0;
++ if(desc){
++ MppBufferInfo info;
++ AVDRMLayerDescriptor *layer = &desc->layers[0];
++ rkmpp_get_drm_format(&format, layer->format);
++
++ size = desc->objects[0].size;
++ if(haspitch)
++ hstride = layer->planes[0].pitch;
++ else
++ hstride = layer->planes[0].pitch * hstride_mult;
++
++ if(planes == 1)
++ vstride = size / hstride;
++ else
++ vstride = layer->planes[1].offset / hstride;
++
++ memset(&info, 0, sizeof(info));
++ info.type = MPP_BUFFER_TYPE_DRM;
++ info.size = size;
++ info.fd = desc->objects[0].fd;
++
++ ret = mpp_buffer_import(&mppbuffer, &info);
++ rkmpp_get_drm_format(&format, layer->format);
++ } else {
++ ret = mpp_buffer_get(buffer_group, &mppbuffer, size);
++ rkmpp_get_av_format(&format, avformat);
++ }
++
++ if (ret)
++ goto clean;
++
++ mpp_frame_set_width(mppframe, width);
++ mpp_frame_set_height(mppframe, height);
++ mpp_frame_set_fmt(mppframe, format.mpp);
++ mpp_frame_set_hor_stride(mppframe, hstride);
++ mpp_frame_set_ver_stride(mppframe, vstride);
++ mpp_frame_set_buffer(mppframe, mppbuffer);
++ mpp_frame_set_buf_size(mppframe, size);
++ mpp_buffer_put(mppbuffer);
++
++ if(frame){
++ for(int i = 0; i < planes; i++){
++ CopyPlane(frame->data[i], frame->linesize[i],
++ (char *)mpp_buffer_get_ptr(mppbuffer) + avmap[i][0], avmap[i][1], avmap[i][2], avmap[i][3]);
++ }
++ }
++
++ return mppframe;
++
++clean:
++ if(mppbuffer)
++ mpp_buffer_put(mppbuffer);
++ if(mppframe)
++ mpp_frame_deinit(&mppframe);
++ return mppframe;
+}
++//for decoder
++int mpp_nv15_av_yuv420p(AVCodecContext *avctx, MppFrame mppframe, AVFrame *frame){
++ // rga1 which supports yuv420P output does not support nv15 input
++ // therefore this first converts NV15->NV12 with rga2 than NV12 -> yuv420P with libyuv
++ RKMPPCodecContext *rk_context = avctx->priv_data;
++ RKMPPCodec *codec = (RKMPPCodec *)rk_context->codec_ref->data;
++ MppFrame nv12frame = create_mpp_frame(mpp_frame_get_width(mppframe), mpp_frame_get_height(mppframe),
++ AV_PIX_FMT_NV12, codec->buffer_group, NULL, NULL);
++ int ret = rga_convert_mpp_mpp(avctx, mppframe, nv12frame);
++
++ rkmpp_release_mppframe(mppframe, NULL);
++
++ if(!ret){
++ // if there is no avbuffer for frame, claim it
++ if(!frame->buf[0])
++ ff_get_buffer(avctx, frame, 0);
++ // due to hdr being mostly 8k, rga1 the only rga support yuv420p output
++ // wont convert this, therefore always use soft conv.
++ ret = mpp_nv12_av_yuv420p_soft(nv12frame, frame);
++ } else {
++ if(nv12frame)
++ rkmpp_release_mppframe(nv12frame, NULL);
++ av_log(avctx, AV_LOG_ERROR, "RGA failed to convert NV15 -> YUV420P. No Soft Conversion Possible\n");
++ }
+
-+static int rkmpp_rga_convert_buf(AVCodecContext *avctx, AVFrame *frame, MppFrame mppframe)
-+{
-+ RKMPPDecodeContext *rk_context = avctx->priv_data;
-+ RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data;
++ return ret;
++}
+
++//for decoder
++int mpp_nv12_av_nv12(AVCodecContext *avctx, MppFrame mppframe, AVFrame *frame){
+ MppBuffer buffer = mpp_frame_get_buffer(mppframe);
-+ char *src = mpp_buffer_get_ptr(buffer);
-+ 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 ret;
+
-+ ret = ff_get_buffer(avctx, frame, 0);
-+ if (ret < 0)
-+ return ret;
++ frame->data[0] = mpp_buffer_get_ptr(buffer); // y
++ frame->data[1] = frame->data[0] + hstride * vstride; // u + v
++ frame->extended_data = frame->data;
+
-+ if (!decoder->norga && decoder->rga_fd >= 0){
-+ struct rga_req req = {
-+ .src = {
-+ .yrgb_addr = mpp_buffer_get_fd(buffer),
-+ .v_addr = hstride * vstride,
-+ .format = decoder->rga_informat,
-+ .act_w = width,
-+ .act_h = height,
-+ .vir_w = hstride,
-+ .vir_h = vstride,
-+ .rd_mode = RGA_RASTER_MODE,
-+ },
-+ .dst = {
-+ .uv_addr = (uintptr_t) frame->data[0],
-+ .v_addr = (uintptr_t) frame->data[1],
-+ .format = decoder->rga_outformat,
-+ .act_w = width,
-+ .act_h = height,
-+ .vir_w = frame->linesize[0],
-+ .vir_h = (frame->data[1] - frame->data[0]) / frame->linesize[0],
-+ .rd_mode = RGA_RASTER_MODE,
-+ },
-+ .mmu_info = {
-+ .mmu_en = 1,
-+ .mmu_flag = 0x80000521,
-+ },
-+ };
++ frame->linesize[0] = hstride;
++ frame->linesize[1] = hstride;
+
-+ ret = ioctl(decoder->rga_fd, RGA_BLIT_SYNC, &req);
-+ if (ret < 0){
-+ decoder->norga = 1;
-+ av_log(avctx, AV_LOG_WARNING, "RGA failed with code %d, falling back to soft conversion\n", ret);
-+ } else {
-+ rkmpp_release_buf(mppframe, NULL);
-+ return 0;
-+ }
++ ret = set_mppframe_to_avbuff(mppframe, frame);
++ if(ret >= 0)
++ frame->data[RKMPP_MPPFRAME_BUFINDEX] = frame->buf[ret]->data;
++ return ret;
++}
++//for decoder
++int mpp_nv15_av_nv12(AVCodecContext *avctx, MppFrame mppframe, AVFrame *frame){
++ RKMPPCodecContext *rk_context = avctx->priv_data;
++ RKMPPCodec *codec = (RKMPPCodec *)rk_context->codec_ref->data;
++ MppFrame nv12frame = create_mpp_frame(mpp_frame_get_width(mppframe), mpp_frame_get_height(mppframe),
++ AV_PIX_FMT_NV12, codec->buffer_group, NULL, NULL);
++ int ret = rga_convert_mpp_mpp(avctx, mppframe, nv12frame);
++
++ rkmpp_release_mppframe(mppframe, NULL);
++
++ if(!ret){
++ ret = mpp_nv12_av_nv12(avctx, nv12frame, frame);
++ } else {
++ if(nv12frame)
++ rkmpp_release_mppframe(nv12frame, NULL);
++ av_log(avctx, AV_LOG_ERROR, "RGA failed to convert NV15 -> NV12. No Soft Conversion Possible\n");
+ }
+
-+ if ((decoder->norga || decoder->rga_fd < 0) && decoder->rga_outformat == RGA_FORMAT_YCbCr_420_P){
-+ //data[0] points to buf[1] where the mppbuffer is referenced for y plane
-+ //so that we can still use y plane without extra copies
-+ //data[1,2] points to allready allocated AVBuffer Pool (buf[0]), we will convert to
-+ //that buffer only u+v planes, which is half the size operation
-+ frame->data[0] = mpp_buffer_get_ptr(buffer);
-+ frame->buf[1] = av_buffer_create(frame->data[0], mpp_buffer_get_size(buffer),
-+ rkmpp_release_buf, mppframe,
-+ AV_BUFFER_FLAG_READONLY);
-+ if (!frame->buf[1]) {
-+ return AVERROR(ENOMEM);
-+ }
-+ frame->linesize[0] = hstride;
-+
-+ src += hstride * vstride;
-+ if(decoder->rga_informat == RGA_FORMAT_YCbCr_422_SP){
-+ /* In case the input format has 4:2:2 UV planes, it will have double the size of 4:2:0 UV Planes
-+ * Therefore we scale them to the half the size to the unused FFbuffer's Y Plane (We are using MPP 's Y)
-+ * Then we convert to Planar in the next step. Normally it should be possible to this in 1 step
-+ * But i can not find a way to do it in 1 step using libyuv. But thats fine enough
-+ */
-+ UVScale(src, hstride, frame->width, frame->height,
-+ frame->buf[0]->data, hstride,
-+ (frame->width + 1) >> 1, (frame->height + 1) >> 1, kFilterNone);
-+ src = frame->buf[0]->data;
++ return ret;
++}
++
++int convert_mpp_to_av(AVCodecContext *avctx, MppFrame mppframe, AVFrame *frame,
++ enum AVPixelFormat informat, enum AVPixelFormat outformat){
++ int ret = 0;
++
++ if(!frame->buf[0])
++ ff_get_buffer(avctx, frame, 0);
++
++ if(rga_convert_mpp_av(avctx, mppframe, frame, informat, outformat)){
++ if (informat == AV_PIX_FMT_NV16 && outformat == AV_PIX_FMT_NV12)
++ ret = mpp_nv16_av_nv12_soft(mppframe, frame);
++ else if (informat == AV_PIX_FMT_NV16 && outformat == AV_PIX_FMT_YUV420P)
++ ret = mpp_nv16_av_yuv420p_soft(mppframe, frame);
++ else if (informat == AV_PIX_FMT_NV12 && outformat == AV_PIX_FMT_YUV420P)
++ ret = mpp_nv12_av_yuv420p_soft(mppframe, frame);
++ else {
++ ret = -1;
++ av_log(avctx, AV_LOG_ERROR, "No software conversion for %s -> %s available\n",
++ av_get_pix_fmt_name(informat), av_get_pix_fmt_name(outformat));
+ }
-+ SplitUVPlane(src, hstride, frame->data[1], frame->linesize[1], frame->data[2], frame->linesize[2],
-+ (frame->width + 1) >> 1, (frame->height + 1) >> 1);
-+ return 0;
++ } else{
++ ret = set_mppframe_to_avbuff(mppframe, frame);
++ if(ret >= 0)
++ frame->data[RKMPP_MPPFRAME_BUFINDEX] = frame->buf[ret]->data;
+ }
+
-+ return AVERROR_UNKNOWN;
++ if (ret < 0)
++ rkmpp_release_mppframe(mppframe, NULL);
++ return ret;
+}
+
- static int rkmpp_init_decoder(AVCodecContext *avctx)
- {
- RKMPPDecodeContext *rk_context = avctx->priv_data;
-@@ -234,9 +349,14 @@ static int rkmpp_init_decoder(AVCodecContext *avctx)
- goto fail;
- }
-
-- decoder->rga_fd = open("/dev/rga", O_RDWR);
-- if (decoder->rga_fd < 0) {
-- av_log(avctx, AV_LOG_WARNING, "Failed to open RGA, Falling back to libyuv\n");
-+ env = getenv("FFMPEG_RKMPP_NORGA");
-+ if (env != NULL)
-+ decoder->rga_fd = -1;
-+ else {
-+ decoder->rga_fd = open("/dev/rga", O_RDWR);
-+ if (decoder->rga_fd < 0) {
-+ av_log(avctx, AV_LOG_WARNING, "Failed to open RGA, Falling back to libyuv\n");
++MppFrame import_drm_to_mpp(AVCodecContext *avctx, AVFrame *frame){
++ RKMPPCodecContext *rk_context = avctx->priv_data;
++ RKMPPCodec *codec = (RKMPPCodec *)rk_context->codec_ref->data;
++ MppFrame mppframe = NULL;
++ AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor*) frame->data[0];
++ AVDRMLayerDescriptor *layer = &desc->layers[0];
++ rkformat format;
++ char drmname[4];
++ DRMFORMATNAME(drmname, layer->format)
++
++ if(rkmpp_get_drm_format(&format, layer->format)){
++ av_log(avctx, AV_LOG_ERROR, "Unsupported DRM Format %s\n", drmname);
++ return NULL;
++ }
++
++ if(format.drm == DRM_FORMAT_NV15){
++ // encoder does not support 10bit frames, we down scale them to 8bit
++ MppFrame nv15frame = create_mpp_frame(frame->width, frame->height, AV_PIX_FMT_NONE, NULL, desc, NULL);
++ if(nv15frame){
++ mppframe = create_mpp_frame(frame->width, frame->height, AV_PIX_FMT_NV12, codec->buffer_group, NULL, NULL);
++ if(mppframe && rga_convert_mpp_mpp(avctx, nv15frame, mppframe))
++ rkmpp_release_mppframe(mppframe, NULL);
++ rkmpp_release_mppframe(nv15frame, NULL);
+ }
- }
-
- ret = decoder->mpi->control(decoder->ctx, MPP_DEC_SET_EXT_BUF_GROUP, decoder->frame_group);
-@@ -272,109 +392,6 @@ fail:
- return ret;
- }
-
--static void rkmpp_release_frame(void *opaque, uint8_t *data)
--{
-- AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor *)data;
-- AVBufferRef *framecontextref = (AVBufferRef *)opaque;
-- RKMPPFrameContext *framecontext = (RKMPPFrameContext *)framecontextref->data;
--
-- mpp_frame_deinit(&framecontext->frame);
-- av_buffer_unref(&framecontext->decoder_ref);
-- av_buffer_unref(&framecontextref);
--
-- av_free(desc);
--}
--
--static void rkmpp_release_buffer(void *opaque, uint8_t *data)
--{
-- MppFrame mppframe = opaque;
-- mpp_frame_deinit(&mppframe);
--}
--
--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];
-- enum rga_surf_format rgaformat = 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);
-- 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 ret;
--
-- int dst_height = (dst_u - dst_y) / y_pitch;
--
-- if (decoder->softconvert || decoder->rga_fd < 0)
-- goto softconvert;
--
-- struct rga_req req = {
-- .src = {
-- .yrgb_addr = mpp_buffer_get_fd(buffer),
-- .v_addr = hstride * vstride,
-- .format = rgaformat,
-- .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,
-- },
-- };
--
-- ret = ioctl(decoder->rga_fd, RGA_BLIT_SYNC, &req);
-- if (ret < 0){
-- decoder->softconvert = 1;
-- av_log(avctx, AV_LOG_WARNING, "RGA failed with code %d, falling back to soft conversion of uv planes\n", ret);
-- goto softconvert;
-- }
--
-- rkmpp_release_buffer(mppframe, NULL);
-- return 0;
--
--softconvert:
-- //data[0] points to buf[1] where the mppbuffer is referenced for y plane
-- //so that we can still use y plane without extra copies
-- //data[1,2] points to allready allocated AVBuffer Pool (buf[0]), we will convert to
-- //that buffer only u+v planes, which is half the size operation
-- frame->data[0] = mpp_buffer_get_ptr(buffer);
-- frame->buf[1] = av_buffer_create(frame->data[0], mpp_buffer_get_size(buffer),
-- rkmpp_release_buffer, mppframe,
-- AV_BUFFER_FLAG_READONLY);
-- if (!frame->buf[1]) {
-- return AVERROR(ENOMEM);
-- }
-- frame->linesize[0] = hstride;
--
-- src += hstride * vstride;
--
-- SplitUVPlane(src, hstride, dst_u, u_pitch, dst_v, v_pitch,
-- (frame->width + 1) >> 1, (frame->height + 1) >> 1);
-- return 0;
--}
--
- static void rkmpp_update_fps(AVCodecContext *avctx)
- {
- RKMPPDecodeContext *rk_context = avctx->priv_data;
-@@ -405,20 +422,151 @@ static void rkmpp_update_fps(AVCodecContext *avctx)
- fps, decoder->frames);
- }
-
--static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
-+static int rkmpp_set_drm_buf(AVCodecContext *avctx, AVFrame *frame, MppFrame mppframe)
- {
- RKMPPDecodeContext *rk_context = avctx->priv_data;
- RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data;
- RKMPPFrameContext *framecontext = NULL;
- AVBufferRef *framecontextref = NULL;
++ } else {
++ mppframe = create_mpp_frame(frame->width, frame->height, format.av, NULL, desc, NULL);
++ }
++
++ return mppframe;
++}
++
++int import_mpp_to_drm(AVCodecContext *avctx, MppFrame mppframe, AVFrame *frame)
++{
++ // mppframe & desc is cleared when AVFrame is released
++ RKMPPCodecContext *rk_context = avctx->priv_data;
++ RKMPPCodec *codec = (RKMPPCodec *)rk_context->codec_ref->data;
+ AVDRMFrameDescriptor *desc = NULL;
+ AVDRMLayerDescriptor *layer = NULL;
++ rkformat format;
+ MppBuffer buffer = mpp_frame_get_buffer(mppframe);
- int ret;
++ int hstride = mpp_frame_get_hor_stride(mppframe);
++ int vstride = mpp_frame_get_ver_stride(mppframe);
++ int ret;
++
++ rkmpp_get_mpp_format(&format, mpp_frame_get_fmt(mppframe) & MPP_FRAME_FMT_MASK);
++
++ if(set_mppframe_to_avbuff(mppframe, frame) < 0){
++ ret = AVERROR(ENOMEM);
++ goto error;
++ }
+
+ desc = av_mallocz(sizeof(AVDRMFrameDescriptor));
-+ if (!desc) {
++ if (!desc || set_drmdesc_to_avbuff(desc, frame) < 0) {
+ ret = AVERROR(ENOMEM);
-+ goto fail;
++ goto error;
+ }
+
+ desc->nb_objects = 1;
@@ -3481,566 +3638,617 @@ index bd87d74e39..f71511d0d0 100644
+
+ desc->nb_layers = 1;
+ layer = &desc->layers[0];
-+ layer->format = decoder->drm_format;
++ layer->format = format.drm;
+ 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[0].pitch = hstride;
+
+ 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;
-+ }
-+
-+ // 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;
++ layer->planes[1].offset = hstride * vstride;
++ layer->planes[1].pitch = hstride;
+
+ frame->data[0] = (uint8_t *)desc;
-+ frame->buf[0] = av_buffer_create((uint8_t *)desc, sizeof(*desc), rkmpp_release_drmbuf,
-+ framecontextref, AV_BUFFER_FLAG_READONLY);
-+
-+ if (!frame->buf[0]) {
-+ ret = AVERROR(ENOMEM);
-+ goto fail;
-+ }
+
-+ frame->hw_frames_ctx = av_buffer_ref(decoder->frames_ref);
++ frame->hw_frames_ctx = av_buffer_ref(codec->hwframes_ref);
+ if (!frame->hw_frames_ctx) {
+ ret = AVERROR(ENOMEM);
-+ goto fail;
++ goto error;
+ }
+
+ return 0;
+
-+fail:
-+ if (framecontext)
-+ av_buffer_unref(&framecontext->decoder_ref);
-+
-+ if (framecontextref)
-+ av_buffer_unref(&framecontextref);
-+
++error:
++ av_log(avctx, AV_LOG_ERROR, "Memory Error during importing mpp frame to drmprime\n");
++ if (mppframe)
++ rkmpp_release_mppframe(mppframe, NULL);
+ if (desc)
-+ av_free(desc);
++ rkmpp_release_drm_desc(desc, NULL);
+
+ return ret;
+}
+
-+static int set_buffer_callback(RKMPPDecoder *decoder, AVCodecContext *avctx){
-+ if (avctx->pix_fmt == AV_PIX_FMT_DRM_PRIME){
-+ decoder->buffer_callback = rkmpp_set_drm_buf;
-+ switch(decoder->mpp_format){
-+ case MPP_FMT_YUV420SP_10BIT:
-+ decoder->drm_format = DRM_FORMAT_NV15;
-+ decoder->sw_format = AV_PIX_FMT_NONE;
-+ av_log(avctx, AV_LOG_INFO, "Decoder is set to use DRMPrime with NV15.\n");
-+ return 0;
-+ case MPP_FMT_YUV420SP:
-+ decoder->drm_format = DRM_FORMAT_NV12;
-+ decoder->sw_format = AV_PIX_FMT_NV12;
-+ av_log(avctx, AV_LOG_INFO, "Decoder is set to use DRMPrime with NV12.\n");
-+ return 0;
-+ case MPP_FMT_YUV422SP:
-+ decoder->drm_format = DRM_FORMAT_NV16;
-+ decoder->sw_format = AV_PIX_FMT_NV16;
-+ av_log(avctx, AV_LOG_INFO, "Decoder is set to use DRMPrime with NV16.\n");
-+ return 0;
-+ }
-+ } else if(avctx->pix_fmt == AV_PIX_FMT_NV12){
-+ decoder->rga_outformat = RGA_FORMAT_YCbCr_420_SP;
-+ switch(decoder->mpp_format){
-+ case MPP_FMT_YUV420SP_10BIT:
-+ decoder->rga_informat = RGA_FORMAT_YCbCr_420_SP_10B;
-+ decoder->buffer_callback = rkmpp_rga_convert_buf;
-+ av_log(avctx, AV_LOG_INFO, "Decoder is set to use AVBuffer with NV15->NV12 conversion through RGA3.\n");
-+ return 0;
-+ case MPP_FMT_YUV420SP:
-+ decoder->buffer_callback = rkmpp_set_nv12_buf;
-+ av_log(avctx, AV_LOG_INFO, "Decoder is set to use MppBuffer with NV12.\n");
-+ return 0;
-+ case MPP_FMT_YUV422SP:
-+ decoder->rga_informat = RGA_FORMAT_YCbCr_422_SP;
-+ decoder->buffer_callback = rkmpp_rga_convert_buf;
-+ av_log(avctx, AV_LOG_INFO, "Decoder is set to use AVBuffer with NV16->NV12 conversion through RGA3.\n");
-+ return 0;
-+ }
-+ } else if (avctx->pix_fmt == AV_PIX_FMT_YUV420P){
-+ decoder->rga_outformat = RGA_FORMAT_YCbCr_420_P;
-+ switch(decoder->mpp_format){
-+ case MPP_FMT_YUV420SP:
-+ decoder->rga_informat = RGA_FORMAT_YCbCr_420_SP;
-+ break;
-+ case MPP_FMT_YUV422SP:
-+ decoder->rga_informat = RGA_FORMAT_YCbCr_422_SP;
-+ break;
-+ }
-+ if(decoder->rga_informat){
-+ decoder->buffer_callback = rkmpp_rga_convert_buf;
-+ if(decoder->norga || decoder->rga_fd < 0)
-+ av_log(avctx, AV_LOG_INFO, "Decoder is set to use AVBuffer with NV12->YUV420P conversion through libyuv.\n");
-+ else
-+ av_log(avctx, AV_LOG_INFO, "Decoder is set to use AVBuffer with NV12->YUV420P conversion through RGA2.\n");
-+ return 0;
-+ }
++MppFrame get_mppframe_from_av(AVFrame *frame){
++ if(frame->data[RKMPP_MPPFRAME_BUFINDEX]){
++ rkmpp_frame_type * mppframe = (rkmpp_frame_type *) frame->data[RKMPP_MPPFRAME_BUFINDEX];
++ if(mppframe->name && !strcmp(mppframe->name, "mpp_frame") &&
++ mpp_frame_get_fmt(frame->data[RKMPP_MPPFRAME_BUFINDEX]) != MPP_FMT_YUV420SP_10BIT)
++ return frame->data[RKMPP_MPPFRAME_BUFINDEX];
+ }
-+ av_log(avctx, AV_LOG_ERROR, "Unknown MPP format:%d and AVFormat:%d.\n", decoder->mpp_format, avctx->pix_fmt);
-+ return AVERROR_UNKNOWN;
++ return NULL;
+}
-+
-+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;
- MppFrame mppframe = NULL;
- MppBuffer buffer = NULL;
-- AVDRMFrameDescriptor *desc = NULL;
-- AVDRMLayerDescriptor *layer = NULL;
-- int mode;
-- MppFrameFormat mppformat;
-- uint32_t drmformat;
-+ int ret, mode;
-
- // should not provide any frame after EOS
- if (decoder->eos)
-@@ -458,6 +606,7 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
-
- if (mpp_frame_get_info_change(mppframe)) {
- AVHWFramesContext *hwframes;
-+ decoder->mpp_format = mpp_frame_get_fmt(mppframe) & MPP_FRAME_FMT_MASK;
-
- 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),
-@@ -474,6 +623,10 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
- decoder->mpi->control(decoder->ctx, MPP_DEC_SET_FRAME_INFO, (MppParam) mppframe);
- decoder->mpi->control(decoder->ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL);
-
-+ ret = set_buffer_callback(decoder, avctx);
-+ if (ret)
-+ goto fail;
-+
- av_buffer_unref(&decoder->frames_ref);
-
- decoder->frames_ref = av_hwframe_ctx_alloc(decoder->device_ref);
-@@ -482,11 +635,9 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
- goto fail;
- }
-
-- mppformat = mpp_frame_get_fmt(mppframe);
--
- hwframes = (AVHWFramesContext*)decoder->frames_ref->data;
- hwframes->format = AV_PIX_FMT_DRM_PRIME;
-- hwframes->sw_format = rkmpp_get_avformat(mppformat);
-+ hwframes->sw_format = decoder->sw_format;
- hwframes->width = avctx->width;
- hwframes->height = avctx->height;
- ret = av_hwframe_ctx_init(decoder->frames_ref);
-@@ -509,10 +660,17 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
-
- rkmpp_update_fps(avctx);
-
-- if (avctx->pix_fmt != AV_PIX_FMT_DRM_PRIME) {
-- ret = ff_get_buffer(avctx, frame, 0);
-- if (ret < 0)
-- goto fail;
-+ if(!decoder->buffer_callback){
-+ ret = AVERROR_UNKNOWN;
-+ av_log(avctx, AV_LOG_ERROR, "Decoder has no valid buffer_callback\n");
-+ goto fail;
-+ }
-+
-+ ret = decoder->buffer_callback(avctx, frame, mppframe);
-+
-+ if(ret){
-+ av_log(avctx, AV_LOG_ERROR, "Failed set frame buffer (code = %d)\n", ret);
-+ goto fail;
- }
-
- // setup general frame fields
-@@ -530,79 +688,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) {
-- return rkmpp_convert_frame(avctx, frame, mppframe, buffer);
-- }
--
-- mppformat = mpp_frame_get_fmt(mppframe);
-- drmformat = rkmpp_get_frameformat(mppformat);
--
-- 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;
-- }
--
-- // 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;
-- }
--
-- 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)
- mpp_frame_deinit(&mppframe);
--
-- if (framecontext)
-- av_buffer_unref(&framecontext->decoder_ref);
--
-- if (framecontextref)
-- av_buffer_unref(&framecontextref);
--
-- if (desc)
-- av_free(desc);
--
- return ret;
- }
-
-@@ -720,19 +810,13 @@ static void rkmpp_flush(AVCodecContext *avctx)
- decoder->mpi->reset(decoder->ctx);
-
- decoder->eos = 0;
-- decoder->softconvert = 0;
-+ decoder->norga = 0;
-
- decoder->last_fps_time = decoder->frames = 0;
-
- av_packet_unref(&decoder->packet);
- }
-
--static const AVCodecHWConfigInternal *const rkmpp_hw_configs[] = {
-- HW_CONFIG_INTERNAL(DRM_PRIME),
-- HW_CONFIG_INTERNAL(YUV420P),
-- NULL
--};
--
- #define RKMPP_DEC_CLASS(NAME) \
- static const AVClass rkmpp_##NAME##_dec_class = { \
- .class_name = "rkmpp_" #NAME "_dec", \
-@@ -754,9 +838,12 @@ 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_NV12, \
- AV_PIX_FMT_YUV420P, \
- AV_PIX_FMT_NONE}, \
-- .hw_configs = rkmpp_hw_configs, \
-+ .hw_configs = (const AVCodecHWConfigInternal *const []) { HW_CONFIG_INTERNAL(DRM_PRIME), \
-+ HW_CONFIG_INTERNAL(NV12), \
-+ NULL}, \
- .bsfs = BSFS, \
- .p.wrapper_name = "rkmpp", \
- .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | FF_CODEC_CAP_CONTIGUOUS_BUFFERS \
+diff --git a/libavcodec/rkplane.h b/libavcodec/rkplane.h
+new file mode 100644
+index 0000000000..f52d29228b
+--- /dev/null
++++ b/libavcodec/rkplane.h
+@@ -0,0 +1,17 @@
++#include <rockchip/rk_mpi.h>
++#include "avcodec.h"
++
++typedef struct {
++ char *name;
++} rkmpp_frame_type;
++
++int rga_convert_mpp_mpp(AVCodecContext *avctx, MppFrame in_mppframe, MppFrame out_mppframe);
++int mpp_nv15_av_yuv420p(AVCodecContext *avctx, MppFrame mppframe, AVFrame *frame);
++int mpp_nv15_av_nv12(AVCodecContext *avctx, MppFrame mppframe, AVFrame *frame);
++int mpp_nv12_av_nv12(AVCodecContext *avctx, MppFrame mppframe, AVFrame *frame);
++int convert_mpp_to_av(AVCodecContext *avctx, MppFrame mppframe, AVFrame *frame,
++ enum AVPixelFormat informat, enum AVPixelFormat outformat);
++MppFrame create_mpp_frame(int width, int height, enum AVPixelFormat avformat, MppBufferGroup buffer_group, AVDRMFrameDescriptor *desc, AVFrame *frame);
++MppFrame import_drm_to_mpp(AVCodecContext *avctx, AVFrame *frame);
++int import_mpp_to_drm(AVCodecContext *avctx, MppFrame mppframe, AVFrame *frame);
++MppFrame get_mppframe_from_av(AVFrame *frame);
--
-2.40.0
+2.41.0
-From 3493b0fb8f50a57ce94c3544dfe899afe7800822 Mon Sep 17 00:00:00 2001
+From 15e6c6593aa50e89c62274399055da5325aa2887 Mon Sep 17 00:00:00 2001
From: boogie <boogiepop@gmx.com>
-Date: Sun, 30 Apr 2023 16:52:57 +0200
-Subject: [PATCH 21/24] more verbose stats with latency and MACD FPS
+Date: Mon, 24 Jul 2023 19:27:37 +0200
+Subject: [PATCH 10/13] lavu/hwcontext_drm: Add internal frame allocation
---
- libavcodec/rkmppdec.c | 56 ++++++++++++++++++++++++-------------------
- 1 file changed, 31 insertions(+), 25 deletions(-)
+ libavutil/hwcontext_drm.c | 322 +++++++++++++++++++++++++++++++++++++-
+ libavutil/hwcontext_drm.h | 14 +-
+ 2 files changed, 328 insertions(+), 8 deletions(-)
-diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
-index f71511d0d0..ecee5dd338 100644
---- a/libavcodec/rkmppdec.c
-+++ b/libavcodec/rkmppdec.c
-@@ -50,7 +50,7 @@
- #define DRM_FORMAT_NV15 fourcc_code('N', 'A', '1', '2')
- #endif
+diff --git a/libavutil/hwcontext_drm.c b/libavutil/hwcontext_drm.c
+index 7a9fdbd263..2d1962c9c0 100644
+--- a/libavutil/hwcontext_drm.c
++++ b/libavutil/hwcontext_drm.c
+@@ -18,6 +18,7 @@
--#define FPS_UPDATE_INTERVAL 60
-+#define FPS_FRAME_MACD 30
+ #include "config.h"
- typedef struct {
- MppCtx ctx;
-@@ -65,8 +65,9 @@ typedef struct {
++#define _GNU_SOURCE
+ #include <fcntl.h>
+ #include <sys/mman.h>
+ #include <unistd.h>
+@@ -30,7 +31,7 @@
+ #include <sys/ioctl.h>
+ #endif
- char print_fps;
+-#include <drm.h>
++#include <drm_fourcc.h>
+ #include <xf86drm.h>
-- uint64_t last_fps_time;
-+ uint64_t last_frame_time;
- uint64_t frames;
-+ uint64_t latencies[FPS_FRAME_MACD];
+ #include "avassert.h"
+@@ -39,6 +40,103 @@
+ #include "hwcontext_internal.h"
+ #include "imgutils.h"
- uint32_t mpp_format;
- uint32_t rga_informat;
-@@ -392,34 +393,37 @@ fail:
- return ret;
- }
++/**
++ * Copy from libdrm_macros.h while is not exposed by libdrm,
++ * be replaced by #include "libdrm_macros.h" someday.
++ */
++
++/**
++ * Static (compile-time) assertion.
++ * Basically, use COND to dimension an array. If COND is false/zero the
++ * array size will be -1 and we'll get a compilation error.
++ */
++#define STATIC_ASSERT(COND) \
++ do { \
++ (void) sizeof(char [1 - 2*!(COND)]); \
++ } while (0)
++
++#if defined(ANDROID) && !defined(__LP64__)
++#include <errno.h> /* for EINVAL */
++
++extern void *__mmap2(void *, size_t, int, int, int, size_t);
++
++static inline void *drm_mmap(void *addr, size_t length, int prot, int flags,
++ int fd, loff_t offset)
++{
++ /* offset must be aligned to 4096 (not necessarily the page size) */
++ if (offset & 4095) {
++ errno = EINVAL;
++ return MAP_FAILED;
++ }
++
++ return __mmap2(addr, length, prot, flags, fd, (size_t) (offset >> 12));
++}
++
++# define drm_munmap(addr, length) \
++ munmap(addr, length)
++
++#else
++
++/* assume large file support exists */
++# define drm_mmap(addr, length, prot, flags, fd, offset) \
++ mmap(addr, length, prot, flags, fd, offset)
++
++static inline int drm_munmap(void *addr, size_t length)
++{
++ /* Copied from configure code generated by AC_SYS_LARGEFILE */
++#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + \
++ (((off_t) 1 << 31) << 31))
++ STATIC_ASSERT(LARGE_OFF_T % 2147483629 == 721 &&
++ LARGE_OFF_T % 2147483647 == 1);
++#undef LARGE_OFF_T
++
++ return munmap(addr, length);
++}
++#endif
++
++// default
++static int card_index = 0;
++
++static const struct {
++ enum AVPixelFormat pixfmt;
++ uint32_t drm_format;
++} supported_formats[] = {
++ { AV_PIX_FMT_NV12, DRM_FORMAT_NV12, },
++//#ifdef DRM_FORMAT_NV12_10
++// { AV_PIX_FMT_P010LE, DRM_FORMAT_NV12_10, },
++// { AV_PIX_FMT_P010BE, DRM_FORMAT_NV12_10 | DRM_FORMAT_BIG_ENDIAN },
++//#endif
++ { AV_PIX_FMT_NV21, DRM_FORMAT_NV21, },
++ { AV_PIX_FMT_YUV420P, DRM_FORMAT_YUV420, },
++ { AV_PIX_FMT_YUYV422, DRM_FORMAT_YUYV, },
++ { AV_PIX_FMT_YVYU422, DRM_FORMAT_YVYU, },
++ { AV_PIX_FMT_UYVY422, DRM_FORMAT_UYVY, },
++ { AV_PIX_FMT_NV16, DRM_FORMAT_NV16, },
++ { AV_PIX_FMT_YUV422P, DRM_FORMAT_YUV422, },
++#ifdef DRM_FORMAT_R16
++ { AV_PIX_FMT_GRAY16LE, DRM_FORMAT_R16, },
++ { AV_PIX_FMT_GRAY16BE, DRM_FORMAT_R16 | DRM_FORMAT_BIG_ENDIAN },
++#endif
++ { AV_PIX_FMT_BGR8, DRM_FORMAT_BGR233, },
++ { AV_PIX_FMT_RGB555LE, DRM_FORMAT_XRGB1555, },
++ { AV_PIX_FMT_RGB555BE, DRM_FORMAT_XRGB1555 | DRM_FORMAT_BIG_ENDIAN },
++ { AV_PIX_FMT_BGR555LE, DRM_FORMAT_XBGR1555, },
++ { AV_PIX_FMT_BGR555BE, DRM_FORMAT_XBGR1555 | DRM_FORMAT_BIG_ENDIAN },
++ { AV_PIX_FMT_RGB565LE, DRM_FORMAT_RGB565, },
++ { AV_PIX_FMT_RGB565BE, DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN },
++ { AV_PIX_FMT_BGR565LE, DRM_FORMAT_BGR565, },
++ { AV_PIX_FMT_BGR565BE, DRM_FORMAT_BGR565 | DRM_FORMAT_BIG_ENDIAN },
++ { AV_PIX_FMT_RGB24, DRM_FORMAT_RGB888, },
++ { AV_PIX_FMT_BGR24, DRM_FORMAT_BGR888, },
++ { AV_PIX_FMT_0RGB, DRM_FORMAT_BGRX8888, },
++ { AV_PIX_FMT_0BGR, DRM_FORMAT_RGBX8888, },
++ { AV_PIX_FMT_RGB0, DRM_FORMAT_XBGR8888, },
++ { AV_PIX_FMT_BGR0, DRM_FORMAT_XRGB8888, },
++ { AV_PIX_FMT_ARGB, DRM_FORMAT_BGRA8888, },
++ { AV_PIX_FMT_ABGR, DRM_FORMAT_RGBA8888, },
++ { AV_PIX_FMT_RGBA, DRM_FORMAT_ABGR8888, },
++ { AV_PIX_FMT_BGRA, DRM_FORMAT_ARGB8888, },
++};
--static void rkmpp_update_fps(AVCodecContext *avctx)
-+static uint64_t rkmpp_update_latency(AVCodecContext *avctx, uint64_t latency)
+ static void drm_device_free(AVHWDeviceContext *hwdev)
{
- RKMPPDecodeContext *rk_context = avctx->priv_data;
- RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data;
-- struct timeval tv;
-+ struct timespec tv;
- uint64_t curr_time;
-- float fps;
-+ float fps = 0.0f;
-
- 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;
+@@ -52,7 +150,14 @@ static int drm_device_create(AVHWDeviceContext *hwdev, const char *device,
+ {
+ AVDRMDeviceContext *hwctx = hwdev->hwctx;
+ drmVersionPtr version;
-
-- gettimeofday(&tv, NULL);
-- curr_time = tv.tv_sec * 1000 + tv.tv_usec / 1000;
-+ return 0;
-
-- fps = 1000.0f * FPS_UPDATE_INTERVAL / (curr_time - decoder->last_fps_time);
-- decoder->last_fps_time = curr_time;
-+ clock_gettime(CLOCK_MONOTONIC, &tv);
-+ curr_time = tv.tv_sec * 10e5 + tv.tv_nsec / 10e2;
-+ if (latency == -1){
-+ latency = decoder->last_frame_time ? curr_time - decoder->last_frame_time : 0;
-+ decoder->last_frame_time = curr_time;
-+ decoder->latencies[++decoder->frames % FPS_FRAME_MACD] = latency;
-+ return latency;
-+ } else if (latency == 0 || decoder->frames < FPS_FRAME_MACD) {
-+ fps = -1.0f;
-+ } else {
-+ for(int i = 0; i < FPS_FRAME_MACD; i++) {
-+ fps += decoder->latencies[i];
-+ }
-+ fps = FPS_FRAME_MACD * 1000000.0f / fps;
-+ }
-+ av_log(avctx, AV_LOG_INFO,
-+ "[FFMPEG RKMPP] FPS(MACD%d): %6.1f || Frames: %" PRIu64 " || Latency: %" PRIu64 "us || Buffer Delay %" PRIu64 "us\n",
-+ FPS_FRAME_MACD, fps, decoder->frames, latency, (uint64_t)(curr_time - decoder->last_frame_time));
++ char drm_dev[] = "/dev/dri/card0000";
++ uint64_t has_dumb;
++
++ if (!device) {
++ snprintf(drm_dev, sizeof(drm_dev), DRM_DEV_NAME, DRM_DIR_NAME,
++ card_index);
++ device = drm_dev;
++ }
+ hwctx->fd = open(device, O_RDWR);
+ if (hwctx->fd < 0)
+ return AVERROR(errno);
+@@ -72,11 +177,219 @@ static int drm_device_create(AVHWDeviceContext *hwdev, const char *device,
+
+ drmFreeVersion(version);
+
++ if (drmGetCap(hwctx->fd, DRM_CAP_DUMB_BUFFER, &has_dumb) < 0 ||
++ !has_dumb) {
++ av_log(hwdev, AV_LOG_ERROR, "drm device '%s' "
++ "does not support dumb buffers\n", device);
++ close(hwctx->fd);
++ return AVERROR(EINVAL);
++ }
++
+ hwdev->free = &drm_device_free;
-- av_log(avctx, AV_LOG_INFO,
-- "[FFMPEG RKMPP] FPS: %6.1f || Frames: %" PRIu64 "\n",
-- fps, decoder->frames);
-+ return 0;
+ return 0;
}
- static int rkmpp_set_drm_buf(AVCodecContext *avctx, AVFrame *frame, MppFrame mppframe)
-@@ -566,7 +570,7 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
- RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data;
- MppFrame mppframe = NULL;
- MppBuffer buffer = NULL;
-- int ret, mode;
-+ int ret, mode, latency;
-
- // should not provide any frame after EOS
- if (decoder->eos)
-@@ -658,7 +662,7 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
- goto fail;
- }
-
-- rkmpp_update_fps(avctx);
-+ latency = rkmpp_update_latency(avctx, -1);
-
- if(!decoder->buffer_callback){
- ret = AVERROR_UNKNOWN;
-@@ -673,6 +677,8 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
- goto fail;
- }
-
-+ latency = rkmpp_update_latency(avctx, latency);
-+
- // setup general frame fields
- frame->format = avctx->pix_fmt;
- frame->width = mpp_frame_get_width(mppframe);
-@@ -812,7 +818,7 @@ static void rkmpp_flush(AVCodecContext *avctx)
- decoder->eos = 0;
- decoder->norga = 0;
-
-- decoder->last_fps_time = decoder->frames = 0;
-+ decoder->last_frame_time = decoder->frames = 0;
++static int drm_frames_get_constraints(AVHWDeviceContext *hwdev,
++ const void *hwconfig,
++ AVHWFramesConstraints *constraints)
++{
++ int i;
++
++ constraints->min_width = 16;
++ constraints->min_height = 16;
++
++ constraints->valid_hw_formats =
++ av_malloc_array(2, sizeof(enum AVPixelFormat));
++ if (!constraints->valid_hw_formats)
++ return AVERROR(ENOMEM);
++ constraints->valid_hw_formats[0] = AV_PIX_FMT_DRM_PRIME;
++ constraints->valid_hw_formats[1] = AV_PIX_FMT_NONE;
++
++ constraints->valid_sw_formats =
++ av_malloc_array(FF_ARRAY_ELEMS(supported_formats) + 1,
++ sizeof(enum AVPixelFormat));
++ if (!constraints->valid_sw_formats)
++ return AVERROR(ENOMEM);
++ for(i = 0; i < FF_ARRAY_ELEMS(supported_formats); i++)
++ constraints->valid_sw_formats[i] = supported_formats[i].pixfmt;
++ constraints->valid_sw_formats[i] = AV_PIX_FMT_NONE;
++
++ return 0;
++}
++
++static void free_drm_frame_descriptor(AVDRMDeviceContext *hwctx,
++ AVDRMFrameDescriptor *desc)
++{
++ int i;
++ if (!desc)
++ return;
++
++ for (i = 0; i < desc->nb_objects; i++) {
++ AVDRMObjectDescriptor *object = &desc->objects[i];
++ if (object->ptr)
++ drm_munmap(object->ptr, object->size);
++ if (object->fd > 0) {
++ int ret;
++ uint32_t handle = 0;
++
++ ret = drmPrimeFDToHandle(hwctx->fd, object->fd, &handle);
++ if (ret)
++ av_log(NULL, AV_LOG_WARNING,
++ "Failed to convert drm fd to handle: %m\n");
++ if (handle > 0) {
++ struct drm_mode_destroy_dumb data = {
++ .handle = handle,
++ };
++ ret = drmIoctl(hwctx->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &data);
++ if (ret)
++ av_log(NULL, AV_LOG_WARNING,
++ "Failed to free drm handle: %m\n");
++ }
++
++ ret = close(object->fd);
++ if (ret)
++ av_log(NULL, AV_LOG_WARNING,
++ "Failed to close drm buffer fd = %d: %m\n", object->fd);
++ }
++ }
++
++ memset(desc, 0, sizeof(*desc));
++ av_free(desc);
++}
++
++static void drm_buffer_free(void *opaque, uint8_t *data)
++{
++ AVHWFramesContext *hwfc = opaque;
++ AVDRMDeviceContext *hwctx = hwfc->device_ctx->hwctx;
++ AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor *)data;
++
++ free_drm_frame_descriptor(hwctx, desc);
++}
++
++static AVBufferRef *drm_pool_alloc(void *opaque, size_t size)
++{
++ int ret;
++ AVHWFramesContext *hwfc = opaque;
++ AVDRMDeviceContext *hwctx = hwfc->device_ctx->hwctx;
++ AVDRMFrameDescriptor *desc;
++ AVDRMLayerDescriptor *layer;
++ AVBufferRef *ref;
++
++ int i;
++ const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(hwfc->sw_format);
++ struct drm_mode_create_dumb dmcb;
++ struct drm_mode_map_dumb dmmd;
++
++ desc = av_mallocz(sizeof(*desc));
++ if (!desc)
++ return NULL;
++
++ memset(&dmcb, 0, sizeof(struct drm_mode_create_dumb));
++ dmcb.bpp = av_get_bits_per_pixel(pixdesc);
++ dmcb.width = FFALIGN(hwfc->width, 16);
++ dmcb.height = FFALIGN(hwfc->height, 16);
++ ret = drmIoctl(hwctx->fd, DRM_IOCTL_MODE_CREATE_DUMB, &dmcb);
++ if (ret < 0) {
++ av_log(hwfc, AV_LOG_ERROR,
++ "Failed to create dumb<w,h,bpp: %d,%d,%d>: %m.\n",
++ dmcb.width, dmcb.height, dmcb.bpp);
++ goto fail;
++ }
++ av_assert0(dmcb.size >= dmcb.width * dmcb.height * dmcb.bpp / 8);
++
++ desc->nb_objects = 1;
++ desc->nb_layers = 1;
++ ret = drmPrimeHandleToFD(hwctx->fd, dmcb.handle, DRM_CLOEXEC | DRM_RDWR,
++ &desc->objects[0].fd);
++ if (ret) {
++ av_log(hwfc, AV_LOG_ERROR, "Failed to convert handle to fd: %m\n");
++ goto fail;
++ }
++ memset(&dmmd, 0, sizeof(dmmd));
++ dmmd.handle = dmcb.handle;
++
++ ret = drmIoctl(hwctx->fd, DRM_IOCTL_MODE_MAP_DUMB, &dmmd);
++ if (ret) {
++ av_log(hwfc, AV_LOG_ERROR, "Failed to map dumb: %m\n");
++ goto fail;
++ }
++
++ // default read and write
++ desc->objects[0].ptr = drm_mmap(NULL, dmcb.size, PROT_READ | PROT_WRITE,
++ MAP_SHARED, hwctx->fd, dmmd.offset);
++ if (desc->objects[0].ptr == MAP_FAILED) {
++ av_log(hwfc, AV_LOG_ERROR, "Failed to drm_mmap: %m\n");
++ goto fail;
++ }
++
++ desc->objects[0].size = dmcb.size;
++
++ layer = &desc->layers[0];
++ for (i = 0; i < FF_ARRAY_ELEMS(supported_formats); i++) {
++ if (supported_formats[i].pixfmt == hwfc->sw_format) {
++ layer->format = supported_formats[i].drm_format;
++ break;
++ }
++ }
++ layer->nb_planes = av_pix_fmt_count_planes(hwfc->sw_format);
++ layer->planes[0].object_index = 0;
++ layer->planes[0].offset = 0;
++ layer->planes[0].pitch =
++ av_image_get_linesize(hwfc->sw_format, hwfc->width, 0);
++
++ for (i = 1; i < layer->nb_planes; i++) {
++ layer->planes[i].object_index = 0;
++ layer->planes[i].offset = layer->planes[i-1].pitch * hwfc->height;
++ layer->planes[i].pitch =
++ av_image_get_linesize(hwfc->sw_format, hwfc->width, i);
++ }
++
++ ref = av_buffer_create((uint8_t*)desc, sizeof(*desc), drm_buffer_free,
++ opaque, 0);
++ if (!ref) {
++ av_log(hwfc, AV_LOG_ERROR, "Failed to create drm buffer.\n");
++ goto fail;
++ }
++
++ return ref;
++
++fail:
++ free_drm_frame_descriptor(hwctx, desc);
++ return NULL;
++}
++
++static int drm_frames_init(AVHWFramesContext *hwfc)
++{
++ int i;
++ if (hwfc->pool) {
++ // has been set outside?
++ return 0;
++ }
++
++ for (i = 0; i < FF_ARRAY_ELEMS(supported_formats); i++)
++ if (supported_formats[i].pixfmt == hwfc->sw_format)
++ break;
++ if (i >= FF_ARRAY_ELEMS(supported_formats)) {
++ av_log(hwfc, AV_LOG_ERROR, "Unsupported format: %s.\n",
++ av_get_pix_fmt_name(hwfc->sw_format));
++ return AVERROR(EINVAL);
++ }
++
++ hwfc->internal->pool_internal =
++ av_buffer_pool_init2(sizeof(AVDRMFrameDescriptor), hwfc, drm_pool_alloc,
++ NULL);
++ if (!hwfc->internal->pool_internal) {
++ av_log(hwfc, AV_LOG_ERROR, "Failed to create drm buffer pool.\n");
++ return AVERROR(ENOMEM);
++ }
++
++ return 0;
++}
++
++static void drm_frames_uninit(AVHWFramesContext *hwfc av_unused)
++{}
++
+ static int drm_get_buffer(AVHWFramesContext *hwfc, AVFrame *frame)
+ {
+ frame->buf[0] = av_buffer_pool_get(hwfc->pool);
+@@ -309,8 +622,11 @@ const HWContextType ff_hwcontext_type_drm = {
+
+ .device_create = &drm_device_create,
+
+- .frames_get_buffer = &drm_get_buffer,
++ .frames_get_constraints = &drm_frames_get_constraints,
+
++ .frames_get_buffer = &drm_get_buffer,
++ .frames_init = &drm_frames_init,
++ .frames_uninit = &drm_frames_uninit,
+ .transfer_get_formats = &drm_transfer_get_formats,
+ .transfer_data_to = &drm_transfer_data_to,
+ .transfer_data_from = &drm_transfer_data_from,
+diff --git a/libavutil/hwcontext_drm.h b/libavutil/hwcontext_drm.h
+index 42709f215e..80f2e8597e 100644
+--- a/libavutil/hwcontext_drm.h
++++ b/libavutil/hwcontext_drm.h
+@@ -25,11 +25,6 @@
+ /**
+ * @file
+ * API-specific header for AV_HWDEVICE_TYPE_DRM.
+- *
+- * Internal frame allocation is not currently supported - all frames
+- * must be allocated by the user. Thus AVHWFramesContext is always
+- * NULL, though this may change if support for frame allocation is
+- * added in future.
+ */
- av_packet_unref(&decoder->packet);
- }
+ enum {
+@@ -50,6 +45,12 @@ typedef struct AVDRMObjectDescriptor {
+ * DRM PRIME fd for the object.
+ */
+ int fd;
++ /**
++ * DRM PRIME mapped virtual ptr for above fd.
++ *
++ * The content of this buffer must be readonly when acting decoder's out buffer.
++ */
++ void *ptr;
+ /**
+ * Total size of the object.
+ *
+@@ -141,10 +142,13 @@ typedef struct AVDRMFrameDescriptor {
+ AVDRMObjectDescriptor objects[AV_DRM_MAX_PLANES];
+ /**
+ * Number of layers in the frame.
++ *
++ * Set by users if need more than 1.
+ */
+ int nb_layers;
+ /**
+ * Array of layers in the frame.
++ * NOTE: total planes of layers must not be more than AV_NUM_DATA_POINTERS.
+ */
+ AVDRMLayerDescriptor layers[AV_DRM_MAX_PLANES];
+ } AVDRMFrameDescriptor;
--
-2.40.0
+2.41.0
-From 893dca97e199609f22a73082af1eba87b6512530 Mon Sep 17 00:00:00 2001
+From 02c903151922d7f1427fbf56312585ca94237a56 Mon Sep 17 00:00:00 2001
From: boogie <boogiepop@gmx.com>
-Date: Mon, 1 May 2023 19:00:21 +0200
-Subject: [PATCH 22/24] Allow users to choose pix_fmt using
- "FFMPEG_RKMPP_PIXFMT" env variable. Valid options are: YUV420P, YUV420PSOFT,
- NV12, DRMPRIME. Case sensitive
+Date: Mon, 24 Jul 2023 22:19:14 +0200
+Subject: [PATCH 11/13] add yuv444 & nv24 support for drm hwcontext
---
- libavcodec/rkmppdec.c | 25 +++++++++++++++++++------
- 1 file changed, 19 insertions(+), 6 deletions(-)
+ libavutil/hwcontext_drm.c | 2 ++
+ 1 file changed, 2 insertions(+)
-diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
-index ecee5dd338..4f9ecb0155 100644
---- a/libavcodec/rkmppdec.c
-+++ b/libavcodec/rkmppdec.c
-@@ -75,7 +75,6 @@ typedef struct {
- uint32_t drm_format;
- uint32_t sw_format;
- int rga_fd;
-- int8_t rgafbc;
- int8_t norga;
- int (*buffer_callback)(struct AVCodecContext *avctx, struct AVFrame *frame, MppFrame mppframe);
-
-@@ -287,8 +286,6 @@ static int rkmpp_init_decoder(AVCodecContext *avctx)
- char *env;
- int ret;
-
-- avctx->pix_fmt = ff_get_format(avctx, avctx->codec->pix_fmts);
--
- // create a decoder and a ref to it
- decoder = av_mallocz(sizeof(RKMPPDecoder));
- if (!decoder) {
-@@ -350,8 +347,24 @@ static int rkmpp_init_decoder(AVCodecContext *avctx)
- goto fail;
- }
-
-- env = getenv("FFMPEG_RKMPP_NORGA");
-- if (env != NULL)
-+ avctx->pix_fmt = ff_get_format(avctx, avctx->codec->pix_fmts);
-+
-+ // override the the pixfmt according env variable
-+ env = getenv("FFMPEG_RKMPP_PIXFMT");
-+ if(env != NULL){
-+ if(!strcmp(env, "YUV420P"))
-+ avctx->pix_fmt = AV_PIX_FMT_YUV420P;
-+ else if (!strcmp(env, "NV12"))
-+ avctx->pix_fmt = AV_PIX_FMT_NV12;
-+ else if(!strcmp(env, "DRMPRIME"))
-+ avctx->pix_fmt = AV_PIX_FMT_DRM_PRIME;
-+ else if(!strcmp(env, "YUV420PSOFT")){
-+ avctx->pix_fmt = AV_PIX_FMT_YUV420P;
-+ decoder->norga = 1;
-+ }
-+ }
-+
-+ if (decoder->norga)
- decoder->rga_fd = -1;
- else {
- decoder->rga_fd = open("/dev/rga", O_RDWR);
-@@ -844,8 +857,8 @@ static void rkmpp_flush(AVCodecContext *avctx)
- .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_NV12, \
- AV_PIX_FMT_YUV420P, \
-+ AV_PIX_FMT_NV12, \
- AV_PIX_FMT_NONE}, \
- .hw_configs = (const AVCodecHWConfigInternal *const []) { HW_CONFIG_INTERNAL(DRM_PRIME), \
- HW_CONFIG_INTERNAL(NV12), \
+diff --git a/libavutil/hwcontext_drm.c b/libavutil/hwcontext_drm.c
+index 2d1962c9c0..9210b6c9f5 100644
+--- a/libavutil/hwcontext_drm.c
++++ b/libavutil/hwcontext_drm.c
+@@ -117,6 +117,8 @@ static const struct {
+ { AV_PIX_FMT_GRAY16LE, DRM_FORMAT_R16, },
+ { AV_PIX_FMT_GRAY16BE, DRM_FORMAT_R16 | DRM_FORMAT_BIG_ENDIAN },
+ #endif
++ { AV_PIX_FMT_NV24, DRM_FORMAT_NV24, },
++ { AV_PIX_FMT_YUV444P, DRM_FORMAT_YUV444, },
+ { AV_PIX_FMT_BGR8, DRM_FORMAT_BGR233, },
+ { AV_PIX_FMT_RGB555LE, DRM_FORMAT_XRGB1555, },
+ { AV_PIX_FMT_RGB555BE, DRM_FORMAT_XRGB1555 | DRM_FORMAT_BIG_ENDIAN },
--
-2.40.0
+2.41.0
-From 7612f91257a22339bfde5e3258b4b8c2671bb876 Mon Sep 17 00:00:00 2001
+From fe7abf1ad8ec7522d86c87c1b55164122199a327 Mon Sep 17 00:00:00 2001
From: boogie <boogiepop@gmx.com>
-Date: Mon, 1 May 2023 20:03:53 +0200
-Subject: [PATCH 23/24] Workaround for Mpp bug, where color primaries, trc and
- colorspace is giving wrong UNSPECIFIED values
+Date: Fri, 28 Jul 2023 22:08:47 +0200
+Subject: [PATCH 12/13] add AV_PIX_FMT_NV15 definition as a placeholder to
+ enable supported DRM frames
---
- libavcodec/rkmppdec.c | 6 ++++++
- 1 file changed, 6 insertions(+)
+ libavcodec/rkmpp.c | 2 +-
+ libavutil/hwcontext_drm.c | 1 +
+ libavutil/pixfmt.h | 2 ++
+ 3 files changed, 4 insertions(+), 1 deletion(-)
-diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
-index 4f9ecb0155..60f1506804 100644
---- a/libavcodec/rkmppdec.c
-+++ b/libavcodec/rkmppdec.c
-@@ -703,6 +703,12 @@ 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);
+diff --git a/libavcodec/rkmpp.c b/libavcodec/rkmpp.c
+index b76dc1a868..dfb76e1d91 100644
+--- a/libavcodec/rkmpp.c
++++ b/libavcodec/rkmpp.c
+@@ -27,7 +27,7 @@ static rkformat rkformats[13] = {
+ { .av = AV_PIX_FMT_YUV422P, .mpp = MPP_FMT_YUV422P, .drm = DRM_FORMAT_YUV422, .rga = RK_FORMAT_YCbCr_422_P},
+ { .av = AV_PIX_FMT_NV12, .mpp = MPP_FMT_YUV420SP, .drm = DRM_FORMAT_NV12, .rga = RK_FORMAT_YCbCr_420_SP},
+ { .av = AV_PIX_FMT_NV16, .mpp = MPP_FMT_YUV422SP, .drm = DRM_FORMAT_NV16, .rga = RK_FORMAT_YCbCr_422_SP},
+- { .av = AV_PIX_FMT_NONE, .mpp = MPP_FMT_YUV420SP_10BIT, .drm = DRM_FORMAT_NV15, .rga = RK_FORMAT_YCbCr_420_SP_10B},
++ { .av = AV_PIX_FMT_NV15, .mpp = MPP_FMT_YUV420SP_10BIT, .drm = DRM_FORMAT_NV15, .rga = RK_FORMAT_YCbCr_420_SP_10B},
+ { .av = AV_PIX_FMT_BGR24, .mpp = MPP_FMT_BGR888, .drm = DRM_FORMAT_BGR888, .rga = RK_FORMAT_BGR_888},
+ { .av = AV_PIX_FMT_BGR0, .mpp = MPP_FMT_BGRA8888, .drm = DRM_FORMAT_XRGB8888, .rga = RK_FORMAT_BGRX_8888},
+ { .av = AV_PIX_FMT_BGRA, .mpp = MPP_FMT_BGRA8888, .drm = DRM_FORMAT_ARGB8888, .rga = RK_FORMAT_BGRA_8888},
+diff --git a/libavutil/hwcontext_drm.c b/libavutil/hwcontext_drm.c
+index 9210b6c9f5..32bf958c5d 100644
+--- a/libavutil/hwcontext_drm.c
++++ b/libavutil/hwcontext_drm.c
+@@ -138,6 +138,7 @@ static const struct {
+ { AV_PIX_FMT_ABGR, DRM_FORMAT_RGBA8888, },
+ { AV_PIX_FMT_RGBA, DRM_FORMAT_ABGR8888, },
+ { AV_PIX_FMT_BGRA, DRM_FORMAT_ARGB8888, },
++ { AV_PIX_FMT_NV15, DRM_FORMAT_NV15, },
+ };
-+ // when mpp can not determine the color space, it returns reserved (0) value
-+ // firefox does not understand this and instead expect unspecified (2) values
-+ frame->color_primaries = frame->color_primaries == AVCOL_PRI_RESERVED0 ? AVCOL_PRI_UNSPECIFIED : frame->color_primaries;
-+ frame->color_trc = frame->color_trc == AVCOL_TRC_RESERVED0 ? AVCOL_TRC_UNSPECIFIED : frame->color_trc;
-+ frame->colorspace = frame->colorspace == AVCOL_SPC_RGB ? AVCOL_SPC_UNSPECIFIED: frame->color_trc;
+ static void drm_device_free(AVHWDeviceContext *hwdev)
+diff --git a/libavutil/pixfmt.h b/libavutil/pixfmt.h
+index 37c2c79e01..d2348b016b 100644
+--- a/libavutil/pixfmt.h
++++ b/libavutil/pixfmt.h
+@@ -420,6 +420,8 @@ enum AVPixelFormat {
+ AV_PIX_FMT_RGBAF32BE, ///< IEEE-754 single precision packed RGBA 32:32:32:32, 128bpp, RGBARGBA..., big-endian
+ AV_PIX_FMT_RGBAF32LE, ///< IEEE-754 single precision packed RGBA 32:32:32:32, 128bpp, RGBARGBA..., little-endian
+
++ AV_PIX_FMT_NV15, ///< Rockchip Specific 10bit NV12
+
- 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);
+ AV_PIX_FMT_NB ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions
+ };
+
--
-2.40.0
+2.41.0
-From d8ecadf7de6ec350502b2613dfc34c815969b518 Mon Sep 17 00:00:00 2001
+From ac1a698091e8457472391cbf279bcd228e4b8fb9 Mon Sep 17 00:00:00 2001
From: boogie <boogiepop@gmx.com>
-Date: Tue, 2 May 2023 02:07:20 +0200
-Subject: [PATCH 24/24] Log more understandable errors
+Date: Mon, 31 Jul 2023 01:32:54 +0200
+Subject: [PATCH 13/13] give pixel descriptor to prevent crashes. descriptor
+ might not be %100 correct
---
- libavcodec/rkmppdec.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
+ libavutil/pixdesc.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
-diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
-index 60f1506804..c1d357344b 100644
---- a/libavcodec/rkmppdec.c
-+++ b/libavcodec/rkmppdec.c
-@@ -679,7 +679,7 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
-
- if(!decoder->buffer_callback){
- ret = AVERROR_UNKNOWN;
-- av_log(avctx, AV_LOG_ERROR, "Decoder has no valid buffer_callback\n");
-+ av_log(avctx, AV_LOG_ERROR, "Decoder can't set output for MPP format:%d and AVFormat:%d.\n", decoder->mpp_format, avctx->pix_fmt);
- goto fail;
- }
+diff --git a/libavutil/pixdesc.c b/libavutil/pixdesc.c
+index 62a2ae08d9..c5e8c7bd9a 100644
+--- a/libavutil/pixdesc.c
++++ b/libavutil/pixdesc.c
+@@ -2717,6 +2717,18 @@ static const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = {
+ .flags = AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_FLOAT |
+ AV_PIX_FMT_FLAG_ALPHA,
+ },
++ [AV_PIX_FMT_NV15] = {
++ .name = "nv15",
++ .nb_components = 3,
++ .log2_chroma_w = 1,
++ .log2_chroma_h = 1,
++ .comp = {
++ { 0, 1, 0, 0, 10 }, /* Y */
++ { 1, 2, 0, 0, 10 }, /* U */
++ { 1, 2, 1, 0, 10 }, /* V */
++ },
++ .flags = AV_PIX_FMT_FLAG_PLANAR,
++ },
+ };
+ static const char * const color_range_names[] = {
--
-2.40.0
+2.41.0