Build fixes.

This commit is contained in:
fewtarius 2022-07-12 06:52:40 -04:00
parent 1c07a31565
commit 47e8822da6
No known key found for this signature in database
GPG key ID: F4AE55305D1B8C1A
9 changed files with 18862 additions and 5442 deletions

View file

@ -13,7 +13,7 @@ diff -rupN pcsx_rearmed.orig/Makefile.libretro pcsx_rearmed/Makefile.libretro
+ DYNAREC = ari64
+ BUILTIN_GPU = peops
+ CFLAGS += -fomit-frame-pointer -ffast-math -Ofast -DARM
+ CPUFLAGS += -march=armv8-a+crc -mcpu=cortex-a55 -mtune=cortex-a55
+ CPUFLAGS += -march=armv8-a+crc+simd -mtune=cortex-a55
+
# ALLWINNER H5
else ifneq (,$(findstring h5,$(platform)))

View file

@ -12,7 +12,7 @@ diff -rupN pcsx_rearmed.orig/Makefile.libretro pcsx_rearmed/Makefile.libretro
+ ARCH = arm
+ DYNAREC = ari64
+ BUILTIN_GPU = neon
+ CFLAGS += -march=armv8-a+crc -mcpu=cortex-a55 -mtune=cortex-a55 -Ofast
+ CFLAGS += -march=armv8-a+crc+simd -mtune=cortex-a55 -Ofast
+ CPUFLAGS += -mtune=cortex-a55 -mfpu=neon-fp-armv8 -mfloat-abi=hard
+
# ALLWINNER H5

View file

@ -41,7 +41,7 @@ LIBRETRO_CORES="2048 81 a5200 atari800 beetle-gba beetle-lynx beetle-ngp beetle-
fbalpha2019 fbneo fceumm fmsx flycast flycast_libretro freechaf freeintv \
freej2me fuse-libretro gambatte gearboy gearcoleco gearsystem genesis-plus-gx \
genesis-plus-gx-wide gme gpsp gw-libretro handy hatari mame2000 mame2003-plus \
mame2010 mame2015 mame melonds meowpc98 mgba mrboom mupen64plus mupen64plus-nx \
mame2010 mame2015 melonds meowpc98 mgba mrboom mupen64plus mupen64plus-nx \
neocd_libretro nestopia np2kai nxengine o2em opera parallel-n64_rice \
parallel-n64_gln64 parallel-n64_glide64 pcsx_rearmed picodrive pokemini potator \
ppsspp prboom prosystem puae px68k quasi88 quicknes race reminiscence sameboy \

View file

