mirror of
https://github.com/LibreELEC/LibreELEC.tv.git
synced 2025-07-24 11:16:51 +00:00
Merge pull request #7043 from HiassofT/le11-ffmpeg-5.1.2
ffmpeg: update to 5.1.2
This commit is contained in:
commit
341c3dbd4b
@ -3,14 +3,14 @@
|
||||
# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv)
|
||||
|
||||
PKG_NAME="ffmpeg"
|
||||
PKG_VERSION="4.4.1"
|
||||
PKG_SHA256="eadbad9e9ab30b25f5520fbfde99fae4a92a1ae3c0257a8d68569a4651e30e02"
|
||||
PKG_VERSION="5.1.2"
|
||||
PKG_SHA256="619e706d662c8420859832ddc259cd4d4096a48a2ce1eefd052db9e440eef3dc"
|
||||
PKG_LICENSE="GPL-3.0-only"
|
||||
PKG_SITE="https://ffmpeg.org"
|
||||
PKG_URL="http://ffmpeg.org/releases/ffmpeg-${PKG_VERSION}.tar.xz"
|
||||
PKG_DEPENDS_TARGET="toolchain zlib bzip2 openssl speex"
|
||||
PKG_LONGDESC="FFmpeg is a complete, cross-platform solution to record, convert and stream audio and video."
|
||||
PKG_PATCH_DIRS="kodi libreelec"
|
||||
PKG_PATCH_DIRS="libreelec"
|
||||
|
||||
case "${PROJECT}" in
|
||||
Amlogic)
|
||||
@ -18,14 +18,17 @@ case "${PROJECT}" in
|
||||
PKG_FFMPEG_BRANCH="dev/4.4/rpi_import_1"
|
||||
PKG_SHA256="3b42cbffd15d95d59e402475fcdb1aaac9ae6a8404a521b95d1fe79c6b2baad4"
|
||||
PKG_URL="https://github.com/jc-kynesim/rpi-ffmpeg/archive/${PKG_VERSION}.tar.gz"
|
||||
PKG_PATCH_DIRS="libreelec dav1d"
|
||||
;;
|
||||
RPi)
|
||||
PKG_FFMPEG_RPI="--disable-mmal --disable-rpi --enable-sand"
|
||||
PKG_FFMPEG_RPI="--disable-mmal --enable-sand"
|
||||
PKG_PATCH_DIRS+=" rpi"
|
||||
;;
|
||||
*)
|
||||
PKG_PATCH_DIRS+=" v4l2-request v4l2-drmprime"
|
||||
case "${PROJECT}" in
|
||||
Allwinner|Rockchip)
|
||||
PKG_PATCH_DIRS+=" vf-deinterlace-v4l2m2m"
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
|
||||
@ -48,14 +51,8 @@ if [ "${V4L2_SUPPORT}" = "yes" ]; then
|
||||
PKG_NEED_UNPACK+=" $(get_pkg_directory libdrm)"
|
||||
PKG_FFMPEG_V4L2="--enable-v4l2_m2m --enable-libdrm"
|
||||
|
||||
if [ "${PROJECT}" = "Allwinner" -o "${PROJECT}" = "Rockchip" -o "${DEVICE}" = "iMX8" ]; then
|
||||
if [ "${PROJECT}" = "Allwinner" -o "${PROJECT}" = "Rockchip" -o "${DEVICE}" = "iMX8" -o "${DEVICE}" = "RPi4" ]; then
|
||||
PKG_V4L2_REQUEST="yes"
|
||||
elif [ "${PROJECT}" = "RPi" -a "${DEVICE}" = "RPi4" ]; then
|
||||
PKG_V4L2_REQUEST="yes"
|
||||
PKG_FFMPEG_HWACCEL="--disable-hwaccel=h264_v4l2request \
|
||||
--disable-hwaccel=mpeg2_v4l2request \
|
||||
--disable-hwaccel=vp8_v4l2request \
|
||||
--disable-hwaccel=vp9_v4l2request"
|
||||
else
|
||||
PKG_V4L2_REQUEST="no"
|
||||
fi
|
||||
|
@ -1,124 +0,0 @@
|
||||
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 },
|
@ -1,44 +0,0 @@
|
||||
From 1d23e125b6f76e74b754560c3b6931507cacddce Mon Sep 17 00:00:00 2001
|
||||
From: Timo Rothenpieler <timo@rothenpieler.org>
|
||||
Date: Tue, 7 Sep 2021 19:35:31 +0200
|
||||
Subject: [PATCH] configure: account for openssl3 license change
|
||||
|
||||
---
|
||||
configure | 7 +++++--
|
||||
1 file changed, 5 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/configure b/configure
|
||||
index c87a010387..ed7345b2c1 100755
|
||||
--- a/configure
|
||||
+++ b/configure
|
||||
@@ -1765,7 +1765,6 @@ EXTERNAL_LIBRARY_GPL_LIST="
|
||||
EXTERNAL_LIBRARY_NONFREE_LIST="
|
||||
decklink
|
||||
libfdk_aac
|
||||
- openssl
|
||||
libtls
|
||||
"
|
||||
|
||||
@@ -1857,6 +1856,7 @@ EXTERNAL_LIBRARY_LIST="
|
||||
mediacodec
|
||||
openal
|
||||
opengl
|
||||
+ openssl
|
||||
pocketsphinx
|
||||
vapoursynth
|
||||
"
|
||||
@@ -6572,7 +6572,10 @@ enabled omx_rpi && { test_code cc OMX_Core.h OMX_IndexConfigBrcmVideoR
|
||||
die "ERROR: OpenMAX IL headers from raspberrypi/firmware not found"; } &&
|
||||
enable omx
|
||||
enabled omx && require_headers OMX_Core.h
|
||||
-enabled openssl && { check_pkg_config openssl openssl openssl/ssl.h OPENSSL_init_ssl ||
|
||||
+enabled openssl && { { check_pkg_config openssl "openssl >= 3.0.0" openssl/ssl.h OPENSSL_init_ssl &&
|
||||
+ { enabled gplv3 || ! enabled gpl || enabled nonfree || die "ERROR: OpenSSL >=3.0.0 requires --enable-version3"; }; } ||
|
||||
+ { enabled gpl && ! enabled nonfree && die "ERROR: OpenSSL <3.0.0 is incompatible with the gpl"; } ||
|
||||
+ check_pkg_config openssl openssl openssl/ssl.h OPENSSL_init_ssl ||
|
||||
check_pkg_config openssl openssl openssl/ssl.h SSL_library_init ||
|
||||
check_lib openssl openssl/ssl.h OPENSSL_init_ssl -lssl -lcrypto ||
|
||||
check_lib openssl openssl/ssl.h SSL_library_init -lssl -lcrypto ||
|
||||
--
|
||||
2.34.1
|
||||
|
@ -1,880 +0,0 @@
|
||||
From 5180cdc317139414eedcb49627d240519435b104 Mon Sep 17 00:00:00 2001
|
||||
From: marc <mhocking@ubuntu-desktop.(none)>
|
||||
Date: Mon, 18 Feb 2013 17:18:18 +0000
|
||||
Subject: [PATCH 01/15] dxva-h264: Fix an AMD driver issue with playback of
|
||||
streams that don't start with an I-Frame
|
||||
|
||||
---
|
||||
libavcodec/dxva2_h264.c | 8 ++++++++
|
||||
libavcodec/h264_slice.c | 1 +
|
||||
libavcodec/h264dec.c | 1 +
|
||||
libavcodec/h264dec.h | 2 ++
|
||||
4 files changed, 12 insertions(+)
|
||||
|
||||
diff --git a/libavcodec/dxva2_h264.c b/libavcodec/dxva2_h264.c
|
||||
index 5b23b28f12..c0a8d80f3b 100644
|
||||
--- a/libavcodec/dxva2_h264.c
|
||||
+++ b/libavcodec/dxva2_h264.c
|
||||
@@ -504,6 +504,14 @@ static int dxva2_h264_end_frame(AVCodecContext *avctx)
|
||||
|
||||
if (ctx_pic->slice_count <= 0 || ctx_pic->bitstream_size <= 0)
|
||||
return -1;
|
||||
+
|
||||
+ // Wait for an I-frame before start decoding. Workaround for ATI UVD and UVD+ GPUs
|
||||
+ if (!h->got_first_iframe) {
|
||||
+ if (!(ctx_pic->pp.wBitFields & (1 << 15)))
|
||||
+ return -1;
|
||||
+ h->got_first_iframe = 1;
|
||||
+ }
|
||||
+
|
||||
ret = ff_dxva2_common_end_frame(avctx, h->cur_pic_ptr->f,
|
||||
&ctx_pic->pp, sizeof(ctx_pic->pp),
|
||||
&ctx_pic->qm, sizeof(ctx_pic->qm),
|
||||
diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c
|
||||
index 7c69016338..0b415ada6f 100644
|
||||
--- a/libavcodec/h264_slice.c
|
||||
+++ b/libavcodec/h264_slice.c
|
||||
@@ -942,6 +942,7 @@ static int h264_slice_header_init(H264Context *h)
|
||||
|
||||
h->first_field = 0;
|
||||
h->prev_interlaced_frame = 1;
|
||||
+ h->got_first_iframe = 0;
|
||||
|
||||
init_scan_tables(h);
|
||||
ret = ff_h264_alloc_tables(h);
|
||||
diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c
|
||||
index 485f47d36e..1705046e29 100644
|
||||
--- a/libavcodec/h264dec.c
|
||||
+++ b/libavcodec/h264dec.c
|
||||
@@ -442,6 +442,7 @@ void ff_h264_flush_change(H264Context *h)
|
||||
|
||||
h->next_outputed_poc = INT_MIN;
|
||||
h->prev_interlaced_frame = 1;
|
||||
+ h->got_first_iframe = 0;
|
||||
idr(h);
|
||||
|
||||
h->poc.prev_frame_num = -1;
|
||||
diff --git a/libavcodec/h264dec.h b/libavcodec/h264dec.h
|
||||
index b3677cdbb9..b7b19ba4f1 100644
|
||||
--- a/libavcodec/h264dec.h
|
||||
+++ b/libavcodec/h264dec.h
|
||||
@@ -540,6 +540,8 @@ typedef struct H264Context {
|
||||
* slices) anymore */
|
||||
int setup_finished;
|
||||
|
||||
+ int got_first_iframe;
|
||||
+
|
||||
int cur_chroma_format_idc;
|
||||
int cur_bit_depth_luma;
|
||||
int16_t slice_row[MAX_SLICES]; ///< to detect when MAX_SLICES is too low
|
||||
|
||||
From 02731d93b4c725f13bf3b3217b48db3be18e0bce Mon Sep 17 00:00:00 2001
|
||||
From: Rechi <Rechi@users.noreply.github.com>
|
||||
Date: Tue, 21 Nov 2017 08:16:53 +0100
|
||||
Subject: [PATCH 02/15] use Kodi as extra version
|
||||
|
||||
---
|
||||
Makefile | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/Makefile b/Makefile
|
||||
index 7e9d8b08c3..882a3cb31b 100644
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -130,7 +130,7 @@ GIT_LOG = $(SRC_PATH)/.git/logs/HEAD
|
||||
.version: M=@
|
||||
|
||||
libavutil/ffversion.h .version:
|
||||
- $(M)$(VERSION_SH) $(SRC_PATH) libavutil/ffversion.h $(EXTRA_VERSION)
|
||||
+ $(M)$(VERSION_SH) $(SRC_PATH) libavutil/ffversion.h Kodi
|
||||
$(Q)touch .version
|
||||
|
||||
# force version.sh to run whenever version might have changed
|
||||
|
||||
From 1ec811b6f330f60ec7a522cc60e98bd8ae30c766 Mon Sep 17 00:00:00 2001
|
||||
From: Rechi <Rechi@users.noreply.github.com>
|
||||
Date: Tue, 21 Nov 2017 08:16:53 +0100
|
||||
Subject: [PATCH 03/15] common.mak: never ignore an error if strip doesn't
|
||||
succeed
|
||||
|
||||
---
|
||||
ffbuild/common.mak | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/ffbuild/common.mak b/ffbuild/common.mak
|
||||
index 164a43932d..2ab5dd0dfd 100644
|
||||
--- a/ffbuild/common.mak
|
||||
+++ b/ffbuild/common.mak
|
||||
@@ -87,7 +87,7 @@ COMPILE_MSA = $(call COMPILE,CC,MSAFLAGS)
|
||||
|
||||
%.o: %.asm
|
||||
$(COMPILE_X86ASM)
|
||||
- -$(if $(ASMSTRIPFLAGS), $(STRIP) $(ASMSTRIPFLAGS) $@)
|
||||
+ $(if $(STRIP), $(if $(ASMSTRIPFLAGS), $(STRIP) $(ASMSTRIPFLAGS) $@))
|
||||
|
||||
%.o: %.rc
|
||||
$(WINDRES) $(IFLAGS) $(foreach ARG,$(CC_DEPFLAGS),--preprocessor-arg "$(ARG)") -o $@ $<
|
||||
|
||||
From 29b9dec3de00f69339e6a5fed79b2d8ce2b3c105 Mon Sep 17 00:00:00 2001
|
||||
From: wsnipex <wsnipex@a1.net>
|
||||
Date: Tue, 21 Nov 2017 08:16:53 +0100
|
||||
Subject: [PATCH 04/15] only check for a git rev if the src tree is in a git
|
||||
repo
|
||||
|
||||
fixes the version string when building from the kodi depends src tree
|
||||
---
|
||||
ffbuild/version.sh | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/ffbuild/version.sh b/ffbuild/version.sh
|
||||
index edc4dd33c5..239a138ca7 100755
|
||||
--- a/ffbuild/version.sh
|
||||
+++ b/ffbuild/version.sh
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
# Usage: version.sh <ffmpeg-root-dir> <output-version.h> <extra-version>
|
||||
|
||||
+if [ -d $1/.git ]; then # only check for a git rev, if the src tree is in a git repo
|
||||
# check for git short hash
|
||||
if ! test "$revision"; then
|
||||
if (cd "$1" && grep git RELEASE 2> /dev/null >/dev/null) ; then
|
||||
@@ -27,6 +28,7 @@ if [ -z "$revision" ]; then
|
||||
git_hash="${srcdir##*-}";;
|
||||
esac
|
||||
fi
|
||||
+fi
|
||||
|
||||
# no revision number found
|
||||
test "$revision" || revision=$(cd "$1" && cat RELEASE 2> /dev/null)
|
||||
|
||||
From d2e9030c8a0d55426e13d1007e163c48f2533819 Mon Sep 17 00:00:00 2001
|
||||
From: Anton Fedchin <afedchin at ruswizards.com>
|
||||
Date: Fri, 11 Jan 2019 10:47:43 +0100
|
||||
Subject: [PATCH 05/15] after 153b36f there is a possibility to crash when
|
||||
trying to get index of a surface which points to nirvana.
|
||||
|
||||
it may occurs when a stream starts with non i-frame.
|
||||
---
|
||||
libavcodec/dxva2.c | 10 ++++++----
|
||||
1 file changed, 6 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/libavcodec/dxva2.c b/libavcodec/dxva2.c
|
||||
index b57ea21941..542bc2f18d 100644
|
||||
--- a/libavcodec/dxva2.c
|
||||
+++ b/libavcodec/dxva2.c
|
||||
@@ -777,16 +777,18 @@ unsigned ff_dxva2_get_surface_index(const AVCodecContext *avctx,
|
||||
#if CONFIG_D3D11VA
|
||||
if (avctx->pix_fmt == AV_PIX_FMT_D3D11)
|
||||
return (intptr_t)frame->data[1];
|
||||
- if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) {
|
||||
+ if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD && surface) {
|
||||
D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC viewDesc;
|
||||
ID3D11VideoDecoderOutputView_GetDesc((ID3D11VideoDecoderOutputView*) surface, &viewDesc);
|
||||
return viewDesc.Texture2D.ArraySlice;
|
||||
}
|
||||
#endif
|
||||
#if CONFIG_DXVA2
|
||||
- for (i = 0; i < DXVA_CONTEXT_COUNT(avctx, ctx); i++) {
|
||||
- if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD && ctx->dxva2.surface[i] == surface)
|
||||
- return i;
|
||||
+ if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
|
||||
+ for (i = 0; i < DXVA_CONTEXT_COUNT(avctx, ctx); i++) {
|
||||
+ if (ctx->dxva2.surface[i] == surface)
|
||||
+ return i;
|
||||
+ }
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
From 916223c0a47091272c9d0b6035f187310908ff37 Mon Sep 17 00:00:00 2001
|
||||
From: Rainer Hochecker <fernetmenta@online.de>
|
||||
Date: Sat, 26 Jan 2019 19:48:35 +0100
|
||||
Subject: [PATCH 06/15] avcodec/vaapi_h264: skip decode if pic has no slices
|
||||
|
||||
This fixes / workarounds https://bugs.freedesktop.org/show_bug.cgi?id=105368.
|
||||
It was hit frequently when watching h264 channels received via DVB-X.
|
||||
Corresponding kodi bug: https://github.com/xbmc/xbmc/issues/15704
|
||||
---
|
||||
libavcodec/vaapi_h264.c | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/libavcodec/vaapi_h264.c b/libavcodec/vaapi_h264.c
|
||||
index 9332aa6f31..d4494beebf 100644
|
||||
--- a/libavcodec/vaapi_h264.c
|
||||
+++ b/libavcodec/vaapi_h264.c
|
||||
@@ -314,6 +314,11 @@ static int vaapi_h264_end_frame(AVCodecContext *avctx)
|
||||
H264SliceContext *sl = &h->slice_ctx[0];
|
||||
int ret;
|
||||
|
||||
+ if (pic->nb_slices == 0) {
|
||||
+ ret = AVERROR_INVALIDDATA;
|
||||
+ goto finish;
|
||||
+ }
|
||||
+
|
||||
ret = ff_vaapi_decode_issue(avctx, pic);
|
||||
if (ret < 0)
|
||||
goto finish;
|
||||
|
||||
From b211c09d17ef86d7b38d1bfe9814a01e9040bf03 Mon Sep 17 00:00:00 2001
|
||||
From: Fei Wang <fei.w.wang@intel.com>
|
||||
Date: Tue, 12 Oct 2021 16:23:56 +0800
|
||||
Subject: [PATCH 07/15] cbs_av1: fix incorrect data type
|
||||
|
||||
Since order_hint_bits_minus_1 range is 0~7, cur_frame_hint can be
|
||||
most 128. And similar return value for cbs_av1_get_relative_dist.
|
||||
So if plus them and use int8_t for the result may lose its precision.
|
||||
|
||||
Signed-off-by: Fei Wang <fei.w.wang@intel.com>
|
||||
(cherry picked from commit e7ff5722b1abae4284e79da707e71ff82b409699)
|
||||
(cherry picked from commit 8aab15a91d6e8ca726580e969ff71828ad63baaa)
|
||||
---
|
||||
libavcodec/cbs_av1_syntax_template.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/libavcodec/cbs_av1_syntax_template.c b/libavcodec/cbs_av1_syntax_template.c
|
||||
index 6fe6e9a4f3..d98d3d42de 100644
|
||||
--- a/libavcodec/cbs_av1_syntax_template.c
|
||||
+++ b/libavcodec/cbs_av1_syntax_template.c
|
||||
@@ -355,7 +355,7 @@ static int FUNC(set_frame_refs)(CodedBitstreamContext *ctx, RWContext *rw,
|
||||
AV1_REF_FRAME_ALTREF2, AV1_REF_FRAME_ALTREF
|
||||
};
|
||||
int8_t ref_frame_idx[AV1_REFS_PER_FRAME], used_frame[AV1_NUM_REF_FRAMES];
|
||||
- int8_t shifted_order_hints[AV1_NUM_REF_FRAMES];
|
||||
+ int16_t shifted_order_hints[AV1_NUM_REF_FRAMES];
|
||||
int cur_frame_hint, latest_order_hint, earliest_order_hint, ref;
|
||||
int i, j;
|
||||
|
||||
|
||||
From 2db5def80f1913a00410d6f16ae3730de567c3b8 Mon Sep 17 00:00:00 2001
|
||||
From: Fei Wang <fei.w.wang@intel.com>
|
||||
Date: Tue, 12 Oct 2021 16:23:57 +0800
|
||||
Subject: [PATCH 08/15] avcodec/av1: extend some definitions in spec section 3
|
||||
|
||||
Signed-off-by: Fei Wang <fei.w.wang@intel.com>
|
||||
(cherry picked from commit 75de7fe26218cb37fff9d5afa7b5b2b8bee4a9a8)
|
||||
(cherry picked from commit 2f459697445df67cc61c9a6c2930fdf3f830e629)
|
||||
---
|
||||
libavcodec/av1.h | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
diff --git a/libavcodec/av1.h b/libavcodec/av1.h
|
||||
index 0f99ae4829..951a18ecb2 100644
|
||||
--- a/libavcodec/av1.h
|
||||
+++ b/libavcodec/av1.h
|
||||
@@ -114,6 +114,13 @@ enum {
|
||||
AV1_WARP_MODEL_TRANSLATION = 1,
|
||||
AV1_WARP_MODEL_ROTZOOM = 2,
|
||||
AV1_WARP_MODEL_AFFINE = 3,
|
||||
+ AV1_WARP_PARAM_REDUCE_BITS = 6,
|
||||
+
|
||||
+ AV1_DIV_LUT_BITS = 8,
|
||||
+ AV1_DIV_LUT_PREC_BITS = 14,
|
||||
+ AV1_DIV_LUT_NUM = 257,
|
||||
+
|
||||
+ AV1_MAX_LOOP_FILTER = 63,
|
||||
};
|
||||
|
||||
|
||||
|
||||
From ddc3058a3e7b7c44a3911fb356f932853565b3d0 Mon Sep 17 00:00:00 2001
|
||||
From: Fei Wang <fei.w.wang@intel.com>
|
||||
Date: Tue, 12 Oct 2021 16:23:58 +0800
|
||||
Subject: [PATCH 09/15] avcodec/av1dec: support setup shear process
|
||||
|
||||
Defined in spec 7.11.3.6/7.11.3.7.
|
||||
|
||||
Signed-off-by: Fei Wang <fei.w.wang@intel.com>
|
||||
(cherry picked from commit de7475b111679120b3b089fe543224f50882287c)
|
||||
(cherry picked from commit 481d3930d90d52587ad76d277cbd2f9cb3109079)
|
||||
---
|
||||
libavcodec/av1dec.c | 98 +++++++++++++++++++++++++++++++++++++++++++++
|
||||
libavcodec/av1dec.h | 1 +
|
||||
2 files changed, 99 insertions(+)
|
||||
|
||||
diff --git a/libavcodec/av1dec.c b/libavcodec/av1dec.c
|
||||
index a75d6744d3..a3301f454f 100644
|
||||
--- a/libavcodec/av1dec.c
|
||||
+++ b/libavcodec/av1dec.c
|
||||
@@ -28,6 +28,34 @@
|
||||
#include "internal.h"
|
||||
#include "profiles.h"
|
||||
|
||||
+/**< same with Div_Lut defined in spec 7.11.3.7 */
|
||||
+static const uint16_t div_lut[AV1_DIV_LUT_NUM] = {
|
||||
+ 16384, 16320, 16257, 16194, 16132, 16070, 16009, 15948, 15888, 15828, 15768,
|
||||
+ 15709, 15650, 15592, 15534, 15477, 15420, 15364, 15308, 15252, 15197, 15142,
|
||||
+ 15087, 15033, 14980, 14926, 14873, 14821, 14769, 14717, 14665, 14614, 14564,
|
||||
+ 14513, 14463, 14413, 14364, 14315, 14266, 14218, 14170, 14122, 14075, 14028,
|
||||
+ 13981, 13935, 13888, 13843, 13797, 13752, 13707, 13662, 13618, 13574, 13530,
|
||||
+ 13487, 13443, 13400, 13358, 13315, 13273, 13231, 13190, 13148, 13107, 13066,
|
||||
+ 13026, 12985, 12945, 12906, 12866, 12827, 12788, 12749, 12710, 12672, 12633,
|
||||
+ 12596, 12558, 12520, 12483, 12446, 12409, 12373, 12336, 12300, 12264, 12228,
|
||||
+ 12193, 12157, 12122, 12087, 12053, 12018, 11984, 11950, 11916, 11882, 11848,
|
||||
+ 11815, 11782, 11749, 11716, 11683, 11651, 11619, 11586, 11555, 11523, 11491,
|
||||
+ 11460, 11429, 11398, 11367, 11336, 11305, 11275, 11245, 11215, 11185, 11155,
|
||||
+ 11125, 11096, 11067, 11038, 11009, 10980, 10951, 10923, 10894, 10866, 10838,
|
||||
+ 10810, 10782, 10755, 10727, 10700, 10673, 10645, 10618, 10592, 10565, 10538,
|
||||
+ 10512, 10486, 10460, 10434, 10408, 10382, 10356, 10331, 10305, 10280, 10255,
|
||||
+ 10230, 10205, 10180, 10156, 10131, 10107, 10082, 10058, 10034, 10010, 9986,
|
||||
+ 9963, 9939, 9916, 9892, 9869, 9846, 9823, 9800, 9777, 9754, 9732,
|
||||
+ 9709, 9687, 9664, 9642, 9620, 9598, 9576, 9554, 9533, 9511, 9489,
|
||||
+ 9468, 9447, 9425, 9404, 9383, 9362, 9341, 9321, 9300, 9279, 9259,
|
||||
+ 9239, 9218, 9198, 9178, 9158, 9138, 9118, 9098, 9079, 9059, 9039,
|
||||
+ 9020, 9001, 8981, 8962, 8943, 8924, 8905, 8886, 8867, 8849, 8830,
|
||||
+ 8812, 8793, 8775, 8756, 8738, 8720, 8702, 8684, 8666, 8648, 8630,
|
||||
+ 8613, 8595, 8577, 8560, 8542, 8525, 8508, 8490, 8473, 8456, 8439,
|
||||
+ 8422, 8405, 8389, 8372, 8355, 8339, 8322, 8306, 8289, 8273, 8257,
|
||||
+ 8240, 8224, 8208, 8192
|
||||
+};
|
||||
+
|
||||
static uint32_t inverse_recenter(int r, uint32_t v)
|
||||
{
|
||||
if (v > 2 * r)
|
||||
@@ -97,6 +125,70 @@ static void read_global_param(AV1DecContext *s, int type, int ref, int idx)
|
||||
-mx, mx + 1, r) << prec_diff) + round;
|
||||
}
|
||||
|
||||
+static uint64_t round_two(uint64_t x, uint16_t n)
|
||||
+{
|
||||
+ if (n == 0)
|
||||
+ return x;
|
||||
+ return ((x + ((uint64_t)1 << (n - 1))) >> n);
|
||||
+}
|
||||
+
|
||||
+static int64_t round_two_signed(int64_t x, uint16_t n)
|
||||
+{
|
||||
+ return ((x<0) ? -((int64_t)round_two(-x, n)) : (int64_t)round_two(x, n));
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * Resolve divisor process.
|
||||
+ * see spec 7.11.3.7
|
||||
+ */
|
||||
+static int16_t resolve_divisor(uint32_t d, uint16_t *shift)
|
||||
+{
|
||||
+ int32_t e, f;
|
||||
+
|
||||
+ *shift = av_log2(d);
|
||||
+ e = d - (1 << (*shift));
|
||||
+ if (*shift > AV1_DIV_LUT_BITS)
|
||||
+ f = round_two(e, *shift - AV1_DIV_LUT_BITS);
|
||||
+ else
|
||||
+ f = e << (AV1_DIV_LUT_BITS - (*shift));
|
||||
+
|
||||
+ *shift += AV1_DIV_LUT_PREC_BITS;
|
||||
+
|
||||
+ return div_lut[f];
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * check if global motion params is valid.
|
||||
+ * see spec 7.11.3.6
|
||||
+ */
|
||||
+static uint8_t get_shear_params_valid(AV1DecContext *s, int idx)
|
||||
+{
|
||||
+ int16_t alpha, beta, gamma, delta, divf, divs;
|
||||
+ int64_t v, w;
|
||||
+ int32_t *param = &s->cur_frame.gm_params[idx][0];
|
||||
+ if (param[2] < 0)
|
||||
+ return 0;
|
||||
+
|
||||
+ alpha = av_clip_int16(param[2] - (1 << AV1_WARPEDMODEL_PREC_BITS));
|
||||
+ beta = av_clip_int16(param[3]);
|
||||
+ divf = resolve_divisor(abs(param[2]), &divs);
|
||||
+ v = (int64_t)param[4] * (1 << AV1_WARPEDMODEL_PREC_BITS);
|
||||
+ w = (int64_t)param[3] * param[4];
|
||||
+ gamma = av_clip_int16((int)round_two_signed((v * divf), divs));
|
||||
+ delta = av_clip_int16(param[5] - (int)round_two_signed((w * divf), divs) - (1 << AV1_WARPEDMODEL_PREC_BITS));
|
||||
+
|
||||
+ alpha = round_two_signed(alpha, AV1_WARP_PARAM_REDUCE_BITS) << AV1_WARP_PARAM_REDUCE_BITS;
|
||||
+ beta = round_two_signed(beta, AV1_WARP_PARAM_REDUCE_BITS) << AV1_WARP_PARAM_REDUCE_BITS;
|
||||
+ gamma = round_two_signed(gamma, AV1_WARP_PARAM_REDUCE_BITS) << AV1_WARP_PARAM_REDUCE_BITS;
|
||||
+ delta = round_two_signed(delta, AV1_WARP_PARAM_REDUCE_BITS) << AV1_WARP_PARAM_REDUCE_BITS;
|
||||
+
|
||||
+ if ((4 * abs(alpha) + 7 * abs(beta)) >= (1 << AV1_WARPEDMODEL_PREC_BITS) ||
|
||||
+ (4 * abs(gamma) + 4 * abs(delta)) >= (1 << AV1_WARPEDMODEL_PREC_BITS))
|
||||
+ return 0;
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* update gm type/params, since cbs already implemented part of this funcation,
|
||||
* so we don't need to full implement spec.
|
||||
@@ -144,6 +236,9 @@ static void global_motion_params(AV1DecContext *s)
|
||||
read_global_param(s, type, ref, 0);
|
||||
read_global_param(s, type, ref, 1);
|
||||
}
|
||||
+ if (type <= AV1_WARP_MODEL_AFFINE) {
|
||||
+ s->cur_frame.gm_invalid[ref] = !get_shear_params_valid(s, ref);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -509,6 +604,9 @@ static int av1_frame_ref(AVCodecContext *avctx, AV1Frame *dst, const AV1Frame *s
|
||||
|
||||
dst->spatial_id = src->spatial_id;
|
||||
dst->temporal_id = src->temporal_id;
|
||||
+ memcpy(dst->gm_invalid,
|
||||
+ src->gm_invalid,
|
||||
+ AV1_NUM_REF_FRAMES * sizeof(uint8_t));
|
||||
memcpy(dst->gm_type,
|
||||
src->gm_type,
|
||||
AV1_NUM_REF_FRAMES * sizeof(uint8_t));
|
||||
diff --git a/libavcodec/av1dec.h b/libavcodec/av1dec.h
|
||||
index 248a68750f..4e140588b9 100644
|
||||
--- a/libavcodec/av1dec.h
|
||||
+++ b/libavcodec/av1dec.h
|
||||
@@ -42,6 +42,7 @@ typedef struct AV1Frame {
|
||||
int temporal_id;
|
||||
int spatial_id;
|
||||
|
||||
+ uint8_t gm_invalid[AV1_NUM_REF_FRAMES];
|
||||
uint8_t gm_type[AV1_NUM_REF_FRAMES];
|
||||
int32_t gm_params[AV1_NUM_REF_FRAMES][6];
|
||||
|
||||
|
||||
From ad58733c84c131216e04ceb39d0dff64bfac5a2c Mon Sep 17 00:00:00 2001
|
||||
From: Fei Wang <fei.w.wang@intel.com>
|
||||
Date: Tue, 12 Oct 2021 16:23:59 +0800
|
||||
Subject: [PATCH 10/15] avcodec/av1_vaapi: add gm params valid check
|
||||
|
||||
Signed-off-by: Fei Wang <fei.w.wang@intel.com>
|
||||
(cherry picked from commit 0d0ea70e7bdd85def85d526480d728740a371744)
|
||||
(cherry picked from commit 8b9a48b7aa3c14103f975035bb18601b13ed1707)
|
||||
---
|
||||
libavcodec/vaapi_av1.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/libavcodec/vaapi_av1.c b/libavcodec/vaapi_av1.c
|
||||
index 16b7e35747..f577447be4 100644
|
||||
--- a/libavcodec/vaapi_av1.c
|
||||
+++ b/libavcodec/vaapi_av1.c
|
||||
@@ -213,7 +213,8 @@ static int vaapi_av1_start_frame(AVCodecContext *avctx,
|
||||
frame_header->height_in_sbs_minus_1[i];
|
||||
}
|
||||
for (int i = AV1_REF_FRAME_LAST; i <= AV1_REF_FRAME_ALTREF; i++) {
|
||||
- pic_param.wm[i - 1].wmtype = s->cur_frame.gm_type[i];
|
||||
+ pic_param.wm[i - 1].invalid = s->cur_frame.gm_invalid[i];
|
||||
+ pic_param.wm[i - 1].wmtype = s->cur_frame.gm_type[i];
|
||||
for (int j = 0; j < 6; j++)
|
||||
pic_param.wm[i - 1].wmmat[j] = s->cur_frame.gm_params[i][j];
|
||||
}
|
||||
|
||||
From fd1acddbee3686c97c2c38cc4befea38794eb44d Mon Sep 17 00:00:00 2001
|
||||
From: Tong Wu <tong1.wu@intel.com>
|
||||
Date: Tue, 12 Oct 2021 16:24:00 +0800
|
||||
Subject: [PATCH 11/15] avcodec/dxva2_av1: fix global motion params
|
||||
|
||||
Defined in spec 5.9.24/5.9.25. Since function void
|
||||
global_motion_params(AV1DecContext *s) already updates
|
||||
gm type/params, the wminvalid parameter only need to get
|
||||
the value from cur_frame.gm_invalid.
|
||||
|
||||
Signed-off-by: Tong Wu <tong1.wu@intel.com>
|
||||
(cherry picked from commit 4e7a7d75e3c21a6af03c4cd52ffc50270664e58a)
|
||||
(cherry picked from commit 03f5a57b9364d7ce789589594450fdf714a23e70)
|
||||
---
|
||||
libavcodec/dxva2_av1.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/libavcodec/dxva2_av1.c b/libavcodec/dxva2_av1.c
|
||||
index c30b57799c..8a912bf6c1 100644
|
||||
--- a/libavcodec/dxva2_av1.c
|
||||
+++ b/libavcodec/dxva2_av1.c
|
||||
@@ -139,7 +139,7 @@ static int fill_picture_parameters(const AVCodecContext *avctx, AVDXVAContext *c
|
||||
pp->frame_refs[i].Index = ref_frame->buf[0] ? ref_idx : 0xFF;
|
||||
|
||||
/* Global Motion */
|
||||
- pp->frame_refs[i].wminvalid = (h->cur_frame.gm_type[AV1_REF_FRAME_LAST + i] == AV1_WARP_MODEL_IDENTITY);
|
||||
+ pp->frame_refs[i].wminvalid = h->cur_frame.gm_invalid[AV1_REF_FRAME_LAST + i];
|
||||
pp->frame_refs[i].wmtype = h->cur_frame.gm_type[AV1_REF_FRAME_LAST + i];
|
||||
for (j = 0; j < 6; ++j) {
|
||||
pp->frame_refs[i].wmmat[j] = h->cur_frame.gm_params[AV1_REF_FRAME_LAST + i][j];
|
||||
|
||||
From 06181d3fd98d040ad2e1cb297896b3ba9235a9b4 Mon Sep 17 00:00:00 2001
|
||||
From: Fei Wang <fei.w.wang@intel.com>
|
||||
Date: Tue, 12 Oct 2021 16:24:01 +0800
|
||||
Subject: [PATCH 12/15] avcodec/vaapi: increase av1 decode pool size
|
||||
|
||||
For film grain clip, vaapi_av1 decoder will cache additional 8
|
||||
surfaces that will be used to store frames which apply film grain.
|
||||
So increase the pool size by plus 8 to avoid leak of surface.
|
||||
|
||||
Signed-off-by: Fei Wang <fei.w.wang@intel.com>
|
||||
(cherry picked from commit 53403158cc19b9e5baeff6af9317f14d1a20d0cb)
|
||||
(cherry picked from commit 5774a0524c0851293a36acf3f3586e7c39a64b4a)
|
||||
---
|
||||
libavcodec/vaapi_decode.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/libavcodec/vaapi_decode.c b/libavcodec/vaapi_decode.c
|
||||
index 57a0eb4e6e..032e8531f2 100644
|
||||
--- a/libavcodec/vaapi_decode.c
|
||||
+++ b/libavcodec/vaapi_decode.c
|
||||
@@ -577,10 +577,10 @@ static int vaapi_decode_make_config(AVCodecContext *avctx,
|
||||
switch (avctx->codec_id) {
|
||||
case AV_CODEC_ID_H264:
|
||||
case AV_CODEC_ID_HEVC:
|
||||
+ case AV_CODEC_ID_AV1:
|
||||
frames->initial_pool_size += 16;
|
||||
break;
|
||||
case AV_CODEC_ID_VP9:
|
||||
- case AV_CODEC_ID_AV1:
|
||||
frames->initial_pool_size += 8;
|
||||
break;
|
||||
case AV_CODEC_ID_VP8:
|
||||
|
||||
From 1d82fef4ddc4e5512219c8c0e2e93fe351d1f65a Mon Sep 17 00:00:00 2001
|
||||
From: Fei Wang <fei.w.wang@intel.com>
|
||||
Date: Tue, 12 Oct 2021 16:24:02 +0800
|
||||
Subject: [PATCH 13/15] avcodec/av1_vaapi: setting 2 output surface for film
|
||||
grain
|
||||
|
||||
VAAPI needs 2 output surface for film grain frame. One used for
|
||||
reference and the other used for applying film grain and pushing
|
||||
to downstream.
|
||||
|
||||
Signed-off-by: Fei Wang <fei.w.wang@intel.com>
|
||||
(cherry picked from commit 7871144cf801bc8b9e3b00319dd7c3c3d91dd3fa)
|
||||
(cherry picked from commit 5962698d25f148d6b89dc4e526fffc5db2295f1e)
|
||||
---
|
||||
libavcodec/vaapi_av1.c | 115 ++++++++++++++++++++++++++++++++++++++---
|
||||
1 file changed, 108 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/libavcodec/vaapi_av1.c b/libavcodec/vaapi_av1.c
|
||||
index f577447be4..26476c7738 100644
|
||||
--- a/libavcodec/vaapi_av1.c
|
||||
+++ b/libavcodec/vaapi_av1.c
|
||||
@@ -21,8 +21,28 @@
|
||||
#include "libavutil/pixdesc.h"
|
||||
#include "hwconfig.h"
|
||||
#include "vaapi_decode.h"
|
||||
+#include "internal.h"
|
||||
#include "av1dec.h"
|
||||
|
||||
+typedef struct VAAPIAV1FrameRef {
|
||||
+ ThreadFrame frame;
|
||||
+ int valid;
|
||||
+} VAAPIAV1FrameRef;
|
||||
+
|
||||
+typedef struct VAAPIAV1DecContext {
|
||||
+ VAAPIDecodeContext base;
|
||||
+
|
||||
+ /**
|
||||
+ * For film grain case, VAAPI generate 2 output for each frame,
|
||||
+ * current_frame will not apply film grain, and will be used for
|
||||
+ * references for next frames. Maintain the reference list without
|
||||
+ * applying film grain here. And current_display_picture will be
|
||||
+ * used to apply film grain and push to downstream.
|
||||
+ */
|
||||
+ VAAPIAV1FrameRef ref_tab[AV1_NUM_REF_FRAMES];
|
||||
+ ThreadFrame tmp_frame;
|
||||
+} VAAPIAV1DecContext;
|
||||
+
|
||||
static VASurfaceID vaapi_av1_surface_id(AV1Frame *vf)
|
||||
{
|
||||
if (vf)
|
||||
@@ -49,6 +69,48 @@ static int8_t vaapi_av1_get_bit_depth_idx(AVCodecContext *avctx)
|
||||
return bit_depth == 8 ? 0 : bit_depth == 10 ? 1 : 2;
|
||||
}
|
||||
|
||||
+static int vaapi_av1_decode_init(AVCodecContext *avctx)
|
||||
+{
|
||||
+ VAAPIAV1DecContext *ctx = avctx->internal->hwaccel_priv_data;
|
||||
+
|
||||
+ ctx->tmp_frame.f = av_frame_alloc();
|
||||
+ if (!ctx->tmp_frame.f) {
|
||||
+ av_log(avctx, AV_LOG_ERROR,
|
||||
+ "Failed to allocate frame.\n");
|
||||
+ return AVERROR(ENOMEM);
|
||||
+ }
|
||||
+
|
||||
+ for (int i = 0; i < FF_ARRAY_ELEMS(ctx->ref_tab); i++) {
|
||||
+ ctx->ref_tab[i].frame.f = av_frame_alloc();
|
||||
+ if (!ctx->ref_tab[i].frame.f) {
|
||||
+ av_log(avctx, AV_LOG_ERROR,
|
||||
+ "Failed to allocate reference table frame %d.\n", i);
|
||||
+ return AVERROR(ENOMEM);
|
||||
+ }
|
||||
+ ctx->ref_tab[i].valid = 0;
|
||||
+ }
|
||||
+
|
||||
+ return ff_vaapi_decode_init(avctx);
|
||||
+}
|
||||
+
|
||||
+static int vaapi_av1_decode_uninit(AVCodecContext *avctx)
|
||||
+{
|
||||
+ VAAPIAV1DecContext *ctx = avctx->internal->hwaccel_priv_data;
|
||||
+
|
||||
+ if (ctx->tmp_frame.f->buf[0])
|
||||
+ ff_thread_release_buffer(avctx, &ctx->tmp_frame);
|
||||
+ av_frame_free(&ctx->tmp_frame.f);
|
||||
+
|
||||
+ for (int i = 0; i < FF_ARRAY_ELEMS(ctx->ref_tab); i++) {
|
||||
+ if (ctx->ref_tab[i].frame.f->buf[0])
|
||||
+ ff_thread_release_buffer(avctx, &ctx->ref_tab[i].frame);
|
||||
+ av_frame_free(&ctx->ref_tab[i].frame.f);
|
||||
+ }
|
||||
+
|
||||
+ return ff_vaapi_decode_uninit(avctx);
|
||||
+}
|
||||
+
|
||||
+
|
||||
static int vaapi_av1_start_frame(AVCodecContext *avctx,
|
||||
av_unused const uint8_t *buffer,
|
||||
av_unused uint32_t size)
|
||||
@@ -58,18 +120,28 @@ static int vaapi_av1_start_frame(AVCodecContext *avctx,
|
||||
const AV1RawFrameHeader *frame_header = s->raw_frame_header;
|
||||
const AV1RawFilmGrainParams *film_grain = &s->cur_frame.film_grain;
|
||||
VAAPIDecodePicture *pic = s->cur_frame.hwaccel_picture_private;
|
||||
+ VAAPIAV1DecContext *ctx = avctx->internal->hwaccel_priv_data;
|
||||
VADecPictureParameterBufferAV1 pic_param;
|
||||
int8_t bit_depth_idx;
|
||||
int err = 0;
|
||||
int apply_grain = !(avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN) && film_grain->apply_grain;
|
||||
uint8_t remap_lr_type[4] = {AV1_RESTORE_NONE, AV1_RESTORE_SWITCHABLE, AV1_RESTORE_WIENER, AV1_RESTORE_SGRPROJ};
|
||||
|
||||
- pic->output_surface = vaapi_av1_surface_id(&s->cur_frame);
|
||||
-
|
||||
bit_depth_idx = vaapi_av1_get_bit_depth_idx(avctx);
|
||||
if (bit_depth_idx < 0)
|
||||
goto fail;
|
||||
|
||||
+ if (apply_grain) {
|
||||
+ if (ctx->tmp_frame.f->buf[0])
|
||||
+ ff_thread_release_buffer(avctx, &ctx->tmp_frame);
|
||||
+ err = ff_thread_get_buffer(avctx, &ctx->tmp_frame, AV_GET_BUFFER_FLAG_REF);
|
||||
+ if (err < 0)
|
||||
+ goto fail;
|
||||
+ pic->output_surface = ff_vaapi_get_surface_id(ctx->tmp_frame.f);
|
||||
+ } else {
|
||||
+ pic->output_surface = vaapi_av1_surface_id(&s->cur_frame);
|
||||
+ }
|
||||
+
|
||||
memset(&pic_param, 0, sizeof(VADecPictureParameterBufferAV1));
|
||||
pic_param = (VADecPictureParameterBufferAV1) {
|
||||
.profile = seq->seq_profile,
|
||||
@@ -77,6 +149,7 @@ static int vaapi_av1_start_frame(AVCodecContext *avctx,
|
||||
.bit_depth_idx = bit_depth_idx,
|
||||
.current_frame = pic->output_surface,
|
||||
.current_display_picture = pic->output_surface,
|
||||
+ .current_display_picture = vaapi_av1_surface_id(&s->cur_frame),
|
||||
.frame_width_minus1 = frame_header->frame_width_minus_1,
|
||||
.frame_height_minus1 = frame_header->frame_height_minus_1,
|
||||
.primary_ref_frame = frame_header->primary_ref_frame,
|
||||
@@ -185,7 +258,9 @@ static int vaapi_av1_start_frame(AVCodecContext *avctx,
|
||||
if (pic_param.pic_info_fields.bits.frame_type == AV1_FRAME_KEY)
|
||||
pic_param.ref_frame_map[i] = VA_INVALID_ID;
|
||||
else
|
||||
- pic_param.ref_frame_map[i] = vaapi_av1_surface_id(&s->ref[i]);
|
||||
+ pic_param.ref_frame_map[i] = ctx->ref_tab[i].valid ?
|
||||
+ ff_vaapi_get_surface_id(ctx->ref_tab[i].frame.f) :
|
||||
+ vaapi_av1_surface_id(&s->ref[i]);
|
||||
}
|
||||
for (int i = 0; i < AV1_REFS_PER_FRAME; i++) {
|
||||
pic_param.ref_frame_idx[i] = frame_header->ref_frame_idx[i];
|
||||
@@ -264,8 +339,34 @@ fail:
|
||||
static int vaapi_av1_end_frame(AVCodecContext *avctx)
|
||||
{
|
||||
const AV1DecContext *s = avctx->priv_data;
|
||||
+ const AV1RawFrameHeader *header = s->raw_frame_header;
|
||||
+ const AV1RawFilmGrainParams *film_grain = &s->cur_frame.film_grain;
|
||||
VAAPIDecodePicture *pic = s->cur_frame.hwaccel_picture_private;
|
||||
- return ff_vaapi_decode_issue(avctx, pic);
|
||||
+ VAAPIAV1DecContext *ctx = avctx->internal->hwaccel_priv_data;
|
||||
+
|
||||
+ int apply_grain = !(avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN) && film_grain->apply_grain;
|
||||
+ int ret;
|
||||
+ ret = ff_vaapi_decode_issue(avctx, pic);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ for (int i = 0; i < AV1_NUM_REF_FRAMES; i++) {
|
||||
+ if (header->refresh_frame_flags & (1 << i)) {
|
||||
+ if (ctx->ref_tab[i].frame.f->buf[0])
|
||||
+ ff_thread_release_buffer(avctx, &ctx->ref_tab[i].frame);
|
||||
+
|
||||
+ if (apply_grain) {
|
||||
+ ret = ff_thread_ref_frame(&ctx->ref_tab[i].frame, &ctx->tmp_frame);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ ctx->ref_tab[i].valid = 1;
|
||||
+ } else {
|
||||
+ ctx->ref_tab[i].valid = 0;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static int vaapi_av1_decode_slice(AVCodecContext *avctx,
|
||||
@@ -312,9 +413,9 @@ const AVHWAccel ff_av1_vaapi_hwaccel = {
|
||||
.end_frame = vaapi_av1_end_frame,
|
||||
.decode_slice = vaapi_av1_decode_slice,
|
||||
.frame_priv_data_size = sizeof(VAAPIDecodePicture),
|
||||
- .init = ff_vaapi_decode_init,
|
||||
- .uninit = ff_vaapi_decode_uninit,
|
||||
+ .init = vaapi_av1_decode_init,
|
||||
+ .uninit = vaapi_av1_decode_uninit,
|
||||
.frame_params = ff_vaapi_common_frame_params,
|
||||
- .priv_data_size = sizeof(VAAPIDecodeContext),
|
||||
+ .priv_data_size = sizeof(VAAPIAV1DecContext),
|
||||
.caps_internal = HWACCEL_CAP_ASYNC_SAFE,
|
||||
};
|
||||
|
||||
From be18092cec1867b5e30525e023f49c5e7547931b Mon Sep 17 00:00:00 2001
|
||||
From: Fei Wang <fei.w.wang@intel.com>
|
||||
Date: Tue, 12 Oct 2021 16:24:03 +0800
|
||||
Subject: [PATCH 14/15] avcodec/av1_vaapi: enable segmentation features
|
||||
|
||||
Signed-off-by: Fei Wang <fei.w.wang@intel.com>
|
||||
(cherry picked from commit dc94f2eaaf0ae623d7dc02e1273c829015c025a3)
|
||||
(cherry picked from commit 582fb329a483774f0345cbfebc3a12f0ad8f5bba)
|
||||
---
|
||||
libavcodec/vaapi_av1.c | 14 ++++++++++++++
|
||||
1 file changed, 14 insertions(+)
|
||||
|
||||
diff --git a/libavcodec/vaapi_av1.c b/libavcodec/vaapi_av1.c
|
||||
index 26476c7738..c57d1b898a 100644
|
||||
--- a/libavcodec/vaapi_av1.c
|
||||
+++ b/libavcodec/vaapi_av1.c
|
||||
@@ -126,6 +126,9 @@ static int vaapi_av1_start_frame(AVCodecContext *avctx,
|
||||
int err = 0;
|
||||
int apply_grain = !(avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN) && film_grain->apply_grain;
|
||||
uint8_t remap_lr_type[4] = {AV1_RESTORE_NONE, AV1_RESTORE_SWITCHABLE, AV1_RESTORE_WIENER, AV1_RESTORE_SGRPROJ};
|
||||
+ uint8_t segmentation_feature_signed[AV1_SEG_LVL_MAX] = {1, 1, 1, 1, 1, 0, 0, 0};
|
||||
+ uint8_t segmentation_feature_max[AV1_SEG_LVL_MAX] = {255, AV1_MAX_LOOP_FILTER,
|
||||
+ AV1_MAX_LOOP_FILTER, AV1_MAX_LOOP_FILTER, AV1_MAX_LOOP_FILTER, 7 , 0 , 0 };
|
||||
|
||||
bit_depth_idx = vaapi_av1_get_bit_depth_idx(avctx);
|
||||
if (bit_depth_idx < 0)
|
||||
@@ -293,6 +296,17 @@ static int vaapi_av1_start_frame(AVCodecContext *avctx,
|
||||
for (int j = 0; j < 6; j++)
|
||||
pic_param.wm[i - 1].wmmat[j] = s->cur_frame.gm_params[i][j];
|
||||
}
|
||||
+ for (int i = 0; i < AV1_MAX_SEGMENTS; i++) {
|
||||
+ for (int j = 0; j < AV1_SEG_LVL_MAX; j++) {
|
||||
+ pic_param.seg_info.feature_mask[i] |= (frame_header->feature_enabled[i][j] << j);
|
||||
+ if (segmentation_feature_signed[j])
|
||||
+ pic_param.seg_info.feature_data[i][j] = av_clip(frame_header->feature_value[i][j],
|
||||
+ -segmentation_feature_max[j], segmentation_feature_max[j]);
|
||||
+ else
|
||||
+ pic_param.seg_info.feature_data[i][j] = av_clip(frame_header->feature_value[i][j],
|
||||
+ 0, segmentation_feature_max[j]);
|
||||
+ }
|
||||
+ }
|
||||
if (apply_grain) {
|
||||
for (int i = 0; i < film_grain->num_y_points; i++) {
|
||||
pic_param.film_grain_info.point_y_value[i] =
|
||||
|
||||
From 293e067b0c0f592628ee0de71769ed2e9c3d07f2 Mon Sep 17 00:00:00 2001
|
||||
From: Fei Wang <fei.w.wang@intel.com>
|
||||
Date: Tue, 12 Oct 2021 16:24:04 +0800
|
||||
Subject: [PATCH 15/15] avcodec/av1_vaapi: improve decode quality
|
||||
|
||||
- quantizer delta and matrix level specific.
|
||||
- support loop filter delta.
|
||||
- support use superres.
|
||||
|
||||
Signed-off-by: Fei Wang <fei.w.wang@intel.com>
|
||||
(cherry picked from commit 84c73102d933c9b7f64f504196c91edddad99618)
|
||||
(cherry picked from commit 2c887141b8318b7d4b198461bbb8d94ac662a96c)
|
||||
---
|
||||
libavcodec/vaapi_av1.c | 68 +++++++++++++++++++++++++-----------------
|
||||
1 file changed, 41 insertions(+), 27 deletions(-)
|
||||
|
||||
diff --git a/libavcodec/vaapi_av1.c b/libavcodec/vaapi_av1.c
|
||||
index c57d1b898a..5985493b8d 100644
|
||||
--- a/libavcodec/vaapi_av1.c
|
||||
+++ b/libavcodec/vaapi_av1.c
|
||||
@@ -147,27 +147,35 @@ static int vaapi_av1_start_frame(AVCodecContext *avctx,
|
||||
|
||||
memset(&pic_param, 0, sizeof(VADecPictureParameterBufferAV1));
|
||||
pic_param = (VADecPictureParameterBufferAV1) {
|
||||
- .profile = seq->seq_profile,
|
||||
- .order_hint_bits_minus_1 = seq->order_hint_bits_minus_1,
|
||||
- .bit_depth_idx = bit_depth_idx,
|
||||
- .current_frame = pic->output_surface,
|
||||
- .current_display_picture = pic->output_surface,
|
||||
- .current_display_picture = vaapi_av1_surface_id(&s->cur_frame),
|
||||
- .frame_width_minus1 = frame_header->frame_width_minus_1,
|
||||
- .frame_height_minus1 = frame_header->frame_height_minus_1,
|
||||
- .primary_ref_frame = frame_header->primary_ref_frame,
|
||||
- .order_hint = frame_header->order_hint,
|
||||
- .tile_cols = frame_header->tile_cols,
|
||||
- .tile_rows = frame_header->tile_rows,
|
||||
- .context_update_tile_id = frame_header->context_update_tile_id,
|
||||
- .interp_filter = frame_header->interpolation_filter,
|
||||
- .filter_level[0] = frame_header->loop_filter_level[0],
|
||||
- .filter_level[1] = frame_header->loop_filter_level[1],
|
||||
- .filter_level_u = frame_header->loop_filter_level[2],
|
||||
- .filter_level_v = frame_header->loop_filter_level[3],
|
||||
- .base_qindex = frame_header->base_q_idx,
|
||||
- .cdef_damping_minus_3 = frame_header->cdef_damping_minus_3,
|
||||
- .cdef_bits = frame_header->cdef_bits,
|
||||
+ .profile = seq->seq_profile,
|
||||
+ .order_hint_bits_minus_1 = seq->order_hint_bits_minus_1,
|
||||
+ .bit_depth_idx = bit_depth_idx,
|
||||
+ .matrix_coefficients = seq->color_config.matrix_coefficients,
|
||||
+ .current_frame = pic->output_surface,
|
||||
+ .current_display_picture = vaapi_av1_surface_id(&s->cur_frame),
|
||||
+ .frame_width_minus1 = frame_header->frame_width_minus_1,
|
||||
+ .frame_height_minus1 = frame_header->frame_height_minus_1,
|
||||
+ .primary_ref_frame = frame_header->primary_ref_frame,
|
||||
+ .order_hint = frame_header->order_hint,
|
||||
+ .tile_cols = frame_header->tile_cols,
|
||||
+ .tile_rows = frame_header->tile_rows,
|
||||
+ .context_update_tile_id = frame_header->context_update_tile_id,
|
||||
+ .superres_scale_denominator = frame_header->use_superres ?
|
||||
+ frame_header->coded_denom + AV1_SUPERRES_DENOM_MIN :
|
||||
+ AV1_SUPERRES_NUM,
|
||||
+ .interp_filter = frame_header->interpolation_filter,
|
||||
+ .filter_level[0] = frame_header->loop_filter_level[0],
|
||||
+ .filter_level[1] = frame_header->loop_filter_level[1],
|
||||
+ .filter_level_u = frame_header->loop_filter_level[2],
|
||||
+ .filter_level_v = frame_header->loop_filter_level[3],
|
||||
+ .base_qindex = frame_header->base_q_idx,
|
||||
+ .y_dc_delta_q = frame_header->delta_q_y_dc,
|
||||
+ .u_dc_delta_q = frame_header->delta_q_u_dc,
|
||||
+ .u_ac_delta_q = frame_header->delta_q_u_ac,
|
||||
+ .v_dc_delta_q = frame_header->delta_q_v_dc,
|
||||
+ .v_ac_delta_q = frame_header->delta_q_v_ac,
|
||||
+ .cdef_damping_minus_3 = frame_header->cdef_damping_minus_3,
|
||||
+ .cdef_bits = frame_header->cdef_bits,
|
||||
.seq_info_fields.fields = {
|
||||
.still_picture = seq->still_picture,
|
||||
.use_128x128_superblock = seq->use_128x128_superblock,
|
||||
@@ -238,12 +246,15 @@ static int vaapi_av1_start_frame(AVCodecContext *avctx,
|
||||
.mode_ref_delta_update = frame_header->loop_filter_delta_update,
|
||||
},
|
||||
.mode_control_fields.bits = {
|
||||
- .delta_q_present_flag = frame_header->delta_q_present,
|
||||
- .log2_delta_q_res = frame_header->delta_q_res,
|
||||
- .tx_mode = frame_header->tx_mode,
|
||||
- .reference_select = frame_header->reference_select,
|
||||
- .reduced_tx_set_used = frame_header->reduced_tx_set,
|
||||
- .skip_mode_present = frame_header->skip_mode_present,
|
||||
+ .delta_q_present_flag = frame_header->delta_q_present,
|
||||
+ .log2_delta_q_res = frame_header->delta_q_res,
|
||||
+ .delta_lf_present_flag = frame_header->delta_lf_present,
|
||||
+ .log2_delta_lf_res = frame_header->delta_lf_res,
|
||||
+ .delta_lf_multi = frame_header->delta_lf_multi,
|
||||
+ .tx_mode = frame_header->tx_mode,
|
||||
+ .reference_select = frame_header->reference_select,
|
||||
+ .reduced_tx_set_used = frame_header->reduced_tx_set,
|
||||
+ .skip_mode_present = frame_header->skip_mode_present,
|
||||
},
|
||||
.loop_restoration_fields.bits = {
|
||||
.yframe_restoration_type = remap_lr_type[frame_header->lr_type[0]],
|
||||
@@ -254,6 +265,9 @@ static int vaapi_av1_start_frame(AVCodecContext *avctx,
|
||||
},
|
||||
.qmatrix_fields.bits = {
|
||||
.using_qmatrix = frame_header->using_qmatrix,
|
||||
+ .qm_y = frame_header->qm_y,
|
||||
+ .qm_u = frame_header->qm_u,
|
||||
+ .qm_v = frame_header->qm_v,
|
||||
}
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
From 8f7c8a0f9e28641880d72996b9452e0a9da1288c Mon Sep 17 00:00:00 2001
|
||||
From 3c53cf80b0de8af387694a464bdce294988d0fa5 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
|
||||
@ -18,10 +18,10 @@ decoding is properly activated.
|
||||
1 file changed, 11 insertions(+)
|
||||
|
||||
diff --git a/libavcodec/libdav1d.c b/libavcodec/libdav1d.c
|
||||
index 3c2a68b7e0..68996426cc 100644
|
||||
index 0a46cf2264..1f4e708bcf 100644
|
||||
--- a/libavcodec/libdav1d.c
|
||||
+++ b/libavcodec/libdav1d.c
|
||||
@@ -58,6 +58,16 @@ static const enum AVPixelFormat pix_fmt_rgb[3] = {
|
||||
@@ -66,6 +66,16 @@ static const enum AVPixelFormat pix_fmt_rgb[3] = {
|
||||
AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12,
|
||||
};
|
||||
|
||||
@ -38,16 +38,16 @@ index 3c2a68b7e0..68996426cc 100644
|
||||
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;
|
||||
@@ -390,6 +400,7 @@ static int libdav1d_receive_frame(AVCodecContext *c, AVFrame *frame)
|
||||
if (res < 0)
|
||||
goto fail;
|
||||
|
||||
+ 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 3af25a2cae2ad3152e2969eefd9f13c9bb183969 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
|
||||
@ -57,7 +57,7 @@ Subject: [PATCH 2/2] add long-term yuv2rgb logging patch
|
||||
1 file changed, 4 deletions(-)
|
||||
|
||||
diff --git a/libswscale/yuv2rgb.c b/libswscale/yuv2rgb.c
|
||||
index 6a3956e8e2..d6f9aea166 100644
|
||||
index 6ee483d12a..c22161741b 100644
|
||||
--- a/libswscale/yuv2rgb.c
|
||||
+++ b/libswscale/yuv2rgb.c
|
||||
@@ -688,10 +688,6 @@ SwsFunc ff_yuv2rgb_get_func_ptr(SwsContext *c)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
From 1e73397d52d69378ebac5a390da508cd16d7d97e Mon Sep 17 00:00:00 2001
|
||||
From c4be609d822229be09cd9dd6f64cad716b0a48ce 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
|
||||
@ -42,7 +42,7 @@ V5:
|
||||
5 files changed, 213 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c
|
||||
index 4b2679eb38..cbd3e5680d 100644
|
||||
index 3f5471067a..07662b5fc3 100644
|
||||
--- a/libavcodec/v4l2_buffers.c
|
||||
+++ b/libavcodec/v4l2_buffers.c
|
||||
@@ -21,6 +21,7 @@
|
||||
@ -53,15 +53,15 @@ index 4b2679eb38..cbd3e5680d 100644
|
||||
#include <linux/videodev2.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
@@ -30,6 +31,7 @@
|
||||
@@ -29,6 +30,7 @@
|
||||
#include <poll.h>
|
||||
#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)
|
||||
@@ -209,7 +211,79 @@ static enum AVColorTransferCharacteristic v4l2_get_color_trc(V4L2Buffer *buf)
|
||||
return AVCOL_TRC_UNSPECIFIED;
|
||||
}
|
||||
|
||||
@ -142,7 +142,7 @@ index 4b2679eb38..cbd3e5680d 100644
|
||||
{
|
||||
V4L2Buffer* avbuf = opaque;
|
||||
V4L2m2mContext *s = buf_to_m2mctx(avbuf);
|
||||
@@ -234,6 +308,36 @@ static void v4l2_free_buffer(void *opaque, uint8_t *unused)
|
||||
@@ -233,6 +307,36 @@ static void v4l2_free_buffer(void *opaque, uint8_t *unused)
|
||||
}
|
||||
}
|
||||
|
||||
@ -179,7 +179,7 @@ index 4b2679eb38..cbd3e5680d 100644
|
||||
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)
|
||||
@@ -253,6 +357,24 @@ static int v4l2_buf_increase_ref(V4L2Buffer *in)
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -204,7 +204,7 @@ index 4b2679eb38..cbd3e5680d 100644
|
||||
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)
|
||||
@@ -302,13 +424,24 @@ static int v4l2_buffer_buf_to_swframe(AVFrame *frame, V4L2Buffer *avbuf)
|
||||
|
||||
frame->format = avbuf->context->av_pix_fmt;
|
||||
|
||||
@ -233,7 +233,7 @@ index 4b2679eb38..cbd3e5680d 100644
|
||||
}
|
||||
|
||||
/* fixup special cases */
|
||||
@@ -543,9 +676,6 @@ int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index)
|
||||
@@ -542,9 +675,6 @@ int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index)
|
||||
|
||||
avbuf->status = V4L2BUF_AVAILABLE;
|
||||
|
||||
@ -243,7 +243,7 @@ index 4b2679eb38..cbd3e5680d 100644
|
||||
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)
|
||||
@@ -554,6 +684,15 @@ int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index)
|
||||
avbuf->buf.length = avbuf->planes[0].length;
|
||||
}
|
||||
|
||||
@ -260,18 +260,18 @@ index 4b2679eb38..cbd3e5680d 100644
|
||||
}
|
||||
|
||||
diff --git a/libavcodec/v4l2_buffers.h b/libavcodec/v4l2_buffers.h
|
||||
index 8dbc7fc104..037e667997 100644
|
||||
index 3d2ff1b9a5..b82c990dcc 100644
|
||||
--- a/libavcodec/v4l2_buffers.h
|
||||
+++ b/libavcodec/v4l2_buffers.h
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <stdatomic.h>
|
||||
#include <linux/videodev2.h>
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
#include "libavutil/buffer.h"
|
||||
#include "libavutil/frame.h"
|
||||
+#include "libavutil/hwcontext_drm.h"
|
||||
#include "avcodec.h"
|
||||
#include "packet.h"
|
||||
|
||||
enum V4L2Buffer_status {
|
||||
@@ -42,6 +43,9 @@ typedef struct V4L2Buffer {
|
||||
@@ -45,6 +46,9 @@ typedef struct V4L2Buffer {
|
||||
/* each buffer needs to have a reference to its context */
|
||||
struct V4L2Context *context;
|
||||
|
||||
@ -282,10 +282,10 @@ index 8dbc7fc104..037e667997 100644
|
||||
* 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
|
||||
index e891649f92..4de23e687c 100644
|
||||
--- a/libavcodec/v4l2_context.c
|
||||
+++ b/libavcodec/v4l2_context.c
|
||||
@@ -455,22 +455,54 @@ static int v4l2_release_buffers(V4L2Context* ctx)
|
||||
@@ -441,22 +441,54 @@ static int v4l2_release_buffers(V4L2Context* ctx)
|
||||
struct v4l2_requestbuffers req = {
|
||||
.memory = V4L2_MEMORY_MMAP,
|
||||
.type = ctx->type,
|
||||
@ -359,7 +359,7 @@ index b67b216331..0fbd19a013 100644
|
||||
|
||||
typedef struct V4L2m2mPriv {
|
||||
diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c
|
||||
index ab07c0a24a..6bc7442702 100644
|
||||
index 8a51dec3fa..d916a3b726 100644
|
||||
--- a/libavcodec/v4l2_m2m_dec.c
|
||||
+++ b/libavcodec/v4l2_m2m_dec.c
|
||||
@@ -23,6 +23,9 @@
|
||||
@ -373,8 +373,8 @@ index ab07c0a24a..6bc7442702 100644
|
||||
#include "libavutil/pixdesc.h"
|
||||
#include "libavutil/opt.h"
|
||||
@@ -30,6 +33,9 @@
|
||||
#include "codec_internal.h"
|
||||
#include "libavcodec/decode.h"
|
||||
#include "libavcodec/internal.h"
|
||||
|
||||
+#include "libavcodec/hwaccels.h"
|
||||
+#include "libavcodec/internal.h"
|
||||
@ -382,7 +382,7 @@ index ab07c0a24a..6bc7442702 100644
|
||||
#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)
|
||||
@@ -205,6 +211,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;
|
||||
|
||||
@ -398,7 +398,7 @@ index ab07c0a24a..6bc7442702 100644
|
||||
s->avctx = avctx;
|
||||
ret = ff_v4l2_m2m_codec_init(priv);
|
||||
if (ret) {
|
||||
@@ -226,6 +241,11 @@ static const AVOption options[] = {
|
||||
@@ -230,6 +245,11 @@ static const AVOption options[] = {
|
||||
{ NULL},
|
||||
};
|
||||
|
||||
@ -410,18 +410,18 @@ index ab07c0a24a..6bc7442702 100644
|
||||
#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[] = {
|
||||
@@ -253,6 +273,9 @@ static const AVOption options[] = {
|
||||
.bsfs = bsf_name, \
|
||||
.capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING, \
|
||||
.p.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, \
|
||||
+ .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_DRM_PRIME, \
|
||||
+ AV_PIX_FMT_NONE}, \
|
||||
+ .hw_configs = v4l2_m2m_hw_configs, \
|
||||
.wrapper_name = "v4l2m2m", \
|
||||
.p.wrapper_name = "v4l2m2m", \
|
||||
}
|
||||
|
||||
|
||||
From deb0ba531401f069dc6e4dcf235dfc08bca6577c Mon Sep 17 00:00:00 2001
|
||||
From bb47b0e2ce4dda5ddeb4568d2b0260ec950d68cd 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
|
||||
@ -432,10 +432,10 @@ Subject: [PATCH 2/9] libavcodec: v4l2m2m: depends on libdrm
|
||||
2 files changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/configure b/configure
|
||||
index 4ba72bf84b..efb065905c 100755
|
||||
index ba5793b2ff..1872046e0e 100755
|
||||
--- a/configure
|
||||
+++ b/configure
|
||||
@@ -3438,6 +3438,7 @@ sndio_indev_deps="sndio"
|
||||
@@ -3539,6 +3539,7 @@ sndio_indev_deps="sndio"
|
||||
sndio_outdev_deps="sndio"
|
||||
v4l2_indev_deps_any="linux_videodev2_h sys_videoio_h"
|
||||
v4l2_indev_suggest="libv4l2"
|
||||
@ -444,7 +444,7 @@ index 4ba72bf84b..efb065905c 100755
|
||||
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
|
||||
index 07662b5fc3..d41558527c 100644
|
||||
--- a/libavcodec/v4l2_buffers.c
|
||||
+++ b/libavcodec/v4l2_buffers.c
|
||||
@@ -21,7 +21,7 @@
|
||||
@ -457,7 +457,7 @@ index cbd3e5680d..bebe2c1796 100644
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
From f89fad11f53110cd6968c83e89bafb0c449f34ec Mon Sep 17 00:00:00 2001
|
||||
From a362c4ec155e5e38c7a1ed3d3c57054ba09d9945 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
|
||||
@ -468,10 +468,10 @@ Subject: [PATCH 3/9] libavcodec: v4l2m2m: set format_modifier to
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c
|
||||
index bebe2c1796..12037d5d66 100644
|
||||
index d41558527c..95c8a1e409 100644
|
||||
--- a/libavcodec/v4l2_buffers.c
|
||||
+++ b/libavcodec/v4l2_buffers.c
|
||||
@@ -328,10 +328,12 @@ static int v4l2_buffer_export_drm(V4L2Buffer* avbuf)
|
||||
@@ -327,10 +327,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;
|
||||
@ -485,7 +485,7 @@ index bebe2c1796..12037d5d66 100644
|
||||
}
|
||||
|
||||
|
||||
From d5a37af1a8fe1ed70428e55286126d241986dd0c Mon Sep 17 00:00:00 2001
|
||||
From d4c8398a40baae35c79c1baf7e99306edda53e1a 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
|
||||
@ -496,10 +496,10 @@ Subject: [PATCH 4/9] libavcodec: v4l2m2m: only mmap the buffer when it is
|
||||
1 file changed, 14 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c
|
||||
index 12037d5d66..1adf518ab9 100644
|
||||
index 95c8a1e409..0a65f32cb2 100644
|
||||
--- a/libavcodec/v4l2_buffers.c
|
||||
+++ b/libavcodec/v4l2_buffers.c
|
||||
@@ -662,14 +662,22 @@ int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index)
|
||||
@@ -661,14 +661,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;
|
||||
@ -529,7 +529,7 @@ index 12037d5d66..1adf518ab9 100644
|
||||
|
||||
if (avbuf->plane_info[i].mm_addr == MAP_FAILED)
|
||||
|
||||
From d0be699166cdc413a5dc3e1c087433ac7cf142e7 Mon Sep 17 00:00:00 2001
|
||||
From 5c468fefad99503d2fe53e5a83ef29a409f0abaa 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
|
||||
@ -539,10 +539,10 @@ Subject: [PATCH 5/9] libavcodec: v4l2m2m: allow using software pixel formats
|
||||
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
|
||||
index d916a3b726..7787a2c185 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)
|
||||
@@ -217,8 +217,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.
|
||||
*/
|
||||
@ -560,16 +560,16 @@ index 6bc7442702..4b9baf833c 100644
|
||||
|
||||
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, \
|
||||
@@ -274,6 +282,7 @@ static const AVCodecHWConfigInternal *v4l2_m2m_hw_configs[] = {
|
||||
.p.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, \
|
||||
.p.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", \
|
||||
.p.wrapper_name = "v4l2m2m", \
|
||||
|
||||
From c4736742883eb2a1965ac65a5c75d5409e3c85a0 Mon Sep 17 00:00:00 2001
|
||||
From dd923e56e054df2f1bb275cef039b82e94fcbcb6 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
|
||||
@ -582,10 +582,10 @@ Subject: [PATCH 6/9] libavcodec: v4l2m2m: implement hwcontext
|
||||
4 files changed, 37 insertions(+)
|
||||
|
||||
diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c
|
||||
index 1adf518ab9..6e2a544394 100644
|
||||
index 0a65f32cb2..a040d418d9 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)
|
||||
@@ -434,6 +434,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;
|
||||
@ -593,7 +593,7 @@ index 1adf518ab9..6e2a544394 100644
|
||||
} 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)
|
||||
@@ -634,6 +635,27 @@ int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index)
|
||||
avbuf->buf.type = ctx->type;
|
||||
avbuf->buf.index = index;
|
||||
|
||||
@ -622,10 +622,10 @@ index 1adf518ab9..6e2a544394 100644
|
||||
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
|
||||
index 6f7460c89a..02fbb6eec3 100644
|
||||
--- a/libavcodec/v4l2_context.h
|
||||
+++ b/libavcodec/v4l2_context.h
|
||||
@@ -92,6 +92,8 @@ typedef struct V4L2Context {
|
||||
@@ -93,6 +93,8 @@ typedef struct V4L2Context {
|
||||
*/
|
||||
int done;
|
||||
|
||||
@ -648,7 +648,7 @@ index 0fbd19a013..adf5997bb5 100644
|
||||
int output_drm;
|
||||
} V4L2m2mContext;
|
||||
diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c
|
||||
index 4b9baf833c..6c23693137 100644
|
||||
index 7787a2c185..9aca68e48c 100644
|
||||
--- a/libavcodec/v4l2_m2m_dec.c
|
||||
+++ b/libavcodec/v4l2_m2m_dec.c
|
||||
@@ -35,6 +35,7 @@
|
||||
@ -659,7 +659,7 @@ index 4b9baf833c..6c23693137 100644
|
||||
|
||||
#include "v4l2_context.h"
|
||||
#include "v4l2_m2m.h"
|
||||
@@ -224,6 +225,16 @@ static av_cold int v4l2_decode_init(AVCodecContext *avctx)
|
||||
@@ -228,6 +229,16 @@ static av_cold int v4l2_decode_init(AVCodecContext *avctx)
|
||||
break;
|
||||
}
|
||||
|
||||
@ -677,7 +677,7 @@ index 4b9baf833c..6c23693137 100644
|
||||
ret = ff_v4l2_m2m_codec_init(priv);
|
||||
if (ret) {
|
||||
|
||||
From 0b15c77718900bf60c91217ed1492390022ad6db Mon Sep 17 00:00:00 2001
|
||||
From 32ca7163c62887aa4b4032bbd5858a03bf3e145e 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
|
||||
@ -705,10 +705,10 @@ index adf5997bb5..1082b9dad2 100644
|
||||
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
|
||||
index 9aca68e48c..7afc81180d 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)
|
||||
@@ -260,7 +260,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",
|
||||
@ -718,7 +718,7 @@ index 6c23693137..e323c37052 100644
|
||||
};
|
||||
|
||||
|
||||
From acc86933e5fe3a13aae44cf84c48bab6c717e49b Mon Sep 17 00:00:00 2001
|
||||
From 199d87bed11be1665913b88d7cae9417f48afa37 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
|
||||
@ -731,10 +731,10 @@ Subject: [PATCH 8/9] libavcodec: v4l2m2m: add option to specify pixel format
|
||||
3 files changed, 12 insertions(+)
|
||||
|
||||
diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c
|
||||
index e9e8c27a54..a97b70e836 100644
|
||||
index 4de23e687c..49ef4a684f 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
|
||||
@@ -517,6 +517,8 @@ static inline int v4l2_try_raw_format(V4L2Context* ctx, enum AVPixelFormat pixfm
|
||||
|
||||
static int v4l2_get_raw_format(V4L2Context* ctx, enum AVPixelFormat *p)
|
||||
{
|
||||
@ -743,7 +743,7 @@ index e9e8c27a54..a97b70e836 100644
|
||||
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)
|
||||
@@ -535,6 +537,13 @@ static int v4l2_get_raw_format(V4L2Context* ctx, enum AVPixelFormat *p)
|
||||
if (ret)
|
||||
return AVERROR(EINVAL);
|
||||
|
||||
@ -778,10 +778,10 @@ index 1082b9dad2..943a8923c4 100644
|
||||
|
||||
/**
|
||||
diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c
|
||||
index e323c37052..363e998142 100644
|
||||
index 7afc81180d..de89d0ff18 100644
|
||||
--- a/libavcodec/v4l2_m2m_dec.c
|
||||
+++ b/libavcodec/v4l2_m2m_dec.c
|
||||
@@ -257,6 +257,7 @@ static const AVOption options[] = {
|
||||
@@ -261,6 +261,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 },
|
||||
@ -790,7 +790,7 @@ index e323c37052..363e998142 100644
|
||||
};
|
||||
|
||||
|
||||
From 909ca6380d9112cc0111266da02a4a8e1e5abc1e Mon Sep 17 00:00:00 2001
|
||||
From 38c65aab679c04e4dd5a58f889844e68e34c80ab 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
|
||||
@ -800,10 +800,10 @@ Subject: [PATCH 9/9] libavcodec: v4l2m2m: implement flush
|
||||
1 file changed, 36 insertions(+)
|
||||
|
||||
diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c
|
||||
index 363e998142..52ec67cb59 100644
|
||||
index de89d0ff18..3278627553 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)
|
||||
@@ -254,6 +254,41 @@ static av_cold int v4l2_decode_close(AVCodecContext *avctx)
|
||||
return ff_v4l2_m2m_codec_end(avctx->priv_data);
|
||||
}
|
||||
|
||||
@ -815,6 +815,11 @@ index 363e998142..52ec67cb59 100644
|
||||
+ V4L2Context* capture = &s->capture;
|
||||
+ int ret, i;
|
||||
+
|
||||
+ struct v4l2_decoder_cmd cmd = {
|
||||
+ .cmd = V4L2_DEC_CMD_START,
|
||||
+ .flags = 0,
|
||||
+ };
|
||||
+
|
||||
+ 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);
|
||||
@ -828,11 +833,6 @@ index 363e998142..52ec67cb59 100644
|
||||
+ 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);
|
||||
@ -845,11 +845,11 @@ index 363e998142..52ec67cb59 100644
|
||||
#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[] = {
|
||||
@@ -290,6 +325,7 @@ static const AVCodecHWConfigInternal *v4l2_m2m_hw_configs[] = {
|
||||
.init = v4l2_decode_init, \
|
||||
.receive_frame = v4l2_receive_frame, \
|
||||
FF_CODEC_RECEIVE_FRAME_CB(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, \
|
||||
.p.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
@ -1,20 +1,21 @@
|
||||
From 39069d9cc03a42cd497dd6b9756116ff4b684a5d Mon Sep 17 00:00:00 2001
|
||||
From d14859b090dc3b2e1bd761698b947b0b55e4d831 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
Date: Tue, 3 Dec 2019 21:01:18 +0100
|
||||
Subject: [PATCH] WIP deint filter
|
||||
Subject: [PATCH] Add V4L2 m2m deinterlace filter
|
||||
|
||||
Signed-off-by: Alex Bee <knaerzche@gmail.com>
|
||||
---
|
||||
libavfilter/Makefile | 1 +
|
||||
libavfilter/allfilters.c | 1 +
|
||||
libavfilter/vf_deinterlace_v4l2m2m.c | 879 +++++++++++++++++++++++++++
|
||||
3 files changed, 881 insertions(+)
|
||||
libavfilter/Makefile | 1 +
|
||||
libavfilter/allfilters.c | 1 +
|
||||
libavfilter/vf_deinterlace_v4l2m2m.c | 1009 ++++++++++++++++++++++++++
|
||||
3 files changed, 1011 insertions(+)
|
||||
create mode 100644 libavfilter/vf_deinterlace_v4l2m2m.c
|
||||
|
||||
diff --git a/libavfilter/Makefile b/libavfilter/Makefile
|
||||
index 512354065305..625fd29f9313 100644
|
||||
index 30cc329fb6..2fe6ab223e 100644
|
||||
--- a/libavfilter/Makefile
|
||||
+++ b/libavfilter/Makefile
|
||||
@@ -218,6 +218,7 @@ OBJS-$(CONFIG_DEFLATE_FILTER) += vf_neighbor.o
|
||||
@@ -254,6 +254,7 @@ OBJS-$(CONFIG_DEFLATE_FILTER) += vf_neighbor.o
|
||||
OBJS-$(CONFIG_DEFLICKER_FILTER) += vf_deflicker.o
|
||||
OBJS-$(CONFIG_DEINTERLACE_QSV_FILTER) += vf_deinterlace_qsv.o
|
||||
OBJS-$(CONFIG_DEINTERLACE_VAAPI_FILTER) += vf_deinterlace_vaapi.o vaapi_vpp.o
|
||||
@ -23,23 +24,23 @@ index 512354065305..625fd29f9313 100644
|
||||
OBJS-$(CONFIG_DELOGO_FILTER) += vf_delogo.o
|
||||
OBJS-$(CONFIG_DENOISE_VAAPI_FILTER) += vf_misc_vaapi.o vaapi_vpp.o
|
||||
diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c
|
||||
index 1183e4026751..fe5a2e8c02e8 100644
|
||||
index 5ebacfde27..4b74bac3c8 100644
|
||||
--- a/libavfilter/allfilters.c
|
||||
+++ b/libavfilter/allfilters.c
|
||||
@@ -204,6 +204,7 @@ extern AVFilter ff_vf_dedot;
|
||||
extern AVFilter ff_vf_deflate;
|
||||
extern AVFilter ff_vf_deflicker;
|
||||
extern AVFilter ff_vf_deinterlace_qsv;
|
||||
+extern AVFilter ff_vf_deinterlace_v4l2m2m;
|
||||
extern AVFilter ff_vf_deinterlace_vaapi;
|
||||
extern AVFilter ff_vf_dejudder;
|
||||
extern AVFilter ff_vf_delogo;
|
||||
@@ -234,6 +234,7 @@ extern const AVFilter ff_vf_dedot;
|
||||
extern const AVFilter ff_vf_deflate;
|
||||
extern const AVFilter ff_vf_deflicker;
|
||||
extern const AVFilter ff_vf_deinterlace_qsv;
|
||||
+extern const AVFilter ff_vf_deinterlace_v4l2m2m;
|
||||
extern const AVFilter ff_vf_deinterlace_vaapi;
|
||||
extern const AVFilter ff_vf_dejudder;
|
||||
extern const AVFilter ff_vf_delogo;
|
||||
diff --git a/libavfilter/vf_deinterlace_v4l2m2m.c b/libavfilter/vf_deinterlace_v4l2m2m.c
|
||||
new file mode 100644
|
||||
index 000000000000..1029e5b620fd
|
||||
index 0000000000..ff5ed500a9
|
||||
--- /dev/null
|
||||
+++ b/libavfilter/vf_deinterlace_v4l2m2m.c
|
||||
@@ -0,0 +1,879 @@
|
||||
@@ -0,0 +1,1009 @@
|
||||
+/*
|
||||
+ * This file is part of FFmpeg.
|
||||
+ *
|
||||
@ -127,12 +128,21 @@ index 000000000000..1029e5b620fd
|
||||
+ int height;
|
||||
+ int orig_width;
|
||||
+ int orig_height;
|
||||
+ uint64_t drm_in_format;
|
||||
+ uint64_t drm_out_format;
|
||||
+
|
||||
+ atomic_uint refcount;
|
||||
+
|
||||
+ AVBufferRef *hw_frames_ctx;
|
||||
+
|
||||
+ int frame_count;
|
||||
+ AVFrame *frames[2];
|
||||
+ /*
|
||||
+ * TODO: check if its really neccessary to hold this
|
||||
+ * ref, it's only used for freeing av_frame on decoding
|
||||
+ * end/abort
|
||||
+ */
|
||||
+ AVFrame *cur_in_frame;
|
||||
+ AVFrame *prev_in_frame;
|
||||
+ unsigned int field_order;
|
||||
+
|
||||
+ V4L2Queue output;
|
||||
+ V4L2Queue capture;
|
||||
@ -144,6 +154,76 @@ index 000000000000..1029e5b620fd
|
||||
+ DeintV4L2M2MContextShared *shared;
|
||||
+} DeintV4L2M2MContext;
|
||||
+
|
||||
+static inline uint32_t v4l2_pix_fmt_from_drm_format(uint64_t drm_format)
|
||||
+{
|
||||
+ switch(drm_format) {
|
||||
+#if defined(V4L2_PIX_FMT_SUNXI_TILED_NV12) && defined(DRM_FORMAT_MOD_ALLWINNER_TILED)
|
||||
+ case DRM_FORMAT_MOD_ALLWINNER_TILED:
|
||||
+ return V4L2_PIX_FMT_SUNXI_TILED_NV12;
|
||||
+#endif
|
||||
+ case DRM_FORMAT_NV12:
|
||||
+ return V4L2_PIX_FMT_NV12;
|
||||
+#if defined(V4L2_PIX_FMT_NV15) && defined(DRM_FORMAT_NV15)
|
||||
+ case DRM_FORMAT_NV15:
|
||||
+ return V4L2_PIX_FMT_NV15;
|
||||
+#endif
|
||||
+ case DRM_FORMAT_NV16:
|
||||
+ return V4L2_PIX_FMT_NV16;
|
||||
+#if defined(V4L2_PIX_FMT_NV20) && defined(DRM_FORMAT_NV20)
|
||||
+ case DRM_FORMAT_NV20:
|
||||
+ return V4L2_PIX_FMT_NV20;
|
||||
+#endif
|
||||
+ case DRM_FORMAT_NV21:
|
||||
+ return V4L2_PIX_FMT_NV21;
|
||||
+ case DRM_FORMAT_NV61:
|
||||
+ return V4L2_PIX_FMT_NV61;
|
||||
+ default:
|
||||
+ av_log(NULL, AV_LOG_WARNING, "%s unknown drm format 0x%llx using default v4l2_pix_fmt 0x%x\n",
|
||||
+ __func__ , drm_format, V4L2_PIX_FMT_NV12);
|
||||
+ return V4L2_PIX_FMT_NV12;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static inline uint64_t drm_format_from_v4l2_pix_fmt(uint32_t v4l2_pix_fmt)
|
||||
+{
|
||||
+ switch(v4l2_pix_fmt) {
|
||||
+ case V4L2_PIX_FMT_NV12:
|
||||
+ return DRM_FORMAT_NV12;
|
||||
+#if defined(V4L2_PIX_FMT_NV15) && defined(DRM_FORMAT_NV15)
|
||||
+ case V4L2_PIX_FMT_NV15:
|
||||
+ return DRM_FORMAT_NV15;
|
||||
+#endif
|
||||
+ case V4L2_PIX_FMT_NV16:
|
||||
+ return DRM_FORMAT_NV16;
|
||||
+#if defined(V4L2_PIX_FMT_NV20) && defined(DRM_FORMAT_NV20)
|
||||
+ case V4L2_PIX_FMT_NV20:
|
||||
+ return DRM_FORMAT_NV20;
|
||||
+#endif
|
||||
+ case V4L2_PIX_FMT_NV21:
|
||||
+ return DRM_FORMAT_NV21;
|
||||
+ case V4L2_PIX_FMT_NV61:
|
||||
+ return DRM_FORMAT_NV61;
|
||||
+#if defined(V4L2_PIX_FMT_SUNXI_TILED_NV12) && defined(DRM_FORMAT_MOD_ALLWINNER_TILED)
|
||||
+ case V4L2_PIX_FMT_SUNXI_TILED_NV12:
|
||||
+ return DRM_FORMAT_MOD_ALLWINNER_TILED;
|
||||
+#endif
|
||||
+ default:
|
||||
+ av_log(NULL, AV_LOG_WARNING, "%s unknown v4l2_pix_fmt format 0x%x using default drm_format 0x%x\n",
|
||||
+ __func__ , v4l2_pix_fmt, DRM_FORMAT_NV12);
|
||||
+ return DRM_FORMAT_NV12;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static inline uint64_t drm_format_modifier(uint64_t drm_format)
|
||||
+{
|
||||
+#ifdef DRM_FORMAT_MOD_ALLWINNER_TILED
|
||||
+ if (drm_format == DRM_FORMAT_MOD_ALLWINNER_TILED)
|
||||
+ return DRM_FORMAT_MOD_ALLWINNER_TILED;
|
||||
+#endif
|
||||
+ return DRM_FORMAT_MOD_LINEAR;
|
||||
+
|
||||
+}
|
||||
+
|
||||
+static int deint_v4l2m2m_prepare_context(DeintV4L2M2MContextShared *ctx)
|
||||
+{
|
||||
+ struct v4l2_capability cap;
|
||||
@ -174,11 +254,12 @@ index 000000000000..1029e5b620fd
|
||||
+ return AVERROR(EINVAL);
|
||||
+}
|
||||
+
|
||||
+static int deint_v4l2m2m_try_format(V4L2Queue *queue)
|
||||
+static int deint_v4l2m2m_try_format(V4L2Queue *queue, uint64_t drm_format)
|
||||
+{
|
||||
+ struct v4l2_format *fmt = &queue->format;
|
||||
+ DeintV4L2M2MContextShared *ctx = queue->ctx;
|
||||
+ int ret, field;
|
||||
+ uint32_t v4l2_pix_fmt = v4l2_pix_fmt_from_drm_format(drm_format);
|
||||
+
|
||||
+ ret = ioctl(ctx->fd, VIDIOC_G_FMT, fmt);
|
||||
+ if (ret)
|
||||
@ -190,12 +271,12 @@ index 000000000000..1029e5b620fd
|
||||
+ field = V4L2_FIELD_NONE;
|
||||
+
|
||||
+ if (V4L2_TYPE_IS_MULTIPLANAR(fmt->type)) {
|
||||
+ fmt->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12;
|
||||
+ fmt->fmt.pix_mp.pixelformat = v4l2_pix_fmt;
|
||||
+ fmt->fmt.pix_mp.field = field;
|
||||
+ fmt->fmt.pix_mp.width = ctx->width;
|
||||
+ fmt->fmt.pix_mp.height = ctx->height;
|
||||
+ } else {
|
||||
+ fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_NV12;
|
||||
+ fmt->fmt.pix.pixelformat = v4l2_pix_fmt;
|
||||
+ fmt->fmt.pix.field = field;
|
||||
+ fmt->fmt.pix.width = ctx->width;
|
||||
+ fmt->fmt.pix.height = ctx->height;
|
||||
@ -206,14 +287,14 @@ index 000000000000..1029e5b620fd
|
||||
+ return AVERROR(EINVAL);
|
||||
+
|
||||
+ if (V4L2_TYPE_IS_MULTIPLANAR(fmt->type)) {
|
||||
+ if (fmt->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_NV12 ||
|
||||
+ if (fmt->fmt.pix_mp.pixelformat != v4l2_pix_fmt ||
|
||||
+ fmt->fmt.pix_mp.field != field) {
|
||||
+ av_log(NULL, AV_LOG_DEBUG, "format not supported for type %d\n", fmt->type);
|
||||
+
|
||||
+ return AVERROR(EINVAL);
|
||||
+ }
|
||||
+ } else {
|
||||
+ if (fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_NV12 ||
|
||||
+ if (fmt->fmt.pix.pixelformat != v4l2_pix_fmt ||
|
||||
+ fmt->fmt.pix.field != field) {
|
||||
+ av_log(NULL, AV_LOG_DEBUG, "format not supported for type %d\n", fmt->type);
|
||||
+
|
||||
@ -223,19 +304,21 @@ index 000000000000..1029e5b620fd
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int deint_v4l2m2m_set_format(V4L2Queue *queue, uint32_t field, int width, int height)
|
||||
+static int deint_v4l2m2m_set_format(V4L2Queue *queue, uint32_t field, int width, int height, uint64_t drm_format)
|
||||
+{
|
||||
+ struct v4l2_format *fmt = &queue->format;
|
||||
+ DeintV4L2M2MContextShared *ctx = queue->ctx;
|
||||
+ int ret;
|
||||
+ uint32_t v4l2_pix_fmt = v4l2_pix_fmt_from_drm_format(drm_format);
|
||||
+
|
||||
+ if (V4L2_TYPE_IS_MULTIPLANAR(fmt->type)) {
|
||||
+ fmt->fmt.pix_mp.pixelformat = v4l2_pix_fmt;
|
||||
+ fmt->fmt.pix_mp.field = field;
|
||||
+ fmt->fmt.pix_mp.width = width;
|
||||
+ fmt->fmt.pix_mp.height = height;
|
||||
+ /* TODO: bytesperline and imagesize */
|
||||
+ } else {
|
||||
+ fmt->fmt.pix.pixelformat = v4l2_pix_fmt;
|
||||
+ fmt->fmt.pix.field = field;
|
||||
+ fmt->fmt.pix.width = width;
|
||||
+ fmt->fmt.pix.height = height;
|
||||
@ -247,6 +330,18 @@ index 000000000000..1029e5b620fd
|
||||
+ if (ret)
|
||||
+ av_log(NULL, AV_LOG_ERROR, "VIDIOC_S_FMT failed: %d\n", ret);
|
||||
+
|
||||
+ else if (!V4L2_TYPE_IS_OUTPUT(queue->format.type)) {
|
||||
+ if (V4L2_TYPE_IS_MULTIPLANAR(fmt->type) && fmt->fmt.pix_mp.pixelformat != v4l2_pix_fmt) {
|
||||
+ ctx->drm_out_format = drm_format_from_v4l2_pix_fmt(fmt->fmt.pix_mp.pixelformat);
|
||||
+ av_log(NULL, AV_LOG_DEBUG, "%s driver updated v4l2_pixfmt from: %x to %x, so now using %llx as drm output format\n",
|
||||
+ __func__, v4l2_pix_fmt, fmt->fmt.pix_mp.pixelformat, ctx->drm_out_format);
|
||||
+ } else if (fmt->fmt.pix.pixelformat != v4l2_pix_fmt) {
|
||||
+ ctx->drm_out_format = drm_format_from_v4l2_pix_fmt(fmt->fmt.pix.pixelformat);
|
||||
+ av_log(NULL, AV_LOG_DEBUG, "%s driver updated v4l2_pixfmt from: %x to %x, so now using %llx as drm output format\n",
|
||||
+ __func__, v4l2_pix_fmt, fmt->fmt.pix.pixelformat, ctx->drm_out_format);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
@ -262,11 +357,11 @@ index 000000000000..1029e5b620fd
|
||||
+ if (ret)
|
||||
+ goto fail;
|
||||
+
|
||||
+ ret = deint_v4l2m2m_try_format(&ctx->capture);
|
||||
+ ret = deint_v4l2m2m_try_format(&ctx->capture, ctx->drm_out_format);
|
||||
+ if (ret)
|
||||
+ goto fail;
|
||||
+
|
||||
+ ret = deint_v4l2m2m_try_format(&ctx->output);
|
||||
+ ret = deint_v4l2m2m_try_format(&ctx->output, ctx->drm_in_format);
|
||||
+ if (ret)
|
||||
+ goto fail;
|
||||
+
|
||||
@ -329,7 +424,7 @@ index 000000000000..1029e5b620fd
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int v4l2_buffer_export_drm(V4L2Buffer* avbuf)
|
||||
+static int v4l2_buffer_export_drm(V4L2Buffer* avbuf, uint64_t drm_format)
|
||||
+{
|
||||
+ struct v4l2_exportbuffer expbuf;
|
||||
+ int i, ret;
|
||||
@ -351,12 +446,12 @@ index 000000000000..1029e5b620fd
|
||||
+ /* drm frame */
|
||||
+ avbuf->drm_frame.objects[i].size = avbuf->buffer.m.planes[i].length;
|
||||
+ avbuf->drm_frame.objects[i].fd = expbuf.fd;
|
||||
+ avbuf->drm_frame.objects[i].format_modifier = DRM_FORMAT_MOD_LINEAR;
|
||||
+ avbuf->drm_frame.objects[i].format_modifier = drm_format_modifier(drm_format);
|
||||
+ } else {
|
||||
+ /* drm frame */
|
||||
+ avbuf->drm_frame.objects[0].size = avbuf->buffer.length;
|
||||
+ avbuf->drm_frame.objects[0].fd = expbuf.fd;
|
||||
+ avbuf->drm_frame.objects[0].format_modifier = DRM_FORMAT_MOD_LINEAR;
|
||||
+ avbuf->drm_frame.objects[0].format_modifier = drm_format_modifier(drm_format);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
@ -441,7 +536,7 @@ index 000000000000..1029e5b620fd
|
||||
+ if (ret)
|
||||
+ goto fail;
|
||||
+
|
||||
+ ret = v4l2_buffer_export_drm(buf);
|
||||
+ ret = v4l2_buffer_export_drm(buf, ctx->drm_out_format);
|
||||
+ if (ret)
|
||||
+ goto fail;
|
||||
+ }
|
||||
@ -599,8 +694,11 @@ index 000000000000..1029e5b620fd
|
||||
+ close(capture->buffers[i].fd);
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < ctx->frame_count; i++)
|
||||
+ av_frame_free(&ctx->frames[i]);
|
||||
+ if (ctx->cur_in_frame)
|
||||
+ av_frame_free(&ctx->cur_in_frame);
|
||||
+
|
||||
+ if (ctx->prev_in_frame)
|
||||
+ av_frame_free(&ctx->prev_in_frame);
|
||||
+
|
||||
+ av_buffer_unref(&ctx->hw_frames_ctx);
|
||||
+
|
||||
@ -630,7 +728,7 @@ index 000000000000..1029e5b620fd
|
||||
+ deint_v4l2m2m_destroy_context(ctx);
|
||||
+}
|
||||
+
|
||||
+static uint8_t *v4l2_get_drm_frame(V4L2Buffer *avbuf, int height)
|
||||
+static uint8_t *v4l2_get_drm_frame(V4L2Buffer *avbuf, int height, uint64_t drm_format)
|
||||
+{
|
||||
+ AVDRMFrameDescriptor *drm_desc = &avbuf->drm_frame;
|
||||
+ AVDRMLayerDescriptor *layer;
|
||||
@ -648,7 +746,7 @@ index 000000000000..1029e5b620fd
|
||||
+ layer->planes[i].pitch = avbuf->plane_info[i].bytesperline;
|
||||
+ }
|
||||
+
|
||||
+ layer->format = DRM_FORMAT_NV12;
|
||||
+ layer->format = drm_format;
|
||||
+
|
||||
+ if (avbuf->num_planes == 1) {
|
||||
+ layer->nb_planes = 2;
|
||||
@ -680,7 +778,7 @@ index 000000000000..1029e5b620fd
|
||||
+
|
||||
+ atomic_fetch_add(&ctx->refcount, 1);
|
||||
+
|
||||
+ frame->data[0] = (uint8_t *)v4l2_get_drm_frame(avbuf, ctx->orig_height);
|
||||
+ frame->data[0] = (uint8_t *)v4l2_get_drm_frame(avbuf, ctx->orig_height, ctx->drm_out_format);
|
||||
+ frame->format = AV_PIX_FMT_DRM_PRIME;
|
||||
+ frame->hw_frames_ctx = av_buffer_ref(ctx->hw_frames_ctx);
|
||||
+ frame->height = ctx->height;
|
||||
@ -694,49 +792,79 @@ index 000000000000..1029e5b620fd
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int deint_v4l2m2m_dequeue(AVFilterContext *avctx, AVFrame *input_frame, int field)
|
||||
+static int deint_v4l2m2m_dequeue(AVFilterContext *avctx, AVFrame *input_frame)
|
||||
+{
|
||||
+ DeintV4L2M2MContext *priv = avctx->priv;
|
||||
+ DeintV4L2M2MContextShared *ctx = priv->shared;
|
||||
+ AVFilterLink *outlink = avctx->outputs[0];
|
||||
+ AVFrame *output_frame;
|
||||
+ AVFrame *output_frame_1, *output_frame_2;
|
||||
+ int64_t first_pts = AV_NOPTS_VALUE;
|
||||
+ int err;
|
||||
+
|
||||
+ output_frame = av_frame_alloc();
|
||||
+ av_log(priv, AV_LOG_DEBUG, "input pts: %"PRId64" (field %d)\n",
|
||||
+ input_frame->pts, ctx->field_order);
|
||||
+
|
||||
+ if (!output_frame)
|
||||
+ output_frame_1 = av_frame_alloc();
|
||||
+ if (!output_frame_1)
|
||||
+ return AVERROR(ENOMEM);
|
||||
+
|
||||
+ err = deint_v4l2m2m_dequeue_frame(&ctx->capture, output_frame, 500);
|
||||
+ err = deint_v4l2m2m_dequeue_frame(&ctx->capture, output_frame_1, 500);
|
||||
+ if (err < 0) {
|
||||
+ av_log(priv, AV_LOG_ERROR, "no frame (field %d)\n", field);
|
||||
+ goto fail;
|
||||
+ av_log(priv, AV_LOG_ERROR, "no 1st frame (field %d)\n", ctx->field_order);
|
||||
+ goto fail_out1;
|
||||
+ }
|
||||
+
|
||||
+ err = av_frame_copy_props(output_frame, input_frame);
|
||||
+ err = av_frame_copy_props(output_frame_1, input_frame);
|
||||
+ if (err < 0)
|
||||
+ goto fail;
|
||||
+ goto fail_out1;
|
||||
+
|
||||
+ output_frame->interlaced_frame = 0;
|
||||
+ output_frame_1->interlaced_frame = 0;
|
||||
+
|
||||
+ if (field == 0) {
|
||||
+ output_frame->pts *= 2;
|
||||
+ } else {
|
||||
+ int64_t cur_pts = ctx->frames[0]->pts;
|
||||
+ int64_t next_pts = ctx->frames[1]->pts;
|
||||
+
|
||||
+ if (next_pts != AV_NOPTS_VALUE && cur_pts != AV_NOPTS_VALUE) {
|
||||
+ output_frame->pts = next_pts + cur_pts;
|
||||
+ } else {
|
||||
+ output_frame->pts = AV_NOPTS_VALUE;
|
||||
+ }
|
||||
+ output_frame_2 = av_frame_alloc();
|
||||
+ if (!output_frame_2) {
|
||||
+ err = AVERROR(ENOMEM);
|
||||
+ goto fail_out1;
|
||||
+ }
|
||||
+ av_log(priv, AV_LOG_DEBUG, "pts: %"PRId64" (field %d)\n", output_frame->pts, field);
|
||||
+
|
||||
+ return ff_filter_frame(outlink, output_frame);
|
||||
+ err = deint_v4l2m2m_dequeue_frame(&ctx->capture, output_frame_2, 500);
|
||||
+ if (err < 0) {
|
||||
+ av_log(priv, AV_LOG_ERROR, "no 2nd frame (field %d)\n", ctx->field_order);
|
||||
+ goto fail_out2;
|
||||
+ }
|
||||
+
|
||||
+fail:
|
||||
+ av_frame_free(&output_frame);
|
||||
+ err = av_frame_copy_props(output_frame_2, input_frame);
|
||||
+ if (err < 0)
|
||||
+ goto fail_out2;
|
||||
+
|
||||
+ output_frame_2->interlaced_frame = 0;
|
||||
+
|
||||
+ if (ctx->prev_in_frame && ctx->prev_in_frame->pts != AV_NOPTS_VALUE
|
||||
+ && input_frame->pts != AV_NOPTS_VALUE) {
|
||||
+ first_pts = (ctx->prev_in_frame->pts + input_frame->pts) / 2;
|
||||
+ av_log(priv, AV_LOG_DEBUG, "calculated first pts %"PRId64"\n", first_pts);
|
||||
+ }
|
||||
+
|
||||
+ output_frame_1->pts = first_pts;
|
||||
+
|
||||
+ err = ff_filter_frame(outlink, output_frame_1);
|
||||
+ if (err < 0) {
|
||||
+ av_frame_free(&output_frame_2);
|
||||
+ return err;
|
||||
+ }
|
||||
+ err = ff_filter_frame(outlink, output_frame_2);
|
||||
+
|
||||
+ if (err < 0)
|
||||
+ return err;
|
||||
+
|
||||
+ av_log(priv, AV_LOG_DEBUG, "1st frame pts: %"PRId64" 2nd frame pts: %"PRId64" first pts: %"PRId64" (field %d)\n",
|
||||
+ output_frame_1->pts, output_frame_2->pts, first_pts, ctx->field_order);
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+fail_out2:
|
||||
+ av_frame_free(&output_frame_2);
|
||||
+fail_out1:
|
||||
+ av_frame_free(&output_frame_1);
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
@ -791,24 +919,32 @@ index 000000000000..1029e5b620fd
|
||||
+ V4L2Queue *output = &ctx->output;
|
||||
+ int ret;
|
||||
+
|
||||
+ av_log(priv, AV_LOG_DEBUG, "input pts: %"PRId64"\n", in->pts);
|
||||
+ if (!ctx->frame_count) {
|
||||
+ AVDRMFrameDescriptor *drm_desc = (AVDRMFrameDescriptor *)in->data[0];
|
||||
+ unsigned int field;
|
||||
+ av_log(priv, AV_LOG_DEBUG, "input pts: %"PRId64" field :%d interlaced: %d\n",
|
||||
+ in->pts, in->top_field_first, in->interlaced_frame);
|
||||
+
|
||||
+ ctx->cur_in_frame = in;
|
||||
+
|
||||
+ if (ctx->field_order == V4L2_FIELD_ANY) {
|
||||
+ AVDRMFrameDescriptor *drm_desc = (AVDRMFrameDescriptor *)in->data[0];
|
||||
+ ctx->orig_width = drm_desc->layers[0].planes[0].pitch;
|
||||
+ ctx->orig_height = drm_desc->layers[0].planes[1].offset / ctx->orig_width;
|
||||
+ ctx->drm_in_format = drm_desc->layers->format;
|
||||
+ ctx->drm_out_format = drm_desc->layers->format;
|
||||
+
|
||||
+ if (in->top_field_first)
|
||||
+ field = V4L2_FIELD_INTERLACED_TB;
|
||||
+ if (in->top_field_first)
|
||||
+ ctx->field_order = V4L2_FIELD_INTERLACED_TB;
|
||||
+ else
|
||||
+ field = V4L2_FIELD_INTERLACED_BT;
|
||||
+ ctx->field_order = V4L2_FIELD_INTERLACED_BT;
|
||||
+
|
||||
+ ret = deint_v4l2m2m_set_format(output, field, ctx->orig_width, ctx->orig_height);
|
||||
+ ret = deint_v4l2m2m_set_format(output, ctx->field_order,
|
||||
+ ctx->orig_width, ctx->orig_height,
|
||||
+ ctx->drm_in_format);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = deint_v4l2m2m_set_format(capture, V4L2_FIELD_NONE, ctx->orig_width, ctx->orig_height);
|
||||
+ ret = deint_v4l2m2m_set_format(capture, V4L2_FIELD_NONE,
|
||||
+ ctx->orig_width, ctx->orig_height,
|
||||
+ ctx->drm_out_format);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
@ -829,27 +965,19 @@ index 000000000000..1029e5b620fd
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ if (ctx->frame_count < 2) {
|
||||
+ ctx->frames[ctx->frame_count++] = in;
|
||||
+ } else {
|
||||
+ av_frame_free(&ctx->frames[0]);
|
||||
+ ctx->frames[0] = ctx->frames[1];
|
||||
+ ctx->frames[1] = in;
|
||||
+ }
|
||||
+
|
||||
+ ret = deint_v4l2m2m_enqueue(output, in);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ if (ctx->frame_count == 2) {
|
||||
+ ret = deint_v4l2m2m_dequeue(avctx, ctx->frames[0], 0);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ ret = deint_v4l2m2m_dequeue(avctx, in);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = deint_v4l2m2m_dequeue(avctx, ctx->frames[0], 1);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
+ if (ctx->prev_in_frame)
|
||||
+ av_frame_free(&ctx->prev_in_frame);
|
||||
+
|
||||
+ ctx->prev_in_frame = in;
|
||||
+ ctx->cur_in_frame = NULL;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
@ -870,6 +998,11 @@ index 000000000000..1029e5b620fd
|
||||
+ ctx->capture.ctx = ctx;
|
||||
+ ctx->capture.num_buffers = 6;
|
||||
+ ctx->done = 0;
|
||||
+ ctx->field_order = V4L2_FIELD_ANY;
|
||||
+ ctx->cur_in_frame = NULL;
|
||||
+ ctx->prev_in_frame = NULL;
|
||||
+ ctx->drm_in_format = DRM_FORMAT_NV12;
|
||||
+ ctx->drm_out_format = DRM_FORMAT_NV12;
|
||||
+ atomic_init(&ctx->refcount, 1);
|
||||
+
|
||||
+ return 0;
|
||||
@ -896,7 +1029,6 @@ index 000000000000..1029e5b620fd
|
||||
+ .type = AVMEDIA_TYPE_VIDEO,
|
||||
+ .filter_frame = deint_v4l2m2m_filter_frame,
|
||||
+ },
|
||||
+ { NULL }
|
||||
+};
|
||||
+
|
||||
+static const AVFilterPad deint_v4l2m2m_outputs[] = {
|
||||
@ -905,7 +1037,6 @@ index 000000000000..1029e5b620fd
|
||||
+ .type = AVMEDIA_TYPE_VIDEO,
|
||||
+ .config_props = deint_v4l2m2m_config_props,
|
||||
+ },
|
||||
+ { NULL }
|
||||
+};
|
||||
+
|
||||
+AVFilter ff_vf_deinterlace_v4l2m2m = {
|
||||
@ -914,11 +1045,8 @@ index 000000000000..1029e5b620fd
|
||||
+ .priv_size = sizeof(DeintV4L2M2MContext),
|
||||
+ .init = &deint_v4l2m2m_init,
|
||||
+ .uninit = &deint_v4l2m2m_uninit,
|
||||
+ .query_formats = &deint_v4l2m2m_query_formats,
|
||||
+ .inputs = deint_v4l2m2m_inputs,
|
||||
+ .outputs = deint_v4l2m2m_outputs,
|
||||
+ FILTER_QUERY_FUNC(&deint_v4l2m2m_query_formats),
|
||||
+ FILTER_INPUTS(deint_v4l2m2m_inputs),
|
||||
+ FILTER_OUTPUTS(deint_v4l2m2m_outputs),
|
||||
+ .priv_class = &deinterlace_v4l2m2m_class,
|
||||
+};
|
||||
--
|
||||
2.29.2
|
||||
|
@ -1,924 +0,0 @@
|
||||
From 39069d9cc03a42cd497dd6b9756116ff4b684a5d Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
Date: Tue, 3 Dec 2019 21:01:18 +0100
|
||||
Subject: [PATCH] WIP deint filter
|
||||
|
||||
---
|
||||
libavfilter/Makefile | 1 +
|
||||
libavfilter/allfilters.c | 1 +
|
||||
libavfilter/vf_deinterlace_v4l2m2m.c | 879 +++++++++++++++++++++++++++
|
||||
3 files changed, 881 insertions(+)
|
||||
create mode 100644 libavfilter/vf_deinterlace_v4l2m2m.c
|
||||
|
||||
diff --git a/libavfilter/Makefile b/libavfilter/Makefile
|
||||
index 512354065305..625fd29f9313 100644
|
||||
--- a/libavfilter/Makefile
|
||||
+++ b/libavfilter/Makefile
|
||||
@@ -218,6 +218,7 @@ OBJS-$(CONFIG_DEFLATE_FILTER) += vf_neighbor.o
|
||||
OBJS-$(CONFIG_DEFLICKER_FILTER) += vf_deflicker.o
|
||||
OBJS-$(CONFIG_DEINTERLACE_QSV_FILTER) += vf_deinterlace_qsv.o
|
||||
OBJS-$(CONFIG_DEINTERLACE_VAAPI_FILTER) += vf_deinterlace_vaapi.o vaapi_vpp.o
|
||||
+OBJS-$(CONFIG_DEINTERLACE_V4L2M2M_FILTER) += vf_deinterlace_v4l2m2m.o
|
||||
OBJS-$(CONFIG_DEJUDDER_FILTER) += vf_dejudder.o
|
||||
OBJS-$(CONFIG_DELOGO_FILTER) += vf_delogo.o
|
||||
OBJS-$(CONFIG_DENOISE_VAAPI_FILTER) += vf_misc_vaapi.o vaapi_vpp.o
|
||||
diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c
|
||||
index 1183e4026751..fe5a2e8c02e8 100644
|
||||
--- a/libavfilter/allfilters.c
|
||||
+++ b/libavfilter/allfilters.c
|
||||
@@ -204,6 +204,7 @@ extern AVFilter ff_vf_dedot;
|
||||
extern AVFilter ff_vf_deflate;
|
||||
extern AVFilter ff_vf_deflicker;
|
||||
extern AVFilter ff_vf_deinterlace_qsv;
|
||||
+extern AVFilter ff_vf_deinterlace_v4l2m2m;
|
||||
extern AVFilter ff_vf_deinterlace_vaapi;
|
||||
extern AVFilter ff_vf_dejudder;
|
||||
extern AVFilter ff_vf_delogo;
|
||||
diff --git a/libavfilter/vf_deinterlace_v4l2m2m.c b/libavfilter/vf_deinterlace_v4l2m2m.c
|
||||
new file mode 100644
|
||||
index 000000000000..1029e5b620fd
|
||||
--- /dev/null
|
||||
+++ b/libavfilter/vf_deinterlace_v4l2m2m.c
|
||||
@@ -0,0 +1,879 @@
|
||||
+/*
|
||||
+ * This file is part of FFmpeg.
|
||||
+ *
|
||||
+ * FFmpeg is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU Lesser General Public
|
||||
+ * License as published by the Free Software Foundation; either
|
||||
+ * version 2.1 of the License, or (at your option) any later version.
|
||||
+ *
|
||||
+ * FFmpeg is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ * Lesser General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU Lesser General Public
|
||||
+ * License along with FFmpeg; if not, write to the Free Software
|
||||
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
+ */
|
||||
+
|
||||
+/**
|
||||
+ * @file
|
||||
+ * deinterlace video filter - V4L2 M2M
|
||||
+ */
|
||||
+
|
||||
+#include <drm_fourcc.h>
|
||||
+
|
||||
+#include <linux/videodev2.h>
|
||||
+
|
||||
+#include <dirent.h>
|
||||
+#include <fcntl.h>
|
||||
+#include <poll.h>
|
||||
+#include <stdatomic.h>
|
||||
+#include <stdio.h>
|
||||
+#include <string.h>
|
||||
+#include <sys/ioctl.h>
|
||||
+#include <sys/mman.h>
|
||||
+#include <unistd.h>
|
||||
+
|
||||
+#include "libavutil/avassert.h"
|
||||
+#include "libavutil/avstring.h"
|
||||
+#include "libavutil/common.h"
|
||||
+#include "libavutil/hwcontext.h"
|
||||
+#include "libavutil/hwcontext_drm.h"
|
||||
+#include "libavutil/internal.h"
|
||||
+#include "libavutil/mathematics.h"
|
||||
+#include "libavutil/opt.h"
|
||||
+#include "libavutil/pixdesc.h"
|
||||
+#include "libavutil/time.h"
|
||||
+
|
||||
+#include "avfilter.h"
|
||||
+#include "formats.h"
|
||||
+#include "internal.h"
|
||||
+#include "video.h"
|
||||
+
|
||||
+typedef struct V4L2Queue V4L2Queue;
|
||||
+typedef struct DeintV4L2M2MContextShared DeintV4L2M2MContextShared;
|
||||
+
|
||||
+typedef struct V4L2PlaneInfo {
|
||||
+ int bytesperline;
|
||||
+ size_t length;
|
||||
+} V4L2PlaneInfo;
|
||||
+
|
||||
+typedef struct V4L2Buffer {
|
||||
+ int enqueued;
|
||||
+ int reenqueue;
|
||||
+ int fd;
|
||||
+ struct v4l2_buffer buffer;
|
||||
+ struct v4l2_plane planes[VIDEO_MAX_PLANES];
|
||||
+ int num_planes;
|
||||
+ V4L2PlaneInfo plane_info[VIDEO_MAX_PLANES];
|
||||
+ AVDRMFrameDescriptor drm_frame;
|
||||
+ V4L2Queue *q;
|
||||
+} V4L2Buffer;
|
||||
+
|
||||
+typedef struct V4L2Queue {
|
||||
+ struct v4l2_format format;
|
||||
+ int num_buffers;
|
||||
+ V4L2Buffer *buffers;
|
||||
+ DeintV4L2M2MContextShared *ctx;
|
||||
+} V4L2Queue;
|
||||
+
|
||||
+typedef struct DeintV4L2M2MContextShared {
|
||||
+ int fd;
|
||||
+ int done;
|
||||
+ int width;
|
||||
+ int height;
|
||||
+ int orig_width;
|
||||
+ int orig_height;
|
||||
+ atomic_uint refcount;
|
||||
+
|
||||
+ AVBufferRef *hw_frames_ctx;
|
||||
+
|
||||
+ int frame_count;
|
||||
+ AVFrame *frames[2];
|
||||
+
|
||||
+ V4L2Queue output;
|
||||
+ V4L2Queue capture;
|
||||
+} DeintV4L2M2MContextShared;
|
||||
+
|
||||
+typedef struct DeintV4L2M2MContext {
|
||||
+ const AVClass *class;
|
||||
+
|
||||
+ DeintV4L2M2MContextShared *shared;
|
||||
+} DeintV4L2M2MContext;
|
||||
+
|
||||
+static int deint_v4l2m2m_prepare_context(DeintV4L2M2MContextShared *ctx)
|
||||
+{
|
||||
+ struct v4l2_capability cap;
|
||||
+ int ret;
|
||||
+
|
||||
+ memset(&cap, 0, sizeof(cap));
|
||||
+ ret = ioctl(ctx->fd, VIDIOC_QUERYCAP, &cap);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ if (!(cap.capabilities & V4L2_CAP_STREAMING))
|
||||
+ return AVERROR(EINVAL);
|
||||
+
|
||||
+ if (cap.capabilities & V4L2_CAP_VIDEO_M2M) {
|
||||
+ ctx->capture.format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
+ ctx->output.format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
|
||||
+
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ if (cap.capabilities & V4L2_CAP_VIDEO_M2M_MPLANE) {
|
||||
+ ctx->capture.format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
|
||||
+ ctx->output.format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
|
||||
+
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ return AVERROR(EINVAL);
|
||||
+}
|
||||
+
|
||||
+static int deint_v4l2m2m_try_format(V4L2Queue *queue)
|
||||
+{
|
||||
+ struct v4l2_format *fmt = &queue->format;
|
||||
+ DeintV4L2M2MContextShared *ctx = queue->ctx;
|
||||
+ int ret, field;
|
||||
+
|
||||
+ ret = ioctl(ctx->fd, VIDIOC_G_FMT, fmt);
|
||||
+ if (ret)
|
||||
+ av_log(NULL, AV_LOG_ERROR, "VIDIOC_G_FMT failed: %d\n", ret);
|
||||
+
|
||||
+ if (V4L2_TYPE_IS_OUTPUT(fmt->type))
|
||||
+ field = V4L2_FIELD_INTERLACED_TB;
|
||||
+ else
|
||||
+ field = V4L2_FIELD_NONE;
|
||||
+
|
||||
+ if (V4L2_TYPE_IS_MULTIPLANAR(fmt->type)) {
|
||||
+ fmt->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12;
|
||||
+ fmt->fmt.pix_mp.field = field;
|
||||
+ fmt->fmt.pix_mp.width = ctx->width;
|
||||
+ fmt->fmt.pix_mp.height = ctx->height;
|
||||
+ } else {
|
||||
+ fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_NV12;
|
||||
+ fmt->fmt.pix.field = field;
|
||||
+ fmt->fmt.pix.width = ctx->width;
|
||||
+ fmt->fmt.pix.height = ctx->height;
|
||||
+ }
|
||||
+
|
||||
+ ret = ioctl(ctx->fd, VIDIOC_TRY_FMT, fmt);
|
||||
+ if (ret)
|
||||
+ return AVERROR(EINVAL);
|
||||
+
|
||||
+ if (V4L2_TYPE_IS_MULTIPLANAR(fmt->type)) {
|
||||
+ if (fmt->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_NV12 ||
|
||||
+ fmt->fmt.pix_mp.field != field) {
|
||||
+ av_log(NULL, AV_LOG_DEBUG, "format not supported for type %d\n", fmt->type);
|
||||
+
|
||||
+ return AVERROR(EINVAL);
|
||||
+ }
|
||||
+ } else {
|
||||
+ if (fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_NV12 ||
|
||||
+ fmt->fmt.pix.field != field) {
|
||||
+ av_log(NULL, AV_LOG_DEBUG, "format not supported for type %d\n", fmt->type);
|
||||
+
|
||||
+ return AVERROR(EINVAL);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int deint_v4l2m2m_set_format(V4L2Queue *queue, uint32_t field, int width, int height)
|
||||
+{
|
||||
+ struct v4l2_format *fmt = &queue->format;
|
||||
+ DeintV4L2M2MContextShared *ctx = queue->ctx;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (V4L2_TYPE_IS_MULTIPLANAR(fmt->type)) {
|
||||
+ fmt->fmt.pix_mp.field = field;
|
||||
+ fmt->fmt.pix_mp.width = width;
|
||||
+ fmt->fmt.pix_mp.height = height;
|
||||
+ /* TODO: bytesperline and imagesize */
|
||||
+ } else {
|
||||
+ fmt->fmt.pix.field = field;
|
||||
+ fmt->fmt.pix.width = width;
|
||||
+ fmt->fmt.pix.height = height;
|
||||
+ fmt->fmt.pix.sizeimage = 0;
|
||||
+ fmt->fmt.pix.bytesperline = 0;
|
||||
+ }
|
||||
+
|
||||
+ ret = ioctl(ctx->fd, VIDIOC_S_FMT, fmt);
|
||||
+ if (ret)
|
||||
+ av_log(NULL, AV_LOG_ERROR, "VIDIOC_S_FMT failed: %d\n", ret);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int deint_v4l2m2m_probe_device(DeintV4L2M2MContextShared *ctx, char *node)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ ctx->fd = open(node, O_RDWR | O_NONBLOCK, 0);
|
||||
+ if (ctx->fd < 0)
|
||||
+ return AVERROR(errno);
|
||||
+
|
||||
+ ret = deint_v4l2m2m_prepare_context(ctx);
|
||||
+ if (ret)
|
||||
+ goto fail;
|
||||
+
|
||||
+ ret = deint_v4l2m2m_try_format(&ctx->capture);
|
||||
+ if (ret)
|
||||
+ goto fail;
|
||||
+
|
||||
+ ret = deint_v4l2m2m_try_format(&ctx->output);
|
||||
+ if (ret)
|
||||
+ goto fail;
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+fail:
|
||||
+ close(ctx->fd);
|
||||
+ ctx->fd = -1;
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int deint_v4l2m2m_find_device(DeintV4L2M2MContextShared *ctx)
|
||||
+{
|
||||
+ int ret = AVERROR(EINVAL);
|
||||
+ struct dirent *entry;
|
||||
+ char node[PATH_MAX];
|
||||
+ DIR *dirp;
|
||||
+
|
||||
+ dirp = opendir("/dev");
|
||||
+ if (!dirp)
|
||||
+ return AVERROR(errno);
|
||||
+
|
||||
+ for (entry = readdir(dirp); entry; entry = readdir(dirp)) {
|
||||
+
|
||||
+ if (strncmp(entry->d_name, "video", 5))
|
||||
+ continue;
|
||||
+
|
||||
+ snprintf(node, sizeof(node), "/dev/%s", entry->d_name);
|
||||
+ av_log(NULL, AV_LOG_DEBUG, "probing device %s\n", node);
|
||||
+ ret = deint_v4l2m2m_probe_device(ctx, node);
|
||||
+ if (!ret)
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ closedir(dirp);
|
||||
+
|
||||
+ if (ret) {
|
||||
+ av_log(NULL, AV_LOG_ERROR, "Could not find a valid device\n");
|
||||
+ ctx->fd = -1;
|
||||
+
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ av_log(NULL, AV_LOG_INFO, "Using device %s\n", node);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int deint_v4l2m2m_enqueue_buffer(V4L2Buffer *buf)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = ioctl(buf->q->ctx->fd, VIDIOC_QBUF, &buf->buffer);
|
||||
+ if (ret < 0)
|
||||
+ return AVERROR(errno);
|
||||
+
|
||||
+ buf->enqueued = 1;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int v4l2_buffer_export_drm(V4L2Buffer* avbuf)
|
||||
+{
|
||||
+ struct v4l2_exportbuffer expbuf;
|
||||
+ int i, ret;
|
||||
+
|
||||
+ for (i = 0; i < avbuf->num_planes; i++) {
|
||||
+ memset(&expbuf, 0, sizeof(expbuf));
|
||||
+
|
||||
+ expbuf.index = avbuf->buffer.index;
|
||||
+ expbuf.type = avbuf->buffer.type;
|
||||
+ expbuf.plane = i;
|
||||
+
|
||||
+ ret = ioctl(avbuf->q->ctx->fd, VIDIOC_EXPBUF, &expbuf);
|
||||
+ if (ret < 0)
|
||||
+ return AVERROR(errno);
|
||||
+
|
||||
+ avbuf->fd = expbuf.fd;
|
||||
+
|
||||
+ if (V4L2_TYPE_IS_MULTIPLANAR(avbuf->buffer.type)) {
|
||||
+ /* drm frame */
|
||||
+ avbuf->drm_frame.objects[i].size = avbuf->buffer.m.planes[i].length;
|
||||
+ avbuf->drm_frame.objects[i].fd = expbuf.fd;
|
||||
+ avbuf->drm_frame.objects[i].format_modifier = DRM_FORMAT_MOD_LINEAR;
|
||||
+ } else {
|
||||
+ /* drm frame */
|
||||
+ avbuf->drm_frame.objects[0].size = avbuf->buffer.length;
|
||||
+ avbuf->drm_frame.objects[0].fd = expbuf.fd;
|
||||
+ avbuf->drm_frame.objects[0].format_modifier = DRM_FORMAT_MOD_LINEAR;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int deint_v4l2m2m_allocate_buffers(V4L2Queue *queue)
|
||||
+{
|
||||
+ struct v4l2_format *fmt = &queue->format;
|
||||
+ DeintV4L2M2MContextShared *ctx = queue->ctx;
|
||||
+ struct v4l2_requestbuffers req;
|
||||
+ int ret, i, j, multiplanar;
|
||||
+ uint32_t memory;
|
||||
+
|
||||
+ memory = V4L2_TYPE_IS_OUTPUT(fmt->type) ?
|
||||
+ V4L2_MEMORY_DMABUF : V4L2_MEMORY_MMAP;
|
||||
+
|
||||
+ multiplanar = V4L2_TYPE_IS_MULTIPLANAR(fmt->type);
|
||||
+
|
||||
+ memset(&req, 0, sizeof(req));
|
||||
+ req.count = queue->num_buffers;
|
||||
+ req.memory = memory;
|
||||
+ req.type = fmt->type;
|
||||
+
|
||||
+ ret = ioctl(ctx->fd, VIDIOC_REQBUFS, &req);
|
||||
+ if (ret < 0) {
|
||||
+ av_log(NULL, AV_LOG_ERROR, "VIDIOC_REQBUFS failed: %s\n", strerror(errno));
|
||||
+
|
||||
+ return AVERROR(errno);
|
||||
+ }
|
||||
+
|
||||
+ queue->num_buffers = req.count;
|
||||
+ queue->buffers = av_mallocz(queue->num_buffers * sizeof(V4L2Buffer));
|
||||
+ if (!queue->buffers) {
|
||||
+ av_log(NULL, AV_LOG_ERROR, "malloc enomem\n");
|
||||
+
|
||||
+ return AVERROR(ENOMEM);
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < queue->num_buffers; i++) {
|
||||
+ V4L2Buffer *buf = &queue->buffers[i];
|
||||
+
|
||||
+ buf->enqueued = 0;
|
||||
+ buf->fd = -1;
|
||||
+ buf->q = queue;
|
||||
+
|
||||
+ buf->buffer.type = fmt->type;
|
||||
+ buf->buffer.memory = memory;
|
||||
+ buf->buffer.index = i;
|
||||
+
|
||||
+ if (multiplanar) {
|
||||
+ buf->buffer.length = VIDEO_MAX_PLANES;
|
||||
+ buf->buffer.m.planes = buf->planes;
|
||||
+ }
|
||||
+
|
||||
+ ret = ioctl(ctx->fd, VIDIOC_QUERYBUF, &buf->buffer);
|
||||
+ if (ret < 0) {
|
||||
+ ret = AVERROR(errno);
|
||||
+
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ if (multiplanar)
|
||||
+ buf->num_planes = buf->buffer.length;
|
||||
+ else
|
||||
+ buf->num_planes = 1;
|
||||
+
|
||||
+ for (j = 0; j < buf->num_planes; j++) {
|
||||
+ V4L2PlaneInfo *info = &buf->plane_info[j];
|
||||
+
|
||||
+ if (multiplanar) {
|
||||
+ info->bytesperline = fmt->fmt.pix_mp.plane_fmt[j].bytesperline;
|
||||
+ info->length = buf->buffer.m.planes[j].length;
|
||||
+ } else {
|
||||
+ info->bytesperline = fmt->fmt.pix.bytesperline;
|
||||
+ info->length = buf->buffer.length;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!V4L2_TYPE_IS_OUTPUT(fmt->type)) {
|
||||
+ ret = deint_v4l2m2m_enqueue_buffer(buf);
|
||||
+ if (ret)
|
||||
+ goto fail;
|
||||
+
|
||||
+ ret = v4l2_buffer_export_drm(buf);
|
||||
+ if (ret)
|
||||
+ goto fail;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+fail:
|
||||
+ for (i = 0; i < queue->num_buffers; i++)
|
||||
+ if (queue->buffers[i].fd >= 0)
|
||||
+ close(queue->buffers[i].fd);
|
||||
+ av_free(queue->buffers);
|
||||
+ queue->buffers = NULL;
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int deint_v4l2m2m_streamon(V4L2Queue *queue)
|
||||
+{
|
||||
+ int type = queue->format.type;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = ioctl(queue->ctx->fd, VIDIOC_STREAMON, &type);
|
||||
+ if (ret < 0)
|
||||
+ return AVERROR(errno);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int deint_v4l2m2m_streamoff(V4L2Queue *queue)
|
||||
+{
|
||||
+ int type = queue->format.type;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = ioctl(queue->ctx->fd, VIDIOC_STREAMOFF, &type);
|
||||
+ if (ret < 0)
|
||||
+ return AVERROR(errno);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static V4L2Buffer* deint_v4l2m2m_dequeue_buffer(V4L2Queue *queue, int timeout)
|
||||
+{
|
||||
+ struct v4l2_plane planes[VIDEO_MAX_PLANES];
|
||||
+ DeintV4L2M2MContextShared *ctx = queue->ctx;
|
||||
+ struct v4l2_buffer buf = { 0 };
|
||||
+ V4L2Buffer* avbuf = NULL;
|
||||
+ struct pollfd pfd;
|
||||
+ short events;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (V4L2_TYPE_IS_OUTPUT(queue->format.type))
|
||||
+ events = POLLOUT | POLLWRNORM;
|
||||
+ else
|
||||
+ events = POLLIN | POLLRDNORM;
|
||||
+
|
||||
+ pfd.events = events;
|
||||
+ pfd.fd = ctx->fd;
|
||||
+
|
||||
+ for (;;) {
|
||||
+ ret = poll(&pfd, 1, timeout);
|
||||
+ if (ret > 0)
|
||||
+ break;
|
||||
+ if (errno == EINTR)
|
||||
+ continue;
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (pfd.revents & POLLERR)
|
||||
+ return NULL;
|
||||
+
|
||||
+ if (pfd.revents & events) {
|
||||
+ memset(&buf, 0, sizeof(buf));
|
||||
+ buf.memory = V4L2_MEMORY_MMAP;
|
||||
+ buf.type = queue->format.type;
|
||||
+ if (V4L2_TYPE_IS_MULTIPLANAR(queue->format.type)) {
|
||||
+ memset(planes, 0, sizeof(planes));
|
||||
+ buf.length = VIDEO_MAX_PLANES;
|
||||
+ buf.m.planes = planes;
|
||||
+ }
|
||||
+
|
||||
+ ret = ioctl(ctx->fd, VIDIOC_DQBUF, &buf);
|
||||
+ if (ret) {
|
||||
+ if (errno != EAGAIN)
|
||||
+ av_log(NULL, AV_LOG_DEBUG, "VIDIOC_DQBUF, errno (%s)\n",
|
||||
+ av_err2str(AVERROR(errno)));
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ avbuf = &queue->buffers[buf.index];
|
||||
+ avbuf->enqueued = 0;
|
||||
+ avbuf->buffer = buf;
|
||||
+ if (V4L2_TYPE_IS_MULTIPLANAR(queue->format.type)) {
|
||||
+ memcpy(avbuf->planes, planes, sizeof(planes));
|
||||
+ avbuf->buffer.m.planes = avbuf->planes;
|
||||
+ }
|
||||
+
|
||||
+ return avbuf;
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static V4L2Buffer *deint_v4l2m2m_find_free_buf(V4L2Queue *queue)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < queue->num_buffers; i++)
|
||||
+ if (!queue->buffers[i].enqueued)
|
||||
+ return &queue->buffers[i];
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static int deint_v4l2m2m_enqueue(V4L2Queue *queue, const AVFrame* frame)
|
||||
+{
|
||||
+ AVDRMFrameDescriptor *drm_desc = (AVDRMFrameDescriptor *)frame->data[0];
|
||||
+ V4L2Buffer *buf;
|
||||
+ int i;
|
||||
+
|
||||
+ if (V4L2_TYPE_IS_OUTPUT(queue->format.type))
|
||||
+ while (deint_v4l2m2m_dequeue_buffer(queue, 0));
|
||||
+
|
||||
+ buf = deint_v4l2m2m_find_free_buf(queue);
|
||||
+ if (!buf)
|
||||
+ return AVERROR(ENOMEM);
|
||||
+
|
||||
+ if (V4L2_TYPE_IS_MULTIPLANAR(buf->buffer.type))
|
||||
+ for (i = 0; i < drm_desc->nb_objects; i++)
|
||||
+ buf->buffer.m.planes[i].m.fd = drm_desc->objects[i].fd;
|
||||
+ else
|
||||
+ buf->buffer.m.fd = drm_desc->objects[0].fd;
|
||||
+
|
||||
+ return deint_v4l2m2m_enqueue_buffer(buf);
|
||||
+}
|
||||
+
|
||||
+static void deint_v4l2m2m_destroy_context(DeintV4L2M2MContextShared *ctx)
|
||||
+{
|
||||
+ if (atomic_fetch_sub(&ctx->refcount, 1) == 1) {
|
||||
+ V4L2Queue *capture = &ctx->capture;
|
||||
+ V4L2Queue *output = &ctx->output;
|
||||
+ int i;
|
||||
+
|
||||
+ av_log(NULL, AV_LOG_DEBUG, "%s - destroying context\n", __func__);
|
||||
+
|
||||
+ if (ctx->fd >= 0) {
|
||||
+ deint_v4l2m2m_streamoff(capture);
|
||||
+ deint_v4l2m2m_streamoff(output);
|
||||
+ }
|
||||
+
|
||||
+ if (capture->buffers)
|
||||
+ for (i = 0; i < capture->num_buffers; i++) {
|
||||
+ capture->buffers[i].q = NULL;
|
||||
+ if (capture->buffers[i].fd >= 0)
|
||||
+ close(capture->buffers[i].fd);
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < ctx->frame_count; i++)
|
||||
+ av_frame_free(&ctx->frames[i]);
|
||||
+
|
||||
+ av_buffer_unref(&ctx->hw_frames_ctx);
|
||||
+
|
||||
+ if (capture->buffers)
|
||||
+ av_free(capture->buffers);
|
||||
+
|
||||
+ if (output->buffers)
|
||||
+ av_free(output->buffers);
|
||||
+
|
||||
+ if (ctx->fd >= 0) {
|
||||
+ close(ctx->fd);
|
||||
+ ctx->fd = -1;
|
||||
+ }
|
||||
+
|
||||
+ av_free(ctx);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void v4l2_free_buffer(void *opaque, uint8_t *unused)
|
||||
+{
|
||||
+ V4L2Buffer *buf = opaque;
|
||||
+ DeintV4L2M2MContextShared *ctx = buf->q->ctx;
|
||||
+
|
||||
+ if (!ctx->done)
|
||||
+ deint_v4l2m2m_enqueue_buffer(buf);
|
||||
+
|
||||
+ deint_v4l2m2m_destroy_context(ctx);
|
||||
+}
|
||||
+
|
||||
+static uint8_t *v4l2_get_drm_frame(V4L2Buffer *avbuf, int height)
|
||||
+{
|
||||
+ AVDRMFrameDescriptor *drm_desc = &avbuf->drm_frame;
|
||||
+ AVDRMLayerDescriptor *layer;
|
||||
+
|
||||
+ /* fill the DRM frame descriptor */
|
||||
+ drm_desc->nb_objects = avbuf->num_planes;
|
||||
+ drm_desc->nb_layers = 1;
|
||||
+
|
||||
+ layer = &drm_desc->layers[0];
|
||||
+ layer->nb_planes = avbuf->num_planes;
|
||||
+
|
||||
+ for (int i = 0; i < avbuf->num_planes; i++) {
|
||||
+ layer->planes[i].object_index = i;
|
||||
+ layer->planes[i].offset = 0;
|
||||
+ layer->planes[i].pitch = avbuf->plane_info[i].bytesperline;
|
||||
+ }
|
||||
+
|
||||
+ layer->format = DRM_FORMAT_NV12;
|
||||
+
|
||||
+ if (avbuf->num_planes == 1) {
|
||||
+ layer->nb_planes = 2;
|
||||
+
|
||||
+ layer->planes[1].object_index = 0;
|
||||
+ layer->planes[1].offset = avbuf->plane_info[0].bytesperline * height;
|
||||
+ layer->planes[1].pitch = avbuf->plane_info[0].bytesperline;
|
||||
+ }
|
||||
+
|
||||
+ return (uint8_t *)drm_desc;
|
||||
+}
|
||||
+
|
||||
+static int deint_v4l2m2m_dequeue_frame(V4L2Queue *queue, AVFrame* frame, int timeout)
|
||||
+{
|
||||
+ DeintV4L2M2MContextShared *ctx = queue->ctx;
|
||||
+ V4L2Buffer* avbuf;
|
||||
+
|
||||
+ avbuf = deint_v4l2m2m_dequeue_buffer(queue, timeout);
|
||||
+ if (!avbuf) {
|
||||
+ av_log(NULL, AV_LOG_ERROR, "dequeueing failed\n");
|
||||
+ return AVERROR(EINVAL);
|
||||
+ }
|
||||
+
|
||||
+ frame->buf[0] = av_buffer_create((uint8_t *) &avbuf->drm_frame,
|
||||
+ sizeof(avbuf->drm_frame), v4l2_free_buffer,
|
||||
+ avbuf, AV_BUFFER_FLAG_READONLY);
|
||||
+ if (!frame->buf[0])
|
||||
+ return AVERROR(ENOMEM);
|
||||
+
|
||||
+ atomic_fetch_add(&ctx->refcount, 1);
|
||||
+
|
||||
+ frame->data[0] = (uint8_t *)v4l2_get_drm_frame(avbuf, ctx->orig_height);
|
||||
+ frame->format = AV_PIX_FMT_DRM_PRIME;
|
||||
+ frame->hw_frames_ctx = av_buffer_ref(ctx->hw_frames_ctx);
|
||||
+ frame->height = ctx->height;
|
||||
+ frame->width = ctx->width;
|
||||
+
|
||||
+ if (avbuf->buffer.flags & V4L2_BUF_FLAG_ERROR) {
|
||||
+ av_log(NULL, AV_LOG_ERROR, "driver decode error\n");
|
||||
+ frame->decode_error_flags |= FF_DECODE_ERROR_INVALID_BITSTREAM;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int deint_v4l2m2m_dequeue(AVFilterContext *avctx, AVFrame *input_frame, int field)
|
||||
+{
|
||||
+ DeintV4L2M2MContext *priv = avctx->priv;
|
||||
+ DeintV4L2M2MContextShared *ctx = priv->shared;
|
||||
+ AVFilterLink *outlink = avctx->outputs[0];
|
||||
+ AVFrame *output_frame;
|
||||
+ int err;
|
||||
+
|
||||
+ output_frame = av_frame_alloc();
|
||||
+
|
||||
+ if (!output_frame)
|
||||
+ return AVERROR(ENOMEM);
|
||||
+
|
||||
+ err = deint_v4l2m2m_dequeue_frame(&ctx->capture, output_frame, 500);
|
||||
+ if (err < 0) {
|
||||
+ av_log(priv, AV_LOG_ERROR, "no frame (field %d)\n", field);
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ err = av_frame_copy_props(output_frame, input_frame);
|
||||
+ if (err < 0)
|
||||
+ goto fail;
|
||||
+
|
||||
+ output_frame->interlaced_frame = 0;
|
||||
+
|
||||
+ if (field == 0) {
|
||||
+ output_frame->pts *= 2;
|
||||
+ } else {
|
||||
+ int64_t cur_pts = ctx->frames[0]->pts;
|
||||
+ int64_t next_pts = ctx->frames[1]->pts;
|
||||
+
|
||||
+ if (next_pts != AV_NOPTS_VALUE && cur_pts != AV_NOPTS_VALUE) {
|
||||
+ output_frame->pts = next_pts + cur_pts;
|
||||
+ } else {
|
||||
+ output_frame->pts = AV_NOPTS_VALUE;
|
||||
+ }
|
||||
+ }
|
||||
+ av_log(priv, AV_LOG_DEBUG, "pts: %"PRId64" (field %d)\n", output_frame->pts, field);
|
||||
+
|
||||
+ return ff_filter_frame(outlink, output_frame);
|
||||
+
|
||||
+fail:
|
||||
+ av_frame_free(&output_frame);
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+static int deint_v4l2m2m_config_props(AVFilterLink *outlink)
|
||||
+{
|
||||
+ AVFilterLink *inlink = outlink->src->inputs[0];
|
||||
+ AVFilterContext *avctx = outlink->src;
|
||||
+ DeintV4L2M2MContext *priv = avctx->priv;
|
||||
+ DeintV4L2M2MContextShared *ctx = priv->shared;
|
||||
+ int ret;
|
||||
+
|
||||
+ ctx->height = avctx->inputs[0]->h;
|
||||
+ ctx->width = avctx->inputs[0]->w;
|
||||
+
|
||||
+ outlink->frame_rate = av_mul_q(inlink->frame_rate,
|
||||
+ (AVRational){ 2, 1 });
|
||||
+ outlink->time_base = av_mul_q(inlink->time_base,
|
||||
+ (AVRational){ 1, 2 });
|
||||
+
|
||||
+ ret = deint_v4l2m2m_find_device(ctx);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ if (!inlink->hw_frames_ctx) {
|
||||
+ av_log(priv, AV_LOG_ERROR, "No hw context provided on input\n");
|
||||
+ return AVERROR(EINVAL);
|
||||
+ }
|
||||
+
|
||||
+ ctx->hw_frames_ctx = av_buffer_ref(inlink->hw_frames_ctx);
|
||||
+ if (!ctx->hw_frames_ctx)
|
||||
+ return AVERROR(ENOMEM);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int deint_v4l2m2m_query_formats(AVFilterContext *avctx)
|
||||
+{
|
||||
+ static const enum AVPixelFormat pixel_formats[] = {
|
||||
+ AV_PIX_FMT_DRM_PRIME,
|
||||
+ AV_PIX_FMT_NONE,
|
||||
+ };
|
||||
+
|
||||
+ return ff_set_common_formats(avctx, ff_make_format_list(pixel_formats));
|
||||
+}
|
||||
+
|
||||
+static int deint_v4l2m2m_filter_frame(AVFilterLink *link, AVFrame *in)
|
||||
+{
|
||||
+ AVFilterContext *avctx = link->dst;
|
||||
+ DeintV4L2M2MContext *priv = avctx->priv;
|
||||
+ DeintV4L2M2MContextShared *ctx = priv->shared;
|
||||
+ V4L2Queue *capture = &ctx->capture;
|
||||
+ V4L2Queue *output = &ctx->output;
|
||||
+ int ret;
|
||||
+
|
||||
+ av_log(priv, AV_LOG_DEBUG, "input pts: %"PRId64"\n", in->pts);
|
||||
+ if (!ctx->frame_count) {
|
||||
+ AVDRMFrameDescriptor *drm_desc = (AVDRMFrameDescriptor *)in->data[0];
|
||||
+ unsigned int field;
|
||||
+
|
||||
+ ctx->orig_width = drm_desc->layers[0].planes[0].pitch;
|
||||
+ ctx->orig_height = drm_desc->layers[0].planes[1].offset / ctx->orig_width;
|
||||
+
|
||||
+ if (in->top_field_first)
|
||||
+ field = V4L2_FIELD_INTERLACED_TB;
|
||||
+ else
|
||||
+ field = V4L2_FIELD_INTERLACED_BT;
|
||||
+
|
||||
+ ret = deint_v4l2m2m_set_format(output, field, ctx->orig_width, ctx->orig_height);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = deint_v4l2m2m_set_format(capture, V4L2_FIELD_NONE, ctx->orig_width, ctx->orig_height);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = deint_v4l2m2m_allocate_buffers(capture);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = deint_v4l2m2m_streamon(capture);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = deint_v4l2m2m_allocate_buffers(output);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = deint_v4l2m2m_streamon(output);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ if (ctx->frame_count < 2) {
|
||||
+ ctx->frames[ctx->frame_count++] = in;
|
||||
+ } else {
|
||||
+ av_frame_free(&ctx->frames[0]);
|
||||
+ ctx->frames[0] = ctx->frames[1];
|
||||
+ ctx->frames[1] = in;
|
||||
+ }
|
||||
+
|
||||
+ ret = deint_v4l2m2m_enqueue(output, in);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ if (ctx->frame_count == 2) {
|
||||
+ ret = deint_v4l2m2m_dequeue(avctx, ctx->frames[0], 0);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = deint_v4l2m2m_dequeue(avctx, ctx->frames[0], 1);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static av_cold int deint_v4l2m2m_init(AVFilterContext *avctx)
|
||||
+{
|
||||
+ DeintV4L2M2MContext *priv = avctx->priv;
|
||||
+ DeintV4L2M2MContextShared *ctx;
|
||||
+
|
||||
+ ctx = av_mallocz(sizeof(DeintV4L2M2MContextShared));
|
||||
+ if (!ctx)
|
||||
+ return AVERROR(ENOMEM);
|
||||
+
|
||||
+ priv->shared = ctx;
|
||||
+ ctx->fd = -1;
|
||||
+ ctx->output.ctx = ctx;
|
||||
+ ctx->output.num_buffers = 6;
|
||||
+ ctx->capture.ctx = ctx;
|
||||
+ ctx->capture.num_buffers = 6;
|
||||
+ ctx->done = 0;
|
||||
+ atomic_init(&ctx->refcount, 1);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void deint_v4l2m2m_uninit(AVFilterContext *avctx)
|
||||
+{
|
||||
+ DeintV4L2M2MContext *priv = avctx->priv;
|
||||
+ DeintV4L2M2MContextShared *ctx = priv->shared;
|
||||
+
|
||||
+ ctx->done = 1;
|
||||
+ deint_v4l2m2m_destroy_context(ctx);
|
||||
+}
|
||||
+
|
||||
+static const AVOption deinterlace_v4l2m2m_options[] = {
|
||||
+ { NULL },
|
||||
+};
|
||||
+
|
||||
+AVFILTER_DEFINE_CLASS(deinterlace_v4l2m2m);
|
||||
+
|
||||
+static const AVFilterPad deint_v4l2m2m_inputs[] = {
|
||||
+ {
|
||||
+ .name = "default",
|
||||
+ .type = AVMEDIA_TYPE_VIDEO,
|
||||
+ .filter_frame = deint_v4l2m2m_filter_frame,
|
||||
+ },
|
||||
+ { NULL }
|
||||
+};
|
||||
+
|
||||
+static const AVFilterPad deint_v4l2m2m_outputs[] = {
|
||||
+ {
|
||||
+ .name = "default",
|
||||
+ .type = AVMEDIA_TYPE_VIDEO,
|
||||
+ .config_props = deint_v4l2m2m_config_props,
|
||||
+ },
|
||||
+ { NULL }
|
||||
+};
|
||||
+
|
||||
+AVFilter ff_vf_deinterlace_v4l2m2m = {
|
||||
+ .name = "deinterlace_v4l2m2m",
|
||||
+ .description = NULL_IF_CONFIG_SMALL("V4L2 M2M deinterlacer"),
|
||||
+ .priv_size = sizeof(DeintV4L2M2MContext),
|
||||
+ .init = &deint_v4l2m2m_init,
|
||||
+ .uninit = &deint_v4l2m2m_uninit,
|
||||
+ .query_formats = &deint_v4l2m2m_query_formats,
|
||||
+ .inputs = deint_v4l2m2m_inputs,
|
||||
+ .outputs = deint_v4l2m2m_outputs,
|
||||
+ .priv_class = &deinterlace_v4l2m2m_class,
|
||||
+};
|
||||
--
|
||||
2.29.2
|
||||
|
@ -1,230 +0,0 @@
|
||||
From 6bea46839ba23bffaa093bb9ed805d571aaa66ea Mon Sep 17 00:00:00 2001
|
||||
From: Alex Bee <knaerzche@gmail.com>
|
||||
Date: Wed, 30 Sep 2020 21:11:34 +0200
|
||||
Subject: [PATCH] libavfilter: v4l2deinterlace: dequeue both destination
|
||||
buffers on time
|
||||
|
||||
Signed-off-by: Alex Bee <knaerzche@gmail.com>
|
||||
---
|
||||
libavfilter/vf_deinterlace_v4l2m2m.c | 140 +++++++++++++++++----------
|
||||
1 file changed, 88 insertions(+), 52 deletions(-)
|
||||
|
||||
diff --git a/libavfilter/vf_deinterlace_v4l2m2m.c b/libavfilter/vf_deinterlace_v4l2m2m.c
|
||||
index 1029e5b620fd..72d28333ffa7 100644
|
||||
--- a/libavfilter/vf_deinterlace_v4l2m2m.c
|
||||
+++ b/libavfilter/vf_deinterlace_v4l2m2m.c
|
||||
@@ -89,8 +89,14 @@ typedef struct DeintV4L2M2MContextShared {
|
||||
|
||||
AVBufferRef *hw_frames_ctx;
|
||||
|
||||
- int frame_count;
|
||||
- AVFrame *frames[2];
|
||||
+ /*
|
||||
+ * TODO: check if its really neccessary to hold this
|
||||
+ * ref, it's only used for freeing av_frame on decoding
|
||||
+ * end/abort
|
||||
+ */
|
||||
+ AVFrame *cur_in_frame;
|
||||
+ AVFrame *prev_in_frame;
|
||||
+ unsigned int field_order;
|
||||
|
||||
V4L2Queue output;
|
||||
V4L2Queue capture;
|
||||
@@ -557,8 +563,11 @@ static void deint_v4l2m2m_destroy_context(DeintV4L2M2MContextShared *ctx)
|
||||
close(capture->buffers[i].fd);
|
||||
}
|
||||
|
||||
- for (i = 0; i < ctx->frame_count; i++)
|
||||
- av_frame_free(&ctx->frames[i]);
|
||||
+ if (ctx->cur_in_frame)
|
||||
+ av_frame_free(&ctx->cur_in_frame);
|
||||
+
|
||||
+ if (ctx->prev_in_frame)
|
||||
+ av_frame_free(&ctx->prev_in_frame);
|
||||
|
||||
av_buffer_unref(&ctx->hw_frames_ctx);
|
||||
|
||||
@@ -652,49 +661,79 @@ static int deint_v4l2m2m_dequeue_frame(V4L2Queue *queue, AVFrame* frame, int tim
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int deint_v4l2m2m_dequeue(AVFilterContext *avctx, AVFrame *input_frame, int field)
|
||||
+static int deint_v4l2m2m_dequeue(AVFilterContext *avctx, AVFrame *input_frame)
|
||||
{
|
||||
DeintV4L2M2MContext *priv = avctx->priv;
|
||||
DeintV4L2M2MContextShared *ctx = priv->shared;
|
||||
AVFilterLink *outlink = avctx->outputs[0];
|
||||
- AVFrame *output_frame;
|
||||
+ AVFrame *output_frame_1, *output_frame_2;
|
||||
+ int64_t first_pts = AV_NOPTS_VALUE;
|
||||
int err;
|
||||
|
||||
- output_frame = av_frame_alloc();
|
||||
+ av_log(priv, AV_LOG_DEBUG, "input pts: %"PRId64" (field %d)\n",
|
||||
+ input_frame->pts, ctx->field_order);
|
||||
|
||||
- if (!output_frame)
|
||||
+ output_frame_1 = av_frame_alloc();
|
||||
+ if (!output_frame_1)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
- err = deint_v4l2m2m_dequeue_frame(&ctx->capture, output_frame, 500);
|
||||
+ err = deint_v4l2m2m_dequeue_frame(&ctx->capture, output_frame_1, 500);
|
||||
if (err < 0) {
|
||||
- av_log(priv, AV_LOG_ERROR, "no frame (field %d)\n", field);
|
||||
- goto fail;
|
||||
+ av_log(priv, AV_LOG_ERROR, "no 1st frame (field %d)\n", ctx->field_order);
|
||||
+ goto fail_out1;
|
||||
}
|
||||
|
||||
- err = av_frame_copy_props(output_frame, input_frame);
|
||||
+ err = av_frame_copy_props(output_frame_1, input_frame);
|
||||
if (err < 0)
|
||||
- goto fail;
|
||||
+ goto fail_out1;
|
||||
|
||||
- output_frame->interlaced_frame = 0;
|
||||
+ output_frame_1->interlaced_frame = 0;
|
||||
|
||||
- if (field == 0) {
|
||||
- output_frame->pts *= 2;
|
||||
- } else {
|
||||
- int64_t cur_pts = ctx->frames[0]->pts;
|
||||
- int64_t next_pts = ctx->frames[1]->pts;
|
||||
+ output_frame_2 = av_frame_alloc();
|
||||
+ if (!output_frame_2) {
|
||||
+ err = AVERROR(ENOMEM);
|
||||
+ goto fail_out1;
|
||||
+ }
|
||||
+
|
||||
+ err = deint_v4l2m2m_dequeue_frame(&ctx->capture, output_frame_2, 500);
|
||||
+ if (err < 0) {
|
||||
+ av_log(priv, AV_LOG_ERROR, "no 2nd frame (field %d)\n", ctx->field_order);
|
||||
+ goto fail_out2;
|
||||
+ }
|
||||
+
|
||||
+ err = av_frame_copy_props(output_frame_2, input_frame);
|
||||
+ if (err < 0)
|
||||
+ goto fail_out2;
|
||||
+
|
||||
+ output_frame_2->interlaced_frame = 0;
|
||||
|
||||
- if (next_pts != AV_NOPTS_VALUE && cur_pts != AV_NOPTS_VALUE) {
|
||||
- output_frame->pts = next_pts + cur_pts;
|
||||
- } else {
|
||||
- output_frame->pts = AV_NOPTS_VALUE;
|
||||
- }
|
||||
+ if (ctx->prev_in_frame && ctx->prev_in_frame->pts != AV_NOPTS_VALUE
|
||||
+ && input_frame->pts != AV_NOPTS_VALUE) {
|
||||
+ first_pts = (ctx->prev_in_frame->pts + input_frame->pts) / 2;
|
||||
+ av_log(priv, AV_LOG_DEBUG, "calculated first pts %"PRId64"\n", first_pts);
|
||||
}
|
||||
- av_log(priv, AV_LOG_DEBUG, "pts: %"PRId64" (field %d)\n", output_frame->pts, field);
|
||||
|
||||
- return ff_filter_frame(outlink, output_frame);
|
||||
+ output_frame_1->pts = first_pts;
|
||||
+
|
||||
+ err = ff_filter_frame(outlink, output_frame_1);
|
||||
+ if (err < 0) {
|
||||
+ av_frame_free(&output_frame_2);
|
||||
+ return err;
|
||||
+ }
|
||||
+ err = ff_filter_frame(outlink, output_frame_2);
|
||||
+
|
||||
+ if (err < 0)
|
||||
+ return err;
|
||||
+
|
||||
+ av_log(priv, AV_LOG_DEBUG, "1st frame pts: %"PRId64" 2nd frame pts: %"PRId64" first pts: %"PRId64" (field %d)\n",
|
||||
+ output_frame_1->pts, output_frame_2->pts, first_pts, ctx->field_order);
|
||||
+
|
||||
+ return 0;
|
||||
|
||||
-fail:
|
||||
- av_frame_free(&output_frame);
|
||||
+fail_out2:
|
||||
+ av_frame_free(&output_frame_2);
|
||||
+fail_out1:
|
||||
+ av_frame_free(&output_frame_1);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -749,20 +788,22 @@ static int deint_v4l2m2m_filter_frame(AVFilterLink *link, AVFrame *in)
|
||||
V4L2Queue *output = &ctx->output;
|
||||
int ret;
|
||||
|
||||
- av_log(priv, AV_LOG_DEBUG, "input pts: %"PRId64"\n", in->pts);
|
||||
- if (!ctx->frame_count) {
|
||||
+ av_log(priv, AV_LOG_DEBUG, "input pts: %"PRId64" field :%d interlaced: %d\n",
|
||||
+ in->pts, in->top_field_first, in->interlaced_frame);
|
||||
+
|
||||
+ ctx->cur_in_frame = in;
|
||||
+
|
||||
+ if (ctx->field_order == V4L2_FIELD_ANY) {
|
||||
AVDRMFrameDescriptor *drm_desc = (AVDRMFrameDescriptor *)in->data[0];
|
||||
- unsigned int field;
|
||||
-
|
||||
ctx->orig_width = drm_desc->layers[0].planes[0].pitch;
|
||||
ctx->orig_height = drm_desc->layers[0].planes[1].offset / ctx->orig_width;
|
||||
|
||||
- if (in->top_field_first)
|
||||
- field = V4L2_FIELD_INTERLACED_TB;
|
||||
+ if (in->top_field_first)
|
||||
+ ctx->field_order = V4L2_FIELD_INTERLACED_TB;
|
||||
else
|
||||
- field = V4L2_FIELD_INTERLACED_BT;
|
||||
+ ctx->field_order = V4L2_FIELD_INTERLACED_BT;
|
||||
|
||||
- ret = deint_v4l2m2m_set_format(output, field, ctx->orig_width, ctx->orig_height);
|
||||
+ ret = deint_v4l2m2m_set_format(output, ctx->field_order, ctx->orig_width, ctx->orig_height);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -787,27 +828,19 @@ static int deint_v4l2m2m_filter_frame(AVFilterLink *link, AVFrame *in)
|
||||
return ret;
|
||||
}
|
||||
|
||||
- if (ctx->frame_count < 2) {
|
||||
- ctx->frames[ctx->frame_count++] = in;
|
||||
- } else {
|
||||
- av_frame_free(&ctx->frames[0]);
|
||||
- ctx->frames[0] = ctx->frames[1];
|
||||
- ctx->frames[1] = in;
|
||||
- }
|
||||
-
|
||||
ret = deint_v4l2m2m_enqueue(output, in);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
- if (ctx->frame_count == 2) {
|
||||
- ret = deint_v4l2m2m_dequeue(avctx, ctx->frames[0], 0);
|
||||
- if (ret)
|
||||
- return ret;
|
||||
+ ret = deint_v4l2m2m_dequeue(avctx, in);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
|
||||
- ret = deint_v4l2m2m_dequeue(avctx, ctx->frames[0], 1);
|
||||
- if (ret)
|
||||
- return ret;
|
||||
- }
|
||||
+ if (ctx->prev_in_frame)
|
||||
+ av_frame_free(&ctx->prev_in_frame);
|
||||
+
|
||||
+ ctx->prev_in_frame = in;
|
||||
+ ctx->cur_in_frame = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -828,6 +861,9 @@ static av_cold int deint_v4l2m2m_init(AVFilterContext *avctx)
|
||||
ctx->capture.ctx = ctx;
|
||||
ctx->capture.num_buffers = 6;
|
||||
ctx->done = 0;
|
||||
+ ctx->field_order = V4L2_FIELD_ANY;
|
||||
+ ctx->cur_in_frame = NULL;
|
||||
+ ctx->prev_in_frame = NULL;
|
||||
atomic_init(&ctx->refcount, 1);
|
||||
|
||||
return 0;
|
||||
--
|
||||
2.29.2
|
||||
|
@ -1,80 +0,0 @@
|
||||
From 0770ca82391fb60084080b2fd235cc039a3b8314 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
Date: Sun, 25 Apr 2021 10:40:56 +0000
|
||||
Subject: [PATCH] v4l2_request: revert changes
|
||||
|
||||
---
|
||||
libavcodec/v4l2_request.c | 10 +++-------
|
||||
libavcodec/v4l2_request_h264.c | 8 ++++----
|
||||
2 files changed, 7 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/libavcodec/v4l2_request.c b/libavcodec/v4l2_request.c
|
||||
index 5234b5049b0d..1e513ee5df8d 100644
|
||||
--- a/libavcodec/v4l2_request.c
|
||||
+++ b/libavcodec/v4l2_request.c
|
||||
@@ -142,14 +142,12 @@ static int v4l2_request_queue_buffer(V4L2RequestContext *ctx, int request_fd, V4
|
||||
.type = buf->buffer.type,
|
||||
.memory = buf->buffer.memory,
|
||||
.index = buf->index,
|
||||
- .timestamp.tv_usec = ctx->timestamp,
|
||||
+ .timestamp.tv_usec = buf->index + 1,
|
||||
.bytesused = buf->used,
|
||||
.request_fd = request_fd,
|
||||
.flags = ((request_fd >= 0) ? V4L2_BUF_FLAG_REQUEST_FD : 0) | flags,
|
||||
};
|
||||
|
||||
- buf->buffer.timestamp = buffer.timestamp;
|
||||
-
|
||||
if (V4L2_TYPE_IS_MULTIPLANAR(buf->buffer.type)) {
|
||||
planes[0].bytesused = buf->used;
|
||||
buffer.bytesused = 0;
|
||||
@@ -239,9 +237,6 @@ static int v4l2_request_queue_decode(AVCodecContext *avctx, AVFrame *frame, stru
|
||||
|
||||
av_log(avctx, AV_LOG_DEBUG, "%s: avctx=%p used=%u controls=%d index=%d fd=%d request_fd=%d first_slice=%d last_slice=%d\n", __func__, avctx, req->output.used, count, req->capture.index, req->capture.fd, req->request_fd, first_slice, last_slice);
|
||||
|
||||
- if (first_slice)
|
||||
- ctx->timestamp++;
|
||||
-
|
||||
ret = v4l2_request_set_controls(ctx, req->request_fd, control, count);
|
||||
if (ret < 0) {
|
||||
av_log(avctx, AV_LOG_ERROR, "%s: set controls failed for request %d, %s (%d)\n", __func__, req->request_fd, strerror(errno), errno);
|
||||
@@ -693,7 +688,6 @@ int ff_v4l2_request_init(AVCodecContext *avctx, uint32_t pixelformat, uint32_t b
|
||||
|
||||
ctx->media_fd = -1;
|
||||
ctx->video_fd = -1;
|
||||
- ctx->timestamp = 0;
|
||||
|
||||
udev = udev_new();
|
||||
if (!udev) {
|
||||
@@ -827,6 +821,8 @@ static int v4l2_request_buffer_alloc(AVCodecContext *avctx, V4L2RequestBuffer *b
|
||||
return ret;
|
||||
}
|
||||
|
||||
+ buf->buffer.timestamp.tv_usec = buf->index + 1;
|
||||
+
|
||||
if (V4L2_TYPE_IS_OUTPUT(type)) {
|
||||
void *addr = mmap(NULL, buf->size, PROT_READ | PROT_WRITE, MAP_SHARED, ctx->video_fd, V4L2_TYPE_IS_MULTIPLANAR(type) ? buf->buffer.m.planes[0].m.mem_offset : buf->buffer.m.offset);
|
||||
if (addr == MAP_FAILED) {
|
||||
diff --git a/libavcodec/v4l2_request_h264.c b/libavcodec/v4l2_request_h264.c
|
||||
index 88da8f0a2db0..a14028336a39 100644
|
||||
--- a/libavcodec/v4l2_request_h264.c
|
||||
+++ b/libavcodec/v4l2_request_h264.c
|
||||
@@ -252,7 +252,7 @@ static int v4l2_request_h264_start_frame(AVCodecContext *avctx,
|
||||
|
||||
fill_dpb(&controls->decode_params, h);
|
||||
|
||||
- controls->first_slice = !FIELD_PICTURE(h) || h->first_field;
|
||||
+ controls->first_slice = 1;
|
||||
controls->num_slices = 0;
|
||||
|
||||
return ff_v4l2_request_reset_frame(avctx, h->cur_pic_ptr->f);
|
||||
@@ -383,8 +383,7 @@ static int v4l2_request_h264_decode_slice(AVCodecContext *avctx, const uint8_t *
|
||||
|
||||
static int v4l2_request_h264_end_frame(AVCodecContext *avctx)
|
||||
{
|
||||
- const H264Context *h = avctx->priv_data;
|
||||
- return v4l2_request_h264_queue_decode(avctx, !FIELD_PICTURE(h) || !h->first_field);
|
||||
+ return v4l2_request_h264_queue_decode(avctx, 1);
|
||||
}
|
||||
|
||||
static int v4l2_request_h264_set_controls(AVCodecContext *avctx)
|
@ -1,230 +0,0 @@
|
||||
From 6bea46839ba23bffaa093bb9ed805d571aaa66ea Mon Sep 17 00:00:00 2001
|
||||
From: Alex Bee <knaerzche@gmail.com>
|
||||
Date: Wed, 30 Sep 2020 21:11:34 +0200
|
||||
Subject: [PATCH] libavfilter: v4l2deinterlace: dequeue both destination
|
||||
buffers on time
|
||||
|
||||
Signed-off-by: Alex Bee <knaerzche@gmail.com>
|
||||
---
|
||||
libavfilter/vf_deinterlace_v4l2m2m.c | 140 +++++++++++++++++----------
|
||||
1 file changed, 88 insertions(+), 52 deletions(-)
|
||||
|
||||
diff --git a/libavfilter/vf_deinterlace_v4l2m2m.c b/libavfilter/vf_deinterlace_v4l2m2m.c
|
||||
index 1029e5b620fd..72d28333ffa7 100644
|
||||
--- a/libavfilter/vf_deinterlace_v4l2m2m.c
|
||||
+++ b/libavfilter/vf_deinterlace_v4l2m2m.c
|
||||
@@ -89,8 +89,14 @@ typedef struct DeintV4L2M2MContextShared {
|
||||
|
||||
AVBufferRef *hw_frames_ctx;
|
||||
|
||||
- int frame_count;
|
||||
- AVFrame *frames[2];
|
||||
+ /*
|
||||
+ * TODO: check if its really neccessary to hold this
|
||||
+ * ref, it's only used for freeing av_frame on decoding
|
||||
+ * end/abort
|
||||
+ */
|
||||
+ AVFrame *cur_in_frame;
|
||||
+ AVFrame *prev_in_frame;
|
||||
+ unsigned int field_order;
|
||||
|
||||
V4L2Queue output;
|
||||
V4L2Queue capture;
|
||||
@@ -557,8 +563,11 @@ static void deint_v4l2m2m_destroy_context(DeintV4L2M2MContextShared *ctx)
|
||||
close(capture->buffers[i].fd);
|
||||
}
|
||||
|
||||
- for (i = 0; i < ctx->frame_count; i++)
|
||||
- av_frame_free(&ctx->frames[i]);
|
||||
+ if (ctx->cur_in_frame)
|
||||
+ av_frame_free(&ctx->cur_in_frame);
|
||||
+
|
||||
+ if (ctx->prev_in_frame)
|
||||
+ av_frame_free(&ctx->prev_in_frame);
|
||||
|
||||
av_buffer_unref(&ctx->hw_frames_ctx);
|
||||
|
||||
@@ -652,49 +661,79 @@ static int deint_v4l2m2m_dequeue_frame(V4L2Queue *queue, AVFrame* frame, int tim
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int deint_v4l2m2m_dequeue(AVFilterContext *avctx, AVFrame *input_frame, int field)
|
||||
+static int deint_v4l2m2m_dequeue(AVFilterContext *avctx, AVFrame *input_frame)
|
||||
{
|
||||
DeintV4L2M2MContext *priv = avctx->priv;
|
||||
DeintV4L2M2MContextShared *ctx = priv->shared;
|
||||
AVFilterLink *outlink = avctx->outputs[0];
|
||||
- AVFrame *output_frame;
|
||||
+ AVFrame *output_frame_1, *output_frame_2;
|
||||
+ int64_t first_pts = AV_NOPTS_VALUE;
|
||||
int err;
|
||||
|
||||
- output_frame = av_frame_alloc();
|
||||
+ av_log(priv, AV_LOG_DEBUG, "input pts: %"PRId64" (field %d)\n",
|
||||
+ input_frame->pts, ctx->field_order);
|
||||
|
||||
- if (!output_frame)
|
||||
+ output_frame_1 = av_frame_alloc();
|
||||
+ if (!output_frame_1)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
- err = deint_v4l2m2m_dequeue_frame(&ctx->capture, output_frame, 500);
|
||||
+ err = deint_v4l2m2m_dequeue_frame(&ctx->capture, output_frame_1, 500);
|
||||
if (err < 0) {
|
||||
- av_log(priv, AV_LOG_ERROR, "no frame (field %d)\n", field);
|
||||
- goto fail;
|
||||
+ av_log(priv, AV_LOG_ERROR, "no 1st frame (field %d)\n", ctx->field_order);
|
||||
+ goto fail_out1;
|
||||
}
|
||||
|
||||
- err = av_frame_copy_props(output_frame, input_frame);
|
||||
+ err = av_frame_copy_props(output_frame_1, input_frame);
|
||||
if (err < 0)
|
||||
- goto fail;
|
||||
+ goto fail_out1;
|
||||
|
||||
- output_frame->interlaced_frame = 0;
|
||||
+ output_frame_1->interlaced_frame = 0;
|
||||
|
||||
- if (field == 0) {
|
||||
- output_frame->pts *= 2;
|
||||
- } else {
|
||||
- int64_t cur_pts = ctx->frames[0]->pts;
|
||||
- int64_t next_pts = ctx->frames[1]->pts;
|
||||
+ output_frame_2 = av_frame_alloc();
|
||||
+ if (!output_frame_2) {
|
||||
+ err = AVERROR(ENOMEM);
|
||||
+ goto fail_out1;
|
||||
+ }
|
||||
+
|
||||
+ err = deint_v4l2m2m_dequeue_frame(&ctx->capture, output_frame_2, 500);
|
||||
+ if (err < 0) {
|
||||
+ av_log(priv, AV_LOG_ERROR, "no 2nd frame (field %d)\n", ctx->field_order);
|
||||
+ goto fail_out2;
|
||||
+ }
|
||||
+
|
||||
+ err = av_frame_copy_props(output_frame_2, input_frame);
|
||||
+ if (err < 0)
|
||||
+ goto fail_out2;
|
||||
+
|
||||
+ output_frame_2->interlaced_frame = 0;
|
||||
|
||||
- if (next_pts != AV_NOPTS_VALUE && cur_pts != AV_NOPTS_VALUE) {
|
||||
- output_frame->pts = next_pts + cur_pts;
|
||||
- } else {
|
||||
- output_frame->pts = AV_NOPTS_VALUE;
|
||||
- }
|
||||
+ if (ctx->prev_in_frame && ctx->prev_in_frame->pts != AV_NOPTS_VALUE
|
||||
+ && input_frame->pts != AV_NOPTS_VALUE) {
|
||||
+ first_pts = (ctx->prev_in_frame->pts + input_frame->pts) / 2;
|
||||
+ av_log(priv, AV_LOG_DEBUG, "calculated first pts %"PRId64"\n", first_pts);
|
||||
}
|
||||
- av_log(priv, AV_LOG_DEBUG, "pts: %"PRId64" (field %d)\n", output_frame->pts, field);
|
||||
|
||||
- return ff_filter_frame(outlink, output_frame);
|
||||
+ output_frame_1->pts = first_pts;
|
||||
+
|
||||
+ err = ff_filter_frame(outlink, output_frame_1);
|
||||
+ if (err < 0) {
|
||||
+ av_frame_free(&output_frame_2);
|
||||
+ return err;
|
||||
+ }
|
||||
+ err = ff_filter_frame(outlink, output_frame_2);
|
||||
+
|
||||
+ if (err < 0)
|
||||
+ return err;
|
||||
+
|
||||
+ av_log(priv, AV_LOG_DEBUG, "1st frame pts: %"PRId64" 2nd frame pts: %"PRId64" first pts: %"PRId64" (field %d)\n",
|
||||
+ output_frame_1->pts, output_frame_2->pts, first_pts, ctx->field_order);
|
||||
+
|
||||
+ return 0;
|
||||
|
||||
-fail:
|
||||
- av_frame_free(&output_frame);
|
||||
+fail_out2:
|
||||
+ av_frame_free(&output_frame_2);
|
||||
+fail_out1:
|
||||
+ av_frame_free(&output_frame_1);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -749,20 +788,22 @@ static int deint_v4l2m2m_filter_frame(AVFilterLink *link, AVFrame *in)
|
||||
V4L2Queue *output = &ctx->output;
|
||||
int ret;
|
||||
|
||||
- av_log(priv, AV_LOG_DEBUG, "input pts: %"PRId64"\n", in->pts);
|
||||
- if (!ctx->frame_count) {
|
||||
+ av_log(priv, AV_LOG_DEBUG, "input pts: %"PRId64" field :%d interlaced: %d\n",
|
||||
+ in->pts, in->top_field_first, in->interlaced_frame);
|
||||
+
|
||||
+ ctx->cur_in_frame = in;
|
||||
+
|
||||
+ if (ctx->field_order == V4L2_FIELD_ANY) {
|
||||
AVDRMFrameDescriptor *drm_desc = (AVDRMFrameDescriptor *)in->data[0];
|
||||
- unsigned int field;
|
||||
-
|
||||
ctx->orig_width = drm_desc->layers[0].planes[0].pitch;
|
||||
ctx->orig_height = drm_desc->layers[0].planes[1].offset / ctx->orig_width;
|
||||
|
||||
- if (in->top_field_first)
|
||||
- field = V4L2_FIELD_INTERLACED_TB;
|
||||
+ if (in->top_field_first)
|
||||
+ ctx->field_order = V4L2_FIELD_INTERLACED_TB;
|
||||
else
|
||||
- field = V4L2_FIELD_INTERLACED_BT;
|
||||
+ ctx->field_order = V4L2_FIELD_INTERLACED_BT;
|
||||
|
||||
- ret = deint_v4l2m2m_set_format(output, field, ctx->orig_width, ctx->orig_height);
|
||||
+ ret = deint_v4l2m2m_set_format(output, ctx->field_order, ctx->orig_width, ctx->orig_height);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -787,27 +828,19 @@ static int deint_v4l2m2m_filter_frame(AVFilterLink *link, AVFrame *in)
|
||||
return ret;
|
||||
}
|
||||
|
||||
- if (ctx->frame_count < 2) {
|
||||
- ctx->frames[ctx->frame_count++] = in;
|
||||
- } else {
|
||||
- av_frame_free(&ctx->frames[0]);
|
||||
- ctx->frames[0] = ctx->frames[1];
|
||||
- ctx->frames[1] = in;
|
||||
- }
|
||||
-
|
||||
ret = deint_v4l2m2m_enqueue(output, in);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
- if (ctx->frame_count == 2) {
|
||||
- ret = deint_v4l2m2m_dequeue(avctx, ctx->frames[0], 0);
|
||||
- if (ret)
|
||||
- return ret;
|
||||
+ ret = deint_v4l2m2m_dequeue(avctx, in);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
|
||||
- ret = deint_v4l2m2m_dequeue(avctx, ctx->frames[0], 1);
|
||||
- if (ret)
|
||||
- return ret;
|
||||
- }
|
||||
+ if (ctx->prev_in_frame)
|
||||
+ av_frame_free(&ctx->prev_in_frame);
|
||||
+
|
||||
+ ctx->prev_in_frame = in;
|
||||
+ ctx->cur_in_frame = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -828,6 +861,9 @@ static av_cold int deint_v4l2m2m_init(AVFilterContext *avctx)
|
||||
ctx->capture.ctx = ctx;
|
||||
ctx->capture.num_buffers = 6;
|
||||
ctx->done = 0;
|
||||
+ ctx->field_order = V4L2_FIELD_ANY;
|
||||
+ ctx->cur_in_frame = NULL;
|
||||
+ ctx->prev_in_frame = NULL;
|
||||
atomic_init(&ctx->refcount, 1);
|
||||
|
||||
return 0;
|
||||
--
|
||||
2.29.2
|
||||
|
@ -1,288 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Alex Bee <knaerzche@gmail.com>
|
||||
Date: Wed, 15 Sep 2021 00:37:15 +0200
|
||||
Subject: [PATCH] libavfilter: v4l2deinterlace: support more formats /
|
||||
automatic output format selection
|
||||
|
||||
Signed-off-by: Alex Bee <knaerzche@gmail.com>
|
||||
---
|
||||
libavfilter/vf_deinterlace_v4l2m2m.c | 120 +++++++++++++++++++++++----
|
||||
1 file changed, 102 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/libavfilter/vf_deinterlace_v4l2m2m.c b/libavfilter/vf_deinterlace_v4l2m2m.c
|
||||
index d7935d92f9..8161fd9e75 100644
|
||||
--- a/libavfilter/vf_deinterlace_v4l2m2m.c
|
||||
+++ b/libavfilter/vf_deinterlace_v4l2m2m.c
|
||||
@@ -85,6 +85,9 @@ typedef struct DeintV4L2M2MContextShared {
|
||||
int height;
|
||||
int orig_width;
|
||||
int orig_height;
|
||||
+ uint64_t drm_in_format;
|
||||
+ uint64_t drm_out_format;
|
||||
+
|
||||
atomic_uint refcount;
|
||||
|
||||
AVBufferRef *hw_frames_ctx;
|
||||
@@ -108,6 +111,65 @@ typedef struct DeintV4L2M2MContext {
|
||||
DeintV4L2M2MContextShared *shared;
|
||||
} DeintV4L2M2MContext;
|
||||
|
||||
+typedef struct drm_v4l2_pix_fmt_mapping {
|
||||
+ uint64_t drm_format;
|
||||
+ uint32_t v4l2_pix_fmt;
|
||||
+};
|
||||
+
|
||||
+static struct drm_v4l2_pix_fmt_mapping drm_v4l2_pix_fmt_map[] = {
|
||||
+ { .drm_format = DRM_FORMAT_NV12, .v4l2_pix_fmt = V4L2_PIX_FMT_NV12 },
|
||||
+ { .drm_format = DRM_FORMAT_NV21, .v4l2_pix_fmt = V4L2_PIX_FMT_NV21 },
|
||||
+ { .drm_format = DRM_FORMAT_NV16, .v4l2_pix_fmt = V4L2_PIX_FMT_NV16 },
|
||||
+ { .drm_format = DRM_FORMAT_NV16, .v4l2_pix_fmt = V4L2_PIX_FMT_NV16 },
|
||||
+#ifdef DRM_FORMAT_MOD_ALLWINNER_TILED
|
||||
+ { .drm_format = DRM_FORMAT_MOD_ALLWINNER_TILED, .v4l2_pix_fmt = V4L2_PIX_FMT_SUNXI_TILED_NV12 },
|
||||
+#endif
|
||||
+#if defined(V4L2_PIX_FMT_NV15) && defined(DRM_FORMAT_NV15)
|
||||
+ { .drm_format = DRM_FORMAT_NV15, .v4l2_pix_fmt = V4L2_PIX_FMT_NV15 },
|
||||
+#endif
|
||||
+#if defined(V4L2_PIX_FMT_NV20) && defined(DRM_FORMAT_NV20)
|
||||
+ { .drm_format = DRM_FORMAT_NV20, .v4l2_pix_fmt = V4L2_PIX_FMT_NV20 },
|
||||
+#endif
|
||||
+};
|
||||
+
|
||||
+static inline uint32_t v4l2_pix_fmt_from_drm_format(uint64_t drm_format)
|
||||
+{
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ for (i = 0; i < FF_ARRAY_ELEMS(drm_v4l2_pix_fmt_map); i++) {
|
||||
+ if (drm_v4l2_pix_fmt_map[i].drm_format == drm_format)
|
||||
+ return drm_v4l2_pix_fmt_map[i].v4l2_pix_fmt;
|
||||
+ }
|
||||
+
|
||||
+ av_log(NULL, AV_LOG_WARNING, "%s unknown drm format 0x%llx using default v4l2_pix_fmt 0x%x\n",
|
||||
+ __func__ , drm_format, drm_v4l2_pix_fmt_map[0].v4l2_pix_fmt);
|
||||
+ return drm_v4l2_pix_fmt_map[0].v4l2_pix_fmt;
|
||||
+}
|
||||
+
|
||||
+static inline uint64_t drm_format_from_v4l2_pix_fmt(uint32_t v4l2_pix_fmt)
|
||||
+{
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ for (i = 0; i < FF_ARRAY_ELEMS(drm_v4l2_pix_fmt_map); i++) {
|
||||
+ if (drm_v4l2_pix_fmt_map[i].v4l2_pix_fmt == v4l2_pix_fmt)
|
||||
+ return drm_v4l2_pix_fmt_map[i].drm_format;
|
||||
+ }
|
||||
+
|
||||
+ av_log(NULL, AV_LOG_WARNING, "%s unknown v4l2_pix_fmt format 0x%x using default drm_format 0x%llx\n",
|
||||
+ __func__ , v4l2_pix_fmt, drm_v4l2_pix_fmt_map[0].drm_format);
|
||||
+ return drm_v4l2_pix_fmt_map[0].drm_format;
|
||||
+}
|
||||
+
|
||||
+static inline uint64_t drm_format_modifier(uint64_t drm_format)
|
||||
+{
|
||||
+#ifdef DRM_FORMAT_MOD_ALLWINNER_TILED
|
||||
+ if (drm_format == DRM_FORMAT_MOD_ALLWINNER_TILED)
|
||||
+ return DRM_FORMAT_MOD_ALLWINNER_TILED;
|
||||
+#endif
|
||||
+ return DRM_FORMAT_MOD_LINEAR;
|
||||
+
|
||||
+}
|
||||
+
|
||||
static int deint_v4l2m2m_prepare_context(DeintV4L2M2MContextShared *ctx)
|
||||
{
|
||||
struct v4l2_capability cap;
|
||||
@@ -138,11 +200,12 @@ static int deint_v4l2m2m_prepare_context(DeintV4L2M2MContextShared *ctx)
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
|
||||
-static int deint_v4l2m2m_try_format(V4L2Queue *queue)
|
||||
+static int deint_v4l2m2m_try_format(V4L2Queue *queue, uint64_t drm_format)
|
||||
{
|
||||
struct v4l2_format *fmt = &queue->format;
|
||||
DeintV4L2M2MContextShared *ctx = queue->ctx;
|
||||
int ret, field;
|
||||
+ uint32_t v4l2_pix_fmt = v4l2_pix_fmt_from_drm_format(drm_format);
|
||||
|
||||
ret = ioctl(ctx->fd, VIDIOC_G_FMT, fmt);
|
||||
if (ret)
|
||||
@@ -154,12 +217,12 @@ static int deint_v4l2m2m_try_format(V4L2Queue *queue)
|
||||
field = V4L2_FIELD_NONE;
|
||||
|
||||
if (V4L2_TYPE_IS_MULTIPLANAR(fmt->type)) {
|
||||
- fmt->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12;
|
||||
+ fmt->fmt.pix_mp.pixelformat = v4l2_pix_fmt;
|
||||
fmt->fmt.pix_mp.field = field;
|
||||
fmt->fmt.pix_mp.width = ctx->width;
|
||||
fmt->fmt.pix_mp.height = ctx->height;
|
||||
} else {
|
||||
- fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_NV12;
|
||||
+ fmt->fmt.pix.pixelformat = v4l2_pix_fmt;
|
||||
fmt->fmt.pix.field = field;
|
||||
fmt->fmt.pix.width = ctx->width;
|
||||
fmt->fmt.pix.height = ctx->height;
|
||||
@@ -170,14 +233,14 @@ static int deint_v4l2m2m_try_format(V4L2Queue *queue)
|
||||
return AVERROR(EINVAL);
|
||||
|
||||
if (V4L2_TYPE_IS_MULTIPLANAR(fmt->type)) {
|
||||
- if (fmt->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_NV12 ||
|
||||
+ if (fmt->fmt.pix_mp.pixelformat != v4l2_pix_fmt ||
|
||||
fmt->fmt.pix_mp.field != field) {
|
||||
av_log(NULL, AV_LOG_DEBUG, "format not supported for type %d\n", fmt->type);
|
||||
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
} else {
|
||||
- if (fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_NV12 ||
|
||||
+ if (fmt->fmt.pix.pixelformat != v4l2_pix_fmt ||
|
||||
fmt->fmt.pix.field != field) {
|
||||
av_log(NULL, AV_LOG_DEBUG, "format not supported for type %d\n", fmt->type);
|
||||
|
||||
@@ -187,19 +250,21 @@ static int deint_v4l2m2m_try_format(V4L2Queue *queue)
|
||||
|
||||
return 0;
|
||||
}
|
||||
-
|
||||
-static int deint_v4l2m2m_set_format(V4L2Queue *queue, uint32_t field, int width, int height)
|
||||
+static int deint_v4l2m2m_set_format(V4L2Queue *queue, uint32_t field, int width, int height, uint64_t drm_format)
|
||||
{
|
||||
struct v4l2_format *fmt = &queue->format;
|
||||
DeintV4L2M2MContextShared *ctx = queue->ctx;
|
||||
int ret;
|
||||
+ uint32_t v4l2_pix_fmt = v4l2_pix_fmt_from_drm_format(drm_format);
|
||||
|
||||
if (V4L2_TYPE_IS_MULTIPLANAR(fmt->type)) {
|
||||
+ fmt->fmt.pix_mp.pixelformat = v4l2_pix_fmt;
|
||||
fmt->fmt.pix_mp.field = field;
|
||||
fmt->fmt.pix_mp.width = width;
|
||||
fmt->fmt.pix_mp.height = height;
|
||||
/* TODO: bytesperline and imagesize */
|
||||
} else {
|
||||
+ fmt->fmt.pix.pixelformat = v4l2_pix_fmt;
|
||||
fmt->fmt.pix.field = field;
|
||||
fmt->fmt.pix.width = width;
|
||||
fmt->fmt.pix.height = height;
|
||||
@@ -211,6 +276,18 @@ static int deint_v4l2m2m_set_format(V4L2Queue *queue, uint32_t field, int width,
|
||||
if (ret)
|
||||
av_log(NULL, AV_LOG_ERROR, "VIDIOC_S_FMT failed: %d\n", ret);
|
||||
|
||||
+ else if (!V4L2_TYPE_IS_OUTPUT(queue->format.type)) {
|
||||
+ if (V4L2_TYPE_IS_MULTIPLANAR(fmt->type) && fmt->fmt.pix_mp.pixelformat != v4l2_pix_fmt) {
|
||||
+ ctx->drm_out_format = drm_format_from_v4l2_pix_fmt(fmt->fmt.pix_mp.pixelformat);
|
||||
+ av_log(NULL, AV_LOG_DEBUG, "%s driver updated v4l2_pixfmt from: %x to %x, so now using %llx as drm output format\n",
|
||||
+ __func__, v4l2_pix_fmt, fmt->fmt.pix_mp.pixelformat, ctx->drm_out_format);
|
||||
+ } else if (fmt->fmt.pix.pixelformat != v4l2_pix_fmt) {
|
||||
+ ctx->drm_out_format = drm_format_from_v4l2_pix_fmt(fmt->fmt.pix.pixelformat);
|
||||
+ av_log(NULL, AV_LOG_DEBUG, "%s driver updated v4l2_pixfmt from: %x to %x, so now using %llx as drm output format\n",
|
||||
+ __func__, v4l2_pix_fmt, fmt->fmt.pix.pixelformat, ctx->drm_out_format);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -226,11 +303,11 @@ static int deint_v4l2m2m_probe_device(DeintV4L2M2MContextShared *ctx, char *node
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
- ret = deint_v4l2m2m_try_format(&ctx->capture);
|
||||
+ ret = deint_v4l2m2m_try_format(&ctx->capture, ctx->drm_out_format);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
- ret = deint_v4l2m2m_try_format(&ctx->output);
|
||||
+ ret = deint_v4l2m2m_try_format(&ctx->output, ctx->drm_in_format);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
@@ -293,7 +370,7 @@ static int deint_v4l2m2m_enqueue_buffer(V4L2Buffer *buf)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int v4l2_buffer_export_drm(V4L2Buffer* avbuf)
|
||||
+static int v4l2_buffer_export_drm(V4L2Buffer* avbuf, uint64_t drm_format)
|
||||
{
|
||||
struct v4l2_exportbuffer expbuf;
|
||||
int i, ret;
|
||||
@@ -315,12 +392,12 @@ static int v4l2_buffer_export_drm(V4L2Buffer* avbuf)
|
||||
/* drm frame */
|
||||
avbuf->drm_frame.objects[i].size = avbuf->buffer.m.planes[i].length;
|
||||
avbuf->drm_frame.objects[i].fd = expbuf.fd;
|
||||
- avbuf->drm_frame.objects[i].format_modifier = DRM_FORMAT_MOD_LINEAR;
|
||||
+ avbuf->drm_frame.objects[i].format_modifier = drm_format_modifier(drm_format);
|
||||
} else {
|
||||
/* drm frame */
|
||||
avbuf->drm_frame.objects[0].size = avbuf->buffer.length;
|
||||
avbuf->drm_frame.objects[0].fd = expbuf.fd;
|
||||
- avbuf->drm_frame.objects[0].format_modifier = DRM_FORMAT_MOD_LINEAR;
|
||||
+ avbuf->drm_frame.objects[0].format_modifier = drm_format_modifier(drm_format);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -405,7 +482,7 @@ static int deint_v4l2m2m_allocate_buffers(V4L2Queue *queue)
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
- ret = v4l2_buffer_export_drm(buf);
|
||||
+ ret = v4l2_buffer_export_drm(buf, ctx->drm_out_format);
|
||||
if (ret)
|
||||
goto fail;
|
||||
}
|
||||
@@ -597,7 +674,7 @@ static void v4l2_free_buffer(void *opaque, uint8_t *unused)
|
||||
deint_v4l2m2m_destroy_context(ctx);
|
||||
}
|
||||
|
||||
-static uint8_t *v4l2_get_drm_frame(V4L2Buffer *avbuf, int height)
|
||||
+static uint8_t *v4l2_get_drm_frame(V4L2Buffer *avbuf, int height, uint64_t drm_format)
|
||||
{
|
||||
AVDRMFrameDescriptor *drm_desc = &avbuf->drm_frame;
|
||||
AVDRMLayerDescriptor *layer;
|
||||
@@ -615,7 +692,7 @@ static uint8_t *v4l2_get_drm_frame(V4L2Buffer *avbuf, int height)
|
||||
layer->planes[i].pitch = avbuf->plane_info[i].bytesperline;
|
||||
}
|
||||
|
||||
- layer->format = DRM_FORMAT_NV12;
|
||||
+ layer->format = drm_format;
|
||||
|
||||
if (avbuf->num_planes == 1) {
|
||||
layer->nb_planes = 2;
|
||||
@@ -647,7 +724,7 @@ static int deint_v4l2m2m_dequeue_frame(V4L2Queue *queue, AVFrame* frame, int tim
|
||||
|
||||
atomic_fetch_add(&ctx->refcount, 1);
|
||||
|
||||
- frame->data[0] = (uint8_t *)v4l2_get_drm_frame(avbuf, ctx->orig_height);
|
||||
+ frame->data[0] = (uint8_t *)v4l2_get_drm_frame(avbuf, ctx->orig_height, ctx->drm_out_format);
|
||||
frame->format = AV_PIX_FMT_DRM_PRIME;
|
||||
frame->hw_frames_ctx = av_buffer_ref(ctx->hw_frames_ctx);
|
||||
frame->height = ctx->height;
|
||||
@@ -797,17 +874,22 @@ static int deint_v4l2m2m_filter_frame(AVFilterLink *link, AVFrame *in)
|
||||
AVDRMFrameDescriptor *drm_desc = (AVDRMFrameDescriptor *)in->data[0];
|
||||
ctx->orig_width = drm_desc->layers[0].planes[0].pitch;
|
||||
ctx->orig_height = drm_desc->layers[0].planes[1].offset / ctx->orig_width;
|
||||
+ ctx->drm_in_format = drm_desc->layers->format;
|
||||
+ ctx->drm_out_format = drm_desc->layers->format;
|
||||
+
|
||||
|
||||
if (in->top_field_first)
|
||||
ctx->field_order = V4L2_FIELD_INTERLACED_TB;
|
||||
else
|
||||
ctx->field_order = V4L2_FIELD_INTERLACED_BT;
|
||||
|
||||
- ret = deint_v4l2m2m_set_format(output, ctx->field_order, ctx->orig_width, ctx->orig_height);
|
||||
+ ret = deint_v4l2m2m_set_format(output, ctx->field_order, ctx->orig_width, ctx->orig_height,
|
||||
+ ctx->drm_in_format);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
- ret = deint_v4l2m2m_set_format(capture, V4L2_FIELD_NONE, ctx->orig_width, ctx->orig_height);
|
||||
+ ret = deint_v4l2m2m_set_format(capture, V4L2_FIELD_NONE, ctx->orig_width, ctx->orig_height,
|
||||
+ ctx->drm_out_format);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -864,6 +946,8 @@ static av_cold int deint_v4l2m2m_init(AVFilterContext *avctx)
|
||||
ctx->field_order = V4L2_FIELD_ANY;
|
||||
ctx->cur_in_frame = NULL;
|
||||
ctx->prev_in_frame = NULL;
|
||||
+ ctx->drm_in_format = drm_v4l2_pix_fmt_map[0].drm_format;
|
||||
+ ctx->drm_out_format = drm_v4l2_pix_fmt_map[0].drm_format;
|
||||
atomic_init(&ctx->refcount, 1);
|
||||
|
||||
return 0;
|
@ -2,12 +2,12 @@
|
||||
|
||||
# base ffmpeg version
|
||||
FFMPEG_REPO="git://source.ffmpeg.org/ffmpeg.git"
|
||||
FFMPEG_VERSION="n4.4.1"
|
||||
FFMPEG_VERSION="n5.1.2"
|
||||
|
||||
KODI_FFMPEG_REPO="https://github.com/xbmc/FFmpeg"
|
||||
KODI_FFMPEG_VERSION="4.4.1-Nexus-Alpha1"
|
||||
KODI_FFMPEG_VERSION="5.1.2-Nexus-Alpha3"
|
||||
|
||||
ALL_FEATURE_SETS="v4l2-drmprime v4l2-request libreelec rpi kodi"
|
||||
ALL_FEATURE_SETS="v4l2-drmprime v4l2-request libreelec rpi vf-deinterlace-v4l2m2m"
|
||||
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "usage: $0 all|featureset [githash]"
|
||||
@ -28,31 +28,17 @@ create_patch() {
|
||||
PATCH_CREATE_DIFF="no"
|
||||
|
||||
case "${FEATURE_SET}" in
|
||||
v4l2-drmprime)
|
||||
v4l2-drmprime|v4l2-request|vf-deinterlace-v4l2m2m)
|
||||
REPO="https://github.com/jernejsk/FFmpeg"
|
||||
REFSPEC="v4l2-drmprime-v6-4.4.1-Nexus-Alpha1"
|
||||
BASE_REPO="${KODI_FFMPEG_REPO}"
|
||||
BASE_VERSION="${KODI_FFMPEG_VERSION}"
|
||||
;;
|
||||
v4l2-request)
|
||||
REPO="https://github.com/jernejsk/FFmpeg"
|
||||
REFSPEC="v4l2-request-hwaccel-4.4.1-Nexus-Alpha1"
|
||||
BASE_REPO="${KODI_FFMPEG_REPO}"
|
||||
BASE_VERSION="${KODI_FFMPEG_VERSION}"
|
||||
REFSPEC="${FEATURE_SET}-${FFMPEG_VERSION}"
|
||||
;;
|
||||
libreelec)
|
||||
REPO="https://github.com/LibreELEC/FFmpeg"
|
||||
REFSPEC="4.4-libreelec-misc"
|
||||
REFSPEC="5.1.2-libreelec-misc"
|
||||
;;
|
||||
rpi)
|
||||
REPO="https://github.com/jc-kynesim/rpi-ffmpeg"
|
||||
REFSPEC="dev/4.4/rpi_import_1"
|
||||
PATCH_CREATE_DIFF="yes"
|
||||
;;
|
||||
kodi)
|
||||
REPO="${KODI_FFMPEG_REPO}"
|
||||
REFSPEC="${KODI_FFMPEG_VERSION}"
|
||||
REFTYPE="tag"
|
||||
REFSPEC="dev/5.1.2/rpi_import_1"
|
||||
;;
|
||||
*)
|
||||
echo "illegal feature set ${FEATURE_SET}"
|
||||
|
Loading…
x
Reference in New Issue
Block a user