@ -1,34 +1,41 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv)
# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv)
# Copyright (C) 2022-present Fewtarius
PKG_NAME="ffmpeg"
PKG_VERSION="7e3a070d9aac3ccdd1a5ee9ba08508811ad5202f"
PKG_SHA256="d289bb7c6c1624b6010ad084e18b158c17b5425baa883d8ea01b399f826c46c0"
PKG_LICENSE="LGPLv2.1+"
PKG_SITE="https://ffmpeg.org"
PKG_URL="https://github.com/xbmc/FFmpeg/archive/${PKG_VERSION}.tar.gz"
PKG_DEPENDS_TARGET="toolchain zlib bzip2 gnutls speex x264"
PKG_DEPENDS_TARGET="toolchain zlib bzip2 gnutls speex"
PKG_LONGDESC="FFmpeg is a complete, cross-platform solution to record, convert and stream audio and video."
PKG_BUILD_FLAGS="-gold"
case "${PROJECT}" in
Amlogic)
PKG_VERSION="0e5290bcac015e52f6a65dafaf41ea125816257f" # dev/4.4/rpi_import_1
PKG_SHA256="4bd6e56920b90429bc09e43cda554f5bb9125c4ac090b4331fc459bb709eea68"
PKG_URL="https://github.com/jc-kynesim/rpi-ffmpeg/archive/${PKG_VERSION}.tar.gz"
PKG_PATCH_DIRS="libreelec"
;;
RPi)
PKG_VERSION="4.4-N-Alpha1"
PKG_SHA256="eb396f46ef7c5ac01b67818d0f2c0516fd4ab32aa9065a9ffa71eebede67ff20"
PKG_URL="https://github.com/xbmc/FFmpeg/archive/${PKG_VERSION}.tar.gz"
PKG_FFMPEG_RPI="--disable-mmal --disable-rpi --enable-sand"
PKG_PATCH_DIRS="libreelec rpi"
;;
*)
PKG_VERSION="4.4-N-Alpha1"
PKG_SHA256="eb396f46ef7c5ac01b67818d0f2c0516fd4ab32aa9065a9ffa71eebede67ff20"
PKG_URL="https://github.com/xbmc/FFmpeg/archive/${PKG_VERSION}.tar.gz"
PKG_PATCH_DIRS="libreelec v4l2-request v4l2-drmprime"
;;
esac
# Dependencies
get_graphicdrivers
PKG_FFMPEG_HWACCEL="--enable-hwaccels"
PKG_FFMPEG_RPI="--disable-mmal"
if [ "${PROJECT}" = "RPi" ]; then
PKG_PATCH_DIRS="rpi"
PKG_FFMPEG_RPI+=" --disable-rpi --enable-sand"
else
PKG_PATCH_DIRS="v4l2-request v4l2-drmprime"
fi
PKG_PATCH_DIRS+=" libreelec"
if [ "${V4L2_SUPPORT}" = "yes" ]; then
PKG_DEPENDS_TARGET+=" libdrm"
PKG_NEED_UNPACK+=" $(get_pkg_directory libdrm)"
@ -50,9 +57,11 @@ if [ "${V4L2_SUPPORT}" = "yes" ]; then
PKG_DEPENDS_TARGET+=" systemd"
PKG_NEED_UNPACK+=" $(get_pkg_directory systemd)"
PKG_FFMPEG_V4L2+=" --enable-libudev --enable-v4l2-request"
else
PKG_FFMPEG_V4L2+=" --disable-libudev --disable-v4l2-request"
fi
else
PKG_FFMPEG_V4L2="--disable-v4l2_m2m"
PKG_FFMPEG_V4L2="--disable-v4l2_m2m --disable-libudev --disable-v4l2-request"
fi
if [ "${VAAPI_SUPPORT}" = "yes" ]; then
@ -63,6 +72,12 @@ else
PKG_FFMPEG_VAAPI="--disable-vaapi"
fi
if [ "${DISPLAYSERVER}" != "x11" ]; then
PKG_DEPENDS_TARGET+=" libdrm"
PKG_NEED_UNPACK+=" $(get_pkg_directory libdrm)"
PKG_FFMPEG_VAAPI=" --enable-libdrm"
fi
if [ "${VDPAU_SUPPORT}" = "yes" -a "${DISPLAYSERVER}" = "x11" ]; then
PKG_DEPENDS_TARGET+=" libvdpau"
PKG_NEED_UNPACK+=" $(get_pkg_directory libvdpau)"
@ -87,19 +102,28 @@ if [ "${TARGET_ARCH}" = "x86_64" ]; then
PKG_DEPENDS_TARGET+=" nasm:host"
fi
#if target_has_feature "(neon|sse)"; then
# PKG_DEPENDS_TARGET+=" dav1d"
# PKG_NEED_UNPACK+=" $(get_pkg_directory dav1d)"
# PKG_FFMPEG_AV1="--enable-libdav1d"
#else
# PKG_FFMPEG_AV1="--disable-libdav1d"
#fi
if target_has_feature "(neon|sse)"; then
PKG_DEPENDS_TARGET+=" dav1d"
PKG_NEED_UNPACK+=" $(get_pkg_directory dav1d)"
PKG_FFMPEG_AV1="--enable-libdav1d"
else
PKG_FFMPEG_AV1="--disable-libdav1d"
fi
pre_configure_target() {
cd ${PKG_BUILD}
rm -rf .${TARGET_NAME}
}
if [ "${FFMPEG_TESTING}" = "yes" ]; then
PKG_FFMPEG_TESTING="--enable-encoder=wrapped_avframe --enable-muxer=null"
if [ "${PROJECT}" = "RPi" ]; then
PKG_FFMPEG_TESTING+=" --enable-vout-drm --enable-outdev=vout_drm"
fi
else
PKG_FFMPEG_TESTING="--disable-programs"
fi
configure_target() {
./configure --prefix="/usr" \
--cpu="${TARGET_CPU}" \
@ -131,7 +155,6 @@ configure_target() {
--pkg-config="${TOOLCHAIN}/bin/pkg-config" \
--enable-optimizations \
--disable-extra-warnings \
--disable-programs \
--enable-avdevice \
--enable-avcodec \
--enable-avformat \
@ -196,15 +219,15 @@ configure_target() {
--disable-libvo-amrwbenc \
--disable-libvorbis \
--disable-libvpx \
--enable-libx264 \
--disable-libx264 \
--disable-libxavs \
--disable-libxvid \
--enable-zlib \
--enable-asm \
--enable-ffplay \
--disable-altivec \
${PKG_FFMPEG_FPU} \
--disable-symver
--disable-symver \
${PKG_FFMPEG_TESTING}
}
post_makeinstall_target() {

View file

@ -0,0 +1,124 @@
From 7ee17ec7e46afef0e0af20af196292ec75f50b62 Mon Sep 17 00:00:00 2001
From: James Almer <jamrial@gmail.com>
Date: Sat, 26 Jun 2021 17:24:15 -0300
Subject: [PATCH] avcodec/libdav1d: don't repeatedly parse the same sequence
header
Look at the event flag that signals a new sequence header was found
in the bitstream on supported libdav1d versions for this purpose.
Signed-off-by: James Almer <jamrial@gmail.com>
---
libavcodec/libdav1d.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/libavcodec/libdav1d.c b/libavcodec/libdav1d.c
index 6370ae1fbf02..c39df418d515 100644
--- a/libavcodec/libdav1d.c
+++ b/libavcodec/libdav1d.c
@@ -33,6 +33,9 @@
#include "decode.h"
#include "internal.h"
+#define FF_DAV1D_VERSION_AT_LEAST(x,y) \
+ (DAV1D_API_VERSION_MAJOR > (x) || DAV1D_API_VERSION_MAJOR == (x) && DAV1D_API_VERSION_MINOR >= (y))
+
typedef struct Libdav1dContext {
AVClass *class;
Dav1dContext *c;
From d873b5fffc8292242549c4c026023e370e15c05b Mon Sep 17 00:00:00 2001
From: James Almer <jamrial@gmail.com>
Date: Mon, 20 Sep 2021 22:30:35 -0300
Subject: [PATCH] avcodec/libdav1d: pass auto threads value to libdav1d
libdav1d 1.0.0 will be the first version supporting Dav1dSettings.n_threads == 0.
Signed-off-by: James Almer <jamrial@gmail.com>
---
libavcodec/libdav1d.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/libavcodec/libdav1d.c b/libavcodec/libdav1d.c
index 4711337f39a7..e4fdaf722907 100644
--- a/libavcodec/libdav1d.c
+++ b/libavcodec/libdav1d.c
@@ -207,7 +207,11 @@ static av_cold int libdav1d_init(AVCodecContext *c)
{
Libdav1dContext *dav1d = c->priv_data;
Dav1dSettings s;
+#if FF_DAV1D_VERSION_AT_LEAST(6,0)
+ int threads = c->thread_count;
+#else
int threads = (c->thread_count ? c->thread_count : av_cpu_count()) * 3 / 2;
+#endif
int res;
av_log(c, AV_LOG_INFO, "libdav1d %s\n", dav1d_version());
From e204846ec16c1ab34c7f3a681734cf5190433018 Mon Sep 17 00:00:00 2001
From: James Almer <jamrial@gmail.com>
Date: Fri, 3 Sep 2021 13:50:32 -0300
Subject: [PATCH] avcodec/libdav1d: fix compilation after recent libdav1d API
changes
They were done in preparation for an upcoming 1.0 release.
Keep supporting previous releases for the time being.
Reviewed-by: BBB
Signed-off-by: James Almer <jamrial@gmail.com>
---
libavcodec/libdav1d.c | 21 +++++++++++++++++++--
1 file changed, 19 insertions(+), 2 deletions(-)
diff --git a/libavcodec/libdav1d.c b/libavcodec/libdav1d.c
index 51e0980f6edb..4711337f39a7 100644
--- a/libavcodec/libdav1d.c
+++ b/libavcodec/libdav1d.c
@@ -228,6 +228,15 @@ static av_cold int libdav1d_init(AVCodecContext *c)
if (dav1d->operating_point >= 0)
s.operating_point = dav1d->operating_point;
+#if FF_DAV1D_VERSION_AT_LEAST(6,0)
+ if (dav1d->frame_threads || dav1d->tile_threads)
+ s.n_threads = FFMAX(dav1d->frame_threads, dav1d->tile_threads);
+ else
+ s.n_threads = FFMIN(threads, DAV1D_MAX_THREADS);
+ s.max_frame_delay = (c->flags & AV_CODEC_FLAG_LOW_DELAY) ? 1 : s.n_threads;
+ av_log(c, AV_LOG_DEBUG, "Using %d threads, %d max_frame_delay\n",
+ s.n_threads, s.max_frame_delay);
+#else
s.n_tile_threads = dav1d->tile_threads
? dav1d->tile_threads
: FFMIN(floor(sqrt(threads)), DAV1D_MAX_TILE_THREADS);
@@ -236,6 +245,7 @@ static av_cold int libdav1d_init(AVCodecContext *c)
: FFMIN(ceil(threads / s.n_tile_threads), DAV1D_MAX_FRAME_THREADS);
av_log(c, AV_LOG_DEBUG, "Using %d frame threads, %d tile threads\n",
s.n_frame_threads, s.n_tile_threads);
+#endif
res = libdav1d_parse_extradata(c);
if (res < 0)
@@ -519,11 +529,18 @@ static av_cold int libdav1d_close(AVCodecContext *c)
return 0;
}
+#ifndef DAV1D_MAX_FRAME_THREADS
+#define DAV1D_MAX_FRAME_THREADS DAV1D_MAX_THREADS
+#endif
+#ifndef DAV1D_MAX_TILE_THREADS
+#define DAV1D_MAX_TILE_THREADS DAV1D_MAX_THREADS
+#endif
+
#define OFFSET(x) offsetof(Libdav1dContext, x)
#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
static const AVOption libdav1d_options[] = {
- { "tilethreads", "Tile threads", OFFSET(tile_threads), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, DAV1D_MAX_TILE_THREADS, VD },
- { "framethreads", "Frame threads", OFFSET(frame_threads), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, DAV1D_MAX_FRAME_THREADS, VD },
+ { "tilethreads", "Tile threads", OFFSET(tile_threads), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, DAV1D_MAX_TILE_THREADS, VD | AV_OPT_FLAG_DEPRECATED },
+ { "framethreads", "Frame threads", OFFSET(frame_threads), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, DAV1D_MAX_FRAME_THREADS, VD | AV_OPT_FLAG_DEPRECATED },
{ "filmgrain", "Apply Film Grain", OFFSET(apply_grain), AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, VD | AV_OPT_FLAG_DEPRECATED },
{ "oppoint", "Select an operating point of the scalable bitstream", OFFSET(operating_point), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 31, VD },
{ "alllayers", "Output all spatial layers", OFFSET(all_layers), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VD },

View file

@ -0,0 +1,73 @@
From 8f7c8a0f9e28641880d72996b9452e0a9da1288c Mon Sep 17 00:00:00 2001
From: Lukas Rusak <lorusak@gmail.com>
Date: Wed, 10 Apr 2019 13:39:21 -0700
Subject: [PATCH 1/2] libavcodec/libdav1d: add libdav1d_get_format method to
call ff_get_format
This will allow applications to properly init the decoder in
cases where a hardware decoder is tried first and and software
decoder is tried after by calling the get_format callback.
Even though there is no hardware pixel formats available
we still need to return the software pixel format.
Tested with Kodi by checking if multithreaded software
decoding is properly activated.
---
libavcodec/libdav1d.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/libavcodec/libdav1d.c b/libavcodec/libdav1d.c
index 3c2a68b7e0..68996426cc 100644
--- a/libavcodec/libdav1d.c
+++ b/libavcodec/libdav1d.c
@@ -58,6 +58,16 @@ static const enum AVPixelFormat pix_fmt_rgb[3] = {
AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12,
};
+static enum AVPixelFormat libdav1d_get_format(AVCodecContext *avctx, const Dav1dPicture *p)
+{
+ enum AVPixelFormat pix_fmts[2], *fmt = pix_fmts;
+
+ *fmt++ = pix_fmt[p->p.layout][p->seq_hdr->hbd];
+ *fmt = AV_PIX_FMT_NONE;
+
+ return ff_get_format(avctx, pix_fmts);
+}
+
static void libdav1d_log_callback(void *opaque, const char *fmt, va_list vl)
{
AVCodecContext *c = opaque;
@@ -264,6 +274,7 @@ static int libdav1d_receive_frame(AVCodecContext *c, AVFrame *frame)
c->profile = p->seq_hdr->profile;
c->level = ((p->seq_hdr->operating_points[0].major_level - 2) << 2)
| p->seq_hdr->operating_points[0].minor_level;
+ frame->format = c->pix_fmt = libdav1d_get_format(c, p);
frame->width = p->p.w;
frame->height = p->p.h;
if (c->width != p->p.w || c->height != p->p.h) {
From 635cf67be3d37159c96e75f00399b3e232372251 Mon Sep 17 00:00:00 2001
From: chewitt <github@chrishewitt.net>
Date: Sun, 11 Aug 2019 07:08:19 +0000
Subject: [PATCH 2/2] add long-term yuv2rgb logging patch
---
libswscale/yuv2rgb.c | 4 ----
1 file changed, 4 deletions(-)
diff --git a/libswscale/yuv2rgb.c b/libswscale/yuv2rgb.c
index 6a3956e8e2..d6f9aea166 100644
--- a/libswscale/yuv2rgb.c
+++ b/libswscale/yuv2rgb.c
@@ -688,10 +688,6 @@ SwsFunc ff_yuv2rgb_get_func_ptr(SwsContext *c)
if (t)
return t;
- av_log(c, AV_LOG_WARNING,
- "No accelerated colorspace conversion found from %s to %s.\n",
- av_get_pix_fmt_name(c->srcFormat), av_get_pix_fmt_name(c->dstFormat));
-
switch (c->dstFormat) {
case AV_PIX_FMT_BGR48BE:
case AV_PIX_FMT_BGR48LE:

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,855 @@
From 40a990827399c05ad3ce3f8242321bd8a67aa0bd Mon Sep 17 00:00:00 2001
From: Lukas Rusak <lorusak@gmail.com>
Date: Tue, 24 Apr 2018 23:00:23 -0700
Subject: [PATCH 1/9] libavcodec: v4l2m2m: output AVDRMFrameDescriptor
This allows for a zero-copy output by exporting the v4l2 buffer then wrapping that buffer
in the AVDRMFrameDescriptor like it is done in rkmpp.
This has been in use for quite some time with great success on many platforms including:
- Amlogic S905
- Raspberry Pi
- i.MX6
- Dragonboard 410c
This was developed in conjunction with Kodi to allow handling the zero-copy buffer rendering.
A simply utility for testing is also available here: https://github.com/BayLibre/ffmpeg-drm
todo:
- allow selecting pixel format output from decoder
- allow configuring amount of output and capture buffers
V2:
- allow selecting AV_PIX_FMT_DRM_PRIME
V3:
- use get_format to select AV_PIX_FMT_DRM_PRIME
- use hw_configs
- add handling of AV_PIX_FMT_YUV420P format (for raspberry pi)
- add handling of AV_PIX_FMT_YUYV422 format (for i.MX6 coda decoder)
V4:
- rebased on 4.2.2
V5:
- rebased on 4.3
---
libavcodec/v4l2_buffers.c | 155 ++++++++++++++++++++++++++++++++++++--
libavcodec/v4l2_buffers.h | 4 +
libavcodec/v4l2_context.c | 40 +++++++++-
libavcodec/v4l2_m2m.h | 3 +
libavcodec/v4l2_m2m_dec.c | 23 ++++++
5 files changed, 213 insertions(+), 12 deletions(-)
diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c
index 4b2679eb38..cbd3e5680d 100644
--- a/libavcodec/v4l2_buffers.c
+++ b/libavcodec/v4l2_buffers.c
@@ -21,6 +21,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <drm/drm_fourcc.h>
#include <linux/videodev2.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
@@ -30,6 +31,7 @@
#include "libavcodec/avcodec.h"
#include "libavcodec/internal.h"
#include "libavutil/pixdesc.h"
+#include "libavutil/hwcontext.h"
#include "v4l2_context.h"
#include "v4l2_buffers.h"
#include "v4l2_m2m.h"
@@ -210,7 +212,79 @@ static enum AVColorTransferCharacteristic v4l2_get_color_trc(V4L2Buffer *buf)
return AVCOL_TRC_UNSPECIFIED;
}
-static void v4l2_free_buffer(void *opaque, uint8_t *unused)
+static uint8_t * v4l2_get_drm_frame(V4L2Buffer *avbuf)
+{
+ AVDRMFrameDescriptor *drm_desc = &avbuf->drm_frame;
+ AVDRMLayerDescriptor *layer;
+
+ /* fill the DRM frame descriptor */
+ drm_desc->nb_objects = avbuf->num_planes;
+ drm_desc->nb_layers = 1;
+
+ layer = &drm_desc->layers[0];
+ layer->nb_planes = avbuf->num_planes;
+
+ for (int i = 0; i < avbuf->num_planes; i++) {
+ layer->planes[i].object_index = i;
+ layer->planes[i].offset = 0;
+ layer->planes[i].pitch = avbuf->plane_info[i].bytesperline;
+ }
+
+ switch (avbuf->context->av_pix_fmt) {
+ case AV_PIX_FMT_YUYV422:
+
+ layer->format = DRM_FORMAT_YUYV;
+ layer->nb_planes = 1;
+
+ break;
+
+ case AV_PIX_FMT_NV12:
+ case AV_PIX_FMT_NV21:
+
+ layer->format = avbuf->context->av_pix_fmt == AV_PIX_FMT_NV12 ?
+ DRM_FORMAT_NV12 : DRM_FORMAT_NV21;
+
+ if (avbuf->num_planes > 1)
+ break;
+
+ layer->nb_planes = 2;
+
+ layer->planes[1].object_index = 0;
+ layer->planes[1].offset = avbuf->plane_info[0].bytesperline *
+ avbuf->context->format.fmt.pix.height;
+ layer->planes[1].pitch = avbuf->plane_info[0].bytesperline;
+ break;
+
+ case AV_PIX_FMT_YUV420P:
+
+ layer->format = DRM_FORMAT_YUV420;
+
+ if (avbuf->num_planes > 1)
+ break;
+
+ layer->nb_planes = 3;
+
+ layer->planes[1].object_index = 0;
+ layer->planes[1].offset = avbuf->plane_info[0].bytesperline *
+ avbuf->context->format.fmt.pix.height;
+ layer->planes[1].pitch = avbuf->plane_info[0].bytesperline >> 1;
+
+ layer->planes[2].object_index = 0;
+ layer->planes[2].offset = layer->planes[1].offset +
+ ((avbuf->plane_info[0].bytesperline *
+ avbuf->context->format.fmt.pix.height) >> 2);
+ layer->planes[2].pitch = avbuf->plane_info[0].bytesperline >> 1;
+ break;
+
+ default:
+ drm_desc->nb_layers = 0;
+ break;
+ }
+
+ return (uint8_t *) drm_desc;
+}
+
+static void v4l2_free_buffer(void *opaque, uint8_t *data)
{
V4L2Buffer* avbuf = opaque;
V4L2m2mContext *s = buf_to_m2mctx(avbuf);
@@ -234,6 +308,36 @@ static void v4l2_free_buffer(void *opaque, uint8_t *unused)
}
}
+static int v4l2_buffer_export_drm(V4L2Buffer* avbuf)
+{
+ struct v4l2_exportbuffer expbuf;
+ int i, ret;
+
+ for (i = 0; i < avbuf->num_planes; i++) {
+ memset(&expbuf, 0, sizeof(expbuf));
+
+ expbuf.index = avbuf->buf.index;
+ expbuf.type = avbuf->buf.type;
+ expbuf.plane = i;
+
+ ret = ioctl(buf_to_m2mctx(avbuf)->fd, VIDIOC_EXPBUF, &expbuf);
+ if (ret < 0)
+ return AVERROR(errno);
+
+ if (V4L2_TYPE_IS_MULTIPLANAR(avbuf->buf.type)) {
+ /* drm frame */
+ avbuf->drm_frame.objects[i].size = avbuf->buf.m.planes[i].length;
+ avbuf->drm_frame.objects[i].fd = expbuf.fd;
+ } else {
+ /* drm frame */
+ avbuf->drm_frame.objects[0].size = avbuf->buf.length;
+ avbuf->drm_frame.objects[0].fd = expbuf.fd;
+ }
+ }
+
+ return 0;
+}
+
static int v4l2_buf_increase_ref(V4L2Buffer *in)
{
V4L2m2mContext *s = buf_to_m2mctx(in);
@@ -254,6 +358,24 @@ static int v4l2_buf_increase_ref(V4L2Buffer *in)
return 0;
}
+static int v4l2_buf_to_bufref_drm(V4L2Buffer *in, AVBufferRef **buf)
+{
+ int ret;
+
+ *buf = av_buffer_create((uint8_t *) &in->drm_frame,
+ sizeof(in->drm_frame),
+ v4l2_free_buffer,
+ in, AV_BUFFER_FLAG_READONLY);
+ if (!*buf)
+ return AVERROR(ENOMEM);
+
+ ret = v4l2_buf_increase_ref(in);
+ if (ret)
+ av_buffer_unref(buf);
+
+ return ret;
+}
+
static int v4l2_buf_to_bufref(V4L2Buffer *in, int plane, AVBufferRef **buf)
{
int ret;
@@ -303,13 +425,24 @@ static int v4l2_buffer_buf_to_swframe(AVFrame *frame, V4L2Buffer *avbuf)
frame->format = avbuf->context->av_pix_fmt;
- for (i = 0; i < avbuf->num_planes; i++) {
- ret = v4l2_buf_to_bufref(avbuf, i, &frame->buf[i]);
+ if (buf_to_m2mctx(avbuf)->output_drm) {
+ /* 1. get references to the actual data */
+ ret = v4l2_buf_to_bufref_drm(avbuf, &frame->buf[0]);
if (ret)
return ret;
- frame->linesize[i] = avbuf->plane_info[i].bytesperline;
- frame->data[i] = frame->buf[i]->data;
+ frame->data[0] = (uint8_t *) v4l2_get_drm_frame(avbuf);
+ frame->format = AV_PIX_FMT_DRM_PRIME;
+ } else {
+ /* 1. get references to the actual data */
+ for (i = 0; i < avbuf->num_planes; i++) {
+ ret = v4l2_buf_to_bufref(avbuf, i, &frame->buf[i]);
+ if (ret)
+ return ret;
+
+ frame->linesize[i] = avbuf->plane_info[i].bytesperline;
+ frame->data[i] = frame->buf[i]->data;
+ }
}
/* fixup special cases */
@@ -543,9 +676,6 @@ int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index)
avbuf->status = V4L2BUF_AVAILABLE;
- if (V4L2_TYPE_IS_OUTPUT(ctx->type))
- return 0;
-
if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type)) {
avbuf->buf.m.planes = avbuf->planes;
avbuf->buf.length = avbuf->num_planes;
@@ -555,6 +685,15 @@ int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index)
avbuf->buf.length = avbuf->planes[0].length;
}
+ if (V4L2_TYPE_IS_OUTPUT(ctx->type))
+ return 0;
+
+ if (buf_to_m2mctx(avbuf)->output_drm) {
+ ret = v4l2_buffer_export_drm(avbuf);
+ if (ret)
+ return ret;
+ }
+
return ff_v4l2_buffer_enqueue(avbuf);
}
diff --git a/libavcodec/v4l2_buffers.h b/libavcodec/v4l2_buffers.h
index 8dbc7fc104..037e667997 100644
--- a/libavcodec/v4l2_buffers.h
+++ b/libavcodec/v4l2_buffers.h
@@ -27,6 +27,7 @@
#include <stdatomic.h>
#include <linux/videodev2.h>
+#include "libavutil/hwcontext_drm.h"
#include "avcodec.h"
enum V4L2Buffer_status {
@@ -42,6 +43,9 @@ typedef struct V4L2Buffer {
/* each buffer needs to have a reference to its context */
struct V4L2Context *context;
+ /* DRM descriptor */
+ AVDRMFrameDescriptor drm_frame;
+
/* This object is refcounted per-plane, so we need to keep track
* of how many context-refs we are holding. */
AVBufferRef *context_ref;
diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c
index ff1ea8e57b..e9e8c27a54 100644
--- a/libavcodec/v4l2_context.c
+++ b/libavcodec/v4l2_context.c
@@ -455,22 +455,54 @@ static int v4l2_release_buffers(V4L2Context* ctx)
struct v4l2_requestbuffers req = {
.memory = V4L2_MEMORY_MMAP,
.type = ctx->type,
- .count = 0, /* 0 -> unmaps buffers from the driver */
+ .count = 0, /* 0 -> unmap all buffers from the driver */
};
- int i, j;
+ int ret, i, j;
for (i = 0; i < ctx->num_buffers; i++) {
V4L2Buffer *buffer = &ctx->buffers[i];
for (j = 0; j < buffer->num_planes; j++) {
struct V4L2Plane_info *p = &buffer->plane_info[j];
+
+ if (V4L2_TYPE_IS_OUTPUT(ctx->type)) {
+ /* output buffers are not EXPORTED */
+ goto unmap;
+ }
+
+ if (ctx_to_m2mctx(ctx)->output_drm) {
+ /* use the DRM frame to close */
+ if (buffer->drm_frame.objects[j].fd >= 0) {
+ if (close(buffer->drm_frame.objects[j].fd) < 0) {
+ av_log(logger(ctx), AV_LOG_ERROR, "%s close drm fd "
+ "[buffer=%2d, plane=%d, fd=%2d] - %s \n",
+ ctx->name, i, j, buffer->drm_frame.objects[j].fd,
+ av_err2str(AVERROR(errno)));
+ }
+ }
+ }
+unmap:
if (p->mm_addr && p->length)
if (munmap(p->mm_addr, p->length) < 0)
- av_log(logger(ctx), AV_LOG_ERROR, "%s unmap plane (%s))\n", ctx->name, av_err2str(AVERROR(errno)));
+ av_log(logger(ctx), AV_LOG_ERROR, "%s unmap plane (%s))\n",
+ ctx->name, av_err2str(AVERROR(errno)));
}
}
- return ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_REQBUFS, &req);
+ ret = ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_REQBUFS, &req);
+ if (ret < 0) {
+ av_log(logger(ctx), AV_LOG_ERROR, "release all %s buffers (%s)\n",
+ ctx->name, av_err2str(AVERROR(errno)));
+
+ if (ctx_to_m2mctx(ctx)->output_drm)
+ av_log(logger(ctx), AV_LOG_ERROR,
+ "Make sure the DRM client releases all FB/GEM objects before closing the codec (ie):\n"
+ "for all buffers: \n"
+ " 1. drmModeRmFB(..)\n"
+ " 2. drmIoctl(.., DRM_IOCTL_GEM_CLOSE,... )\n");
+ }
+
+ return ret;
}
static inline int v4l2_try_raw_format(V4L2Context* ctx, enum AVPixelFormat pixfmt)
diff --git a/libavcodec/v4l2_m2m.h b/libavcodec/v4l2_m2m.h
index b67b216331..0fbd19a013 100644
--- a/libavcodec/v4l2_m2m.h
+++ b/libavcodec/v4l2_m2m.h
@@ -66,6 +66,9 @@ typedef struct V4L2m2mContext {
/* reference back to V4L2m2mPriv */
void *priv;
+
+ /* generate DRM frames */
+ int output_drm;
} V4L2m2mContext;
typedef struct V4L2m2mPriv {
diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c
index ab07c0a24a..6bc7442702 100644
--- a/libavcodec/v4l2_m2m_dec.c
+++ b/libavcodec/v4l2_m2m_dec.c
@@ -23,6 +23,9 @@
#include <linux/videodev2.h>
#include <sys/ioctl.h>
+
+#include "libavutil/hwcontext.h"
+#include "libavutil/hwcontext_drm.h"
#include "libavutil/pixfmt.h"
#include "libavutil/pixdesc.h"
#include "libavutil/opt.h"
@@ -30,6 +33,9 @@
#include "libavcodec/decode.h"
#include "libavcodec/internal.h"
+#include "libavcodec/hwaccels.h"
+#include "libavcodec/internal.h"
+
#include "v4l2_context.h"
#include "v4l2_m2m.h"
#include "v4l2_fmt.h"
@@ -201,6 +207,15 @@ static av_cold int v4l2_decode_init(AVCodecContext *avctx)
capture->av_codec_id = AV_CODEC_ID_RAWVIDEO;
capture->av_pix_fmt = avctx->pix_fmt;
+ /* the client requests the codec to generate DRM frames:
+ * - data[0] will therefore point to the returned AVDRMFrameDescriptor
+ * check the ff_v4l2_buffer_to_avframe conversion function.
+ * - the DRM frame format is passed in the DRM frame descriptor layer.
+ * check the v4l2_get_drm_frame function.
+ */
+ if (ff_get_format(avctx, avctx->codec->pix_fmts) == AV_PIX_FMT_DRM_PRIME)
+ s->output_drm = 1;
+
s->avctx = avctx;
ret = ff_v4l2_m2m_codec_init(priv);
if (ret) {
@@ -226,6 +241,11 @@ static const AVOption options[] = {
{ NULL},
};
+static const AVCodecHWConfigInternal *v4l2_m2m_hw_configs[] = {
+ HW_CONFIG_INTERNAL(DRM_PRIME),
+ NULL
+};
+
#define M2MDEC_CLASS(NAME) \
static const AVClass v4l2_m2m_ ## NAME ## _dec_class = { \
.class_name = #NAME "_v4l2m2m_decoder", \
@@ -249,6 +269,9 @@ static const AVOption options[] = {
.bsfs = bsf_name, \
.capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING, \
.caps_internal = FF_CODEC_CAP_SETS_PKT_DTS | FF_CODEC_CAP_INIT_CLEANUP, \
+ .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_DRM_PRIME, \
+ AV_PIX_FMT_NONE}, \
+ .hw_configs = v4l2_m2m_hw_configs, \
.wrapper_name = "v4l2m2m", \
}
From 9a2a361c2c84c8da54cd3a74b0d0bb966df8fe69 Mon Sep 17 00:00:00 2001
From: Lukas Rusak <lorusak@gmail.com>
Date: Thu, 16 Aug 2018 21:09:40 -0700
Subject: [PATCH 2/9] libavcodec: v4l2m2m: depends on libdrm
---
configure | 1 +
libavcodec/v4l2_buffers.c | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/configure b/configure
index d7a3f507e8..d203f6f7da 100755
--- a/configure
+++ b/configure
@@ -3437,6 +3437,7 @@ sndio_indev_deps="sndio"
sndio_outdev_deps="sndio"
v4l2_indev_deps_any="linux_videodev2_h sys_videoio_h"
v4l2_indev_suggest="libv4l2"
+v4l2_outdev_deps="libdrm"
v4l2_outdev_deps_any="linux_videodev2_h sys_videoio_h"
v4l2_outdev_suggest="libv4l2"
vfwcap_indev_deps="vfw32 vfwcap_defines"
diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c
index cbd3e5680d..bebe2c1796 100644
--- a/libavcodec/v4l2_buffers.c
+++ b/libavcodec/v4l2_buffers.c
@@ -21,7 +21,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include <drm/drm_fourcc.h>
+#include <drm_fourcc.h>
#include <linux/videodev2.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
From 7b0fa2d859c12a8a129c884d16673ca731336c06 Mon Sep 17 00:00:00 2001
From: Lukas Rusak <lorusak@gmail.com>
Date: Thu, 16 Aug 2018 21:10:13 -0700
Subject: [PATCH 3/9] libavcodec: v4l2m2m: set format_modifier to
DRM_FORMAT_MOD_LINEAR
---
libavcodec/v4l2_buffers.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c
index bebe2c1796..12037d5d66 100644
--- a/libavcodec/v4l2_buffers.c
+++ b/libavcodec/v4l2_buffers.c
@@ -328,10 +328,12 @@ static int v4l2_buffer_export_drm(V4L2Buffer* avbuf)
/* drm frame */
avbuf->drm_frame.objects[i].size = avbuf->buf.m.planes[i].length;
avbuf->drm_frame.objects[i].fd = expbuf.fd;
+ avbuf->drm_frame.objects[i].format_modifier = DRM_FORMAT_MOD_LINEAR;
} else {
/* drm frame */
avbuf->drm_frame.objects[0].size = avbuf->buf.length;
avbuf->drm_frame.objects[0].fd = expbuf.fd;
+ avbuf->drm_frame.objects[0].format_modifier = DRM_FORMAT_MOD_LINEAR;
}
}
From e1857456c8f24e40d5c898886f2f51014e59ee9d Mon Sep 17 00:00:00 2001
From: Lukas Rusak <lorusak@gmail.com>
Date: Thu, 16 Aug 2018 21:10:53 -0700
Subject: [PATCH 4/9] libavcodec: v4l2m2m: only mmap the buffer when it is
output type and drm prime is used
---
libavcodec/v4l2_buffers.c | 20 ++++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c
index 12037d5d66..1adf518ab9 100644
--- a/libavcodec/v4l2_buffers.c
+++ b/libavcodec/v4l2_buffers.c
@@ -662,14 +662,22 @@ int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index)
if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type)) {
avbuf->plane_info[i].length = avbuf->buf.m.planes[i].length;
- avbuf->plane_info[i].mm_addr = mmap(NULL, avbuf->buf.m.planes[i].length,
- PROT_READ | PROT_WRITE, MAP_SHARED,
- buf_to_m2mctx(avbuf)->fd, avbuf->buf.m.planes[i].m.mem_offset);
+
+ if ((V4L2_TYPE_IS_OUTPUT(ctx->type) && buf_to_m2mctx(avbuf)->output_drm) ||
+ !buf_to_m2mctx(avbuf)->output_drm) {
+ avbuf->plane_info[i].mm_addr = mmap(NULL, avbuf->buf.m.planes[i].length,
+ PROT_READ | PROT_WRITE, MAP_SHARED,
+ buf_to_m2mctx(avbuf)->fd, avbuf->buf.m.planes[i].m.mem_offset);
+ }
} else {
avbuf->plane_info[i].length = avbuf->buf.length;
- avbuf->plane_info[i].mm_addr = mmap(NULL, avbuf->buf.length,
- PROT_READ | PROT_WRITE, MAP_SHARED,
- buf_to_m2mctx(avbuf)->fd, avbuf->buf.m.offset);
+
+ if ((V4L2_TYPE_IS_OUTPUT(ctx->type) && buf_to_m2mctx(avbuf)->output_drm) ||
+ !buf_to_m2mctx(avbuf)->output_drm) {
+ avbuf->plane_info[i].mm_addr = mmap(NULL, avbuf->buf.length,
+ PROT_READ | PROT_WRITE, MAP_SHARED,
+ buf_to_m2mctx(avbuf)->fd, avbuf->buf.m.offset);
+ }
}
if (avbuf->plane_info[i].mm_addr == MAP_FAILED)
From c8fc3ea1b5777546f7ec72a54b053a2d4fa9fd59 Mon Sep 17 00:00:00 2001
From: Lukas Rusak <lorusak@gmail.com>
Date: Thu, 16 Aug 2018 21:11:38 -0700
Subject: [PATCH 5/9] libavcodec: v4l2m2m: allow using software pixel formats
---
libavcodec/v4l2_m2m_dec.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c
index 6bc7442702..4b9baf833c 100644
--- a/libavcodec/v4l2_m2m_dec.c
+++ b/libavcodec/v4l2_m2m_dec.c
@@ -213,8 +213,16 @@ static av_cold int v4l2_decode_init(AVCodecContext *avctx)
* - the DRM frame format is passed in the DRM frame descriptor layer.
* check the v4l2_get_drm_frame function.
*/
- if (ff_get_format(avctx, avctx->codec->pix_fmts) == AV_PIX_FMT_DRM_PRIME)
+ switch (ff_get_format(avctx, avctx->codec->pix_fmts)) {
+ case AV_PIX_FMT_DRM_PRIME:
s->output_drm = 1;
+ break;
+ case AV_PIX_FMT_NONE:
+ return 0;
+ break;
+ default:
+ break;
+ }
s->avctx = avctx;
ret = ff_v4l2_m2m_codec_init(priv);
@@ -270,6 +278,7 @@ static const AVCodecHWConfigInternal *v4l2_m2m_hw_configs[] = {
.capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING, \
.caps_internal = FF_CODEC_CAP_SETS_PKT_DTS | FF_CODEC_CAP_INIT_CLEANUP, \
.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_DRM_PRIME, \
+ AV_PIX_FMT_NV12, \
AV_PIX_FMT_NONE}, \
.hw_configs = v4l2_m2m_hw_configs, \
.wrapper_name = "v4l2m2m", \
From 13f02e940f083f19dbe8b9ac8fc7df45700dd36e Mon Sep 17 00:00:00 2001
From: Lukas Rusak <lorusak@gmail.com>
Date: Mon, 24 Sep 2018 13:39:31 -0700
Subject: [PATCH 6/9] libavcodec: v4l2m2m: implement hwcontext
---
libavcodec/v4l2_buffers.c | 22 ++++++++++++++++++++++
libavcodec/v4l2_context.h | 2 ++
libavcodec/v4l2_m2m.h | 2 ++
libavcodec/v4l2_m2m_dec.c | 11 +++++++++++
4 files changed, 37 insertions(+)
diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c
index 1adf518ab9..6e2a544394 100644
--- a/libavcodec/v4l2_buffers.c
+++ b/libavcodec/v4l2_buffers.c
@@ -435,6 +435,7 @@ static int v4l2_buffer_buf_to_swframe(AVFrame *frame, V4L2Buffer *avbuf)
frame->data[0] = (uint8_t *) v4l2_get_drm_frame(avbuf);
frame->format = AV_PIX_FMT_DRM_PRIME;
+ frame->hw_frames_ctx = av_buffer_ref(avbuf->context->frames_ref);
} else {
/* 1. get references to the actual data */
for (i = 0; i < avbuf->num_planes; i++) {
@@ -635,6 +636,27 @@ int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index)
avbuf->buf.type = ctx->type;
avbuf->buf.index = index;
+ if (buf_to_m2mctx(avbuf)->output_drm) {
+ AVHWFramesContext *hwframes;
+
+ av_buffer_unref(&ctx->frames_ref);
+
+ ctx->frames_ref = av_hwframe_ctx_alloc(buf_to_m2mctx(avbuf)->device_ref);
+ if (!ctx->frames_ref) {
+ ret = AVERROR(ENOMEM);
+ return ret;
+ }
+
+ hwframes = (AVHWFramesContext*)ctx->frames_ref->data;
+ hwframes->format = AV_PIX_FMT_DRM_PRIME;
+ hwframes->sw_format = ctx->av_pix_fmt;
+ hwframes->width = ctx->width;
+ hwframes->height = ctx->height;
+ ret = av_hwframe_ctx_init(ctx->frames_ref);
+ if (ret < 0)
+ return ret;
+ }
+
if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type)) {
avbuf->buf.length = VIDEO_MAX_PLANES;
avbuf->buf.m.planes = avbuf->planes;
diff --git a/libavcodec/v4l2_context.h b/libavcodec/v4l2_context.h
index 22a9532444..e804e94131 100644
--- a/libavcodec/v4l2_context.h
+++ b/libavcodec/v4l2_context.h
@@ -92,6 +92,8 @@ typedef struct V4L2Context {
*/
int done;
+ AVBufferRef *frames_ref;
+
} V4L2Context;
/**
diff --git a/libavcodec/v4l2_m2m.h b/libavcodec/v4l2_m2m.h
index 0fbd19a013..adf5997bb5 100644
--- a/libavcodec/v4l2_m2m.h
+++ b/libavcodec/v4l2_m2m.h
@@ -67,6 +67,8 @@ typedef struct V4L2m2mContext {
/* reference back to V4L2m2mPriv */
void *priv;
+ AVBufferRef *device_ref;
+
/* generate DRM frames */
int output_drm;
} V4L2m2mContext;
diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c
index 4b9baf833c..6c23693137 100644
--- a/libavcodec/v4l2_m2m_dec.c
+++ b/libavcodec/v4l2_m2m_dec.c
@@ -35,6 +35,7 @@
#include "libavcodec/hwaccels.h"
#include "libavcodec/internal.h"
+#include "libavcodec/hwconfig.h"
#include "v4l2_context.h"
#include "v4l2_m2m.h"
@@ -224,6 +225,16 @@ static av_cold int v4l2_decode_init(AVCodecContext *avctx)
break;
}
+ s->device_ref = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_DRM);
+ if (!s->device_ref) {
+ ret = AVERROR(ENOMEM);
+ return ret;
+ }
+
+ ret = av_hwdevice_ctx_init(s->device_ref);
+ if (ret < 0)
+ return ret;
+
s->avctx = avctx;
ret = ff_v4l2_m2m_codec_init(priv);
if (ret) {
From 34be198b8039c9df434792f19f0985e45419407e Mon Sep 17 00:00:00 2001
From: Lukas Rusak <lorusak@gmail.com>
Date: Mon, 4 May 2020 13:01:29 -0700
Subject: [PATCH 7/9] libavcodec: v4l2m2m: allow lower minimum buffer values
There is no reason to enforce a high minimum. In the context
of streaming only a few output buffers and capture buffers
are even needed for continuous playback. This also helps
alleviate memory pressure when decoding 4K media.
---
libavcodec/v4l2_m2m.h | 2 +-
libavcodec/v4l2_m2m_dec.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/libavcodec/v4l2_m2m.h b/libavcodec/v4l2_m2m.h
index adf5997bb5..1082b9dad2 100644
--- a/libavcodec/v4l2_m2m.h
+++ b/libavcodec/v4l2_m2m.h
@@ -38,7 +38,7 @@
#define V4L_M2M_DEFAULT_OPTS \
{ "num_output_buffers", "Number of buffers in the output context",\
- OFFSET(num_output_buffers), AV_OPT_TYPE_INT, { .i64 = 16 }, 6, INT_MAX, FLAGS }
+ OFFSET(num_output_buffers), AV_OPT_TYPE_INT, { .i64 = 16 }, 2, INT_MAX, FLAGS }
typedef struct V4L2m2mContext {
char devname[PATH_MAX];
diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c
index 6c23693137..e323c37052 100644
--- a/libavcodec/v4l2_m2m_dec.c
+++ b/libavcodec/v4l2_m2m_dec.c
@@ -256,7 +256,7 @@ static av_cold int v4l2_decode_close(AVCodecContext *avctx)
static const AVOption options[] = {
V4L_M2M_DEFAULT_OPTS,
{ "num_capture_buffers", "Number of buffers in the capture context",
- OFFSET(num_capture_buffers), AV_OPT_TYPE_INT, {.i64 = 20}, 20, INT_MAX, FLAGS },
+ OFFSET(num_capture_buffers), AV_OPT_TYPE_INT, {.i64 = 20}, 2, INT_MAX, FLAGS },
{ NULL},
};
From 2956fd1881d28abf6bf77bd9a57866c4ba81d199 Mon Sep 17 00:00:00 2001
From: Lukas Rusak <lorusak@gmail.com>
Date: Wed, 6 May 2020 11:12:58 -0700
Subject: [PATCH 8/9] libavcodec: v4l2m2m: add option to specify pixel format
used by the decoder
---
libavcodec/v4l2_context.c | 9 +++++++++
libavcodec/v4l2_m2m.h | 2 ++
libavcodec/v4l2_m2m_dec.c | 1 +
3 files changed, 12 insertions(+)
diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c
index e9e8c27a54..a97b70e836 100644
--- a/libavcodec/v4l2_context.c
+++ b/libavcodec/v4l2_context.c
@@ -531,6 +531,8 @@ static inline int v4l2_try_raw_format(V4L2Context* ctx, enum AVPixelFormat pixfm
static int v4l2_get_raw_format(V4L2Context* ctx, enum AVPixelFormat *p)
{
+ V4L2m2mContext* s = ctx_to_m2mctx(ctx);
+ V4L2m2mPriv *priv = s->avctx->priv_data;
enum AVPixelFormat pixfmt = ctx->av_pix_fmt;
struct v4l2_fmtdesc fdesc;
int ret;
@@ -549,6 +551,13 @@ static int v4l2_get_raw_format(V4L2Context* ctx, enum AVPixelFormat *p)
if (ret)
return AVERROR(EINVAL);
+ if (priv->pix_fmt != AV_PIX_FMT_NONE) {
+ if (fdesc.pixelformat != ff_v4l2_format_avfmt_to_v4l2(priv->pix_fmt)) {
+ fdesc.index++;
+ continue;
+ }
+ }
+
pixfmt = ff_v4l2_format_v4l2_to_avfmt(fdesc.pixelformat, AV_CODEC_ID_RAWVIDEO);
ret = v4l2_try_raw_format(ctx, pixfmt);
if (ret){
diff --git a/libavcodec/v4l2_m2m.h b/libavcodec/v4l2_m2m.h
index 1082b9dad2..943a8923c4 100644
--- a/libavcodec/v4l2_m2m.h
+++ b/libavcodec/v4l2_m2m.h
@@ -30,6 +30,7 @@
#include <linux/videodev2.h>
#include "libavcodec/avcodec.h"
+#include "libavutil/pixfmt.h"
#include "v4l2_context.h"
#define container_of(ptr, type, member) ({ \
@@ -81,6 +82,7 @@ typedef struct V4L2m2mPriv {
int num_output_buffers;
int num_capture_buffers;
+ enum AVPixelFormat pix_fmt;
} V4L2m2mPriv;
/**
diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c
index e323c37052..363e998142 100644
--- a/libavcodec/v4l2_m2m_dec.c
+++ b/libavcodec/v4l2_m2m_dec.c
@@ -257,6 +257,7 @@ static const AVOption options[] = {
V4L_M2M_DEFAULT_OPTS,
{ "num_capture_buffers", "Number of buffers in the capture context",
OFFSET(num_capture_buffers), AV_OPT_TYPE_INT, {.i64 = 20}, 2, INT_MAX, FLAGS },
+ { "pixel_format", "Pixel format to be used by the decoder", OFFSET(pix_fmt), AV_OPT_TYPE_PIXEL_FMT, {.i64 = AV_PIX_FMT_NONE}, AV_PIX_FMT_NONE, AV_PIX_FMT_NB, FLAGS },
{ NULL},
};
From 2bb6d0cb244590f0c70dd111ed978cd87fa3bee1 Mon Sep 17 00:00:00 2001
From: Lukas Rusak <lorusak@gmail.com>
Date: Mon, 24 Sep 2018 13:39:56 -0700
Subject: [PATCH 9/9] libavcodec: v4l2m2m: implement flush
---
libavcodec/v4l2_m2m_dec.c | 36 ++++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c
index 363e998142..52ec67cb59 100644
--- a/libavcodec/v4l2_m2m_dec.c
+++ b/libavcodec/v4l2_m2m_dec.c
@@ -250,6 +250,41 @@ static av_cold int v4l2_decode_close(AVCodecContext *avctx)
return ff_v4l2_m2m_codec_end(avctx->priv_data);
}
+static void v4l2_decode_flush(AVCodecContext *avctx)
+{
+ V4L2m2mPriv *priv = avctx->priv_data;
+ V4L2m2mContext* s = priv->context;
+ V4L2Context* output = &s->output;
+ V4L2Context* capture = &s->capture;
+ int ret, i;
+
+ ret = ff_v4l2_context_set_status(output, VIDIOC_STREAMOFF);
+ if (ret < 0)
+ av_log(avctx, AV_LOG_ERROR, "VIDIOC_STREAMOFF %s error: %d\n", output->name, ret);
+
+ ret = ff_v4l2_context_set_status(output, VIDIOC_STREAMON);
+ if (ret < 0)
+ av_log(avctx, AV_LOG_ERROR, "VIDIOC_STREAMON %s error: %d\n", output->name, ret);
+
+ for (i = 0; i < output->num_buffers; i++) {
+ if (output->buffers[i].status == V4L2BUF_IN_DRIVER)
+ output->buffers[i].status = V4L2BUF_AVAILABLE;
+ }
+
+ struct v4l2_decoder_cmd cmd = {
+ .cmd = V4L2_DEC_CMD_START,
+ .flags = 0,
+ };
+
+ ret = ioctl(s->fd, VIDIOC_DECODER_CMD, &cmd);
+ if (ret < 0)
+ av_log(avctx, AV_LOG_ERROR, "VIDIOC_DECODER_CMD start error: %d\n", errno);
+
+ s->draining = 0;
+ output->done = 0;
+ capture->done = 0;
+}
+
#define OFFSET(x) offsetof(V4L2m2mPriv, x)
#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
@@ -286,6 +321,7 @@ static const AVCodecHWConfigInternal *v4l2_m2m_hw_configs[] = {
.init = v4l2_decode_init, \
.receive_frame = v4l2_receive_frame, \
.close = v4l2_decode_close, \
+ .flush = v4l2_decode_flush, \
.bsfs = bsf_name, \
.capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING, \
.caps_internal = FF_CODEC_CAP_SETS_PKT_DTS | FF_CODEC_CAP_INIT_CLEANUP, \

File diff suppressed because it is too large Load diff