ffmpeg: drop all local patches

Signed-off-by: Matthias Reichl <hias@horus.com>
This commit is contained in:
Matthias Reichl 2020-07-07 13:17:25 +02:00
parent 54ea2ebba8
commit d5d98b3f7b
36 changed files with 0 additions and 105126 deletions

View File

@ -24,7 +24,6 @@ if [ "${V4L2_SUPPORT}" = "yes" ]; then
PKG_FFMPEG_V4L2="--enable-v4l2_m2m --enable-libdrm"
if [ "${PROJECT}" = "RPi" ]; then
PKG_PATCH_DIRS+=" v4l2-rpi"
PKG_FFMPEG_RPI="--disable-rpi --disable-mmal"
if [ "${DEVICE}" = "RPi4" ]; then
PKG_DEPENDS_TARGET+=" systemd"
@ -35,8 +34,6 @@ if [ "${V4L2_SUPPORT}" = "yes" ]; then
--disable-hwaccel=mpeg2_v4l2request \
--disable-hwaccel=vp8_v4l2request"
fi
else
PKG_PATCH_DIRS+=" v4l2"
fi
else
PKG_FFMPEG_V4L2="--disable-v4l2_m2m"
@ -61,7 +58,6 @@ fi
if [ "${PROJECT}" = "Allwinner" -o "${PROJECT}" = "Rockchip" ]; then
PKG_DEPENDS_TARGET+=" libdrm systemd" # systemd is needed for libudev
PKG_NEED_UNPACK+=" $(get_pkg_directory libdrm) $(get_pkg_directory systemd)"
PKG_PATCH_DIRS+=" v4l2-request-api"
PKG_FFMPEG_V4L2_REQUEST="--enable-v4l2-request --enable-libudev --enable-libdrm"
fi

View File

@ -1,47 +0,0 @@
From 85417a4ba42360248b4999e458a6e05c1c2f9b17 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Sat, 4 Mar 2017 19:24:02 +0000
Subject: [PATCH] ffmpeg: Call get_format to fix an issue with MMAL rendering
---
libavcodec/dvdec.c | 6 ++++++
libavcodec/rv34.c | 6 +++++-
2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/libavcodec/dvdec.c b/libavcodec/dvdec.c
index 89864f2edc..b5f9224d72 100644
--- a/libavcodec/dvdec.c
+++ b/libavcodec/dvdec.c
@@ -197,6 +197,12 @@ static av_cold int dvvideo_decode_init(AVCodecContext *avctx)
s->idct_put[0] = idsp.idct_put;
s->idct_put[1] = ff_simple_idct248_put;
+ static const enum AVPixelFormat pix_fmts[] = {
+ AV_PIX_FMT_YUV420P,
+ AV_PIX_FMT_NONE
+ };
+ avctx->pix_fmt = ff_get_format(avctx, pix_fmts);
+
return ff_dvvideo_init(avctx);
}
diff --git a/libavcodec/rv34.c b/libavcodec/rv34.c
index d171e6e1bd..f6f0aa1f74 100644
--- a/libavcodec/rv34.c
+++ b/libavcodec/rv34.c
@@ -1499,7 +1499,11 @@ av_cold int ff_rv34_decode_init(AVCodecContext *avctx)
ff_mpv_decode_init(s, avctx);
s->out_format = FMT_H263;
- avctx->pix_fmt = AV_PIX_FMT_YUV420P;
+ static const enum AVPixelFormat pix_fmts[] = {
+ AV_PIX_FMT_YUV420P,
+ AV_PIX_FMT_NONE
+ };
+ avctx->pix_fmt = ff_get_format(avctx, pix_fmts);
avctx->has_b_frames = 1;
s->low_delay = 0;
--
2.20.1

View File

@ -1,48 +0,0 @@
From 848de6c1923820f1de49ed7875d6c8877d0c321c Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Fri, 5 Jun 2015 22:48:33 +0100
Subject: [PATCH] mpeg4video: Signal unsupported GMC with more than one warp
point
---
libavcodec/avcodec.h | 1 +
libavcodec/mpeg4videodec.c | 4 ++++
2 files changed, 5 insertions(+)
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index a36b675fba..880284d5bd 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -2612,6 +2612,7 @@ typedef struct AVCodecContext {
#define FF_BUG_MS 8192 ///< Work around various bugs in Microsoft's broken decoders.
#define FF_BUG_TRUNCATED 16384
#define FF_BUG_IEDGE 32768
+#define FF_BUG_GMC_UNSUPPORTED (1<<30)
/**
* strictly follow the standard (MPEG-4, ...).
diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c
index 055afabc7e..fa208660c8 100644
--- a/libavcodec/mpeg4videodec.c
+++ b/libavcodec/mpeg4videodec.c
@@ -2662,6 +2662,9 @@ int ff_mpeg4_workaround_bugs(AVCodecContext *avctx)
if (ctx->divx_version >= 0)
s->workaround_bugs |= FF_BUG_HPEL_CHROMA;
+
+ if (ctx->num_sprite_warping_points > 1)
+ s->workaround_bugs |= FF_BUG_GMC_UNSUPPORTED;
}
if (s->workaround_bugs & FF_BUG_STD_QPEL) {
@@ -2686,6 +2689,7 @@ int ff_mpeg4_workaround_bugs(AVCodecContext *avctx)
s->workaround_bugs, ctx->lavc_build, ctx->xvid_build,
ctx->divx_version, ctx->divx_build, s->divx_packed ? "p" : "");
+ avctx->workaround_bugs = s->workaround_bugs;
if (CONFIG_MPEG4_DECODER && ctx->xvid_build >= 0 &&
s->codec_id == AV_CODEC_ID_MPEG4 &&
avctx->idct_algo == FF_IDCT_AUTO) {
--
2.20.1

View File

@ -1,269 +0,0 @@
From a853a9c70339c30ea4d5081366fee4bb84bc09c5 Mon Sep 17 00:00:00 2001
From: Hendrik Leppkes <h.leppkes@gmail.com>
Date: Sat, 9 Jan 2016 16:34:09 +0100
Subject: [PATCH 1/4] avcodec: add h264_mvc codec id and profiles
---
libavcodec/avcodec.h | 3 +++
libavcodec/codec_desc.c | 7 +++++++
libavcodec/profiles.c | 1 +
libavformat/mpegts.c | 2 +-
4 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 880284d5bd..88e01645cd 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -458,6 +458,8 @@ enum AVCodecID {
AV_CODEC_ID_LSCR,
AV_CODEC_ID_VP4,
+ AV_CODEC_ID_H264_MVC,
+
/* various PCM "codecs" */
AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs
AV_CODEC_ID_PCM_S16LE = 0x10000,
@@ -2950,6 +2952,7 @@ typedef struct AVCodecContext {
#define FF_PROFILE_H264_HIGH_444_PREDICTIVE 244
#define FF_PROFILE_H264_HIGH_444_INTRA (244|FF_PROFILE_H264_INTRA)
#define FF_PROFILE_H264_CAVLC_444 44
+#define FF_PROFILE_H264_MULTIVIEW_HIGH_DEPTH 138
#define FF_PROFILE_VC1_SIMPLE 0
#define FF_PROFILE_VC1_MAIN 1
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index 4d033c20ff..def006e033 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -1726,6 +1726,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
.long_name = NULL_IF_CONFIG_SMALL("On2 VP4"),
.props = AV_CODEC_PROP_LOSSY,
},
+ {
+ .id = AV_CODEC_ID_H264_MVC,
+ .type = AVMEDIA_TYPE_VIDEO,
+ .name = "h264_mvc",
+ .long_name = NULL_IF_CONFIG_SMALL("H264 MVC"),
+ .props = AV_CODEC_PROP_LOSSY,
+ },
/* various PCM "codecs" */
{
diff --git a/libavcodec/profiles.c b/libavcodec/profiles.c
index eaf0d68d32..fc1e152420 100644
--- a/libavcodec/profiles.c
+++ b/libavcodec/profiles.c
@@ -71,6 +71,7 @@ const AVProfile ff_h264_profiles[] = {
{ FF_PROFILE_H264_CAVLC_444, "CAVLC 4:4:4" },
{ FF_PROFILE_H264_MULTIVIEW_HIGH, "Multiview High" },
{ FF_PROFILE_H264_STEREO_HIGH, "Stereo High" },
+ { FF_PROFILE_H264_MULTIVIEW_HIGH_DEPTH, "Multiview High Depth" },
{ FF_PROFILE_UNKNOWN },
};
diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
index 0415ceea02..264bf9718b 100644
--- a/libavformat/mpegts.c
+++ b/libavformat/mpegts.c
@@ -798,7 +798,7 @@ static const StreamType ISO_types[] = {
#endif
{ 0x1b, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_H264 },
{ 0x1c, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AAC },
- { 0x20, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_H264 },
+ { 0x20, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_H264_MVC },
{ 0x21, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_JPEG2000 },
{ 0x24, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_HEVC },
{ 0x42, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_CAVS },
--
2.20.1
From 8d479b1b5395f97a8e5ee0eddab6680941edfb5b Mon Sep 17 00:00:00 2001
From: Hendrik Leppkes <h.leppkes@gmail.com>
Date: Sat, 9 Jan 2016 16:34:40 +0100
Subject: [PATCH 2/4] h264_parser: add support for parsing h264 mvc NALUs
---
libavcodec/h264_parser.c | 34 ++++++++++++++++++++++++++++++----
libavcodec/parsers.c | 1 +
2 files changed, 31 insertions(+), 4 deletions(-)
diff --git a/libavcodec/h264_parser.c b/libavcodec/h264_parser.c
index 5f9a9c46ef..991e8e82f3 100644
--- a/libavcodec/h264_parser.c
+++ b/libavcodec/h264_parser.c
@@ -62,6 +62,7 @@ typedef struct H264ParseContext {
int parse_last_mb;
int64_t reference_dts;
int last_frame_num, last_picture_structure;
+ int is_mvc;
} H264ParseContext;
@@ -109,14 +110,18 @@ static int h264_find_frame_end(H264ParseContext *p, const uint8_t *buf,
} else if (state <= 5) {
int nalu_type = buf[i] & 0x1F;
if (nalu_type == H264_NAL_SEI || nalu_type == H264_NAL_SPS ||
- nalu_type == H264_NAL_PPS || nalu_type == H264_NAL_AUD) {
+ nalu_type == H264_NAL_PPS || nalu_type == H264_NAL_AUD ||
+ nalu_type == H264_NAL_SUB_SPS) {
if (pc->frame_start_found) {
i++;
goto found;
}
} else if (nalu_type == H264_NAL_SLICE || nalu_type == H264_NAL_DPA ||
- nalu_type == H264_NAL_IDR_SLICE) {
+ nalu_type == H264_NAL_IDR_SLICE || (p->is_mvc && nalu_type == H264_NAL_EXTEN_SLICE)) {
state += 8;
+
+ if (nalu_type == H264_NAL_EXTEN_SLICE)
+ i += 3; // skip mvc extension
continue;
}
state = 7;
@@ -604,7 +609,8 @@ static int h264_parse(AVCodecParserContext *s,
}
}
- parse_nal_units(s, avctx, buf, buf_size);
+ if (!p->is_mvc)
+ parse_nal_units(s, avctx, buf, buf_size);
if (avctx->framerate.num)
avctx->time_base = av_inv_q(av_mul_q(avctx->framerate, (AVRational){avctx->ticks_per_frame, 1}));
@@ -661,7 +667,7 @@ static int h264_split(AVCodecContext *avctx,
if ((state & 0xFFFFFF00) != 0x100)
break;
nalu_type = state & 0x1F;
- if (nalu_type == H264_NAL_SPS) {
+ if (nalu_type == H264_NAL_SPS || nalu_type == H264_NAL_SUB_SPS) {
has_sps = 1;
} else if (nalu_type == H264_NAL_PPS)
has_pps = 1;
@@ -713,3 +719,23 @@ AVCodecParser ff_h264_parser = {
.parser_close = h264_close,
.split = h264_split,
};
+
+static av_cold int init_mvc(AVCodecParserContext *s)
+{
+ H264ParseContext *p = s->priv_data;
+ int ret = init(s);
+ if (ret < 0)
+ return ret;
+
+ p->is_mvc = 1;
+ return 0;
+}
+
+AVCodecParser ff_h264_mvc_parser = {
+ .codec_ids = { AV_CODEC_ID_H264_MVC },
+ .priv_data_size = sizeof(H264ParseContext),
+ .parser_init = init_mvc,
+ .parser_parse = h264_parse,
+ .parser_close = h264_close,
+ .split = h264_split,
+};
diff --git a/libavcodec/parsers.c b/libavcodec/parsers.c
index 33a71de8a0..80b269b324 100644
--- a/libavcodec/parsers.c
+++ b/libavcodec/parsers.c
@@ -47,6 +47,7 @@ extern AVCodecParser ff_gsm_parser;
extern AVCodecParser ff_h261_parser;
extern AVCodecParser ff_h263_parser;
extern AVCodecParser ff_h264_parser;
+extern AVCodecParser ff_h264_mvc_parser;
extern AVCodecParser ff_hevc_parser;
extern AVCodecParser ff_mjpeg_parser;
extern AVCodecParser ff_mlp_parser;
--
2.20.1
From e2cad00490c9cd339b9266e8b9fe5d86afe2abe1 Mon Sep 17 00:00:00 2001
From: Hendrik Leppkes <h.leppkes@gmail.com>
Date: Tue, 28 Nov 2017 16:12:12 +0000
Subject: [PATCH 3/4] h264_parser: force grabing a new timestamp until a frame
start was found
---
libavcodec/h264_parser.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/libavcodec/h264_parser.c b/libavcodec/h264_parser.c
index 991e8e82f3..f573bd8629 100644
--- a/libavcodec/h264_parser.c
+++ b/libavcodec/h264_parser.c
@@ -597,6 +597,9 @@ static int h264_parse(AVCodecParserContext *s,
} else {
next = h264_find_frame_end(p, buf, buf_size, avctx);
+ if (next == END_NOT_FOUND && pc->frame_start_found == 0)
+ s->fetch_timestamp = 1;
+
if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) {
*poutbuf = NULL;
*poutbuf_size = 0;
--
2.20.1
From fc2954e5eba1791443016cdd17fcea280f464db5 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Mon, 28 May 2018 13:35:36 +0100
Subject: [PATCH 4/4] fixup
---
libavcodec/extract_extradata_bsf.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/libavcodec/extract_extradata_bsf.c b/libavcodec/extract_extradata_bsf.c
index 85cf615ffa..b5f1657528 100644
--- a/libavcodec/extract_extradata_bsf.c
+++ b/libavcodec/extract_extradata_bsf.c
@@ -138,7 +138,7 @@ static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt,
HEVC_NAL_VPS, HEVC_NAL_SPS, HEVC_NAL_PPS,
};
static const int extradata_nal_types_h264[] = {
- H264_NAL_SPS, H264_NAL_PPS,
+ H264_NAL_SPS, H264_NAL_SUB_SPS, H264_NAL_PPS,
};
ExtractExtradataContext *s = ctx->priv_data;
@@ -169,7 +169,7 @@ static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt,
if (nal->type == HEVC_NAL_SPS) has_sps = 1;
if (nal->type == HEVC_NAL_VPS) has_vps = 1;
} else {
- if (nal->type == H264_NAL_SPS) has_sps = 1;
+ if (nal->type == H264_NAL_SPS || nal->type == H264_NAL_SUB_SPS) has_sps = 1;
}
} else if (s->remove) {
filtered_size += nal->raw_size + 3;
@@ -178,7 +178,7 @@ static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt,
if (extradata_size &&
((ctx->par_in->codec_id == AV_CODEC_ID_HEVC && has_sps && has_vps) ||
- (ctx->par_in->codec_id == AV_CODEC_ID_H264 && has_sps))) {
+ ((ctx->par_in->codec_id == AV_CODEC_ID_H264 || ctx->par_in->codec_id == AV_CODEC_ID_H264_MVC) && has_sps))) {
AVBufferRef *filtered_buf = NULL;
uint8_t *extradata, *filtered_data;
@@ -334,6 +334,7 @@ static const struct {
{ AV_CODEC_ID_AVS2, extract_extradata_mpeg4 },
{ AV_CODEC_ID_CAVS, extract_extradata_mpeg4 },
{ AV_CODEC_ID_H264, extract_extradata_h2645 },
+ { AV_CODEC_ID_H264_MVC, extract_extradata_h2645 },
{ AV_CODEC_ID_HEVC, extract_extradata_h2645 },
{ AV_CODEC_ID_MPEG1VIDEO, extract_extradata_mpeg12 },
{ AV_CODEC_ID_MPEG2VIDEO, extract_extradata_mpeg12 },
@@ -401,6 +402,7 @@ static const enum AVCodecID codec_ids[] = {
AV_CODEC_ID_AVS2,
AV_CODEC_ID_CAVS,
AV_CODEC_ID_H264,
+ AV_CODEC_ID_H264_MVC,
AV_CODEC_ID_HEVC,
AV_CODEC_ID_MPEG1VIDEO,
AV_CODEC_ID_MPEG2VIDEO,
--
2.20.1

View File

@ -1,45 +0,0 @@
commit 578b5ee8c0fe7d9ef09ef91ffcafc916f1d7d97b
Author: Lukas Rusak <lorusak@gmail.com>
Date: Wed Apr 10 13:39:21 2019 -0700
libavcodec/libdav1d: add libdav1d_get_format method to call ff_get_format
This will allow applications to properly init the decoder in
cases where a hardware decoder is tried first and and software
decoder is tried after by calling the get_format callback.
Even though there is no hardware pixel formats available
we still need to return the software pixel format.
Tested with Kodi by checking if multithreaded software
decoding is properly activated.
diff --git a/libavcodec/libdav1d.c b/libavcodec/libdav1d.c
index 12c63245f8..1bbb83eda3 100644
--- a/libavcodec/libdav1d.c
+++ b/libavcodec/libdav1d.c
@@ -53,6 +53,16 @@ static const enum AVPixelFormat pix_fmt_rgb[3] = {
AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12,
};
+static enum AVPixelFormat libdav1d_get_format(AVCodecContext *avctx, const Dav1dPicture *p)
+{
+ enum AVPixelFormat pix_fmts[2], *fmt = pix_fmts;
+
+ *fmt++ = pix_fmt[p->p.layout][p->seq_hdr->hbd];
+ *fmt = AV_PIX_FMT_NONE;
+
+ return ff_get_format(avctx, pix_fmts);
+}
+
static void libdav1d_log_callback(void *opaque, const char *fmt, va_list vl)
{
AVCodecContext *c = opaque;
@@ -229,6 +239,7 @@ static int libdav1d_receive_frame(AVCodecContext *c, AVFrame *frame)
c->profile = p->seq_hdr->profile;
c->level = ((p->seq_hdr->operating_points[0].major_level - 2) << 2)
| p->seq_hdr->operating_points[0].minor_level;
+ frame->format = c->pix_fmt = libdav1d_get_format(c, p);
frame->width = p->p.w;
frame->height = p->p.h;
if (c->width != p->p.w || c->height != p->p.h) {

View File

@ -1,13 +0,0 @@
--- a/libswscale/yuv2rgb.c 2018-07-22 10:00:00.000000000 +0100
+++ b/libswscale/yuv2rgb.c 2018-08-20 11:55:46.391543992 +0100
@@ -687,10 +687,6 @@ SwsFunc ff_yuv2rgb_get_func_ptr(SwsConte
if (t)
return t;
- av_log(c, AV_LOG_WARNING,
- "No accelerated colorspace conversion found from %s to %s.\n",
- av_get_pix_fmt_name(c->srcFormat), av_get_pix_fmt_name(c->dstFormat));
-
switch (c->dstFormat) {
case AV_PIX_FMT_BGR48BE:
case AV_PIX_FMT_BGR48LE:

View File

@ -1,51 +0,0 @@
From 3710124dd57ede7588884ecc86cbcaee5d530498 Mon Sep 17 00:00:00 2001
From: Jonas Karlman <jonas@kwiboo.se>
Date: Mon, 3 Dec 2018 23:48:04 +0100
Subject: [PATCH 01/12] avutil: add av_buffer_pool_flush()
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
libavutil/buffer.c | 13 +++++++++++++
libavutil/buffer.h | 5 +++++
2 files changed, 18 insertions(+)
diff --git a/libavutil/buffer.c b/libavutil/buffer.c
index 8d1aa5fa84..58160f62f3 100644
--- a/libavutil/buffer.c
+++ b/libavutil/buffer.c
@@ -272,6 +272,19 @@ static void buffer_pool_free(AVBufferPool *pool)
av_freep(&pool);
}
+void av_buffer_pool_flush(AVBufferPool *pool)
+{
+ ff_mutex_lock(&pool->mutex);
+ while (pool->pool) {
+ BufferPoolEntry *buf = pool->pool;
+ pool->pool = buf->next;
+
+ buf->free(buf->opaque, buf->data);
+ av_freep(&buf);
+ }
+ ff_mutex_unlock(&pool->mutex);
+}
+
void av_buffer_pool_uninit(AVBufferPool **ppool)
{
AVBufferPool *pool;
diff --git a/libavutil/buffer.h b/libavutil/buffer.h
index 73b6bd0b14..0678fa4bea 100644
--- a/libavutil/buffer.h
+++ b/libavutil/buffer.h
@@ -266,6 +266,11 @@ AVBufferPool *av_buffer_pool_init2(int size, void *opaque,
AVBufferRef* (*alloc)(void *opaque, int size),
void (*pool_free)(void *opaque));
+/**
+ * Free all available buffers in a buffer pool.
+ */
+ void av_buffer_pool_flush(AVBufferPool *pool);
+
/**
* Mark the pool as being available for freeing. It will actually be freed only
* once all the allocated buffers associated with the pool are released. Thus it

View File

@ -1,244 +0,0 @@
From 279092b1ef7cb944c513167dd55861ff2f2bb473 Mon Sep 17 00:00:00 2001
From: Jonas Karlman <jonas@kwiboo.se>
Date: Sat, 15 Dec 2018 22:32:16 +0100
Subject: [PATCH 03/12] Add V4L2 request API mpeg2 hwaccel
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
configure | 3 +
libavcodec/Makefile | 1 +
libavcodec/hwaccels.h | 1 +
libavcodec/mpeg12dec.c | 6 ++
libavcodec/v4l2_request_mpeg2.c | 154 ++++++++++++++++++++++++++++++++
5 files changed, 165 insertions(+)
create mode 100644 libavcodec/v4l2_request_mpeg2.c
diff --git a/configure b/configure
index 6b41344dfd..e88c201cce 100755
--- a/configure
+++ b/configure
@@ -2937,6 +2937,8 @@ mpeg2_dxva2_hwaccel_deps="dxva2"
mpeg2_dxva2_hwaccel_select="mpeg2video_decoder"
mpeg2_nvdec_hwaccel_deps="nvdec"
mpeg2_nvdec_hwaccel_select="mpeg2video_decoder"
+mpeg2_v4l2request_hwaccel_deps="v4l2_request mpeg2_v4l2_request"
+mpeg2_v4l2request_hwaccel_select="mpeg2video_decoder"
mpeg2_vaapi_hwaccel_deps="vaapi"
mpeg2_vaapi_hwaccel_select="mpeg2video_decoder"
mpeg2_vdpau_hwaccel_deps="vdpau"
@@ -6455,6 +6457,7 @@ check_cc vp8_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_VP8;"
check_cc vp9_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_VP9;"
check_func_headers "linux/media.h linux/videodev2.h" v4l2_timeval_to_ns
+check_cc mpeg2_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_MPEG2_SLICE;"
check_headers sys/videoio.h
test_code cc sys/videoio.h "struct v4l2_frmsizeenum vfse; vfse.discrete.width = 0;" && enable_sanitized struct_v4l2_frmivalenum_discrete
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 9e847eeadc..864f24a2af 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -891,6 +891,7 @@ OBJS-$(CONFIG_MPEG2_D3D11VA_HWACCEL) += dxva2_mpeg2.o
OBJS-$(CONFIG_MPEG2_DXVA2_HWACCEL) += dxva2_mpeg2.o
OBJS-$(CONFIG_MPEG2_NVDEC_HWACCEL) += nvdec_mpeg12.o
OBJS-$(CONFIG_MPEG2_QSV_HWACCEL) += qsvdec_other.o
+OBJS-$(CONFIG_MPEG2_V4L2REQUEST_HWACCEL) += v4l2_request_mpeg2.o
OBJS-$(CONFIG_MPEG2_VAAPI_HWACCEL) += vaapi_mpeg2.o
OBJS-$(CONFIG_MPEG2_VDPAU_HWACCEL) += vdpau_mpeg12.o
OBJS-$(CONFIG_MPEG2_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o
diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h
index 7d73da8676..ef54de2a3b 100644
--- a/libavcodec/hwaccels.h
+++ b/libavcodec/hwaccels.h
@@ -47,6 +47,7 @@ extern const AVHWAccel ff_mpeg2_d3d11va_hwaccel;
extern const AVHWAccel ff_mpeg2_d3d11va2_hwaccel;
extern const AVHWAccel ff_mpeg2_nvdec_hwaccel;
extern const AVHWAccel ff_mpeg2_dxva2_hwaccel;
+extern const AVHWAccel ff_mpeg2_v4l2request_hwaccel;
extern const AVHWAccel ff_mpeg2_vaapi_hwaccel;
extern const AVHWAccel ff_mpeg2_vdpau_hwaccel;
extern const AVHWAccel ff_mpeg2_videotoolbox_hwaccel;
diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c
index 83e537884b..305127bc94 100644
--- a/libavcodec/mpeg12dec.c
+++ b/libavcodec/mpeg12dec.c
@@ -1156,6 +1156,9 @@ static const enum AVPixelFormat mpeg2_hwaccel_pixfmt_list_420[] = {
#endif
#if CONFIG_MPEG2_VIDEOTOOLBOX_HWACCEL
AV_PIX_FMT_VIDEOTOOLBOX,
+#endif
+#if CONFIG_MPEG2_V4L2REQUEST_HWACCEL
+ AV_PIX_FMT_DRM_PRIME,
#endif
AV_PIX_FMT_YUV420P,
AV_PIX_FMT_NONE
@@ -2941,6 +2944,9 @@ AVCodec ff_mpeg2video_decoder = {
#endif
#if CONFIG_MPEG2_XVMC_HWACCEL
HWACCEL_XVMC(mpeg2),
+#endif
+#if CONFIG_MPEG2_V4L2REQUEST_HWACCEL
+ HWACCEL_V4L2REQUEST(mpeg2),
#endif
NULL
},
diff --git a/libavcodec/v4l2_request_mpeg2.c b/libavcodec/v4l2_request_mpeg2.c
new file mode 100644
index 0000000000..782b9c2471
--- /dev/null
+++ b/libavcodec/v4l2_request_mpeg2.c
@@ -0,0 +1,154 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "hwaccel.h"
+#include "mpegvideo.h"
+#include "v4l2_request.h"
+
+typedef struct V4L2RequestControlsMPEG2 {
+ struct v4l2_ctrl_mpeg2_slice_params slice_params;
+ struct v4l2_ctrl_mpeg2_quantization quantization;
+} V4L2RequestControlsMPEG2;
+
+static int v4l2_request_mpeg2_start_frame(AVCodecContext *avctx,
+ av_unused const uint8_t *buffer,
+ av_unused uint32_t size)
+{
+ const MpegEncContext *s = avctx->priv_data;
+ V4L2RequestControlsMPEG2 *controls = s->current_picture_ptr->hwaccel_picture_private;
+ V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)s->current_picture_ptr->f->data[0];
+
+ controls->slice_params = (struct v4l2_ctrl_mpeg2_slice_params) {
+ .bit_size = 0,
+ .data_bit_offset = 0,
+
+ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Slice */
+ .quantiser_scale_code = s->qscale >> 1,
+
+ .sequence = {
+ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Sequence header */
+ .horizontal_size = s->width,
+ .vertical_size = s->height,
+ .vbv_buffer_size = req->output.size,
+
+ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Sequence extension */
+ .profile_and_level_indication = 0,
+ .progressive_sequence = s->progressive_sequence,
+ .chroma_format = s->chroma_format,
+ },
+
+ .picture = {
+ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Picture header */
+ .picture_coding_type = s->pict_type,
+
+ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Picture coding extension */
+ .f_code[0][0] = s->mpeg_f_code[0][0],
+ .f_code[0][1] = s->mpeg_f_code[0][1],
+ .f_code[1][0] = s->mpeg_f_code[1][0],
+ .f_code[1][1] = s->mpeg_f_code[1][1],
+ .intra_dc_precision = s->intra_dc_precision,
+ .picture_structure = s->picture_structure,
+ .top_field_first = s->top_field_first,
+ .frame_pred_frame_dct = s->frame_pred_frame_dct,
+ .concealment_motion_vectors = s->concealment_motion_vectors,
+ .q_scale_type = s->q_scale_type,
+ .intra_vlc_format = s->intra_vlc_format,
+ .alternate_scan = s->alternate_scan,
+ .repeat_first_field = s->repeat_first_field,
+ .progressive_frame = s->progressive_frame,
+ },
+ };
+
+ switch (s->pict_type) {
+ case AV_PICTURE_TYPE_B:
+ controls->slice_params.backward_ref_ts = ff_v4l2_request_get_capture_timestamp(s->next_picture.f);
+ // fall-through
+ case AV_PICTURE_TYPE_P:
+ controls->slice_params.forward_ref_ts = ff_v4l2_request_get_capture_timestamp(s->last_picture.f);
+ }
+
+ controls->quantization = (struct v4l2_ctrl_mpeg2_quantization) {
+ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Quant matrix extension */
+ .load_intra_quantiser_matrix = 1,
+ .load_non_intra_quantiser_matrix = 1,
+ .load_chroma_intra_quantiser_matrix = 1,
+ .load_chroma_non_intra_quantiser_matrix = 1,
+ };
+
+ for (int i = 0; i < 64; i++) {
+ int n = s->idsp.idct_permutation[ff_zigzag_direct[i]];
+ controls->quantization.intra_quantiser_matrix[i] = s->intra_matrix[n];
+ controls->quantization.non_intra_quantiser_matrix[i] = s->inter_matrix[n];
+ controls->quantization.chroma_intra_quantiser_matrix[i] = s->chroma_intra_matrix[n];
+ controls->quantization.chroma_non_intra_quantiser_matrix[i] = s->chroma_inter_matrix[n];
+ }
+
+ return ff_v4l2_request_reset_frame(avctx, s->current_picture_ptr->f);
+}
+
+static int v4l2_request_mpeg2_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
+{
+ const MpegEncContext *s = avctx->priv_data;
+
+ return ff_v4l2_request_append_output_buffer(avctx, s->current_picture_ptr->f, buffer, size);
+}
+
+static int v4l2_request_mpeg2_end_frame(AVCodecContext *avctx)
+{
+ const MpegEncContext *s = avctx->priv_data;
+ V4L2RequestControlsMPEG2 *controls = s->current_picture_ptr->hwaccel_picture_private;
+ V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)s->current_picture_ptr->f->data[0];
+
+ struct v4l2_ext_control control[] = {
+ {
+ .id = V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS,
+ .ptr = &controls->slice_params,
+ .size = sizeof(controls->slice_params),
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION,
+ .ptr = &controls->quantization,
+ .size = sizeof(controls->quantization),
+ },
+ };
+
+ controls->slice_params.bit_size = req->output.used * 8;
+
+ return ff_v4l2_request_decode_frame(avctx, s->current_picture_ptr->f, control, FF_ARRAY_ELEMS(control));
+}
+
+static int v4l2_request_mpeg2_init(AVCodecContext *avctx)
+{
+ return ff_v4l2_request_init(avctx, V4L2_PIX_FMT_MPEG2_SLICE, 1024 * 1024, NULL, 0);
+}
+
+const AVHWAccel ff_mpeg2_v4l2request_hwaccel = {
+ .name = "mpeg2_v4l2request",
+ .type = AVMEDIA_TYPE_VIDEO,
+ .id = AV_CODEC_ID_MPEG2VIDEO,
+ .pix_fmt = AV_PIX_FMT_DRM_PRIME,
+ .start_frame = v4l2_request_mpeg2_start_frame,
+ .decode_slice = v4l2_request_mpeg2_decode_slice,
+ .end_frame = v4l2_request_mpeg2_end_frame,
+ .frame_priv_data_size = sizeof(V4L2RequestControlsMPEG2),
+ .init = v4l2_request_mpeg2_init,
+ .uninit = ff_v4l2_request_uninit,
+ .priv_data_size = sizeof(V4L2RequestContext),
+ .frame_params = ff_v4l2_request_frame_params,
+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE,
+};

View File

@ -1,547 +0,0 @@
From da483a0eb4802714d9ad3a07ea17c2ec0f65c2a5 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Sat, 15 Dec 2018 22:32:16 +0100
Subject: [PATCH 04/12] Add V4L2 request API h264 hwaccel
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
configure | 3 +
libavcodec/Makefile | 1 +
libavcodec/h264_slice.c | 4 +
libavcodec/h264dec.c | 3 +
libavcodec/hwaccels.h | 1 +
libavcodec/v4l2_request_h264.c | 443 +++++++++++++++++++++++++++++++++
6 files changed, 455 insertions(+)
create mode 100644 libavcodec/v4l2_request_h264.c
diff --git a/configure b/configure
index e88c201cce..576a79ff09 100755
--- a/configure
+++ b/configure
@@ -2895,6 +2895,8 @@ h264_dxva2_hwaccel_deps="dxva2"
h264_dxva2_hwaccel_select="h264_decoder"
h264_nvdec_hwaccel_deps="nvdec"
h264_nvdec_hwaccel_select="h264_decoder"
+h264_v4l2request_hwaccel_deps="v4l2_request h264_v4l2_request"
+h264_v4l2request_hwaccel_select="h264_decoder"
h264_vaapi_hwaccel_deps="vaapi"
h264_vaapi_hwaccel_select="h264_decoder"
h264_vdpau_hwaccel_deps="vdpau"
@@ -6457,6 +6459,7 @@ check_cc vp8_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_VP8;"
check_cc vp9_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_VP9;"
check_func_headers "linux/media.h linux/videodev2.h" v4l2_timeval_to_ns
+check_cc h264_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_H264_SLICE;"
check_cc mpeg2_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_MPEG2_SLICE;"
check_headers sys/videoio.h
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 864f24a2af..58bd444934 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -872,6 +872,7 @@ OBJS-$(CONFIG_H264_D3D11VA_HWACCEL) += dxva2_h264.o
OBJS-$(CONFIG_H264_DXVA2_HWACCEL) += dxva2_h264.o
OBJS-$(CONFIG_H264_NVDEC_HWACCEL) += nvdec_h264.o
OBJS-$(CONFIG_H264_QSV_HWACCEL) += qsvdec_h2645.o
+OBJS-$(CONFIG_H264_V4L2REQUEST_HWACCEL) += v4l2_request_h264.o
OBJS-$(CONFIG_H264_VAAPI_HWACCEL) += vaapi_h264.o
OBJS-$(CONFIG_H264_VDPAU_HWACCEL) += vdpau_h264.o
OBJS-$(CONFIG_H264_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o
diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c
index fc4e65bf01..9912ede703 100644
--- a/libavcodec/h264_slice.c
+++ b/libavcodec/h264_slice.c
@@ -765,6 +765,7 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback)
#define HWACCEL_MAX (CONFIG_H264_DXVA2_HWACCEL + \
(CONFIG_H264_D3D11VA_HWACCEL * 2) + \
CONFIG_H264_NVDEC_HWACCEL + \
+ CONFIG_H264_V4L2REQUEST_HWACCEL + \
CONFIG_H264_VAAPI_HWACCEL + \
CONFIG_H264_VIDEOTOOLBOX_HWACCEL + \
CONFIG_H264_VDPAU_HWACCEL)
@@ -849,6 +850,9 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback)
#endif
#if CONFIG_H264_VIDEOTOOLBOX_HWACCEL
*fmt++ = AV_PIX_FMT_VIDEOTOOLBOX;
+#endif
+#if CONFIG_H264_V4L2REQUEST_HWACCEL
+ *fmt++ = AV_PIX_FMT_DRM_PRIME;
#endif
if (h->avctx->codec->pix_fmts)
choices = h->avctx->codec->pix_fmts;
diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c
index 03c87b59bd..dbcceb915a 100644
--- a/libavcodec/h264dec.c
+++ b/libavcodec/h264dec.c
@@ -1081,6 +1081,9 @@ AVCodec ff_h264_decoder = {
#endif
#if CONFIG_H264_VIDEOTOOLBOX_HWACCEL
HWACCEL_VIDEOTOOLBOX(h264),
+#endif
+#if CONFIG_H264_V4L2REQUEST_HWACCEL
+ HWACCEL_V4L2REQUEST(h264),
#endif
NULL
},
diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h
index ef54de2a3b..003200edea 100644
--- a/libavcodec/hwaccels.h
+++ b/libavcodec/hwaccels.h
@@ -27,6 +27,7 @@ extern const AVHWAccel ff_h264_d3d11va_hwaccel;
extern const AVHWAccel ff_h264_d3d11va2_hwaccel;
extern const AVHWAccel ff_h264_dxva2_hwaccel;
extern const AVHWAccel ff_h264_nvdec_hwaccel;
+extern const AVHWAccel ff_h264_v4l2request_hwaccel;
extern const AVHWAccel ff_h264_vaapi_hwaccel;
extern const AVHWAccel ff_h264_vdpau_hwaccel;
extern const AVHWAccel ff_h264_videotoolbox_hwaccel;
diff --git a/libavcodec/v4l2_request_h264.c b/libavcodec/v4l2_request_h264.c
new file mode 100644
index 0000000000..81b3c4b092
--- /dev/null
+++ b/libavcodec/v4l2_request_h264.c
@@ -0,0 +1,443 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "h264dec.h"
+#include "hwaccel.h"
+#include "v4l2_request.h"
+
+typedef struct V4L2RequestControlsH264 {
+ struct v4l2_ctrl_h264_sps sps;
+ struct v4l2_ctrl_h264_pps pps;
+ struct v4l2_ctrl_h264_scaling_matrix scaling_matrix;
+ struct v4l2_ctrl_h264_decode_params decode_params;
+ struct v4l2_ctrl_h264_slice_params slice_params[16];
+ int first_slice;
+} V4L2RequestControlsH264;
+
+typedef struct V4L2RequestContextH264 {
+ V4L2RequestContext base;
+ int decode_mode;
+ int start_code;
+} V4L2RequestContextH264;
+
+static uint8_t nalu_slice_start_code[] = { 0x00, 0x00, 0x01 };
+
+static void fill_weight_factors(struct v4l2_h264_weight_factors *factors, int list, const H264SliceContext *sl)
+{
+ for (int i = 0; i < sl->ref_count[list]; i++) {
+ if (sl->pwt.luma_weight_flag[list]) {
+ factors->luma_weight[i] = sl->pwt.luma_weight[i][list][0];
+ factors->luma_offset[i] = sl->pwt.luma_weight[i][list][1];
+ } else {
+ factors->luma_weight[i] = 1 << sl->pwt.luma_log2_weight_denom;
+ factors->luma_offset[i] = 0;
+ }
+ for (int j = 0; j < 2; j++) {
+ if (sl->pwt.chroma_weight_flag[list]) {
+ factors->chroma_weight[i][j] = sl->pwt.chroma_weight[i][list][j][0];
+ factors->chroma_offset[i][j] = sl->pwt.chroma_weight[i][list][j][1];
+ } else {
+ factors->chroma_weight[i][j] = 1 << sl->pwt.chroma_log2_weight_denom;
+ factors->chroma_offset[i][j] = 0;
+ }
+ }
+ }
+}
+
+static void fill_dpb_entry(struct v4l2_h264_dpb_entry *entry, const H264Picture *pic)
+{
+ entry->reference_ts = ff_v4l2_request_get_capture_timestamp(pic->f);
+ entry->frame_num = pic->frame_num;
+ entry->pic_num = pic->pic_id;
+ entry->flags = V4L2_H264_DPB_ENTRY_FLAG_VALID;
+ if (pic->reference)
+ entry->flags |= V4L2_H264_DPB_ENTRY_FLAG_ACTIVE;
+ if (pic->long_ref)
+ entry->flags |= V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM;
+ if (pic->field_poc[0] != INT_MAX)
+ entry->top_field_order_cnt = pic->field_poc[0];
+ if (pic->field_poc[1] != INT_MAX)
+ entry->bottom_field_order_cnt = pic->field_poc[1];
+}
+
+static void fill_dpb(struct v4l2_ctrl_h264_decode_params *decode, const H264Context *h)
+{
+ int entries = 0;
+
+ for (int i = 0; i < h->short_ref_count; i++) {
+ const H264Picture *pic = h->short_ref[i];
+ if (pic && (pic->field_poc[0] != INT_MAX || pic->field_poc[1] != INT_MAX))
+ fill_dpb_entry(&decode->dpb[entries++], pic);
+ }
+
+ if (!h->long_ref_count)
+ return;
+
+ for (int i = 0; i < FF_ARRAY_ELEMS(h->long_ref); i++) {
+ const H264Picture *pic = h->long_ref[i];
+ if (pic && (pic->field_poc[0] != INT_MAX || pic->field_poc[1] != INT_MAX))
+ fill_dpb_entry(&decode->dpb[entries++], pic);
+ }
+}
+
+static uint8_t get_dpb_index(struct v4l2_ctrl_h264_decode_params *decode, const H264Ref *ref)
+{
+ uint64_t timestamp;
+
+ if (!ref->parent)
+ return 0;
+
+ timestamp = ff_v4l2_request_get_capture_timestamp(ref->parent->f);
+
+ for (uint8_t i = 0; i < FF_ARRAY_ELEMS(decode->dpb); i++) {
+ struct v4l2_h264_dpb_entry *entry = &decode->dpb[i];
+ if ((entry->flags & V4L2_H264_DPB_ENTRY_FLAG_VALID) &&
+ entry->reference_ts == timestamp)
+ return i;
+ }
+
+ return 0;
+}
+
+static void fill_sps(struct v4l2_ctrl_h264_sps *ctrl, const H264Context *h)
+{
+ const SPS *sps = h->ps.sps;
+
+ *ctrl = (struct v4l2_ctrl_h264_sps) {
+ .profile_idc = sps->profile_idc,
+ .constraint_set_flags = sps->constraint_set_flags,
+ .level_idc = sps->level_idc,
+ .seq_parameter_set_id = sps->sps_id,
+ .chroma_format_idc = sps->chroma_format_idc,
+ .bit_depth_luma_minus8 = sps->bit_depth_luma - 8,
+ .bit_depth_chroma_minus8 = sps->bit_depth_chroma - 8,
+ .log2_max_frame_num_minus4 = sps->log2_max_frame_num - 4,
+ .pic_order_cnt_type = sps->poc_type,
+ .log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_poc_lsb - 4,
+ .max_num_ref_frames = sps->ref_frame_count,
+ .num_ref_frames_in_pic_order_cnt_cycle = sps->poc_cycle_length,
+ //.offset_for_ref_frame[255] - not required? not set by libva-v4l2-request - copy sps->offset_for_ref_frame
+ .offset_for_non_ref_pic = sps->offset_for_non_ref_pic,
+ .offset_for_top_to_bottom_field = sps->offset_for_top_to_bottom_field,
+ .pic_width_in_mbs_minus1 = h->mb_width - 1,
+ .pic_height_in_map_units_minus1 = sps->frame_mbs_only_flag ? h->mb_height - 1 : h->mb_height / 2 - 1,
+ };
+
+ if (sps->residual_color_transform_flag)
+ ctrl->flags |= V4L2_H264_SPS_FLAG_SEPARATE_COLOUR_PLANE;
+ if (sps->transform_bypass)
+ ctrl->flags |= V4L2_H264_SPS_FLAG_QPPRIME_Y_ZERO_TRANSFORM_BYPASS;
+ if (sps->delta_pic_order_always_zero_flag)
+ ctrl->flags |= V4L2_H264_SPS_FLAG_DELTA_PIC_ORDER_ALWAYS_ZERO;
+ if (sps->gaps_in_frame_num_allowed_flag)
+ ctrl->flags |= V4L2_H264_SPS_FLAG_GAPS_IN_FRAME_NUM_VALUE_ALLOWED;
+ if (sps->frame_mbs_only_flag)
+ ctrl->flags |= V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY;
+ if (sps->mb_aff)
+ ctrl->flags |= V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD;
+ if (sps->direct_8x8_inference_flag)
+ ctrl->flags |= V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE;
+}
+
+static void fill_pps(struct v4l2_ctrl_h264_pps *ctrl, const H264Context *h)
+{
+ const PPS *pps = h->ps.pps;
+ const H264SliceContext *sl = &h->slice_ctx[0];
+
+ *ctrl = (struct v4l2_ctrl_h264_pps) {
+ .pic_parameter_set_id = sl->pps_id,
+ .seq_parameter_set_id = pps->sps_id,
+ .num_slice_groups_minus1 = pps->slice_group_count - 1,
+ .num_ref_idx_l0_default_active_minus1 = pps->ref_count[0] - 1,
+ .num_ref_idx_l1_default_active_minus1 = pps->ref_count[1] - 1,
+ .weighted_bipred_idc = pps->weighted_bipred_idc,
+ .pic_init_qp_minus26 = pps->init_qp - 26,
+ .pic_init_qs_minus26 = pps->init_qs - 26,
+ .chroma_qp_index_offset = pps->chroma_qp_index_offset[0],
+ .second_chroma_qp_index_offset = pps->chroma_qp_index_offset[1],
+ };
+
+ if (pps->cabac)
+ ctrl->flags |= V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE;
+ if (pps->pic_order_present)
+ ctrl->flags |= V4L2_H264_PPS_FLAG_BOTTOM_FIELD_PIC_ORDER_IN_FRAME_PRESENT;
+ if (pps->weighted_pred)
+ ctrl->flags |= V4L2_H264_PPS_FLAG_WEIGHTED_PRED;
+ if (pps->deblocking_filter_parameters_present)
+ ctrl->flags |= V4L2_H264_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT;
+ if (pps->constrained_intra_pred)
+ ctrl->flags |= V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED;
+ if (pps->redundant_pic_cnt_present)
+ ctrl->flags |= V4L2_H264_PPS_FLAG_REDUNDANT_PIC_CNT_PRESENT;
+ if (pps->transform_8x8_mode)
+ ctrl->flags |= V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE;
+}
+
+static int v4l2_request_h264_start_frame(AVCodecContext *avctx,
+ av_unused const uint8_t *buffer,
+ av_unused uint32_t size)
+{
+ const H264Context *h = avctx->priv_data;
+ const PPS *pps = h->ps.pps;
+ const SPS *sps = h->ps.sps;
+ V4L2RequestControlsH264 *controls = h->cur_pic_ptr->hwaccel_picture_private;
+
+ fill_sps(&controls->sps, h);
+ fill_pps(&controls->pps, h);
+
+ memcpy(controls->scaling_matrix.scaling_list_4x4, pps->scaling_matrix4, sizeof(controls->scaling_matrix.scaling_list_4x4));
+ memcpy(controls->scaling_matrix.scaling_list_8x8[0], pps->scaling_matrix8[0], sizeof(controls->scaling_matrix.scaling_list_8x8[0]));
+ memcpy(controls->scaling_matrix.scaling_list_8x8[1], pps->scaling_matrix8[3], sizeof(controls->scaling_matrix.scaling_list_8x8[1]));
+
+ if (sps->chroma_format_idc == 3) {
+ memcpy(controls->scaling_matrix.scaling_list_8x8[2], pps->scaling_matrix8[1], sizeof(controls->scaling_matrix.scaling_list_8x8[2]));
+ memcpy(controls->scaling_matrix.scaling_list_8x8[3], pps->scaling_matrix8[4], sizeof(controls->scaling_matrix.scaling_list_8x8[3]));
+ memcpy(controls->scaling_matrix.scaling_list_8x8[4], pps->scaling_matrix8[2], sizeof(controls->scaling_matrix.scaling_list_8x8[4]));
+ memcpy(controls->scaling_matrix.scaling_list_8x8[5], pps->scaling_matrix8[5], sizeof(controls->scaling_matrix.scaling_list_8x8[5]));
+ }
+
+ controls->decode_params = (struct v4l2_ctrl_h264_decode_params) {
+ .num_slices = 0,
+ .nal_ref_idc = h->nal_ref_idc,
+ .top_field_order_cnt = h->cur_pic_ptr->field_poc[0] != INT_MAX ? h->cur_pic_ptr->field_poc[0] : 0,
+ .bottom_field_order_cnt = h->cur_pic_ptr->field_poc[1] != INT_MAX ? h->cur_pic_ptr->field_poc[1] : 0,
+ };
+
+ if (h->picture_idr)
+ controls->decode_params.flags |= V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC;
+
+ fill_dpb(&controls->decode_params, h);
+
+ controls->first_slice = !FIELD_PICTURE(h) || h->first_field;
+
+ return ff_v4l2_request_reset_frame(avctx, h->cur_pic_ptr->f);
+}
+
+static int v4l2_request_h264_queue_decode(AVCodecContext *avctx, int last_slice)
+{
+ const H264Context *h = avctx->priv_data;
+ V4L2RequestControlsH264 *controls = h->cur_pic_ptr->hwaccel_picture_private;
+ V4L2RequestContextH264 *ctx = avctx->internal->hwaccel_priv_data;
+
+ struct v4l2_ext_control control[] = {
+ {
+ .id = V4L2_CID_MPEG_VIDEO_H264_SPS,
+ .ptr = &controls->sps,
+ .size = sizeof(controls->sps),
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_H264_PPS,
+ .ptr = &controls->pps,
+ .size = sizeof(controls->pps),
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX,
+ .ptr = &controls->scaling_matrix,
+ .size = sizeof(controls->scaling_matrix),
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS,
+ .ptr = &controls->slice_params,
+ .size = sizeof(controls->slice_params[0]) * FFMIN(controls->decode_params.num_slices, 16),
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS,
+ .ptr = &controls->decode_params,
+ .size = sizeof(controls->decode_params),
+ },
+ };
+
+ if (ctx->decode_mode == V4L2_MPEG_VIDEO_H264_DECODE_MODE_SLICE_BASED)
+ return ff_v4l2_request_decode_slice(avctx, h->cur_pic_ptr->f, control, FF_ARRAY_ELEMS(control), controls->first_slice, last_slice);
+
+ return ff_v4l2_request_decode_frame(avctx, h->cur_pic_ptr->f, control, FF_ARRAY_ELEMS(control));
+}
+
+static int v4l2_request_h264_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
+{
+ const H264Context *h = avctx->priv_data;
+ const PPS *pps = h->ps.pps;
+ const H264SliceContext *sl = &h->slice_ctx[0];
+ V4L2RequestControlsH264 *controls = h->cur_pic_ptr->hwaccel_picture_private;
+ V4L2RequestContextH264 *ctx = avctx->internal->hwaccel_priv_data;
+ V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)h->cur_pic_ptr->f->data[0];
+ int i, ret, count, slice = FFMIN(controls->decode_params.num_slices, 15);
+
+ if (ctx->decode_mode == V4L2_MPEG_VIDEO_H264_DECODE_MODE_SLICE_BASED && slice) {
+ ret = v4l2_request_h264_queue_decode(avctx, 0);
+ if (ret)
+ return ret;
+
+ ff_v4l2_request_reset_frame(avctx, h->cur_pic_ptr->f);
+ slice = controls->decode_params.num_slices = 0;
+ controls->first_slice = 0;
+ }
+
+ controls->slice_params[slice] = (struct v4l2_ctrl_h264_slice_params) {
+ /* Size in bytes, including header */
+ .size = 0,
+ .start_byte_offset = req->output.used,
+ /* Offset in bits to slice_data() from the beginning of this slice. */
+ .header_bit_size = get_bits_count(&sl->gb),
+
+ .first_mb_in_slice = sl->first_mb_addr,
+ .slice_type = ff_h264_get_slice_type(sl),
+ .pic_parameter_set_id = sl->pps_id,
+ .colour_plane_id = 0, /* what is this? */
+ .frame_num = h->poc.frame_num,
+ .idr_pic_id = 0, /* what is this? */
+ .pic_order_cnt_lsb = sl->poc_lsb,
+ .delta_pic_order_cnt_bottom = sl->delta_poc_bottom,
+ .delta_pic_order_cnt0 = sl->delta_poc[0],
+ .delta_pic_order_cnt1 = sl->delta_poc[1],
+ .redundant_pic_cnt = sl->redundant_pic_count,
+
+ /* Size in bits of dec_ref_pic_marking() syntax element. */
+ .dec_ref_pic_marking_bit_size = 0,
+ /* Size in bits of pic order count syntax. */
+ .pic_order_cnt_bit_size = 0,
+
+ .cabac_init_idc = sl->cabac_init_idc,
+ .slice_qp_delta = sl->qscale - pps->init_qp,
+ .slice_qs_delta = 0, /* XXX not implemented by FFmpeg */
+ .disable_deblocking_filter_idc = sl->deblocking_filter < 2 ? !sl->deblocking_filter : sl->deblocking_filter,
+ .slice_alpha_c0_offset_div2 = sl->slice_alpha_c0_offset / 2,
+ .slice_beta_offset_div2 = sl->slice_beta_offset / 2,
+ .slice_group_change_cycle = 0, /* what is this? */
+
+ .num_ref_idx_l0_active_minus1 = sl->list_count > 0 ? sl->ref_count[0] - 1 : 0,
+ .num_ref_idx_l1_active_minus1 = sl->list_count > 1 ? sl->ref_count[1] - 1 : 0,
+ };
+
+ if (FIELD_PICTURE(h))
+ controls->slice_params[slice].flags |= V4L2_H264_SLICE_FLAG_FIELD_PIC;
+ if (h->picture_structure == PICT_BOTTOM_FIELD)
+ controls->slice_params[slice].flags |= V4L2_H264_SLICE_FLAG_BOTTOM_FIELD;
+ if (sl->slice_type == AV_PICTURE_TYPE_B && sl->direct_spatial_mv_pred)
+ controls->slice_params[slice].flags |= V4L2_H264_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED;
+
+ controls->slice_params[slice].pred_weight_table.chroma_log2_weight_denom = sl->pwt.chroma_log2_weight_denom;
+ controls->slice_params[slice].pred_weight_table.luma_log2_weight_denom = sl->pwt.luma_log2_weight_denom;
+
+ count = sl->list_count > 0 ? sl->ref_count[0] : 0;
+ for (i = 0; i < count; i++)
+ controls->slice_params[slice].ref_pic_list0[i] = get_dpb_index(&controls->decode_params, &sl->ref_list[0][i]);
+ if (count)
+ fill_weight_factors(&controls->slice_params[slice].pred_weight_table.weight_factors[0], 0, sl);
+
+ count = sl->list_count > 1 ? sl->ref_count[1] : 0;
+ for (i = 0; i < count; i++)
+ controls->slice_params[slice].ref_pic_list1[i] = get_dpb_index(&controls->decode_params, &sl->ref_list[1][i]);
+ if (count)
+ fill_weight_factors(&controls->slice_params[slice].pred_weight_table.weight_factors[1], 1, sl);
+
+ if (ctx->start_code == V4L2_MPEG_VIDEO_H264_START_CODE_ANNEX_B) {
+ ret = ff_v4l2_request_append_output_buffer(avctx, h->cur_pic_ptr->f, nalu_slice_start_code, 3);
+ if (ret)
+ return ret;
+ }
+
+ ret = ff_v4l2_request_append_output_buffer(avctx, h->cur_pic_ptr->f, buffer, size);
+ if (ret)
+ return ret;
+
+ controls->slice_params[slice].size = req->output.used - controls->slice_params[slice].start_byte_offset;
+ controls->decode_params.num_slices++;
+ return 0;
+}
+
+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);
+}
+
+static int v4l2_request_h264_set_controls(AVCodecContext *avctx)
+{
+ V4L2RequestContextH264 *ctx = avctx->internal->hwaccel_priv_data;
+
+ struct v4l2_ext_control control[] = {
+ { .id = V4L2_CID_MPEG_VIDEO_H264_DECODE_MODE, },
+ { .id = V4L2_CID_MPEG_VIDEO_H264_START_CODE, },
+ };
+
+ ctx->decode_mode = ff_v4l2_request_query_control_default_value(avctx, V4L2_CID_MPEG_VIDEO_H264_DECODE_MODE);
+ if (ctx->decode_mode != V4L2_MPEG_VIDEO_H264_DECODE_MODE_SLICE_BASED &&
+ ctx->decode_mode != V4L2_MPEG_VIDEO_H264_DECODE_MODE_FRAME_BASED) {
+ av_log(avctx, AV_LOG_ERROR, "%s: unsupported decode mode, %d\n", __func__, ctx->decode_mode);
+ return AVERROR(EINVAL);
+ }
+
+ ctx->start_code = ff_v4l2_request_query_control_default_value(avctx, V4L2_CID_MPEG_VIDEO_H264_START_CODE);
+ if (ctx->start_code != V4L2_MPEG_VIDEO_H264_START_CODE_NONE &&
+ ctx->start_code != V4L2_MPEG_VIDEO_H264_START_CODE_ANNEX_B) {
+ av_log(avctx, AV_LOG_ERROR, "%s: unsupported start code, %d\n", __func__, ctx->start_code);
+ return AVERROR(EINVAL);
+ }
+
+ control[0].value = ctx->decode_mode;
+ control[1].value = ctx->start_code;
+
+ return ff_v4l2_request_set_controls(avctx, control, FF_ARRAY_ELEMS(control));
+}
+
+static int v4l2_request_h264_init(AVCodecContext *avctx)
+{
+ const H264Context *h = avctx->priv_data;
+ struct v4l2_ctrl_h264_sps sps;
+ struct v4l2_ctrl_h264_pps pps;
+ int ret;
+
+ struct v4l2_ext_control control[] = {
+ {
+ .id = V4L2_CID_MPEG_VIDEO_H264_SPS,
+ .ptr = &sps,
+ .size = sizeof(sps),
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_H264_PPS,
+ .ptr = &pps,
+ .size = sizeof(pps),
+ },
+ };
+
+ fill_sps(&sps, h);
+ fill_pps(&pps, h);
+
+ ret = ff_v4l2_request_init(avctx, V4L2_PIX_FMT_H264_SLICE, 2 * 1024 * 1024, control, FF_ARRAY_ELEMS(control));
+ if (ret)
+ return ret;
+
+ return v4l2_request_h264_set_controls(avctx);
+}
+
+const AVHWAccel ff_h264_v4l2request_hwaccel = {
+ .name = "h264_v4l2request",
+ .type = AVMEDIA_TYPE_VIDEO,
+ .id = AV_CODEC_ID_H264,
+ .pix_fmt = AV_PIX_FMT_DRM_PRIME,
+ .start_frame = v4l2_request_h264_start_frame,
+ .decode_slice = v4l2_request_h264_decode_slice,
+ .end_frame = v4l2_request_h264_end_frame,
+ .frame_priv_data_size = sizeof(V4L2RequestControlsH264),
+ .init = v4l2_request_h264_init,
+ .uninit = ff_v4l2_request_uninit,
+ .priv_data_size = sizeof(V4L2RequestContextH264),
+ .frame_params = ff_v4l2_request_frame_params,
+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE,
+};

View File

@ -1,636 +0,0 @@
From 521d06aec85d55a28e946a222f591747a1d3f2f5 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Sat, 15 Dec 2018 22:32:16 +0100
Subject: [PATCH 05/12] Add V4L2 request API hevc hwaccel
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
configure | 3 +
libavcodec/Makefile | 1 +
libavcodec/hevcdec.c | 10 +
libavcodec/hwaccels.h | 1 +
libavcodec/v4l2_request_hevc.c | 527 +++++++++++++++++++++++++++++++++
5 files changed, 542 insertions(+)
create mode 100644 libavcodec/v4l2_request_hevc.c
diff --git a/configure b/configure
index 576a79ff09..d51ee62a70 100755
--- a/configure
+++ b/configure
@@ -2911,6 +2911,8 @@ hevc_dxva2_hwaccel_deps="dxva2 DXVA_PicParams_HEVC"
hevc_dxva2_hwaccel_select="hevc_decoder"
hevc_nvdec_hwaccel_deps="nvdec"
hevc_nvdec_hwaccel_select="hevc_decoder"
+hevc_v4l2request_hwaccel_deps="v4l2_request hevc_v4l2_request"
+hevc_v4l2request_hwaccel_select="hevc_decoder"
hevc_vaapi_hwaccel_deps="vaapi VAPictureParameterBufferHEVC"
hevc_vaapi_hwaccel_select="hevc_decoder"
hevc_vdpau_hwaccel_deps="vdpau VdpPictureInfoHEVC"
@@ -6460,6 +6462,7 @@ check_cc vp9_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_VP9;"
check_func_headers "linux/media.h linux/videodev2.h" v4l2_timeval_to_ns
check_cc h264_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_H264_SLICE;"
+check_cc hevc_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_HEVC_SLICE;"
check_cc mpeg2_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_MPEG2_SLICE;"
check_headers sys/videoio.h
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 58bd444934..2b53d2b650 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -880,6 +880,7 @@ OBJS-$(CONFIG_HEVC_D3D11VA_HWACCEL) += dxva2_hevc.o
OBJS-$(CONFIG_HEVC_DXVA2_HWACCEL) += dxva2_hevc.o
OBJS-$(CONFIG_HEVC_NVDEC_HWACCEL) += nvdec_hevc.o
OBJS-$(CONFIG_HEVC_QSV_HWACCEL) += qsvdec_h2645.o
+OBJS-$(CONFIG_HEVC_V4L2REQUEST_HWACCEL) += v4l2_request_hevc.o
OBJS-$(CONFIG_HEVC_VAAPI_HWACCEL) += vaapi_hevc.o
OBJS-$(CONFIG_HEVC_VDPAU_HWACCEL) += vdpau_hevc.o
OBJS-$(CONFIG_MJPEG_NVDEC_HWACCEL) += nvdec_mjpeg.o
diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c
index 8f1c162ace..4c9c92bfc2 100644
--- a/libavcodec/hevcdec.c
+++ b/libavcodec/hevcdec.c
@@ -373,6 +373,7 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps)
#define HWACCEL_MAX (CONFIG_HEVC_DXVA2_HWACCEL + \
CONFIG_HEVC_D3D11VA_HWACCEL * 2 + \
CONFIG_HEVC_NVDEC_HWACCEL + \
+ CONFIG_HEVC_V4L2REQUEST_HWACCEL + \
CONFIG_HEVC_VAAPI_HWACCEL + \
CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL + \
CONFIG_HEVC_VDPAU_HWACCEL)
@@ -399,6 +400,9 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps)
#endif
#if CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL
*fmt++ = AV_PIX_FMT_VIDEOTOOLBOX;
+#endif
+#if CONFIG_HEVC_V4L2REQUEST_HWACCEL
+ *fmt++ = AV_PIX_FMT_DRM_PRIME;
#endif
break;
case AV_PIX_FMT_YUV420P10:
@@ -417,6 +421,9 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps)
#endif
#if CONFIG_HEVC_NVDEC_HWACCEL
*fmt++ = AV_PIX_FMT_CUDA;
+#endif
+#if CONFIG_HEVC_V4L2REQUEST_HWACCEL
+ *fmt++ = AV_PIX_FMT_DRM_PRIME;
#endif
break;
case AV_PIX_FMT_YUV444P:
@@ -3592,6 +3599,9 @@ AVCodec ff_hevc_decoder = {
#endif
#if CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL
HWACCEL_VIDEOTOOLBOX(hevc),
+#endif
+#if CONFIG_HEVC_V4L2REQUEST_HWACCEL
+ HWACCEL_V4L2REQUEST(hevc),
#endif
NULL
},
diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h
index 003200edea..d183675abe 100644
--- a/libavcodec/hwaccels.h
+++ b/libavcodec/hwaccels.h
@@ -35,6 +35,7 @@ extern const AVHWAccel ff_hevc_d3d11va_hwaccel;
extern const AVHWAccel ff_hevc_d3d11va2_hwaccel;
extern const AVHWAccel ff_hevc_dxva2_hwaccel;
extern const AVHWAccel ff_hevc_nvdec_hwaccel;
+extern const AVHWAccel ff_hevc_v4l2request_hwaccel;
extern const AVHWAccel ff_hevc_vaapi_hwaccel;
extern const AVHWAccel ff_hevc_vdpau_hwaccel;
extern const AVHWAccel ff_hevc_videotoolbox_hwaccel;
diff --git a/libavcodec/v4l2_request_hevc.c b/libavcodec/v4l2_request_hevc.c
new file mode 100644
index 0000000000..da1fd666d7
--- /dev/null
+++ b/libavcodec/v4l2_request_hevc.c
@@ -0,0 +1,527 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "hevcdec.h"
+#include "hwaccel.h"
+#include "v4l2_request.h"
+
+typedef struct V4L2RequestControlsHEVC {
+ struct v4l2_ctrl_hevc_sps sps;
+ struct v4l2_ctrl_hevc_pps pps;
+ struct v4l2_ctrl_hevc_scaling_matrix scaling_matrix;
+ struct v4l2_ctrl_hevc_slice_params slice_params[16];
+ int first_slice;
+ int num_slices; //TODO: this should be in control
+} V4L2RequestControlsHEVC;
+
+typedef struct V4L2RequestContextHEVC {
+ V4L2RequestContext base;
+ int decode_mode;
+ int start_code;
+} V4L2RequestContextHEVC;
+
+static void v4l2_request_hevc_fill_pred_table(const HEVCContext *h, struct v4l2_hevc_pred_weight_table *table)
+{
+ int32_t luma_weight_denom, chroma_weight_denom;
+ const SliceHeader *sh = &h->sh;
+
+ if (sh->slice_type == HEVC_SLICE_I ||
+ (sh->slice_type == HEVC_SLICE_P && !h->ps.pps->weighted_pred_flag) ||
+ (sh->slice_type == HEVC_SLICE_B && !h->ps.pps->weighted_bipred_flag))
+ return;
+
+ table->luma_log2_weight_denom = sh->luma_log2_weight_denom;
+
+ if (h->ps.sps->chroma_format_idc)
+ table->delta_chroma_log2_weight_denom = sh->chroma_log2_weight_denom - sh->luma_log2_weight_denom;
+
+ luma_weight_denom = (1 << sh->luma_log2_weight_denom);
+ chroma_weight_denom = (1 << sh->chroma_log2_weight_denom);
+
+ for (int i = 0; i < 15 && i < sh->nb_refs[L0]; i++) {
+ table->delta_luma_weight_l0[i] = sh->luma_weight_l0[i] - luma_weight_denom;
+ table->luma_offset_l0[i] = sh->luma_offset_l0[i];
+ table->delta_chroma_weight_l0[i][0] = sh->chroma_weight_l0[i][0] - chroma_weight_denom;
+ table->delta_chroma_weight_l0[i][1] = sh->chroma_weight_l0[i][1] - chroma_weight_denom;
+ table->chroma_offset_l0[i][0] = sh->chroma_offset_l0[i][0];
+ table->chroma_offset_l0[i][1] = sh->chroma_offset_l0[i][1];
+ }
+
+ if (sh->slice_type != HEVC_SLICE_B)
+ return;
+
+ for (int i = 0; i < 15 && i < sh->nb_refs[L1]; i++) {
+ table->delta_luma_weight_l1[i] = sh->luma_weight_l1[i] - luma_weight_denom;
+ table->luma_offset_l1[i] = sh->luma_offset_l1[i];
+ table->delta_chroma_weight_l1[i][0] = sh->chroma_weight_l1[i][0] - chroma_weight_denom;
+ table->delta_chroma_weight_l1[i][1] = sh->chroma_weight_l1[i][1] - chroma_weight_denom;
+ table->chroma_offset_l1[i][0] = sh->chroma_offset_l1[i][0];
+ table->chroma_offset_l1[i][1] = sh->chroma_offset_l1[i][1];
+ }
+}
+
+static int find_frame_rps_type(const HEVCContext *h, uint64_t timestamp)
+{
+ const HEVCFrame *frame;
+ int i;
+
+ for (i = 0; i < h->rps[ST_CURR_BEF].nb_refs; i++) {
+ frame = h->rps[ST_CURR_BEF].ref[i];
+ if (frame && timestamp == ff_v4l2_request_get_capture_timestamp(frame->frame))
+ return V4L2_HEVC_DPB_ENTRY_RPS_ST_CURR_BEFORE;
+ }
+
+ for (i = 0; i < h->rps[ST_CURR_AFT].nb_refs; i++) {
+ frame = h->rps[ST_CURR_AFT].ref[i];
+ if (frame && timestamp == ff_v4l2_request_get_capture_timestamp(frame->frame))
+ return V4L2_HEVC_DPB_ENTRY_RPS_ST_CURR_AFTER;
+ }
+
+ for (i = 0; i < h->rps[LT_CURR].nb_refs; i++) {
+ frame = h->rps[LT_CURR].ref[i];
+ if (frame && timestamp == ff_v4l2_request_get_capture_timestamp(frame->frame))
+ return V4L2_HEVC_DPB_ENTRY_RPS_LT_CURR;
+ }
+
+ return 0;
+}
+
+static uint8_t get_ref_pic_index(const HEVCContext *h, const HEVCFrame *frame,
+ struct v4l2_ctrl_hevc_slice_params *slice_params)
+{
+ uint64_t timestamp;
+
+ if (!frame)
+ return 0;
+
+ timestamp = ff_v4l2_request_get_capture_timestamp(frame->frame);
+
+ for (uint8_t i = 0; i < slice_params->num_active_dpb_entries; i++) {
+ struct v4l2_hevc_dpb_entry *entry = &slice_params->dpb[i];
+ if (entry->timestamp == timestamp)
+ return i;
+ }
+
+ return 0;
+}
+
+static void v4l2_request_hevc_fill_slice_params(const HEVCContext *h,
+ struct v4l2_ctrl_hevc_slice_params *slice_params)
+{
+ const HEVCFrame *pic = h->ref;
+ const SliceHeader *sh = &h->sh;
+ int i, entries = 0;
+ RefPicList *rpl;
+
+ *slice_params = (struct v4l2_ctrl_hevc_slice_params) {
+ .bit_size = 0,
+ .data_bit_offset = get_bits_count(&h->HEVClc->gb),
+
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */
+ .slice_segment_addr = sh->slice_segment_addr,
+
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: NAL unit header */
+ .nal_unit_type = h->nal_unit_type,
+ .nuh_temporal_id_plus1 = h->temporal_id + 1,
+
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */
+ .slice_type = sh->slice_type,
+ .colour_plane_id = sh->colour_plane_id,
+ .slice_pic_order_cnt = pic->poc,
+ .num_ref_idx_l0_active_minus1 = sh->nb_refs[L0] ? sh->nb_refs[L0] - 1 : 0,
+ .num_ref_idx_l1_active_minus1 = sh->nb_refs[L1] ? sh->nb_refs[L1] - 1 : 0,
+ .collocated_ref_idx = sh->slice_temporal_mvp_enabled_flag ? sh->collocated_ref_idx : 0,
+ .five_minus_max_num_merge_cand = sh->slice_type == HEVC_SLICE_I ? 0 : 5 - sh->max_num_merge_cand,
+ .slice_qp_delta = sh->slice_qp_delta,
+ .slice_cb_qp_offset = sh->slice_cb_qp_offset,
+ .slice_cr_qp_offset = sh->slice_cr_qp_offset,
+ .slice_act_y_qp_offset = 0,
+ .slice_act_cb_qp_offset = 0,
+ .slice_act_cr_qp_offset = 0,
+ .slice_beta_offset_div2 = sh->beta_offset / 2,
+ .slice_tc_offset_div2 = sh->tc_offset / 2,
+
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture timing SEI message */
+ .pic_struct = h->sei.picture_timing.picture_struct,
+
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */
+ .num_rps_poc_st_curr_before = h->rps[ST_CURR_BEF].nb_refs,
+ .num_rps_poc_st_curr_after = h->rps[ST_CURR_AFT].nb_refs,
+ .num_rps_poc_lt_curr = h->rps[LT_CURR].nb_refs,
+ };
+
+ if (sh->slice_sample_adaptive_offset_flag[0])
+ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_LUMA;
+
+ if (sh->slice_sample_adaptive_offset_flag[1])
+ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_CHROMA;
+
+ if (sh->slice_temporal_mvp_enabled_flag)
+ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_TEMPORAL_MVP_ENABLED;
+
+ if (sh->mvd_l1_zero_flag)
+ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_MVD_L1_ZERO;
+
+ if (sh->cabac_init_flag)
+ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_CABAC_INIT;
+
+ if (sh->collocated_list == L0)
+ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_COLLOCATED_FROM_L0;
+
+ if (sh->disable_deblocking_filter_flag)
+ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_DEBLOCKING_FILTER_DISABLED;
+
+ if (sh->slice_loop_filter_across_slices_enabled_flag)
+ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED;
+
+ for (i = 0; i < FF_ARRAY_ELEMS(h->DPB); i++) {
+ const HEVCFrame *frame = &h->DPB[i];
+ if (frame != pic && (frame->flags & (HEVC_FRAME_FLAG_LONG_REF | HEVC_FRAME_FLAG_SHORT_REF))) {
+ struct v4l2_hevc_dpb_entry *entry = &slice_params->dpb[entries++];
+
+ entry->timestamp = ff_v4l2_request_get_capture_timestamp(frame->frame);
+ entry->rps = find_frame_rps_type(h, entry->timestamp);
+ entry->field_pic = frame->frame->interlaced_frame;
+
+ /* TODO: Interleaved: Get the POC for each field. */
+ entry->pic_order_cnt[0] = frame->poc;
+ entry->pic_order_cnt[1] = frame->poc;
+ }
+ }
+
+ slice_params->num_active_dpb_entries = entries;
+
+ if (sh->slice_type != HEVC_SLICE_I) {
+ rpl = &h->ref->refPicList[0];
+ for (i = 0; i < rpl->nb_refs; i++)
+ slice_params->ref_idx_l0[i] = get_ref_pic_index(h, rpl->ref[i], slice_params);
+ }
+
+ if (sh->slice_type == HEVC_SLICE_B) {
+ rpl = &h->ref->refPicList[1];
+ for (i = 0; i < rpl->nb_refs; i++)
+ slice_params->ref_idx_l1[i] = get_ref_pic_index(h, rpl->ref[i], slice_params);
+ }
+
+ v4l2_request_hevc_fill_pred_table(h, &slice_params->pred_weight_table);
+
+ slice_params->num_entry_point_offsets = sh->num_entry_point_offsets;
+ if (slice_params->num_entry_point_offsets > 256) {
+ slice_params->num_entry_point_offsets = 256;
+ av_log(NULL, AV_LOG_ERROR, "%s: Currently only 256 entry points are supported, but slice has %d entry points.\n", __func__, sh->num_entry_point_offsets);
+ }
+
+ for (i = 0; i < slice_params->num_entry_point_offsets; i++)
+ slice_params->entry_point_offset_minus1[i] = sh->entry_point_offset[i] - 1;
+}
+
+static int v4l2_request_hevc_start_frame(AVCodecContext *avctx,
+ av_unused const uint8_t *buffer,
+ av_unused uint32_t size)
+{
+ const HEVCContext *h = avctx->priv_data;
+ const HEVCSPS *sps = h->ps.sps;
+ const HEVCPPS *pps = h->ps.pps;
+ const ScalingList *sl = pps->scaling_list_data_present_flag ?
+ &pps->scaling_list :
+ sps->scaling_list_enable_flag ?
+ &sps->scaling_list : NULL;
+ V4L2RequestControlsHEVC *controls = h->ref->hwaccel_picture_private;
+
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Sequence parameter set */
+ controls->sps = (struct v4l2_ctrl_hevc_sps) {
+ .chroma_format_idc = sps->chroma_format_idc,
+ .pic_width_in_luma_samples = sps->width,
+ .pic_height_in_luma_samples = sps->height,
+ .bit_depth_luma_minus8 = sps->bit_depth - 8,
+ .bit_depth_chroma_minus8 = sps->bit_depth - 8,
+ .log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_poc_lsb - 4,
+ .sps_max_dec_pic_buffering_minus1 = sps->temporal_layer[sps->max_sub_layers - 1].max_dec_pic_buffering - 1,
+ .sps_max_num_reorder_pics = sps->temporal_layer[sps->max_sub_layers - 1].num_reorder_pics,
+ .sps_max_latency_increase_plus1 = sps->temporal_layer[sps->max_sub_layers - 1].max_latency_increase + 1,
+ .log2_min_luma_coding_block_size_minus3 = sps->log2_min_cb_size - 3,
+ .log2_diff_max_min_luma_coding_block_size = sps->log2_diff_max_min_coding_block_size,
+ .log2_min_luma_transform_block_size_minus2 = sps->log2_min_tb_size - 2,
+ .log2_diff_max_min_luma_transform_block_size = sps->log2_max_trafo_size - sps->log2_min_tb_size,
+ .max_transform_hierarchy_depth_inter = sps->max_transform_hierarchy_depth_inter,
+ .max_transform_hierarchy_depth_intra = sps->max_transform_hierarchy_depth_intra,
+ .pcm_sample_bit_depth_luma_minus1 = sps->pcm.bit_depth - 1,
+ .pcm_sample_bit_depth_chroma_minus1 = sps->pcm.bit_depth_chroma - 1,
+ .log2_min_pcm_luma_coding_block_size_minus3 = sps->pcm.log2_min_pcm_cb_size - 3,
+ .log2_diff_max_min_pcm_luma_coding_block_size = sps->pcm.log2_max_pcm_cb_size - sps->pcm.log2_min_pcm_cb_size,
+ .num_short_term_ref_pic_sets = sps->nb_st_rps,
+ .num_long_term_ref_pics_sps = sps->num_long_term_ref_pics_sps,
+ };
+
+ if (sps->separate_colour_plane_flag)
+ controls->sps.flags |= V4L2_HEVC_SPS_FLAG_SEPARATE_COLOUR_PLANE;
+
+ if (sps->scaling_list_enable_flag)
+ controls->sps.flags |= V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED;
+
+ if (sps->amp_enabled_flag)
+ controls->sps.flags |= V4L2_HEVC_SPS_FLAG_AMP_ENABLED;
+
+ if (sps->sao_enabled)
+ controls->sps.flags |= V4L2_HEVC_SPS_FLAG_SAMPLE_ADAPTIVE_OFFSET;
+
+ if (sps->pcm_enabled_flag)
+ controls->sps.flags |= V4L2_HEVC_SPS_FLAG_PCM_ENABLED;
+
+ if (sps->pcm.loop_filter_disable_flag)
+ controls->sps.flags |= V4L2_HEVC_SPS_FLAG_PCM_LOOP_FILTER_DISABLED;
+
+ if (sps->long_term_ref_pics_present_flag)
+ controls->sps.flags |= V4L2_HEVC_SPS_FLAG_LONG_TERM_REF_PICS_PRESENT;
+
+ if (sps->sps_temporal_mvp_enabled_flag)
+ controls->sps.flags |= V4L2_HEVC_SPS_FLAG_SPS_TEMPORAL_MVP_ENABLED;
+
+ if (sps->sps_strong_intra_smoothing_enable_flag)
+ controls->sps.flags |= V4L2_HEVC_SPS_FLAG_STRONG_INTRA_SMOOTHING_ENABLED;
+
+ if (sl) {
+ for (int i = 0; i < 6; i++) {
+ for (int j = 0; j < 16; j++)
+ controls->scaling_matrix.scaling_list_4x4[i][j] = sl->sl[0][i][j];
+ for (int j = 0; j < 64; j++) {
+ controls->scaling_matrix.scaling_list_8x8[i][j] = sl->sl[1][i][j];
+ controls->scaling_matrix.scaling_list_16x16[i][j] = sl->sl[2][i][j];
+ if (i < 2)
+ controls->scaling_matrix.scaling_list_32x32[i][j] = sl->sl[3][i * 3][j];
+ }
+ controls->scaling_matrix.scaling_list_dc_coef_16x16[i] = sl->sl_dc[0][i];
+ if (i < 2)
+ controls->scaling_matrix.scaling_list_dc_coef_32x32[i] = sl->sl_dc[1][i * 3];
+ }
+ }
+
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture parameter set */
+ controls->pps = (struct v4l2_ctrl_hevc_pps) {
+ .num_extra_slice_header_bits = pps->num_extra_slice_header_bits,
+ .init_qp_minus26 = pps->pic_init_qp_minus26,
+ .diff_cu_qp_delta_depth = pps->diff_cu_qp_delta_depth,
+ .pps_cb_qp_offset = pps->cb_qp_offset,
+ .pps_cr_qp_offset = pps->cr_qp_offset,
+ .pps_beta_offset_div2 = pps->beta_offset / 2,
+ .pps_tc_offset_div2 = pps->tc_offset / 2,
+ .log2_parallel_merge_level_minus2 = pps->log2_parallel_merge_level - 2,
+ };
+
+ if (pps->dependent_slice_segments_enabled_flag)
+ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT;
+
+ if (pps->output_flag_present_flag)
+ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_OUTPUT_FLAG_PRESENT;
+
+ if (pps->sign_data_hiding_flag)
+ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_SIGN_DATA_HIDING_ENABLED;
+
+ if (pps->cabac_init_present_flag)
+ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_CABAC_INIT_PRESENT;
+
+ if (pps->constrained_intra_pred_flag)
+ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_CONSTRAINED_INTRA_PRED;
+
+ if (pps->transform_skip_enabled_flag)
+ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_TRANSFORM_SKIP_ENABLED;
+
+ if (pps->cu_qp_delta_enabled_flag)
+ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_CU_QP_DELTA_ENABLED;
+
+ if (pps->pic_slice_level_chroma_qp_offsets_present_flag)
+ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT;
+
+ if (pps->weighted_pred_flag)
+ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_WEIGHTED_PRED;
+
+ if (pps->weighted_bipred_flag)
+ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED;
+
+ if (pps->transquant_bypass_enable_flag)
+ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_TRANSQUANT_BYPASS_ENABLED;
+
+ if (pps->tiles_enabled_flag)
+ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_TILES_ENABLED;
+
+ if (pps->entropy_coding_sync_enabled_flag)
+ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED;
+
+ if (pps->loop_filter_across_tiles_enabled_flag)
+ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED;
+
+ if (pps->seq_loop_filter_across_slices_enabled_flag)
+ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED;
+
+ if (pps->deblocking_filter_override_enabled_flag)
+ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_OVERRIDE_ENABLED;
+
+ if (pps->disable_dbf)
+ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_PPS_DISABLE_DEBLOCKING_FILTER;
+
+ if (pps->lists_modification_present_flag)
+ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_LISTS_MODIFICATION_PRESENT;
+
+ if (pps->slice_header_extension_present_flag)
+ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_SLICE_SEGMENT_HEADER_EXTENSION_PRESENT;
+
+ if (pps->tiles_enabled_flag) {
+ controls->pps.num_tile_columns_minus1 = pps->num_tile_columns - 1;
+ controls->pps.num_tile_rows_minus1 = pps->num_tile_rows - 1;
+
+ av_log(avctx, AV_LOG_DEBUG, "%s: avctx=%p tiles_enabled_flag=%d num_tile_columns=%d num_tile_rows=%d\n",
+ __func__, avctx, pps->tiles_enabled_flag, pps->num_tile_columns, pps->num_tile_rows);
+
+ for (int i = 0; i < pps->num_tile_columns; i++)
+ controls->pps.column_width_minus1[i] = pps->column_width[i] - 1;
+
+ for (int i = 0; i < pps->num_tile_rows; i++)
+ controls->pps.row_height_minus1[i] = pps->row_height[i] - 1;
+ }
+
+ controls->first_slice = 1;
+ controls->num_slices = 0;
+
+ return ff_v4l2_request_reset_frame(avctx, h->ref->frame);
+}
+
+static int v4l2_request_hevc_queue_decode(AVCodecContext *avctx, int last_slice)
+{
+ const HEVCContext *h = avctx->priv_data;
+ V4L2RequestControlsHEVC *controls = h->ref->hwaccel_picture_private;
+ V4L2RequestContextHEVC *ctx = avctx->internal->hwaccel_priv_data;
+
+ struct v4l2_ext_control control[] = {
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_SPS,
+ .ptr = &controls->sps,
+ .size = sizeof(controls->sps),
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_PPS,
+ .ptr = &controls->pps,
+ .size = sizeof(controls->pps),
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX,
+ .ptr = &controls->scaling_matrix,
+ .size = sizeof(controls->scaling_matrix),
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS,
+ .ptr = &controls->slice_params,
+ .size = sizeof(controls->slice_params[0]) * FFMIN(controls->num_slices, 16),
+ },
+ };
+
+ if (ctx->decode_mode == V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED)
+ return ff_v4l2_request_decode_slice(avctx, h->ref->frame, control, FF_ARRAY_ELEMS(control), controls->first_slice, last_slice);
+
+ return ff_v4l2_request_decode_frame(avctx, h->ref->frame, control, FF_ARRAY_ELEMS(control));
+}
+
+static int v4l2_request_hevc_end_frame(AVCodecContext *avctx)
+{
+ return v4l2_request_hevc_queue_decode(avctx, 1);
+}
+
+static int v4l2_request_hevc_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
+{
+ const HEVCContext *h = avctx->priv_data;
+ V4L2RequestControlsHEVC *controls = h->ref->hwaccel_picture_private;
+ V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)h->ref->frame->data[0];
+ V4L2RequestContextHEVC *ctx = avctx->internal->hwaccel_priv_data;
+ int ret, slice = FFMIN(controls->num_slices, 15);
+
+ if (ctx->decode_mode == V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED && slice) {
+ ret = v4l2_request_hevc_queue_decode(avctx, 0);
+ if (ret)
+ return ret;
+
+ ff_v4l2_request_reset_frame(avctx, h->ref->frame);
+ slice = controls->num_slices = 0;
+ controls->first_slice = 0;
+ }
+
+ v4l2_request_hevc_fill_slice_params(h, &controls->slice_params[slice]);
+
+ ret = ff_v4l2_request_append_output_buffer(avctx, h->ref->frame, buffer, size);
+ if (ret)
+ return ret;
+
+ controls->slice_params[slice].bit_size = req->output.used * 8; //FIXME
+ controls->num_slices++;
+
+ return 0;
+}
+
+static int v4l2_request_hevc_set_controls(AVCodecContext *avctx)
+{
+ V4L2RequestContextHEVC *ctx = avctx->internal->hwaccel_priv_data;
+
+ struct v4l2_ext_control control[] = {
+ { .id = V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE, },
+ { .id = V4L2_CID_MPEG_VIDEO_HEVC_START_CODE, },
+ };
+
+ ctx->decode_mode = ff_v4l2_request_query_control_default_value(avctx, V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE);
+ if (ctx->decode_mode != V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED &&
+ ctx->decode_mode != V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_FRAME_BASED) {
+ av_log(avctx, AV_LOG_ERROR, "%s: unsupported decode mode, %d\n", __func__, ctx->decode_mode);
+ return AVERROR(EINVAL);
+ }
+
+ ctx->start_code = ff_v4l2_request_query_control_default_value(avctx, V4L2_CID_MPEG_VIDEO_HEVC_START_CODE);
+ if (ctx->start_code != V4L2_MPEG_VIDEO_HEVC_START_CODE_NONE &&
+ ctx->start_code != V4L2_MPEG_VIDEO_HEVC_START_CODE_ANNEX_B) {
+ av_log(avctx, AV_LOG_ERROR, "%s: unsupported start code, %d\n", __func__, ctx->start_code);
+ return AVERROR(EINVAL);
+ }
+
+ control[0].value = ctx->decode_mode;
+ control[1].value = ctx->start_code;
+
+ return ff_v4l2_request_set_controls(avctx, control, FF_ARRAY_ELEMS(control));
+}
+
+static int v4l2_request_hevc_init(AVCodecContext *avctx)
+{
+ int ret;
+
+ ret = ff_v4l2_request_init(avctx, V4L2_PIX_FMT_HEVC_SLICE, 3 * 1024 * 1024, NULL, 0);
+ if (ret)
+ return ret;
+
+ return v4l2_request_hevc_set_controls(avctx);
+}
+
+const AVHWAccel ff_hevc_v4l2request_hwaccel = {
+ .name = "hevc_v4l2request",
+ .type = AVMEDIA_TYPE_VIDEO,
+ .id = AV_CODEC_ID_HEVC,
+ .pix_fmt = AV_PIX_FMT_DRM_PRIME,
+ .start_frame = v4l2_request_hevc_start_frame,
+ .decode_slice = v4l2_request_hevc_decode_slice,
+ .end_frame = v4l2_request_hevc_end_frame,
+ .frame_priv_data_size = sizeof(V4L2RequestControlsHEVC),
+ .init = v4l2_request_hevc_init,
+ .uninit = ff_v4l2_request_uninit,
+ .priv_data_size = sizeof(V4L2RequestContextHEVC),
+ .frame_params = ff_v4l2_request_frame_params,
+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE,
+};

View File

@ -1,282 +0,0 @@
From 1084cad0a91e33a95150ff82f1d4ce2a0c180e2c Mon Sep 17 00:00:00 2001
From: Boris Brezillon <boris.brezillon@collabora.com>
Date: Wed, 22 May 2019 14:46:58 +0200
Subject: [PATCH 06/12] Add V4L2 request API vp8 hwaccel
Need to fix the STREAMOFF/STREAMON issue in a proper way.
Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
---
configure | 3 +
libavcodec/Makefile | 1 +
libavcodec/hwaccels.h | 1 +
libavcodec/v4l2_request_vp8.c | 180 ++++++++++++++++++++++++++++++++++
libavcodec/vp8.c | 8 +-
5 files changed, 192 insertions(+), 1 deletion(-)
create mode 100644 libavcodec/v4l2_request_vp8.c
diff --git a/configure b/configure
index d51ee62a70..6bdfe6fd95 100755
--- a/configure
+++ b/configure
@@ -2975,6 +2975,8 @@ vp8_nvdec_hwaccel_deps="nvdec"
vp8_nvdec_hwaccel_select="vp8_decoder"
vp8_vaapi_hwaccel_deps="vaapi"
vp8_vaapi_hwaccel_select="vp8_decoder"
+vp8_v4l2request_hwaccel_deps="v4l2_request vp8_v4l2_request"
+vp8_v4l2request_hwaccel_select="vp8_decoder"
vp9_d3d11va_hwaccel_deps="d3d11va DXVA_PicParams_VP9"
vp9_d3d11va_hwaccel_select="vp9_decoder"
vp9_d3d11va2_hwaccel_deps="d3d11va DXVA_PicParams_VP9"
@@ -6464,6 +6466,7 @@ check_func_headers "linux/media.h linux/videodev2.h" v4l2_timeval_to_ns
check_cc h264_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_H264_SLICE;"
check_cc hevc_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_HEVC_SLICE;"
check_cc mpeg2_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_MPEG2_SLICE;"
+check_cc vp8_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_VP8_FRAME;"
check_headers sys/videoio.h
test_code cc sys/videoio.h "struct v4l2_frmsizeenum vfse; vfse.discrete.width = 0;" && enable_sanitized struct_v4l2_frmivalenum_discrete
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 2b53d2b650..55fa28548b 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -910,6 +910,7 @@ OBJS-$(CONFIG_VC1_VAAPI_HWACCEL) += vaapi_vc1.o
OBJS-$(CONFIG_VC1_VDPAU_HWACCEL) += vdpau_vc1.o
OBJS-$(CONFIG_VP8_NVDEC_HWACCEL) += nvdec_vp8.o
OBJS-$(CONFIG_VP8_VAAPI_HWACCEL) += vaapi_vp8.o
+OBJS-$(CONFIG_VP8_V4L2REQUEST_HWACCEL) += v4l2_request_vp8.o
OBJS-$(CONFIG_VP9_D3D11VA_HWACCEL) += dxva2_vp9.o
OBJS-$(CONFIG_VP9_DXVA2_HWACCEL) += dxva2_vp9.o
OBJS-$(CONFIG_VP9_NVDEC_HWACCEL) += nvdec_vp9.o
diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h
index d183675abe..0fca5be557 100644
--- a/libavcodec/hwaccels.h
+++ b/libavcodec/hwaccels.h
@@ -66,6 +66,7 @@ extern const AVHWAccel ff_vc1_vaapi_hwaccel;
extern const AVHWAccel ff_vc1_vdpau_hwaccel;
extern const AVHWAccel ff_vp8_nvdec_hwaccel;
extern const AVHWAccel ff_vp8_vaapi_hwaccel;
+extern const AVHWAccel ff_vp8_v4l2request_hwaccel;
extern const AVHWAccel ff_vp9_d3d11va_hwaccel;
extern const AVHWAccel ff_vp9_d3d11va2_hwaccel;
extern const AVHWAccel ff_vp9_dxva2_hwaccel;
diff --git a/libavcodec/v4l2_request_vp8.c b/libavcodec/v4l2_request_vp8.c
new file mode 100644
index 0000000000..d24252c5e5
--- /dev/null
+++ b/libavcodec/v4l2_request_vp8.c
@@ -0,0 +1,180 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "hwaccel.h"
+#include "v4l2_request.h"
+#include "vp8.h"
+
+typedef struct V4L2RequestControlsVP8 {
+ struct v4l2_ctrl_vp8_frame_header ctrl;
+} V4L2RequestControlsVP8;
+
+static int v4l2_request_vp8_start_frame(AVCodecContext *avctx,
+ av_unused const uint8_t *buffer,
+ av_unused uint32_t size)
+{
+ const VP8Context *s = avctx->priv_data;
+ V4L2RequestControlsVP8 *controls = s->framep[VP56_FRAME_CURRENT]->hwaccel_picture_private;
+
+ memset(&controls->ctrl, 0, sizeof(controls->ctrl));
+ return ff_v4l2_request_reset_frame(avctx, s->framep[VP56_FRAME_CURRENT]->tf.f);
+}
+
+static int v4l2_request_vp8_end_frame(AVCodecContext *avctx)
+{
+ const VP8Context *s = avctx->priv_data;
+ V4L2RequestControlsVP8 *controls = s->framep[VP56_FRAME_CURRENT]->hwaccel_picture_private;
+ struct v4l2_ext_control control[] = {
+ {
+ .id = V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER,
+ .ptr = &controls->ctrl,
+ .size = sizeof(controls->ctrl),
+ },
+ };
+
+ return ff_v4l2_request_decode_frame(avctx, s->framep[VP56_FRAME_CURRENT]->tf.f,
+ control, FF_ARRAY_ELEMS(control));
+}
+
+static int v4l2_request_vp8_decode_slice(AVCodecContext *avctx,
+ const uint8_t *buffer,
+ uint32_t size)
+{
+ const VP8Context *s = avctx->priv_data;
+ V4L2RequestControlsVP8 *controls = s->framep[VP56_FRAME_CURRENT]->hwaccel_picture_private;
+ struct v4l2_ctrl_vp8_frame_header *hdr = &controls->ctrl;
+ const uint8_t *data = buffer + 3 + 7 * s->keyframe;
+ unsigned int i, j, k;
+
+ hdr->version = s->profile & 0x3;
+ hdr->width = avctx->width;
+ hdr->height = avctx->height;
+ /* FIXME: set ->xx_scale */
+ hdr->prob_skip_false = s->prob->mbskip;
+ hdr->prob_intra = s->prob->intra;
+ hdr->prob_gf = s->prob->golden;
+ hdr->prob_last = s->prob->last;
+ hdr->first_part_size = s->header_partition_size;
+ hdr->first_part_header_bits = (8 * (s->coder_state_at_header_end.input - data) -
+ s->coder_state_at_header_end.bit_count - 8);
+ hdr->num_dct_parts = s->num_coeff_partitions;
+ for (i = 0; i < 8; i++)
+ hdr->dct_part_sizes[i] = s->coeff_partition_size[i];
+
+ hdr->coder_state.range = s->coder_state_at_header_end.range;
+ hdr->coder_state.value = s->coder_state_at_header_end.value;
+ hdr->coder_state.bit_count = s->coder_state_at_header_end.bit_count;
+ if (s->framep[VP56_FRAME_PREVIOUS])
+ hdr->last_frame_ts = ff_v4l2_request_get_capture_timestamp(s->framep[VP56_FRAME_PREVIOUS]->tf.f);
+ if (s->framep[VP56_FRAME_GOLDEN])
+ hdr->golden_frame_ts = ff_v4l2_request_get_capture_timestamp(s->framep[VP56_FRAME_GOLDEN]->tf.f);
+ if (s->framep[VP56_FRAME_GOLDEN2])
+ hdr->alt_frame_ts = ff_v4l2_request_get_capture_timestamp(s->framep[VP56_FRAME_GOLDEN2]->tf.f);
+ hdr->flags |= s->invisible ? 0 : V4L2_VP8_FRAME_HEADER_FLAG_SHOW_FRAME;
+ hdr->flags |= s->mbskip_enabled ? V4L2_VP8_FRAME_HEADER_FLAG_MB_NO_SKIP_COEFF : 0;
+ hdr->flags |= (s->profile & 0x4) ? V4L2_VP8_FRAME_HEADER_FLAG_EXPERIMENTAL : 0;
+ hdr->flags |= s->keyframe ? V4L2_VP8_FRAME_HEADER_FLAG_KEY_FRAME : 0;
+ hdr->flags |= s->sign_bias[VP56_FRAME_GOLDEN] ? V4L2_VP8_FRAME_HEADER_FLAG_SIGN_BIAS_GOLDEN : 0;
+ hdr->flags |= s->sign_bias[VP56_FRAME_GOLDEN2] ? V4L2_VP8_FRAME_HEADER_FLAG_SIGN_BIAS_ALT : 0;
+ hdr->segment_header.flags |= s->segmentation.enabled ? V4L2_VP8_SEGMENT_HEADER_FLAG_ENABLED : 0;
+ hdr->segment_header.flags |= s->segmentation.update_map ? V4L2_VP8_SEGMENT_HEADER_FLAG_UPDATE_MAP : 0;
+ hdr->segment_header.flags |= s->segmentation.update_feature_data ? V4L2_VP8_SEGMENT_HEADER_FLAG_UPDATE_FEATURE_DATA : 0;
+ hdr->segment_header.flags |= s->segmentation.absolute_vals ? 0 : V4L2_VP8_SEGMENT_HEADER_FLAG_DELTA_VALUE_MODE;
+ for (i = 0; i < 4; i++) {
+ hdr->segment_header.quant_update[i] = s->segmentation.base_quant[i];
+ hdr->segment_header.lf_update[i] = s->segmentation.filter_level[i];
+ }
+
+ for (i = 0; i < 3; i++)
+ hdr->segment_header.segment_probs[i] = s->prob->segmentid[i];
+
+ hdr->lf_header.level = s->filter.level;
+ hdr->lf_header.sharpness_level = s->filter.sharpness;
+ hdr->lf_header.flags |= s->lf_delta.enabled ? V4L2_VP8_LF_HEADER_ADJ_ENABLE : 0;
+ hdr->lf_header.flags |= s->lf_delta.update ? V4L2_VP8_LF_HEADER_DELTA_UPDATE : 0;
+ hdr->lf_header.flags |= s->filter.simple ? V4L2_VP8_LF_FILTER_TYPE_SIMPLE : 0;
+ for (i = 0; i < 4; i++) {
+ hdr->lf_header.ref_frm_delta[i] = s->lf_delta.ref[i];
+ hdr->lf_header.mb_mode_delta[i] = s->lf_delta.mode[i + MODE_I4x4];
+ }
+
+ // Probabilites
+ if (s->keyframe) {
+ static const uint8_t keyframe_y_mode_probs[4] = {
+ 145, 156, 163, 128
+ };
+ static const uint8_t keyframe_uv_mode_probs[3] = {
+ 142, 114, 183
+ };
+
+ memcpy(hdr->entropy_header.y_mode_probs, keyframe_y_mode_probs, 4);
+ memcpy(hdr->entropy_header.uv_mode_probs, keyframe_uv_mode_probs, 3);
+ } else {
+ for (i = 0; i < 4; i++)
+ hdr->entropy_header.y_mode_probs[i] = s->prob->pred16x16[i];
+ for (i = 0; i < 3; i++)
+ hdr->entropy_header.uv_mode_probs[i] = s->prob->pred8x8c[i];
+ }
+ for (i = 0; i < 2; i++)
+ for (j = 0; j < 19; j++)
+ hdr->entropy_header.mv_probs[i][j] = s->prob->mvc[i][j];
+
+ for (i = 0; i < 4; i++) {
+ for (j = 0; j < 8; j++) {
+ static const int coeff_bands_inverse[8] = {
+ 0, 1, 2, 3, 5, 6, 4, 15
+ };
+ int coeff_pos = coeff_bands_inverse[j];
+
+ for (k = 0; k < 3; k++) {
+ memcpy(hdr->entropy_header.coeff_probs[i][j][k],
+ s->prob->token[i][coeff_pos][k], 11);
+ }
+ }
+ }
+
+ hdr->quant_header.y_ac_qi = s->quant.yac_qi;
+ hdr->quant_header.y_dc_delta = s->quant.ydc_delta;
+ hdr->quant_header.y2_dc_delta = s->quant.y2dc_delta;
+ hdr->quant_header.y2_ac_delta = s->quant.y2ac_delta;
+ hdr->quant_header.uv_dc_delta = s->quant.uvdc_delta;
+ hdr->quant_header.uv_ac_delta = s->quant.uvac_delta;
+
+ return ff_v4l2_request_append_output_buffer(avctx, s->framep[VP56_FRAME_CURRENT]->tf.f, buffer, size);
+}
+
+static int v4l2_request_vp8_init(AVCodecContext *avctx)
+{
+ return ff_v4l2_request_init(avctx, V4L2_PIX_FMT_VP8_FRAME, 1024 * 1024, NULL, 0);
+}
+
+const AVHWAccel ff_vp8_v4l2request_hwaccel = {
+ .name = "vp8_v4l2request",
+ .type = AVMEDIA_TYPE_VIDEO,
+ .id = AV_CODEC_ID_VP8,
+ .pix_fmt = AV_PIX_FMT_DRM_PRIME,
+ .start_frame = v4l2_request_vp8_start_frame,
+ .decode_slice = v4l2_request_vp8_decode_slice,
+ .end_frame = v4l2_request_vp8_end_frame,
+ .frame_priv_data_size = sizeof(V4L2RequestControlsVP8),
+ .init = v4l2_request_vp8_init,
+ .uninit = ff_v4l2_request_uninit,
+ .priv_data_size = sizeof(V4L2RequestContext),
+ .frame_params = ff_v4l2_request_frame_params,
+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE,
+};
diff --git a/libavcodec/vp8.c b/libavcodec/vp8.c
index 3ddc349a4d..d4289320a9 100644
--- a/libavcodec/vp8.c
+++ b/libavcodec/vp8.c
@@ -175,6 +175,9 @@ static enum AVPixelFormat get_pixel_format(VP8Context *s)
#endif
#if CONFIG_VP8_NVDEC_HWACCEL
AV_PIX_FMT_CUDA,
+#endif
+#if CONFIG_VP8_V4L2REQUEST_HWACCEL
+ AV_PIX_FMT_DRM_PRIME,
#endif
AV_PIX_FMT_YUV420P,
AV_PIX_FMT_NONE,
@@ -198,7 +201,7 @@ int update_dimensions(VP8Context *s, int width, int height, int is_vp7)
return ret;
}
- if (!s->actually_webp && !is_vp7) {
+ if (!s->actually_webp && !is_vp7 && s->pix_fmt == AV_PIX_FMT_NONE) {
s->pix_fmt = get_pixel_format(s);
if (s->pix_fmt < 0)
return AVERROR(EINVAL);
@@ -2981,6 +2984,9 @@ AVCodec ff_vp8_decoder = {
#endif
#if CONFIG_VP8_NVDEC_HWACCEL
HWACCEL_NVDEC(vp8),
+#endif
+#if CONFIG_VP8_V4L2REQUEST_HWACCEL
+ HWACCEL_V4L2REQUEST(vp8),
#endif
NULL
},

View File

@ -1,759 +0,0 @@
From e19fbf3c8c161a24e039b93dee2281d5b22e2ca8 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Thu, 14 Feb 2019 23:20:05 +0100
Subject: [PATCH 07/12] Add and use private linux headers for V4L2 request API
ctrls
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
configure | 6 +-
libavcodec/h264-ctrls.h | 210 +++++++++++++++++++++++++++++
libavcodec/hevc-ctrls.h | 229 ++++++++++++++++++++++++++++++++
libavcodec/mpeg2-ctrls.h | 82 ++++++++++++
libavcodec/v4l2_request_h264.c | 1 +
libavcodec/v4l2_request_hevc.c | 1 +
libavcodec/v4l2_request_mpeg2.c | 1 +
libavcodec/v4l2_request_vp8.c | 1 +
libavcodec/vp8-ctrls.h | 112 ++++++++++++++++
9 files changed, 640 insertions(+), 3 deletions(-)
create mode 100644 libavcodec/h264-ctrls.h
create mode 100644 libavcodec/hevc-ctrls.h
create mode 100644 libavcodec/mpeg2-ctrls.h
create mode 100644 libavcodec/vp8-ctrls.h
diff --git a/configure b/configure
index 6bdfe6fd95..e3a3d82395 100755
--- a/configure
+++ b/configure
@@ -2895,7 +2895,7 @@ h264_dxva2_hwaccel_deps="dxva2"
h264_dxva2_hwaccel_select="h264_decoder"
h264_nvdec_hwaccel_deps="nvdec"
h264_nvdec_hwaccel_select="h264_decoder"
-h264_v4l2request_hwaccel_deps="v4l2_request h264_v4l2_request"
+h264_v4l2request_hwaccel_deps="v4l2_request"
h264_v4l2request_hwaccel_select="h264_decoder"
h264_vaapi_hwaccel_deps="vaapi"
h264_vaapi_hwaccel_select="h264_decoder"
@@ -2911,7 +2911,7 @@ hevc_dxva2_hwaccel_deps="dxva2 DXVA_PicParams_HEVC"
hevc_dxva2_hwaccel_select="hevc_decoder"
hevc_nvdec_hwaccel_deps="nvdec"
hevc_nvdec_hwaccel_select="hevc_decoder"
-hevc_v4l2request_hwaccel_deps="v4l2_request hevc_v4l2_request"
+hevc_v4l2request_hwaccel_deps="v4l2_request"
hevc_v4l2request_hwaccel_select="hevc_decoder"
hevc_vaapi_hwaccel_deps="vaapi VAPictureParameterBufferHEVC"
hevc_vaapi_hwaccel_select="hevc_decoder"
@@ -2975,7 +2975,7 @@ vp8_nvdec_hwaccel_deps="nvdec"
vp8_nvdec_hwaccel_select="vp8_decoder"
vp8_vaapi_hwaccel_deps="vaapi"
vp8_vaapi_hwaccel_select="vp8_decoder"
-vp8_v4l2request_hwaccel_deps="v4l2_request vp8_v4l2_request"
+vp8_v4l2request_hwaccel_deps="v4l2_request"
vp8_v4l2request_hwaccel_select="vp8_decoder"
vp9_d3d11va_hwaccel_deps="d3d11va DXVA_PicParams_VP9"
vp9_d3d11va_hwaccel_select="vp9_decoder"
diff --git a/libavcodec/h264-ctrls.h b/libavcodec/h264-ctrls.h
new file mode 100644
index 0000000000..e877bf1d53
--- /dev/null
+++ b/libavcodec/h264-ctrls.h
@@ -0,0 +1,210 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * These are the H.264 state controls for use with stateless H.264
+ * codec drivers.
+ *
+ * It turns out that these structs are not stable yet and will undergo
+ * more changes. So keep them private until they are stable and ready to
+ * become part of the official public API.
+ */
+
+#ifndef _H264_CTRLS_H_
+#define _H264_CTRLS_H_
+
+#include <linux/videodev2.h>
+
+/* Our pixel format isn't stable at the moment */
+#define V4L2_PIX_FMT_H264_SLICE v4l2_fourcc('S', '2', '6', '4') /* H264 parsed slices */
+
+/*
+ * This is put insanely high to avoid conflicting with controls that
+ * would be added during the phase where those controls are not
+ * stable. It should be fixed eventually.
+ */
+#define V4L2_CID_MPEG_VIDEO_H264_SPS (V4L2_CID_MPEG_BASE+1000)
+#define V4L2_CID_MPEG_VIDEO_H264_PPS (V4L2_CID_MPEG_BASE+1001)
+#define V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX (V4L2_CID_MPEG_BASE+1002)
+#define V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS (V4L2_CID_MPEG_BASE+1003)
+#define V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS (V4L2_CID_MPEG_BASE+1004)
+#define V4L2_CID_MPEG_VIDEO_H264_DECODE_MODE (V4L2_CID_MPEG_BASE+1005)
+#define V4L2_CID_MPEG_VIDEO_H264_START_CODE (V4L2_CID_MPEG_BASE+1006)
+
+/* enum v4l2_ctrl_type type values */
+#define V4L2_CTRL_TYPE_H264_SPS 0x0110
+#define V4L2_CTRL_TYPE_H264_PPS 0x0111
+#define V4L2_CTRL_TYPE_H264_SCALING_MATRIX 0x0112
+#define V4L2_CTRL_TYPE_H264_SLICE_PARAMS 0x0113
+#define V4L2_CTRL_TYPE_H264_DECODE_PARAMS 0x0114
+
+enum v4l2_mpeg_video_h264_decode_mode {
+ V4L2_MPEG_VIDEO_H264_DECODE_MODE_SLICE_BASED,
+ V4L2_MPEG_VIDEO_H264_DECODE_MODE_FRAME_BASED,
+};
+
+enum v4l2_mpeg_video_h264_start_code {
+ V4L2_MPEG_VIDEO_H264_START_CODE_NONE,
+ V4L2_MPEG_VIDEO_H264_START_CODE_ANNEX_B,
+};
+
+#define V4L2_H264_SPS_CONSTRAINT_SET0_FLAG 0x01
+#define V4L2_H264_SPS_CONSTRAINT_SET1_FLAG 0x02
+#define V4L2_H264_SPS_CONSTRAINT_SET2_FLAG 0x04
+#define V4L2_H264_SPS_CONSTRAINT_SET3_FLAG 0x08
+#define V4L2_H264_SPS_CONSTRAINT_SET4_FLAG 0x10
+#define V4L2_H264_SPS_CONSTRAINT_SET5_FLAG 0x20
+
+#define V4L2_H264_SPS_FLAG_SEPARATE_COLOUR_PLANE 0x01
+#define V4L2_H264_SPS_FLAG_QPPRIME_Y_ZERO_TRANSFORM_BYPASS 0x02
+#define V4L2_H264_SPS_FLAG_DELTA_PIC_ORDER_ALWAYS_ZERO 0x04
+#define V4L2_H264_SPS_FLAG_GAPS_IN_FRAME_NUM_VALUE_ALLOWED 0x08
+#define V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY 0x10
+#define V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD 0x20
+#define V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE 0x40
+
+struct v4l2_ctrl_h264_sps {
+ __u8 profile_idc;
+ __u8 constraint_set_flags;
+ __u8 level_idc;
+ __u8 seq_parameter_set_id;
+ __u8 chroma_format_idc;
+ __u8 bit_depth_luma_minus8;
+ __u8 bit_depth_chroma_minus8;
+ __u8 log2_max_frame_num_minus4;
+ __u8 pic_order_cnt_type;
+ __u8 log2_max_pic_order_cnt_lsb_minus4;
+ __u8 max_num_ref_frames;
+ __u8 num_ref_frames_in_pic_order_cnt_cycle;
+ __s32 offset_for_ref_frame[255];
+ __s32 offset_for_non_ref_pic;
+ __s32 offset_for_top_to_bottom_field;
+ __u16 pic_width_in_mbs_minus1;
+ __u16 pic_height_in_map_units_minus1;
+ __u32 flags;
+};
+
+#define V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE 0x0001
+#define V4L2_H264_PPS_FLAG_BOTTOM_FIELD_PIC_ORDER_IN_FRAME_PRESENT 0x0002
+#define V4L2_H264_PPS_FLAG_WEIGHTED_PRED 0x0004
+#define V4L2_H264_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT 0x0008
+#define V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED 0x0010
+#define V4L2_H264_PPS_FLAG_REDUNDANT_PIC_CNT_PRESENT 0x0020
+#define V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE 0x0040
+#define V4L2_H264_PPS_FLAG_PIC_SCALING_MATRIX_PRESENT 0x0080
+
+struct v4l2_ctrl_h264_pps {
+ __u8 pic_parameter_set_id;
+ __u8 seq_parameter_set_id;
+ __u8 num_slice_groups_minus1;
+ __u8 num_ref_idx_l0_default_active_minus1;
+ __u8 num_ref_idx_l1_default_active_minus1;
+ __u8 weighted_bipred_idc;
+ __s8 pic_init_qp_minus26;
+ __s8 pic_init_qs_minus26;
+ __s8 chroma_qp_index_offset;
+ __s8 second_chroma_qp_index_offset;
+ __u16 flags;
+};
+
+struct v4l2_ctrl_h264_scaling_matrix {
+ __u8 scaling_list_4x4[6][16];
+ __u8 scaling_list_8x8[6][64];
+};
+
+struct v4l2_h264_weight_factors {
+ __s16 luma_weight[32];
+ __s16 luma_offset[32];
+ __s16 chroma_weight[32][2];
+ __s16 chroma_offset[32][2];
+};
+
+struct v4l2_h264_pred_weight_table {
+ __u16 luma_log2_weight_denom;
+ __u16 chroma_log2_weight_denom;
+ struct v4l2_h264_weight_factors weight_factors[2];
+};
+
+#define V4L2_H264_SLICE_TYPE_P 0
+#define V4L2_H264_SLICE_TYPE_B 1
+#define V4L2_H264_SLICE_TYPE_I 2
+#define V4L2_H264_SLICE_TYPE_SP 3
+#define V4L2_H264_SLICE_TYPE_SI 4
+
+#define V4L2_H264_SLICE_FLAG_FIELD_PIC 0x01
+#define V4L2_H264_SLICE_FLAG_BOTTOM_FIELD 0x02
+#define V4L2_H264_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED 0x04
+#define V4L2_H264_SLICE_FLAG_SP_FOR_SWITCH 0x08
+
+struct v4l2_ctrl_h264_slice_params {
+ /* Size in bytes, including header */
+ __u32 size;
+
+ /* Offset in bytes to the start of slice in the OUTPUT buffer. */
+ __u32 start_byte_offset;
+
+ /* Offset in bits to slice_data() from the beginning of this slice. */
+ __u32 header_bit_size;
+
+ __u16 first_mb_in_slice;
+ __u8 slice_type;
+ __u8 pic_parameter_set_id;
+ __u8 colour_plane_id;
+ __u8 redundant_pic_cnt;
+ __u16 frame_num;
+ __u16 idr_pic_id;
+ __u16 pic_order_cnt_lsb;
+ __s32 delta_pic_order_cnt_bottom;
+ __s32 delta_pic_order_cnt0;
+ __s32 delta_pic_order_cnt1;
+
+ struct v4l2_h264_pred_weight_table pred_weight_table;
+ /* Size in bits of dec_ref_pic_marking() syntax element. */
+ __u32 dec_ref_pic_marking_bit_size;
+ /* Size in bits of pic order count syntax. */
+ __u32 pic_order_cnt_bit_size;
+
+ __u8 cabac_init_idc;
+ __s8 slice_qp_delta;
+ __s8 slice_qs_delta;
+ __u8 disable_deblocking_filter_idc;
+ __s8 slice_alpha_c0_offset_div2;
+ __s8 slice_beta_offset_div2;
+ __u8 num_ref_idx_l0_active_minus1;
+ __u8 num_ref_idx_l1_active_minus1;
+ __u32 slice_group_change_cycle;
+
+ /*
+ * Entries on each list are indices into
+ * v4l2_ctrl_h264_decode_params.dpb[].
+ */
+ __u8 ref_pic_list0[32];
+ __u8 ref_pic_list1[32];
+
+ __u32 flags;
+};
+
+#define V4L2_H264_DPB_ENTRY_FLAG_VALID 0x01
+#define V4L2_H264_DPB_ENTRY_FLAG_ACTIVE 0x02
+#define V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM 0x04
+
+struct v4l2_h264_dpb_entry {
+ __u64 reference_ts;
+ __u16 frame_num;
+ __u16 pic_num;
+ /* Note that field is indicated by v4l2_buffer.field */
+ __s32 top_field_order_cnt;
+ __s32 bottom_field_order_cnt;
+ __u32 flags; /* V4L2_H264_DPB_ENTRY_FLAG_* */
+};
+
+#define V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC 0x01
+
+struct v4l2_ctrl_h264_decode_params {
+ struct v4l2_h264_dpb_entry dpb[16];
+ __u16 num_slices;
+ __u16 nal_ref_idc;
+ __s32 top_field_order_cnt;
+ __s32 bottom_field_order_cnt;
+ __u32 flags; /* V4L2_H264_DECODE_PARAM_FLAG_* */
+};
+
+#endif
diff --git a/libavcodec/hevc-ctrls.h b/libavcodec/hevc-ctrls.h
new file mode 100644
index 0000000000..d1b094c8aa
--- /dev/null
+++ b/libavcodec/hevc-ctrls.h
@@ -0,0 +1,229 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * These are the HEVC state controls for use with stateless HEVC
+ * codec drivers.
+ *
+ * It turns out that these structs are not stable yet and will undergo
+ * more changes. So keep them private until they are stable and ready to
+ * become part of the official public API.
+ */
+
+#ifndef _HEVC_CTRLS_H_
+#define _HEVC_CTRLS_H_
+
+#include <linux/videodev2.h>
+
+/* The pixel format isn't stable at the moment and will likely be renamed. */
+#define V4L2_PIX_FMT_HEVC_SLICE v4l2_fourcc('S', '2', '6', '5') /* HEVC parsed slices */
+
+#define V4L2_CID_MPEG_VIDEO_HEVC_SPS (V4L2_CID_MPEG_BASE + 1008)
+#define V4L2_CID_MPEG_VIDEO_HEVC_PPS (V4L2_CID_MPEG_BASE + 1009)
+#define V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS (V4L2_CID_MPEG_BASE + 1010)
+#define V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX (V4L2_CID_MPEG_BASE + 1011)
+#define V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE (V4L2_CID_MPEG_BASE + 1015)
+#define V4L2_CID_MPEG_VIDEO_HEVC_START_CODE (V4L2_CID_MPEG_BASE + 1016)
+
+/* enum v4l2_ctrl_type type values */
+#define V4L2_CTRL_TYPE_HEVC_SPS 0x0120
+#define V4L2_CTRL_TYPE_HEVC_PPS 0x0121
+#define V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS 0x0122
+#define V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX 0x0123
+
+enum v4l2_mpeg_video_hevc_decode_mode {
+ V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED,
+ V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_FRAME_BASED,
+};
+
+enum v4l2_mpeg_video_hevc_start_code {
+ V4L2_MPEG_VIDEO_HEVC_START_CODE_NONE,
+ V4L2_MPEG_VIDEO_HEVC_START_CODE_ANNEX_B,
+};
+
+#define V4L2_HEVC_SLICE_TYPE_B 0
+#define V4L2_HEVC_SLICE_TYPE_P 1
+#define V4L2_HEVC_SLICE_TYPE_I 2
+
+#define V4L2_HEVC_SPS_FLAG_SEPARATE_COLOUR_PLANE (1ULL << 0)
+#define V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED (1ULL << 1)
+#define V4L2_HEVC_SPS_FLAG_AMP_ENABLED (1ULL << 2)
+#define V4L2_HEVC_SPS_FLAG_SAMPLE_ADAPTIVE_OFFSET (1ULL << 3)
+#define V4L2_HEVC_SPS_FLAG_PCM_ENABLED (1ULL << 4)
+#define V4L2_HEVC_SPS_FLAG_PCM_LOOP_FILTER_DISABLED (1ULL << 5)
+#define V4L2_HEVC_SPS_FLAG_LONG_TERM_REF_PICS_PRESENT (1ULL << 6)
+#define V4L2_HEVC_SPS_FLAG_SPS_TEMPORAL_MVP_ENABLED (1ULL << 7)
+#define V4L2_HEVC_SPS_FLAG_STRONG_INTRA_SMOOTHING_ENABLED (1ULL << 8)
+
+/* The controls are not stable at the moment and will likely be reworked. */
+struct v4l2_ctrl_hevc_sps {
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Sequence parameter set */
+ __u16 pic_width_in_luma_samples;
+ __u16 pic_height_in_luma_samples;
+ __u8 bit_depth_luma_minus8;
+ __u8 bit_depth_chroma_minus8;
+ __u8 log2_max_pic_order_cnt_lsb_minus4;
+ __u8 sps_max_dec_pic_buffering_minus1;
+ __u8 sps_max_num_reorder_pics;
+ __u8 sps_max_latency_increase_plus1;
+ __u8 log2_min_luma_coding_block_size_minus3;
+ __u8 log2_diff_max_min_luma_coding_block_size;
+ __u8 log2_min_luma_transform_block_size_minus2;
+ __u8 log2_diff_max_min_luma_transform_block_size;
+ __u8 max_transform_hierarchy_depth_inter;
+ __u8 max_transform_hierarchy_depth_intra;
+ __u8 pcm_sample_bit_depth_luma_minus1;
+ __u8 pcm_sample_bit_depth_chroma_minus1;
+ __u8 log2_min_pcm_luma_coding_block_size_minus3;
+ __u8 log2_diff_max_min_pcm_luma_coding_block_size;
+ __u8 num_short_term_ref_pic_sets;
+ __u8 num_long_term_ref_pics_sps;
+ __u8 chroma_format_idc;
+
+ __u8 padding;
+
+ __u64 flags;
+};
+
+#define V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT (1ULL << 0)
+#define V4L2_HEVC_PPS_FLAG_OUTPUT_FLAG_PRESENT (1ULL << 1)
+#define V4L2_HEVC_PPS_FLAG_SIGN_DATA_HIDING_ENABLED (1ULL << 2)
+#define V4L2_HEVC_PPS_FLAG_CABAC_INIT_PRESENT (1ULL << 3)
+#define V4L2_HEVC_PPS_FLAG_CONSTRAINED_INTRA_PRED (1ULL << 4)
+#define V4L2_HEVC_PPS_FLAG_TRANSFORM_SKIP_ENABLED (1ULL << 5)
+#define V4L2_HEVC_PPS_FLAG_CU_QP_DELTA_ENABLED (1ULL << 6)
+#define V4L2_HEVC_PPS_FLAG_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT (1ULL << 7)
+#define V4L2_HEVC_PPS_FLAG_WEIGHTED_PRED (1ULL << 8)
+#define V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED (1ULL << 9)
+#define V4L2_HEVC_PPS_FLAG_TRANSQUANT_BYPASS_ENABLED (1ULL << 10)
+#define V4L2_HEVC_PPS_FLAG_TILES_ENABLED (1ULL << 11)
+#define V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED (1ULL << 12)
+#define V4L2_HEVC_PPS_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED (1ULL << 13)
+#define V4L2_HEVC_PPS_FLAG_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED (1ULL << 14)
+#define V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_OVERRIDE_ENABLED (1ULL << 15)
+#define V4L2_HEVC_PPS_FLAG_PPS_DISABLE_DEBLOCKING_FILTER (1ULL << 16)
+#define V4L2_HEVC_PPS_FLAG_LISTS_MODIFICATION_PRESENT (1ULL << 17)
+#define V4L2_HEVC_PPS_FLAG_SLICE_SEGMENT_HEADER_EXTENSION_PRESENT (1ULL << 18)
+
+struct v4l2_ctrl_hevc_pps {
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture parameter set */
+ __u8 num_extra_slice_header_bits;
+ __s8 init_qp_minus26;
+ __u8 diff_cu_qp_delta_depth;
+ __s8 pps_cb_qp_offset;
+ __s8 pps_cr_qp_offset;
+ __u8 num_tile_columns_minus1;
+ __u8 num_tile_rows_minus1;
+ __u8 column_width_minus1[20];
+ __u8 row_height_minus1[22];
+ __s8 pps_beta_offset_div2;
+ __s8 pps_tc_offset_div2;
+ __u8 log2_parallel_merge_level_minus2;
+
+ __u8 padding[4];
+ __u64 flags;
+};
+
+#define V4L2_HEVC_DPB_ENTRY_RPS_ST_CURR_BEFORE 0x01
+#define V4L2_HEVC_DPB_ENTRY_RPS_ST_CURR_AFTER 0x02
+#define V4L2_HEVC_DPB_ENTRY_RPS_LT_CURR 0x03
+
+#define V4L2_HEVC_DPB_ENTRIES_NUM_MAX 16
+
+struct v4l2_hevc_dpb_entry {
+ __u64 timestamp;
+ __u8 rps;
+ __u8 field_pic;
+ __u16 pic_order_cnt[2];
+ __u8 padding[2];
+};
+
+struct v4l2_hevc_pred_weight_table {
+ __s8 delta_luma_weight_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
+ __s8 luma_offset_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
+ __s8 delta_chroma_weight_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2];
+ __s8 chroma_offset_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2];
+
+ __s8 delta_luma_weight_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
+ __s8 luma_offset_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
+ __s8 delta_chroma_weight_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2];
+ __s8 chroma_offset_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2];
+
+ __u8 padding[6];
+
+ __u8 luma_log2_weight_denom;
+ __s8 delta_chroma_log2_weight_denom;
+};
+
+#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_LUMA (1ULL << 0)
+#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_CHROMA (1ULL << 1)
+#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_TEMPORAL_MVP_ENABLED (1ULL << 2)
+#define V4L2_HEVC_SLICE_PARAMS_FLAG_MVD_L1_ZERO (1ULL << 3)
+#define V4L2_HEVC_SLICE_PARAMS_FLAG_CABAC_INIT (1ULL << 4)
+#define V4L2_HEVC_SLICE_PARAMS_FLAG_COLLOCATED_FROM_L0 (1ULL << 5)
+#define V4L2_HEVC_SLICE_PARAMS_FLAG_USE_INTEGER_MV (1ULL << 6)
+#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_DEBLOCKING_FILTER_DISABLED (1ULL << 7)
+#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED (1ULL << 8)
+
+struct v4l2_ctrl_hevc_slice_params {
+ __u32 bit_size;
+ __u32 data_bit_offset;
+
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */
+ __u32 slice_segment_addr;
+ __u32 num_entry_point_offsets;
+
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: NAL unit header */
+ __u8 nal_unit_type;
+ __u8 nuh_temporal_id_plus1;
+
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */
+ __u8 slice_type;
+ __u8 colour_plane_id;
+ __u16 slice_pic_order_cnt;
+ __u8 num_ref_idx_l0_active_minus1;
+ __u8 num_ref_idx_l1_active_minus1;
+ __u8 collocated_ref_idx;
+ __u8 five_minus_max_num_merge_cand;
+ __s8 slice_qp_delta;
+ __s8 slice_cb_qp_offset;
+ __s8 slice_cr_qp_offset;
+ __s8 slice_act_y_qp_offset;
+ __s8 slice_act_cb_qp_offset;
+ __s8 slice_act_cr_qp_offset;
+ __s8 slice_beta_offset_div2;
+ __s8 slice_tc_offset_div2;
+
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture timing SEI message */
+ __u8 pic_struct;
+
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */
+ __u8 num_active_dpb_entries;
+ __u8 ref_idx_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
+ __u8 ref_idx_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
+
+ __u8 num_rps_poc_st_curr_before;
+ __u8 num_rps_poc_st_curr_after;
+ __u8 num_rps_poc_lt_curr;
+
+ __u8 padding;
+
+ __u32 entry_point_offset_minus1[256];
+
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */
+ struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
+
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Weighted prediction parameter */
+ struct v4l2_hevc_pred_weight_table pred_weight_table;
+
+ __u64 flags;
+};
+
+struct v4l2_ctrl_hevc_scaling_matrix {
+ __u8 scaling_list_4x4[6][16];
+ __u8 scaling_list_8x8[6][64];
+ __u8 scaling_list_16x16[6][64];
+ __u8 scaling_list_32x32[2][64];
+ __u8 scaling_list_dc_coef_16x16[6];
+ __u8 scaling_list_dc_coef_32x32[2];
+};
+
+#endif
diff --git a/libavcodec/mpeg2-ctrls.h b/libavcodec/mpeg2-ctrls.h
new file mode 100644
index 0000000000..6601455b3d
--- /dev/null
+++ b/libavcodec/mpeg2-ctrls.h
@@ -0,0 +1,82 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * These are the MPEG2 state controls for use with stateless MPEG-2
+ * codec drivers.
+ *
+ * It turns out that these structs are not stable yet and will undergo
+ * more changes. So keep them private until they are stable and ready to
+ * become part of the official public API.
+ */
+
+#ifndef _MPEG2_CTRLS_H_
+#define _MPEG2_CTRLS_H_
+
+#define V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS (V4L2_CID_MPEG_BASE+250)
+#define V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION (V4L2_CID_MPEG_BASE+251)
+
+/* enum v4l2_ctrl_type type values */
+#define V4L2_CTRL_TYPE_MPEG2_SLICE_PARAMS 0x0103
+#define V4L2_CTRL_TYPE_MPEG2_QUANTIZATION 0x0104
+
+#define V4L2_MPEG2_PICTURE_CODING_TYPE_I 1
+#define V4L2_MPEG2_PICTURE_CODING_TYPE_P 2
+#define V4L2_MPEG2_PICTURE_CODING_TYPE_B 3
+#define V4L2_MPEG2_PICTURE_CODING_TYPE_D 4
+
+struct v4l2_mpeg2_sequence {
+ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Sequence header */
+ __u16 horizontal_size;
+ __u16 vertical_size;
+ __u32 vbv_buffer_size;
+
+ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Sequence extension */
+ __u16 profile_and_level_indication;
+ __u8 progressive_sequence;
+ __u8 chroma_format;
+};
+
+struct v4l2_mpeg2_picture {
+ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Picture header */
+ __u8 picture_coding_type;
+
+ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Picture coding extension */
+ __u8 f_code[2][2];
+ __u8 intra_dc_precision;
+ __u8 picture_structure;
+ __u8 top_field_first;
+ __u8 frame_pred_frame_dct;
+ __u8 concealment_motion_vectors;
+ __u8 q_scale_type;
+ __u8 intra_vlc_format;
+ __u8 alternate_scan;
+ __u8 repeat_first_field;
+ __u16 progressive_frame;
+};
+
+struct v4l2_ctrl_mpeg2_slice_params {
+ __u32 bit_size;
+ __u32 data_bit_offset;
+ __u64 backward_ref_ts;
+ __u64 forward_ref_ts;
+
+ struct v4l2_mpeg2_sequence sequence;
+ struct v4l2_mpeg2_picture picture;
+
+ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Slice */
+ __u32 quantiser_scale_code;
+};
+
+struct v4l2_ctrl_mpeg2_quantization {
+ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Quant matrix extension */
+ __u8 load_intra_quantiser_matrix;
+ __u8 load_non_intra_quantiser_matrix;
+ __u8 load_chroma_intra_quantiser_matrix;
+ __u8 load_chroma_non_intra_quantiser_matrix;
+
+ __u8 intra_quantiser_matrix[64];
+ __u8 non_intra_quantiser_matrix[64];
+ __u8 chroma_intra_quantiser_matrix[64];
+ __u8 chroma_non_intra_quantiser_matrix[64];
+};
+
+#endif
diff --git a/libavcodec/v4l2_request_h264.c b/libavcodec/v4l2_request_h264.c
index 81b3c4b092..ca306b6a3f 100644
--- a/libavcodec/v4l2_request_h264.c
+++ b/libavcodec/v4l2_request_h264.c
@@ -19,6 +19,7 @@
#include "h264dec.h"
#include "hwaccel.h"
#include "v4l2_request.h"
+#include "h264-ctrls.h"
typedef struct V4L2RequestControlsH264 {
struct v4l2_ctrl_h264_sps sps;
diff --git a/libavcodec/v4l2_request_hevc.c b/libavcodec/v4l2_request_hevc.c
index da1fd666d7..94977c5d0e 100644
--- a/libavcodec/v4l2_request_hevc.c
+++ b/libavcodec/v4l2_request_hevc.c
@@ -19,6 +19,7 @@
#include "hevcdec.h"
#include "hwaccel.h"
#include "v4l2_request.h"
+#include "hevc-ctrls.h"
typedef struct V4L2RequestControlsHEVC {
struct v4l2_ctrl_hevc_sps sps;
diff --git a/libavcodec/v4l2_request_mpeg2.c b/libavcodec/v4l2_request_mpeg2.c
index 782b9c2471..37a4eae62c 100644
--- a/libavcodec/v4l2_request_mpeg2.c
+++ b/libavcodec/v4l2_request_mpeg2.c
@@ -19,6 +19,7 @@
#include "hwaccel.h"
#include "mpegvideo.h"
#include "v4l2_request.h"
+#include "mpeg2-ctrls.h"
typedef struct V4L2RequestControlsMPEG2 {
struct v4l2_ctrl_mpeg2_slice_params slice_params;
diff --git a/libavcodec/v4l2_request_vp8.c b/libavcodec/v4l2_request_vp8.c
index d24252c5e5..c290fe8b9a 100644
--- a/libavcodec/v4l2_request_vp8.c
+++ b/libavcodec/v4l2_request_vp8.c
@@ -19,6 +19,7 @@
#include "hwaccel.h"
#include "v4l2_request.h"
#include "vp8.h"
+#include "vp8-ctrls.h"
typedef struct V4L2RequestControlsVP8 {
struct v4l2_ctrl_vp8_frame_header ctrl;
diff --git a/libavcodec/vp8-ctrls.h b/libavcodec/vp8-ctrls.h
new file mode 100644
index 0000000000..53cba826e4
--- /dev/null
+++ b/libavcodec/vp8-ctrls.h
@@ -0,0 +1,112 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * These are the VP8 state controls for use with stateless VP8
+ * codec drivers.
+ *
+ * It turns out that these structs are not stable yet and will undergo
+ * more changes. So keep them private until they are stable and ready to
+ * become part of the official public API.
+ */
+
+#ifndef _VP8_CTRLS_H_
+#define _VP8_CTRLS_H_
+
+#include <linux/types.h>
+
+#define V4L2_PIX_FMT_VP8_FRAME v4l2_fourcc('V', 'P', '8', 'F')
+
+#define V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER (V4L2_CID_MPEG_BASE + 2000)
+#define V4L2_CTRL_TYPE_VP8_FRAME_HEADER 0x301
+
+#define V4L2_VP8_SEGMENT_HEADER_FLAG_ENABLED 0x01
+#define V4L2_VP8_SEGMENT_HEADER_FLAG_UPDATE_MAP 0x02
+#define V4L2_VP8_SEGMENT_HEADER_FLAG_UPDATE_FEATURE_DATA 0x04
+#define V4L2_VP8_SEGMENT_HEADER_FLAG_DELTA_VALUE_MODE 0x08
+
+struct v4l2_vp8_segment_header {
+ __s8 quant_update[4];
+ __s8 lf_update[4];
+ __u8 segment_probs[3];
+ __u8 padding;
+ __u32 flags;
+};
+
+#define V4L2_VP8_LF_HEADER_ADJ_ENABLE 0x01
+#define V4L2_VP8_LF_HEADER_DELTA_UPDATE 0x02
+#define V4L2_VP8_LF_FILTER_TYPE_SIMPLE 0x04
+struct v4l2_vp8_loopfilter_header {
+ __s8 ref_frm_delta[4];
+ __s8 mb_mode_delta[4];
+ __u8 sharpness_level;
+ __u8 level;
+ __u16 padding;
+ __u32 flags;
+};
+
+struct v4l2_vp8_quantization_header {
+ __u8 y_ac_qi;
+ __s8 y_dc_delta;
+ __s8 y2_dc_delta;
+ __s8 y2_ac_delta;
+ __s8 uv_dc_delta;
+ __s8 uv_ac_delta;
+ __u16 padding;
+};
+
+struct v4l2_vp8_entropy_header {
+ __u8 coeff_probs[4][8][3][11];
+ __u8 y_mode_probs[4];
+ __u8 uv_mode_probs[3];
+ __u8 mv_probs[2][19];
+ __u8 padding[3];
+};
+
+struct v4l2_vp8_entropy_coder_state {
+ __u8 range;
+ __u8 value;
+ __u8 bit_count;
+ __u8 padding;
+};
+
+#define V4L2_VP8_FRAME_HEADER_FLAG_KEY_FRAME 0x01
+#define V4L2_VP8_FRAME_HEADER_FLAG_EXPERIMENTAL 0x02
+#define V4L2_VP8_FRAME_HEADER_FLAG_SHOW_FRAME 0x04
+#define V4L2_VP8_FRAME_HEADER_FLAG_MB_NO_SKIP_COEFF 0x08
+#define V4L2_VP8_FRAME_HEADER_FLAG_SIGN_BIAS_GOLDEN 0x10
+#define V4L2_VP8_FRAME_HEADER_FLAG_SIGN_BIAS_ALT 0x20
+
+#define VP8_FRAME_IS_KEY_FRAME(hdr) \
+ (!!((hdr)->flags & V4L2_VP8_FRAME_HEADER_FLAG_KEY_FRAME))
+
+struct v4l2_ctrl_vp8_frame_header {
+ struct v4l2_vp8_segment_header segment_header;
+ struct v4l2_vp8_loopfilter_header lf_header;
+ struct v4l2_vp8_quantization_header quant_header;
+ struct v4l2_vp8_entropy_header entropy_header;
+ struct v4l2_vp8_entropy_coder_state coder_state;
+
+ __u16 width;
+ __u16 height;
+
+ __u8 horizontal_scale;
+ __u8 vertical_scale;
+
+ __u8 version;
+ __u8 prob_skip_false;
+ __u8 prob_intra;
+ __u8 prob_last;
+ __u8 prob_gf;
+ __u8 num_dct_parts;
+
+ __u32 first_part_size;
+ __u32 first_part_header_bits;
+ __u32 dct_part_sizes[8];
+
+ __u64 last_frame_ts;
+ __u64 golden_frame_ts;
+ __u64 alt_frame_ts;
+
+ __u64 flags;
+};
+
+#endif

View File

@ -1,26 +0,0 @@
From 60383b61fa64aa0e2806de0b8cf8a3f8d85c41e4 Mon Sep 17 00:00:00 2001
From: Jonas Karlman <jonas@kwiboo.se>
Date: Mon, 29 Apr 2019 22:08:59 +0000
Subject: [PATCH 08/12] hwcontext_drm: do not require drm device
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
libavutil/hwcontext_drm.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/libavutil/hwcontext_drm.c b/libavutil/hwcontext_drm.c
index 32cbde82eb..aa4794c5e6 100644
--- a/libavutil/hwcontext_drm.c
+++ b/libavutil/hwcontext_drm.c
@@ -43,6 +43,11 @@ static int drm_device_create(AVHWDeviceContext *hwdev, const char *device,
AVDRMDeviceContext *hwctx = hwdev->hwctx;
drmVersionPtr version;
+ if (device == NULL) {
+ hwctx->fd = -1;
+ return 0;
+ }
+
hwctx->fd = open(device, O_RDWR);
if (hwctx->fd < 0)
return AVERROR(errno);

View File

@ -1,51 +0,0 @@
From 4e1a25f7cbbe9978548680171580afdfbf84d603 Mon Sep 17 00:00:00 2001
From: Ezequiel Garcia <ezequiel@collabora.com>
Date: Wed, 20 Feb 2019 11:18:00 -0300
Subject: [PATCH 09/12] avcodec/h264: parse idr_pic_id
Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
---
libavcodec/h264_slice.c | 2 +-
libavcodec/h264dec.h | 2 ++
libavcodec/v4l2_request_h264.c | 2 +-
3 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c
index 9912ede703..18ba196246 100644
--- a/libavcodec/h264_slice.c
+++ b/libavcodec/h264_slice.c
@@ -1824,7 +1824,7 @@ static int h264_slice_header_parse(const H264Context *h, H264SliceContext *sl,
}
if (nal->type == H264_NAL_IDR_SLICE)
- get_ue_golomb_long(&sl->gb); /* idr_pic_id */
+ sl->idr_pic_id = get_ue_golomb_long(&sl->gb);
if (sps->poc_type == 0) {
sl->poc_lsb = get_bits(&sl->gb, sps->log2_max_poc_lsb);
diff --git a/libavcodec/h264dec.h b/libavcodec/h264dec.h
index b0b42b7672..38efab5c60 100644
--- a/libavcodec/h264dec.h
+++ b/libavcodec/h264dec.h
@@ -184,6 +184,8 @@ typedef struct H264SliceContext {
int slice_type_nos; ///< S free slice type (SI/SP are remapped to I/P)
int slice_type_fixed;
+ int idr_pic_id;
+
int qscale;
int chroma_qp[2]; // QPc
int qp_thresh; ///< QP threshold to skip loopfilter
diff --git a/libavcodec/v4l2_request_h264.c b/libavcodec/v4l2_request_h264.c
index ca306b6a3f..f21c8b3508 100644
--- a/libavcodec/v4l2_request_h264.c
+++ b/libavcodec/v4l2_request_h264.c
@@ -301,7 +301,7 @@ static int v4l2_request_h264_decode_slice(AVCodecContext *avctx, const uint8_t *
.pic_parameter_set_id = sl->pps_id,
.colour_plane_id = 0, /* what is this? */
.frame_num = h->poc.frame_num,
- .idr_pic_id = 0, /* what is this? */
+ .idr_pic_id = sl->idr_pic_id,
.pic_order_cnt_lsb = sl->poc_lsb,
.delta_pic_order_cnt_bottom = sl->delta_poc_bottom,
.delta_pic_order_cnt0 = sl->delta_poc[0],

View File

@ -1,88 +0,0 @@
From 8309a49f4049b6ec8d4fd76a5dc18f8d23f8315c Mon Sep 17 00:00:00 2001
From: Boris Brezillon <boris.brezillon@collabora.com>
Date: Wed, 22 May 2019 14:44:22 +0200
Subject: [PATCH 10/12] avcodec/h264: parse ref_pic_marking_size_in_bits and
pic_order_cnt_bit_size
Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
---
libavcodec/h264_slice.c | 6 +++++-
libavcodec/h264dec.h | 2 ++
libavcodec/v4l2_request_h264.c | 4 ++--
3 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c
index 18ba196246..1bd3388f1e 100644
--- a/libavcodec/h264_slice.c
+++ b/libavcodec/h264_slice.c
@@ -1736,7 +1736,7 @@ static int h264_slice_header_parse(const H264Context *h, H264SliceContext *sl,
unsigned int slice_type, tmp, i;
int field_pic_flag, bottom_field_flag;
int first_slice = sl == h->slice_ctx && !h->current_slice;
- int picture_structure;
+ int picture_structure, pos;
if (first_slice)
av_assert0(!h->setup_finished);
@@ -1826,6 +1826,7 @@ static int h264_slice_header_parse(const H264Context *h, H264SliceContext *sl,
if (nal->type == H264_NAL_IDR_SLICE)
sl->idr_pic_id = get_ue_golomb_long(&sl->gb);
+ pos = sl->gb.index;
if (sps->poc_type == 0) {
sl->poc_lsb = get_bits(&sl->gb, sps->log2_max_poc_lsb);
@@ -1839,6 +1840,7 @@ static int h264_slice_header_parse(const H264Context *h, H264SliceContext *sl,
if (pps->pic_order_present == 1 && picture_structure == PICT_FRAME)
sl->delta_poc[1] = get_se_golomb(&sl->gb);
}
+ sl->pic_order_cnt_bit_size = sl->gb.index - pos;
sl->redundant_pic_count = 0;
if (pps->redundant_pic_cnt_present)
@@ -1878,9 +1880,11 @@ static int h264_slice_header_parse(const H264Context *h, H264SliceContext *sl,
sl->explicit_ref_marking = 0;
if (nal->ref_idc) {
+ int bit_pos = sl->gb.index;
ret = ff_h264_decode_ref_pic_marking(sl, &sl->gb, nal, h->avctx);
if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE))
return AVERROR_INVALIDDATA;
+ sl->ref_pic_marking_size_in_bits = sl->gb.index - bit_pos;
}
if (sl->slice_type_nos != AV_PICTURE_TYPE_I && pps->cabac) {
diff --git a/libavcodec/h264dec.h b/libavcodec/h264dec.h
index 38efab5c60..8e894f565b 100644
--- a/libavcodec/h264dec.h
+++ b/libavcodec/h264dec.h
@@ -324,11 +324,13 @@ typedef struct H264SliceContext {
MMCO mmco[MAX_MMCO_COUNT];
int nb_mmco;
int explicit_ref_marking;
+ int ref_pic_marking_size_in_bits;
int frame_num;
int poc_lsb;
int delta_poc_bottom;
int delta_poc[2];
+ int pic_order_cnt_bit_size;
int curr_pic_num;
int max_pic_num;
} H264SliceContext;
diff --git a/libavcodec/v4l2_request_h264.c b/libavcodec/v4l2_request_h264.c
index f21c8b3508..1a7fb873a0 100644
--- a/libavcodec/v4l2_request_h264.c
+++ b/libavcodec/v4l2_request_h264.c
@@ -309,9 +309,9 @@ static int v4l2_request_h264_decode_slice(AVCodecContext *avctx, const uint8_t *
.redundant_pic_cnt = sl->redundant_pic_count,
/* Size in bits of dec_ref_pic_marking() syntax element. */
- .dec_ref_pic_marking_bit_size = 0,
+ .dec_ref_pic_marking_bit_size = sl->ref_pic_marking_size_in_bits,
/* Size in bits of pic order count syntax. */
- .pic_order_cnt_bit_size = 0,
+ .pic_order_cnt_bit_size = sl->pic_order_cnt_bit_size,
.cabac_init_idc = sl->cabac_init_idc,
.slice_qp_delta = sl->qscale - pps->init_qp,

View File

@ -1,57 +0,0 @@
From ace9eff28953b97fc1832913d4655c0f4227ea16 Mon Sep 17 00:00:00 2001
From: Jonas Karlman <jonas@kwiboo.se>
Date: Fri, 24 May 2019 22:58:24 +0000
Subject: [PATCH 11/12] HACK: add dpb flags for reference usage and field
picture
This or something similar needs to be upstreamed to kernel h264 ctrls
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
libavcodec/h264-ctrls.h | 4 ++++
libavcodec/v4l2_request_h264.c | 6 +++++-
2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/libavcodec/h264-ctrls.h b/libavcodec/h264-ctrls.h
index e877bf1d53..76020ebd1e 100644
--- a/libavcodec/h264-ctrls.h
+++ b/libavcodec/h264-ctrls.h
@@ -185,6 +185,10 @@ struct v4l2_ctrl_h264_slice_params {
#define V4L2_H264_DPB_ENTRY_FLAG_VALID 0x01
#define V4L2_H264_DPB_ENTRY_FLAG_ACTIVE 0x02
#define V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM 0x04
+#define V4L2_H264_DPB_ENTRY_FLAG_FIELD_PICTURE 0x08
+#define V4L2_H264_DPB_ENTRY_FLAG_REF_TOP 0x10
+#define V4L2_H264_DPB_ENTRY_FLAG_REF_BOTTOM 0x20
+#define V4L2_H264_DPB_ENTRY_FLAG_REF_FRAME 0x30
struct v4l2_h264_dpb_entry {
__u64 reference_ts;
diff --git a/libavcodec/v4l2_request_h264.c b/libavcodec/v4l2_request_h264.c
index 1a7fb873a0..13fac3f6f9 100644
--- a/libavcodec/v4l2_request_h264.c
+++ b/libavcodec/v4l2_request_h264.c
@@ -66,10 +66,13 @@ static void fill_dpb_entry(struct v4l2_h264_dpb_entry *entry, const H264Picture
entry->frame_num = pic->frame_num;
entry->pic_num = pic->pic_id;
entry->flags = V4L2_H264_DPB_ENTRY_FLAG_VALID;
+ entry->flags |= (pic->reference & 3) << 4;
if (pic->reference)
entry->flags |= V4L2_H264_DPB_ENTRY_FLAG_ACTIVE;
if (pic->long_ref)
entry->flags |= V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM;
+ if (pic->field_picture)
+ entry->flags |= V4L2_H264_DPB_ENTRY_FLAG_FIELD_PICTURE;
if (pic->field_poc[0] != INT_MAX)
entry->top_field_order_cnt = pic->field_poc[0];
if (pic->field_poc[1] != INT_MAX)
@@ -109,7 +112,8 @@ static uint8_t get_dpb_index(struct v4l2_ctrl_h264_decode_params *decode, const
struct v4l2_h264_dpb_entry *entry = &decode->dpb[i];
if ((entry->flags & V4L2_H264_DPB_ENTRY_FLAG_VALID) &&
entry->reference_ts == timestamp)
- return i;
+ // TODO: signal reference type, possible using top 2 bits
+ return i | ((ref->reference & 3) << 6);
}
return 0;

View File

@ -1,69 +0,0 @@
From fa3f88530ec9083ff15d9637a9019a8a9408435b Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Sat, 9 Nov 2019 10:02:43 +0000
Subject: [PATCH 12/12] WIP: v4l2-request: rolling timestamps
---
libavcodec/v4l2_request.c | 10 +++++++---
libavcodec/v4l2_request.h | 1 +
2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/libavcodec/v4l2_request.c b/libavcodec/v4l2_request.c
index 1dabf77689..611c22f8b6 100644
--- a/libavcodec/v4l2_request.c
+++ b/libavcodec/v4l2_request.c
@@ -105,12 +105,14 @@ 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 = buf->index + 1,
+ .timestamp.tv_usec = ctx->timestamp,
.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;
@@ -200,6 +202,9 @@ 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);
@@ -651,6 +656,7 @@ 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) {
@@ -784,8 +790,6 @@ 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.h b/libavcodec/v4l2_request.h
index d4146bd4ee..72698f6f3c 100644
--- a/libavcodec/v4l2_request.h
+++ b/libavcodec/v4l2_request.h
@@ -28,6 +28,7 @@ typedef struct V4L2RequestContext {
int media_fd;
enum v4l2_buf_type output_type;
struct v4l2_format format;
+ int timestamp;
} V4L2RequestContext;
typedef struct V4L2RequestBuffer {

View File

@ -1,121 +0,0 @@
From 2756ad266f18d546551a3eab0650c95ddb62e0ff Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Sat, 14 Mar 2020 22:21:42 +0000
Subject: [PATCH] v4l2 request hevc: Set SPS control at initialization
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
libavcodec/v4l2_request_hevc.c | 61 ++++++++++++++++++++++------------
1 file changed, 40 insertions(+), 21 deletions(-)
diff --git a/libavcodec/v4l2_request_hevc.c b/libavcodec/v4l2_request_hevc.c
index 94977c5d0e..0ab1c201b0 100644
--- a/libavcodec/v4l2_request_hevc.c
+++ b/libavcodec/v4l2_request_hevc.c
@@ -231,21 +231,12 @@ static void v4l2_request_hevc_fill_slice_params(const HEVCContext *h,
slice_params->entry_point_offset_minus1[i] = sh->entry_point_offset[i] - 1;
}
-static int v4l2_request_hevc_start_frame(AVCodecContext *avctx,
- av_unused const uint8_t *buffer,
- av_unused uint32_t size)
+static void fill_sps(struct v4l2_ctrl_hevc_sps *ctrl, const HEVCContext *h)
{
- const HEVCContext *h = avctx->priv_data;
const HEVCSPS *sps = h->ps.sps;
- const HEVCPPS *pps = h->ps.pps;
- const ScalingList *sl = pps->scaling_list_data_present_flag ?
- &pps->scaling_list :
- sps->scaling_list_enable_flag ?
- &sps->scaling_list : NULL;
- V4L2RequestControlsHEVC *controls = h->ref->hwaccel_picture_private;
/* ISO/IEC 23008-2, ITU-T Rec. H.265: Sequence parameter set */
- controls->sps = (struct v4l2_ctrl_hevc_sps) {
+ *ctrl = (struct v4l2_ctrl_hevc_sps) {
.chroma_format_idc = sps->chroma_format_idc,
.pic_width_in_luma_samples = sps->width,
.pic_height_in_luma_samples = sps->height,
@@ -270,31 +261,47 @@ static int v4l2_request_hevc_start_frame(AVCodecContext *avctx,
};
if (sps->separate_colour_plane_flag)
- controls->sps.flags |= V4L2_HEVC_SPS_FLAG_SEPARATE_COLOUR_PLANE;
+ ctrl->flags |= V4L2_HEVC_SPS_FLAG_SEPARATE_COLOUR_PLANE;
if (sps->scaling_list_enable_flag)
- controls->sps.flags |= V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED;
+ ctrl->flags |= V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED;
if (sps->amp_enabled_flag)
- controls->sps.flags |= V4L2_HEVC_SPS_FLAG_AMP_ENABLED;
+ ctrl->flags |= V4L2_HEVC_SPS_FLAG_AMP_ENABLED;
if (sps->sao_enabled)
- controls->sps.flags |= V4L2_HEVC_SPS_FLAG_SAMPLE_ADAPTIVE_OFFSET;
+ ctrl->flags |= V4L2_HEVC_SPS_FLAG_SAMPLE_ADAPTIVE_OFFSET;
if (sps->pcm_enabled_flag)
- controls->sps.flags |= V4L2_HEVC_SPS_FLAG_PCM_ENABLED;
+ ctrl->flags |= V4L2_HEVC_SPS_FLAG_PCM_ENABLED;
if (sps->pcm.loop_filter_disable_flag)
- controls->sps.flags |= V4L2_HEVC_SPS_FLAG_PCM_LOOP_FILTER_DISABLED;
+ ctrl->flags |= V4L2_HEVC_SPS_FLAG_PCM_LOOP_FILTER_DISABLED;
if (sps->long_term_ref_pics_present_flag)
- controls->sps.flags |= V4L2_HEVC_SPS_FLAG_LONG_TERM_REF_PICS_PRESENT;
+ ctrl->flags |= V4L2_HEVC_SPS_FLAG_LONG_TERM_REF_PICS_PRESENT;
if (sps->sps_temporal_mvp_enabled_flag)
- controls->sps.flags |= V4L2_HEVC_SPS_FLAG_SPS_TEMPORAL_MVP_ENABLED;
+ ctrl->flags |= V4L2_HEVC_SPS_FLAG_SPS_TEMPORAL_MVP_ENABLED;
if (sps->sps_strong_intra_smoothing_enable_flag)
- controls->sps.flags |= V4L2_HEVC_SPS_FLAG_STRONG_INTRA_SMOOTHING_ENABLED;
+ ctrl->flags |= V4L2_HEVC_SPS_FLAG_STRONG_INTRA_SMOOTHING_ENABLED;
+}
+
+static int v4l2_request_hevc_start_frame(AVCodecContext *avctx,
+ av_unused const uint8_t *buffer,
+ av_unused uint32_t size)
+{
+ const HEVCContext *h = avctx->priv_data;
+ const HEVCSPS *sps = h->ps.sps;
+ const HEVCPPS *pps = h->ps.pps;
+ const ScalingList *sl = pps->scaling_list_data_present_flag ?
+ &pps->scaling_list :
+ sps->scaling_list_enable_flag ?
+ &sps->scaling_list : NULL;
+ V4L2RequestControlsHEVC *controls = h->ref->hwaccel_picture_private;
+
+ fill_sps(&controls->sps, h);
if (sl) {
for (int i = 0; i < 6; i++) {
@@ -502,9 +509,21 @@ static int v4l2_request_hevc_set_controls(AVCodecContext *avctx)
static int v4l2_request_hevc_init(AVCodecContext *avctx)
{
+ const HEVCContext *h = avctx->priv_data;
+ struct v4l2_ctrl_hevc_sps sps;
int ret;
- ret = ff_v4l2_request_init(avctx, V4L2_PIX_FMT_HEVC_SLICE, 3 * 1024 * 1024, NULL, 0);
+ struct v4l2_ext_control control[] = {
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_SPS,
+ .ptr = &sps,
+ .size = sizeof(sps),
+ }
+ };
+
+ fill_sps(&sps, h);
+
+ ret = ff_v4l2_request_init(avctx, V4L2_PIX_FMT_HEVC_SLICE, 3 * 1024 * 1024, control, FF_ARRAY_ELEMS(control));
if (ret)
return ret;
--
2.25.1

View File

@ -1,78 +0,0 @@
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index fd87481a1c..d234271c5b 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -2612,7 +2612,6 @@ typedef struct AVCodecContext {
#define FF_BUG_MS 8192 ///< Work around various bugs in Microsoft's broken decoders.
#define FF_BUG_TRUNCATED 16384
#define FF_BUG_IEDGE 32768
-#define FF_BUG_GMC_UNSUPPORTED (1<<30)
/**
* strictly follow the standard (MPEG-4, ...).
diff --git a/libavcodec/libdav1d.c b/libavcodec/libdav1d.c
index 1bbb83eda3..12c63245f8 100644
--- a/libavcodec/libdav1d.c
+++ b/libavcodec/libdav1d.c
@@ -53,16 +53,6 @@ static const enum AVPixelFormat pix_fmt_rgb[3] = {
AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12,
};
-static enum AVPixelFormat libdav1d_get_format(AVCodecContext *avctx, const Dav1dPicture *p)
-{
- enum AVPixelFormat pix_fmts[2], *fmt = pix_fmts;
-
- *fmt++ = pix_fmt[p->p.layout][p->seq_hdr->hbd];
- *fmt = AV_PIX_FMT_NONE;
-
- return ff_get_format(avctx, pix_fmts);
-}
-
static void libdav1d_log_callback(void *opaque, const char *fmt, va_list vl)
{
AVCodecContext *c = opaque;
@@ -239,7 +229,6 @@ static int libdav1d_receive_frame(AVCodecContext *c, AVFrame *frame)
c->profile = p->seq_hdr->profile;
c->level = ((p->seq_hdr->operating_points[0].major_level - 2) << 2)
| p->seq_hdr->operating_points[0].minor_level;
- frame->format = c->pix_fmt = libdav1d_get_format(c, p);
frame->width = p->p.w;
frame->height = p->p.h;
if (c->width != p->p.w || c->height != p->p.h) {
diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c
index fa208660c8..055afabc7e 100644
--- a/libavcodec/mpeg4videodec.c
+++ b/libavcodec/mpeg4videodec.c
@@ -2662,9 +2662,6 @@ int ff_mpeg4_workaround_bugs(AVCodecContext *avctx)
if (ctx->divx_version >= 0)
s->workaround_bugs |= FF_BUG_HPEL_CHROMA;
-
- if (ctx->num_sprite_warping_points > 1)
- s->workaround_bugs |= FF_BUG_GMC_UNSUPPORTED;
}
if (s->workaround_bugs & FF_BUG_STD_QPEL) {
@@ -2689,7 +2686,6 @@ int ff_mpeg4_workaround_bugs(AVCodecContext *avctx)
s->workaround_bugs, ctx->lavc_build, ctx->xvid_build,
ctx->divx_version, ctx->divx_build, s->divx_packed ? "p" : "");
- avctx->workaround_bugs = s->workaround_bugs;
if (CONFIG_MPEG4_DECODER && ctx->xvid_build >= 0 &&
s->codec_id == AV_CODEC_ID_MPEG4 &&
avctx->idct_algo == FF_IDCT_AUTO) {
diff --git a/libswscale/yuv2rgb.c b/libswscale/yuv2rgb.c
index 6fb32fac77..d0df061e4d 100644
--- a/libswscale/yuv2rgb.c
+++ b/libswscale/yuv2rgb.c
@@ -687,6 +687,10 @@ SwsFunc ff_yuv2rgb_get_func_ptr(SwsContext *c)
if (t)
return t;
+ av_log(c, AV_LOG_WARNING,
+ "No accelerated colorspace conversion found from %s to %s.\n",
+ av_get_pix_fmt_name(c->srcFormat), av_get_pix_fmt_name(c->dstFormat));
+
switch (c->dstFormat) {
case AV_PIX_FMT_BGR48BE:
case AV_PIX_FMT_BGR48LE:

View File

@ -1,73 +0,0 @@
From 7134be3260ca6b885aa20447a06d35cab380a09e Mon Sep 17 00:00:00 2001
From: Lukas Rusak <lorusak@gmail.com>
Date: Tue, 24 Apr 2018 22:48:23 -0700
Subject: [PATCH 01/14] libavcodec: v4l2m2m: fix indentation and add
M2MDEC_CLASS
This just makes the M2MDEC_CLASS similar to how it is done in rkmpp. It looks
clean and has proper indentation
---
libavcodec/v4l2_m2m_dec.c | 46 ++++++++++++++++++++-------------------
1 file changed, 24 insertions(+), 22 deletions(-)
diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c
index d0601f0e2f..e1b6925771 100644
--- a/libavcodec/v4l2_m2m_dec.c
+++ b/libavcodec/v4l2_m2m_dec.c
@@ -209,29 +209,31 @@ static const AVOption options[] = {
{ NULL},
};
+#define M2MDEC_CLASS(NAME) \
+ static const AVClass v4l2_m2m_ ## NAME ## _dec_class = { \
+ .class_name = #NAME "_v4l2_m2m_decoder", \
+ .item_name = av_default_item_name, \
+ .option = options, \
+ .version = LIBAVUTIL_VERSION_INT, \
+ };
+
#define M2MDEC(NAME, LONGNAME, CODEC, bsf_name) \
-static const AVClass v4l2_m2m_ ## NAME ## _dec_class = {\
- .class_name = #NAME "_v4l2_m2m_decoder",\
- .item_name = av_default_item_name,\
- .option = options,\
- .version = LIBAVUTIL_VERSION_INT,\
-};\
-\
-AVCodec ff_ ## NAME ## _v4l2m2m_decoder = { \
- .name = #NAME "_v4l2m2m" ,\
- .long_name = NULL_IF_CONFIG_SMALL("V4L2 mem2mem " LONGNAME " decoder wrapper"),\
- .type = AVMEDIA_TYPE_VIDEO,\
- .id = CODEC ,\
- .priv_data_size = sizeof(V4L2m2mPriv),\
- .priv_class = &v4l2_m2m_ ## NAME ## _dec_class,\
- .init = v4l2_decode_init,\
- .receive_frame = v4l2_receive_frame,\
- .close = ff_v4l2_m2m_codec_end,\
- .bsfs = bsf_name, \
- .capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY | \
- AV_CODEC_CAP_AVOID_PROBING, \
- .wrapper_name = "v4l2m2m", \
-};
+ M2MDEC_CLASS(NAME) \
+ AVCodec ff_ ## NAME ## _v4l2m2m_decoder = { \
+ .name = #NAME "_v4l2m2m" , \
+ .long_name = NULL_IF_CONFIG_SMALL("V4L2 mem2mem " LONGNAME " decoder wrapper"), \
+ .type = AVMEDIA_TYPE_VIDEO, \
+ .id = CODEC , \
+ .priv_data_size = sizeof(V4L2m2mPriv), \
+ .priv_class = &v4l2_m2m_ ## NAME ## _dec_class, \
+ .init = v4l2_decode_init, \
+ .receive_frame = v4l2_receive_frame, \
+ .close = ff_v4l2_m2m_codec_end, \
+ .bsfs = bsf_name, \
+ .capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY, \
+ AV_CODEC_CAP_AVOID_PROBING, \
+ .wrapper_name = "v4l2m2m", \
+ };
M2MDEC(h264, "H.264", AV_CODEC_ID_H264, "h264_mp4toannexb");
M2MDEC(hevc, "HEVC", AV_CODEC_ID_HEVC, "hevc_mp4toannexb");
--
2.24.1

View File

@ -1,511 +0,0 @@
From bf9fb2d576488ba08832e7cb7b10fe05a08665a5 Mon Sep 17 00:00:00 2001
From: Lukas Rusak <lorusak@gmail.com>
Date: Tue, 24 Apr 2018 23:00:23 -0700
Subject: [PATCH 02/14] libavcodec: v4l2m2m: output AVDRMFrameDescriptor
This allows for a zero-copy output by exporting the v4l2 buffer then wrapping that buffer
in the AVDRMFrameDescriptor like it is done in rkmpp.
This has been in use for quite some time with great success on many platforms including:
- Amlogic S905
- Raspberry Pi
- i.MX6
- Dragonboard 410c
This was developed in conjunction with Kodi to allow handling the zero-copy buffer rendering.
A simply utility for testing is also available here: https://github.com/BayLibre/ffmpeg-drm
todo:
- allow selecting pixel format output from decoder
- allow configuring amount of output and capture buffers
V2:
- allow selecting AV_PIX_FMT_DRM_PRIME
V3:
- use get_format to select AV_PIX_FMT_DRM_PRIME
- use hw_configs
- add handling of AV_PIX_FMT_YUV420P format (for raspberry pi)
- add handling of AV_PIX_FMT_YUYV422 format (for i.MX6 coda decoder)
---
libavcodec/v4l2_buffers.c | 216 ++++++++++++++++++++++++++++++++------
libavcodec/v4l2_buffers.h | 4 +
libavcodec/v4l2_context.c | 40 ++++++-
libavcodec/v4l2_m2m.c | 4 +-
libavcodec/v4l2_m2m.h | 3 +
libavcodec/v4l2_m2m_dec.c | 23 ++++
6 files changed, 253 insertions(+), 37 deletions(-)
diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c
index aef911f3bb..e5c46ac81e 100644
--- a/libavcodec/v4l2_buffers.c
+++ b/libavcodec/v4l2_buffers.c
@@ -21,6 +21,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <drm/drm_fourcc.h>
#include <linux/videodev2.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
@@ -29,6 +30,7 @@
#include <poll.h>
#include "libavcodec/avcodec.h"
#include "libavcodec/internal.h"
+#include "libavutil/hwcontext.h"
#include "v4l2_context.h"
#include "v4l2_buffers.h"
#include "v4l2_m2m.h"
@@ -203,7 +205,79 @@ static enum AVColorTransferCharacteristic v4l2_get_color_trc(V4L2Buffer *buf)
return AVCOL_TRC_UNSPECIFIED;
}
-static void v4l2_free_buffer(void *opaque, uint8_t *unused)
+static uint8_t * v4l2_get_drm_frame(V4L2Buffer *avbuf)
+{
+ AVDRMFrameDescriptor *drm_desc = &avbuf->drm_frame;
+ AVDRMLayerDescriptor *layer;
+
+ /* fill the DRM frame descriptor */
+ drm_desc->nb_objects = avbuf->num_planes;
+ drm_desc->nb_layers = 1;
+
+ layer = &drm_desc->layers[0];
+ layer->nb_planes = avbuf->num_planes;
+
+ for (int i = 0; i < avbuf->num_planes; i++) {
+ layer->planes[i].object_index = i;
+ layer->planes[i].offset = 0;
+ layer->planes[i].pitch = avbuf->plane_info[i].bytesperline;
+ }
+
+ switch (avbuf->context->av_pix_fmt) {
+ case AV_PIX_FMT_YUYV422:
+
+ layer->format = DRM_FORMAT_YUYV;
+ layer->nb_planes = 1;
+
+ break;
+
+ case AV_PIX_FMT_NV12:
+ case AV_PIX_FMT_NV21:
+
+ layer->format = avbuf->context->av_pix_fmt == AV_PIX_FMT_NV12 ?
+ DRM_FORMAT_NV12 : DRM_FORMAT_NV21;
+
+ if (avbuf->num_planes > 1)
+ break;
+
+ layer->nb_planes = 2;
+
+ layer->planes[1].object_index = 0;
+ layer->planes[1].offset = avbuf->plane_info[0].bytesperline *
+ avbuf->context->format.fmt.pix.height;
+ layer->planes[1].pitch = avbuf->plane_info[0].bytesperline;
+ break;
+
+ case AV_PIX_FMT_YUV420P:
+
+ layer->format = DRM_FORMAT_YUV420;
+
+ if (avbuf->num_planes > 1)
+ break;
+
+ layer->nb_planes = 3;
+
+ layer->planes[1].object_index = 0;
+ layer->planes[1].offset = avbuf->plane_info[0].bytesperline *
+ avbuf->context->format.fmt.pix.height;
+ layer->planes[1].pitch = avbuf->plane_info[0].bytesperline >> 1;
+
+ layer->planes[2].object_index = 0;
+ layer->planes[2].offset = layer->planes[1].offset +
+ ((avbuf->plane_info[0].bytesperline *
+ avbuf->context->format.fmt.pix.height) >> 2);
+ layer->planes[2].pitch = avbuf->plane_info[0].bytesperline >> 1;
+ break;
+
+ default:
+ drm_desc->nb_layers = 0;
+ break;
+ }
+
+ return (uint8_t *) drm_desc;
+}
+
+static void v4l2_free_buffer(void *opaque, uint8_t *data)
{
V4L2Buffer* avbuf = opaque;
V4L2m2mContext *s = buf_to_m2mctx(avbuf);
@@ -227,27 +301,47 @@ static void v4l2_free_buffer(void *opaque, uint8_t *unused)
}
}
-static int v4l2_buf_to_bufref(V4L2Buffer *in, int plane, AVBufferRef **buf)
+static int v4l2_buffer_export_drm(V4L2Buffer* avbuf)
{
- V4L2m2mContext *s = buf_to_m2mctx(in);
+ struct v4l2_exportbuffer expbuf;
+ int i, ret;
- if (plane >= in->num_planes)
- return AVERROR(EINVAL);
+ for (i = 0; i < avbuf->num_planes; i++) {
+ memset(&expbuf, 0, sizeof(expbuf));
- /* even though most encoders return 0 in data_offset encoding vp8 does require this value */
- *buf = av_buffer_create((char *)in->plane_info[plane].mm_addr + in->planes[plane].data_offset,
- in->plane_info[plane].length, v4l2_free_buffer, in, 0);
- if (!*buf)
- return AVERROR(ENOMEM);
+ expbuf.index = avbuf->buf.index;
+ expbuf.type = avbuf->buf.type;
+ expbuf.plane = i;
+
+ ret = ioctl(buf_to_m2mctx(avbuf)->fd, VIDIOC_EXPBUF, &expbuf);
+ if (ret < 0)
+ return AVERROR(errno);
+
+ if (V4L2_TYPE_IS_MULTIPLANAR(avbuf->buf.type)) {
+ /* drm frame */
+ avbuf->drm_frame.objects[i].size = avbuf->buf.m.planes[i].length;
+ avbuf->drm_frame.objects[i].fd = expbuf.fd;
+ } else {
+ /* drm frame */
+ avbuf->drm_frame.objects[0].size = avbuf->buf.length;
+ avbuf->drm_frame.objects[0].fd = expbuf.fd;
+ }
+ }
+
+ return 0;
+}
+
+static int v4l2_buf_increase_ref(V4L2Buffer *in)
+{
+ V4L2m2mContext *s = buf_to_m2mctx(in);
if (in->context_ref)
atomic_fetch_add(&in->context_refcount, 1);
else {
in->context_ref = av_buffer_ref(s->self_ref);
- if (!in->context_ref) {
- av_buffer_unref(buf);
+ if (!in->context_ref)
return AVERROR(ENOMEM);
- }
+
in->context_refcount = 1;
}
@@ -257,6 +351,46 @@ static int v4l2_buf_to_bufref(V4L2Buffer *in, int plane, AVBufferRef **buf)
return 0;
}
+static int v4l2_buf_to_bufref_drm(V4L2Buffer *in, AVBufferRef **buf)
+{
+ int ret;
+
+ *buf = av_buffer_create((uint8_t *) &in->drm_frame,
+ sizeof(in->drm_frame),
+ v4l2_free_buffer,
+ in, AV_BUFFER_FLAG_READONLY);
+ if (!*buf)
+ return AVERROR(ENOMEM);
+
+ ret = v4l2_buf_increase_ref(in);
+ if (ret)
+ av_buffer_unref(buf);
+
+ return ret;
+}
+
+static int v4l2_buf_to_bufref(V4L2Buffer *in, int plane, AVBufferRef **buf)
+{
+ int ret;
+
+ if (plane >= in->num_planes)
+ return AVERROR(EINVAL);
+
+ /* most encoders return 0 in data_offset but vp8 does require this value */
+ *buf = av_buffer_create((char *)in->plane_info[plane].mm_addr + in->planes[plane].data_offset,
+ in->plane_info[plane].length,
+ v4l2_free_buffer,
+ in, 0);
+ if (!*buf)
+ return AVERROR(ENOMEM);
+
+ ret = v4l2_buf_increase_ref(in);
+ if (ret)
+ av_buffer_unref(buf);
+
+ return ret;
+}
+
static int v4l2_bufref_to_buf(V4L2Buffer *out, int plane, const uint8_t* data, int size, AVBufferRef* bref)
{
unsigned int bytesused, length;
@@ -308,31 +442,43 @@ int ff_v4l2_buffer_buf_to_avframe(AVFrame *frame, V4L2Buffer *avbuf)
av_frame_unref(frame);
- /* 1. get references to the actual data */
- for (i = 0; i < avbuf->num_planes; i++) {
- ret = v4l2_buf_to_bufref(avbuf, i, &frame->buf[i]);
+ if (buf_to_m2mctx(avbuf)->output_drm) {
+ /* 1. get references to the actual data */
+ ret = v4l2_buf_to_bufref_drm(avbuf, &frame->buf[0]);
if (ret)
return ret;
- frame->linesize[i] = avbuf->plane_info[i].bytesperline;
- frame->data[i] = frame->buf[i]->data;
- }
+ frame->data[0] = (uint8_t *) v4l2_get_drm_frame(avbuf);
+ frame->format = AV_PIX_FMT_DRM_PRIME;
+ } else {
+ /* 1. get references to the actual data */
+ for (i = 0; i < avbuf->num_planes; i++) {
+ ret = v4l2_buf_to_bufref(avbuf, i, &frame->buf[i]);
+ if (ret)
+ return ret;
+
+ frame->linesize[i] = avbuf->plane_info[i].bytesperline;
+ frame->data[i] = frame->buf[i]->data;
+ }
- /* 1.1 fixup special cases */
- switch (avbuf->context->av_pix_fmt) {
- case AV_PIX_FMT_NV12:
- if (avbuf->num_planes > 1)
+ /* 1.1 fixup special cases */
+ switch (avbuf->context->av_pix_fmt) {
+ case AV_PIX_FMT_NV12:
+ if (avbuf->num_planes > 1)
+ break;
+ frame->linesize[1] = avbuf->plane_info[0].bytesperline;
+ frame->data[1] = frame->buf[0]->data +
+ avbuf->plane_info[0].bytesperline *
+ avbuf->context->format.fmt.pix.height;
break;
- frame->linesize[1] = avbuf->plane_info[0].bytesperline;
- frame->data[1] = frame->buf[0]->data + avbuf->plane_info[0].bytesperline * avbuf->context->format.fmt.pix_mp.height;
- break;
- default:
- break;
+ default:
+ break;
+ }
+ frame->format = avbuf->context->av_pix_fmt;
}
/* 2. get frame information */
frame->key_frame = !!(avbuf->buf.flags & V4L2_BUF_FLAG_KEYFRAME);
- frame->format = avbuf->context->av_pix_fmt;
frame->color_primaries = v4l2_get_color_primaries(avbuf);
frame->colorspace = v4l2_get_color_space(avbuf);
frame->color_range = v4l2_get_color_range(avbuf);
@@ -447,9 +593,6 @@ int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index)
avbuf->status = V4L2BUF_AVAILABLE;
- if (V4L2_TYPE_IS_OUTPUT(ctx->type))
- return 0;
-
if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type)) {
avbuf->buf.m.planes = avbuf->planes;
avbuf->buf.length = avbuf->num_planes;
@@ -459,6 +602,15 @@ int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index)
avbuf->buf.length = avbuf->planes[0].length;
}
+ if (V4L2_TYPE_IS_OUTPUT(ctx->type))
+ return 0;
+
+ if (buf_to_m2mctx(avbuf)->output_drm) {
+ ret = v4l2_buffer_export_drm(avbuf);
+ if (ret)
+ return ret;
+ }
+
return ff_v4l2_buffer_enqueue(avbuf);
}
diff --git a/libavcodec/v4l2_buffers.h b/libavcodec/v4l2_buffers.h
index 7a57caf949..19324541d0 100644
--- a/libavcodec/v4l2_buffers.h
+++ b/libavcodec/v4l2_buffers.h
@@ -27,6 +27,7 @@
#include <stdatomic.h>
#include <linux/videodev2.h>
+#include "libavutil/hwcontext_drm.h"
#include "avcodec.h"
enum V4L2Buffer_status {
@@ -42,6 +43,9 @@ typedef struct V4L2Buffer {
/* each buffer needs to have a reference to its context */
struct V4L2Context *context;
+ /* DRM descriptor */
+ AVDRMFrameDescriptor drm_frame;
+
/* This object is refcounted per-plane, so we need to keep track
* of how many context-refs we are holding. */
AVBufferRef *context_ref;
diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c
index efcb0426e4..9457fadb1e 100644
--- a/libavcodec/v4l2_context.c
+++ b/libavcodec/v4l2_context.c
@@ -393,22 +393,54 @@ static int v4l2_release_buffers(V4L2Context* ctx)
struct v4l2_requestbuffers req = {
.memory = V4L2_MEMORY_MMAP,
.type = ctx->type,
- .count = 0, /* 0 -> unmaps buffers from the driver */
+ .count = 0, /* 0 -> unmap all buffers from the driver */
};
- int i, j;
+ int ret, i, j;
for (i = 0; i < ctx->num_buffers; i++) {
V4L2Buffer *buffer = &ctx->buffers[i];
for (j = 0; j < buffer->num_planes; j++) {
struct V4L2Plane_info *p = &buffer->plane_info[j];
+
+ if (V4L2_TYPE_IS_OUTPUT(ctx->type)) {
+ /* output buffers are not EXPORTED */
+ goto unmap;
+ }
+
+ if (ctx_to_m2mctx(ctx)->output_drm) {
+ /* use the DRM frame to close */
+ if (buffer->drm_frame.objects[j].fd >= 0) {
+ if (close(buffer->drm_frame.objects[j].fd) < 0) {
+ av_log(logger(ctx), AV_LOG_ERROR, "%s close drm fd "
+ "[buffer=%2d, plane=%d, fd=%2d] - %s \n",
+ ctx->name, i, j, buffer->drm_frame.objects[j].fd,
+ av_err2str(AVERROR(errno)));
+ }
+ }
+ }
+unmap:
if (p->mm_addr && p->length)
if (munmap(p->mm_addr, p->length) < 0)
- av_log(logger(ctx), AV_LOG_ERROR, "%s unmap plane (%s))\n", ctx->name, av_err2str(AVERROR(errno)));
+ av_log(logger(ctx), AV_LOG_ERROR, "%s unmap plane (%s))\n",
+ ctx->name, av_err2str(AVERROR(errno)));
}
}
- return ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_REQBUFS, &req);
+ ret = ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_REQBUFS, &req);
+ if (ret < 0) {
+ av_log(logger(ctx), AV_LOG_ERROR, "release all %s buffers (%s)\n",
+ ctx->name, av_err2str(AVERROR(errno)));
+
+ if (ctx_to_m2mctx(ctx)->output_drm)
+ av_log(logger(ctx), AV_LOG_ERROR,
+ "Make sure the DRM client releases all FB/GEM objects before closing the codec (ie):\n"
+ "for all buffers: \n"
+ " 1. drmModeRmFB(..)\n"
+ " 2. drmIoctl(.., DRM_IOCTL_GEM_CLOSE,... )\n");
+ }
+
+ return ret;
}
static inline int v4l2_try_raw_format(V4L2Context* ctx, enum AVPixelFormat pixfmt)
diff --git a/libavcodec/v4l2_m2m.c b/libavcodec/v4l2_m2m.c
index 427e165f58..7896326e80 100644
--- a/libavcodec/v4l2_m2m.c
+++ b/libavcodec/v4l2_m2m.c
@@ -159,7 +159,9 @@ static int v4l2_configure_contexts(V4L2m2mContext* s)
goto error;
}
- /* decoder's buffers need to be updated at a later stage */
+ /* decoder's capture buffers are updated during v4l2_try_start once we find
+ * the valid format.
+ */
if (!av_codec_is_decoder(s->avctx->codec)) {
ret = ff_v4l2_context_init(&s->capture);
if (ret) {
diff --git a/libavcodec/v4l2_m2m.h b/libavcodec/v4l2_m2m.h
index 0d4671beb1..043a81a86a 100644
--- a/libavcodec/v4l2_m2m.h
+++ b/libavcodec/v4l2_m2m.h
@@ -59,6 +59,9 @@ typedef struct V4L2m2mContext {
/* Reference to self; only valid while codec is active. */
AVBufferRef *self_ref;
+
+ /* generate DRM frames */
+ int output_drm;
} V4L2m2mContext;
typedef struct V4L2m2mPriv
diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c
index e1b6925771..b28f4e236a 100644
--- a/libavcodec/v4l2_m2m_dec.c
+++ b/libavcodec/v4l2_m2m_dec.c
@@ -23,12 +23,18 @@
#include <linux/videodev2.h>
#include <sys/ioctl.h>
+
+#include "libavutil/hwcontext.h"
+#include "libavutil/hwcontext_drm.h"
#include "libavutil/pixfmt.h"
#include "libavutil/pixdesc.h"
#include "libavutil/opt.h"
#include "libavcodec/avcodec.h"
#include "libavcodec/decode.h"
+#include "libavcodec/hwaccel.h"
+#include "libavcodec/internal.h"
+
#include "v4l2_context.h"
#include "v4l2_m2m.h"
#include "v4l2_fmt.h"
@@ -186,6 +192,15 @@ static av_cold int v4l2_decode_init(AVCodecContext *avctx)
capture->av_codec_id = AV_CODEC_ID_RAWVIDEO;
capture->av_pix_fmt = avctx->pix_fmt;
+ /* the client requests the codec to generate DRM frames:
+ * - data[0] will therefore point to the returned AVDRMFrameDescriptor
+ * check the ff_v4l2_buffer_to_avframe conversion function.
+ * - the DRM frame format is passed in the DRM frame descriptor layer.
+ * check the v4l2_get_drm_frame function.
+ */
+ if (ff_get_format(avctx, avctx->codec->pix_fmts) == AV_PIX_FMT_DRM_PRIME)
+ s->output_drm = 1;
+
ret = ff_v4l2_m2m_codec_init(avctx);
if (ret) {
V4L2m2mPriv *priv = avctx->priv_data;
@@ -209,6 +224,11 @@ static const AVOption options[] = {
{ NULL},
};
+static const AVCodecHWConfigInternal *v4l2_m2m_hw_configs[] = {
+ HW_CONFIG_INTERNAL(DRM_PRIME),
+ NULL
+};
+
#define M2MDEC_CLASS(NAME) \
static const AVClass v4l2_m2m_ ## NAME ## _dec_class = { \
.class_name = #NAME "_v4l2_m2m_decoder", \
@@ -229,7 +249,10 @@ static const AVOption options[] = {
.init = v4l2_decode_init, \
.receive_frame = v4l2_receive_frame, \
.close = ff_v4l2_m2m_codec_end, \
+ .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_DRM_PRIME, \
+ AV_PIX_FMT_NONE}, \
.bsfs = bsf_name, \
+ .hw_configs = v4l2_m2m_hw_configs, \
.capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY, \
AV_CODEC_CAP_AVOID_PROBING, \
.wrapper_name = "v4l2m2m", \
--
2.24.1

View File

@ -1,106 +0,0 @@
From ebcfd47d8411fcc91d8058643b151068b5a7fedc Mon Sep 17 00:00:00 2001
From: Lukas Rusak <lorusak@gmail.com>
Date: Tue, 8 May 2018 22:40:23 -0700
Subject: [PATCH 03/14] libavcodec: v4l2m2m: adjust formatting
just some simple formatting fixes that unify the code quality
---
libavcodec/v4l2_buffers.c | 23 +++++++++++++++--------
libavcodec/v4l2_buffers.h | 1 -
2 files changed, 15 insertions(+), 9 deletions(-)
diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c
index e5c46ac81e..897c3c4636 100644
--- a/libavcodec/v4l2_buffers.c
+++ b/libavcodec/v4l2_buffers.c
@@ -401,7 +401,8 @@ static int v4l2_bufref_to_buf(V4L2Buffer *out, int plane, const uint8_t* data, i
bytesused = FFMIN(size, out->plane_info[plane].length);
length = out->plane_info[plane].length;
- memcpy(out->plane_info[plane].mm_addr, data, FFMIN(size, out->plane_info[plane].length));
+ memcpy(out->plane_info[plane].mm_addr, data,
+ FFMIN(size, out->plane_info[plane].length));
if (V4L2_TYPE_IS_MULTIPLANAR(out->buf.type)) {
out->planes[plane].bytesused = bytesused;
@@ -425,7 +426,10 @@ int ff_v4l2_buffer_avframe_to_buf(const AVFrame *frame, V4L2Buffer* out)
int i, ret;
for(i = 0; i < out->num_planes; i++) {
- ret = v4l2_bufref_to_buf(out, i, frame->buf[i]->data, frame->buf[i]->size, frame->buf[i]);
+ ret = v4l2_bufref_to_buf(out, i,
+ frame->buf[i]->data,
+ frame->buf[i]->size,
+ frame->buf[i]);
if (ret)
return ret;
}
@@ -480,8 +484,8 @@ int ff_v4l2_buffer_buf_to_avframe(AVFrame *frame, V4L2Buffer *avbuf)
/* 2. get frame information */
frame->key_frame = !!(avbuf->buf.flags & V4L2_BUF_FLAG_KEYFRAME);
frame->color_primaries = v4l2_get_color_primaries(avbuf);
- frame->colorspace = v4l2_get_color_space(avbuf);
frame->color_range = v4l2_get_color_range(avbuf);
+ frame->colorspace = v4l2_get_color_space(avbuf);
frame->color_trc = v4l2_get_color_trc(avbuf);
frame->pts = v4l2_get_pts(avbuf);
@@ -507,7 +511,8 @@ int ff_v4l2_buffer_buf_to_avpkt(AVPacket *pkt, V4L2Buffer *avbuf)
if (ret)
return ret;
- pkt->size = V4L2_TYPE_IS_MULTIPLANAR(avbuf->buf.type) ? avbuf->buf.m.planes[0].bytesused : avbuf->buf.bytesused;
+ pkt->size = V4L2_TYPE_IS_MULTIPLANAR(avbuf->buf.type) ?
+ avbuf->buf.m.planes[0].bytesused : avbuf->buf.bytesused;
pkt->data = pkt->buf->data;
if (avbuf->buf.flags & V4L2_BUF_FLAG_KEYFRAME)
@@ -563,6 +568,7 @@ int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index)
/* in MP, the V4L2 API states that buf.length means num_planes */
if (avbuf->num_planes >= avbuf->buf.length)
break;
+
if (avbuf->buf.m.planes[avbuf->num_planes].length)
avbuf->num_planes++;
}
@@ -579,12 +585,14 @@ int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index)
avbuf->plane_info[i].length = avbuf->buf.m.planes[i].length;
avbuf->plane_info[i].mm_addr = mmap(NULL, avbuf->buf.m.planes[i].length,
PROT_READ | PROT_WRITE, MAP_SHARED,
- buf_to_m2mctx(avbuf)->fd, avbuf->buf.m.planes[i].m.mem_offset);
+ buf_to_m2mctx(avbuf)->fd,
+ avbuf->buf.m.planes[i].m.mem_offset);
} else {
avbuf->plane_info[i].length = avbuf->buf.length;
avbuf->plane_info[i].mm_addr = mmap(NULL, avbuf->buf.length,
PROT_READ | PROT_WRITE, MAP_SHARED,
- buf_to_m2mctx(avbuf)->fd, avbuf->buf.m.offset);
+ buf_to_m2mctx(avbuf)->fd,
+ avbuf->buf.m.offset);
}
if (avbuf->plane_info[i].mm_addr == MAP_FAILED)
@@ -594,9 +602,8 @@ int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index)
avbuf->status = V4L2BUF_AVAILABLE;
if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type)) {
- avbuf->buf.m.planes = avbuf->planes;
avbuf->buf.length = avbuf->num_planes;
-
+ avbuf->buf.m.planes = avbuf->planes;
} else {
avbuf->buf.bytesused = avbuf->planes[0].bytesused;
avbuf->buf.length = avbuf->planes[0].length;
diff --git a/libavcodec/v4l2_buffers.h b/libavcodec/v4l2_buffers.h
index 19324541d0..b6072baec8 100644
--- a/libavcodec/v4l2_buffers.h
+++ b/libavcodec/v4l2_buffers.h
@@ -131,5 +131,4 @@ int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index);
*/
int ff_v4l2_buffer_enqueue(V4L2Buffer* avbuf);
-
#endif // AVCODEC_V4L2_BUFFERS_H
--
2.24.1

View File

@ -1,84 +0,0 @@
From db39d4579d36266a3f3b87312303d5097543633d Mon Sep 17 00:00:00 2001
From: Jorge Ramirez-Ortiz <jramirez@baylibre.com>
Date: Sun, 6 May 2018 19:56:30 +0200
Subject: [PATCH 04/14] libavcodec: v4l2m2m: fix error handling during buffer
init
Signed-off-by: Jorge Ramirez-Ortiz <jramirez@baylibre.com>
---
libavcodec/v4l2_context.c | 19 ++++++++++++++++---
libavcodec/v4l2_m2m_dec.c | 9 +++++++--
2 files changed, 23 insertions(+), 5 deletions(-)
diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c
index 9457fadb1e..12d40d597e 100644
--- a/libavcodec/v4l2_context.c
+++ b/libavcodec/v4l2_context.c
@@ -263,6 +263,12 @@ static V4L2Buffer* v4l2_dequeue_v4l2buf(V4L2Context *ctx, int timeout)
/* if we are draining and there are no more capture buffers queued in the driver we are done */
if (!V4L2_TYPE_IS_OUTPUT(ctx->type) && ctx_to_m2mctx(ctx)->draining) {
for (i = 0; i < ctx->num_buffers; i++) {
+ /* capture buffer initialization happens during decode hence
+ * detection happens at runtime
+ */
+ if (!ctx->buffers)
+ break;
+
if (ctx->buffers[i].status == V4L2BUF_IN_DRIVER)
goto start;
}
@@ -724,9 +730,8 @@ int ff_v4l2_context_init(V4L2Context* ctx)
ctx->buffers[i].context = ctx;
ret = ff_v4l2_buffer_initialize(&ctx->buffers[i], i);
if (ret < 0) {
- av_log(logger(ctx), AV_LOG_ERROR, "%s buffer initialization (%s)\n", ctx->name, av_err2str(ret));
- av_free(ctx->buffers);
- return ret;
+ av_log(logger(ctx), AV_LOG_ERROR, "%s buffer[%d] initialization (%s)\n", ctx->name, i, av_err2str(ret));
+ goto error;
}
}
@@ -739,4 +744,12 @@ int ff_v4l2_context_init(V4L2Context* ctx)
V4L2_TYPE_IS_MULTIPLANAR(ctx->type) ? ctx->format.fmt.pix_mp.plane_fmt[0].bytesperline : ctx->format.fmt.pix.bytesperline);
return 0;
+
+error:
+ v4l2_release_buffers(ctx);
+
+ av_free(ctx->buffers);
+ ctx->buffers = NULL;
+
+ return ret;
}
diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c
index b28f4e236a..fb5406a74e 100644
--- a/libavcodec/v4l2_m2m_dec.c
+++ b/libavcodec/v4l2_m2m_dec.c
@@ -92,8 +92,8 @@ static int v4l2_try_start(AVCodecContext *avctx)
if (!capture->buffers) {
ret = ff_v4l2_context_init(capture);
if (ret) {
- av_log(avctx, AV_LOG_DEBUG, "can't request output buffers\n");
- return ret;
+ av_log(avctx, AV_LOG_ERROR, "can't request capture buffers\n");
+ return AVERROR(ENOMEM);
}
}
@@ -157,6 +157,11 @@ static int v4l2_receive_frame(AVCodecContext *avctx, AVFrame *frame)
ret = v4l2_try_start(avctx);
if (ret) {
av_packet_unref(&avpkt);
+
+ /* cant recover */
+ if (ret == AVERROR(ENOMEM))
+ return ret;
+
return 0;
}
}
--
2.24.1

View File

@ -1,38 +0,0 @@
From 86a709f752d430166b9c1e26fa639886710b79ad Mon Sep 17 00:00:00 2001
From: Lukas Rusak <lorusak@gmail.com>
Date: Thu, 16 Aug 2018 21:09:40 -0700
Subject: [PATCH 05/14] libavcodec: v4l2m2m: depends on libdrm
---
configure | 1 +
libavcodec/v4l2_buffers.c | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/configure b/configure
index 34c2adb4a4..b72f1d6270 100755
--- a/configure
+++ b/configure
@@ -3343,6 +3343,7 @@ sndio_indev_deps="sndio"
sndio_outdev_deps="sndio"
v4l2_indev_deps_any="linux_videodev2_h sys_videoio_h"
v4l2_indev_suggest="libv4l2"
+v4l2_outdev_deps="libdrm"
v4l2_outdev_deps_any="linux_videodev2_h sys_videoio_h"
v4l2_outdev_suggest="libv4l2"
vfwcap_indev_deps="vfw32 vfwcap_defines"
diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c
index 897c3c4636..d6838866b7 100644
--- a/libavcodec/v4l2_buffers.c
+++ b/libavcodec/v4l2_buffers.c
@@ -21,7 +21,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include <drm/drm_fourcc.h>
+#include <drm_fourcc.h>
#include <linux/videodev2.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
--
2.24.1

View File

@ -1,30 +0,0 @@
From e657b496a21056d51f17f187dfdf0c62d1da13f2 Mon Sep 17 00:00:00 2001
From: Lukas Rusak <lorusak@gmail.com>
Date: Thu, 16 Aug 2018 21:10:13 -0700
Subject: [PATCH 06/14] libavcodec: v4l2m2m: set format_modifier to
DRM_FORMAT_MOD_LINEAR
---
libavcodec/v4l2_buffers.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c
index d6838866b7..d879aab7b1 100644
--- a/libavcodec/v4l2_buffers.c
+++ b/libavcodec/v4l2_buffers.c
@@ -321,10 +321,12 @@ static int v4l2_buffer_export_drm(V4L2Buffer* avbuf)
/* drm frame */
avbuf->drm_frame.objects[i].size = avbuf->buf.m.planes[i].length;
avbuf->drm_frame.objects[i].fd = expbuf.fd;
+ avbuf->drm_frame.objects[i].format_modifier = DRM_FORMAT_MOD_LINEAR;
} else {
/* drm frame */
avbuf->drm_frame.objects[0].size = avbuf->buf.length;
avbuf->drm_frame.objects[0].fd = expbuf.fd;
+ avbuf->drm_frame.objects[0].format_modifier = DRM_FORMAT_MOD_LINEAR;
}
}
--
2.24.1

View File

@ -1,50 +0,0 @@
From 013503bba6eefa10caffe2451fe375b31ed1584a Mon Sep 17 00:00:00 2001
From: Lukas Rusak <lorusak@gmail.com>
Date: Thu, 16 Aug 2018 21:10:53 -0700
Subject: [PATCH 07/14] libavcodec: v4l2m2m: only mmap the buffer when it is
output type and drm prime is used
---
libavcodec/v4l2_buffers.c | 24 ++++++++++++++++--------
1 file changed, 16 insertions(+), 8 deletions(-)
diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c
index d879aab7b1..ee19bb5b6f 100644
--- a/libavcodec/v4l2_buffers.c
+++ b/libavcodec/v4l2_buffers.c
@@ -585,16 +585,24 @@ int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index)
if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type)) {
avbuf->plane_info[i].length = avbuf->buf.m.planes[i].length;
- avbuf->plane_info[i].mm_addr = mmap(NULL, avbuf->buf.m.planes[i].length,
- PROT_READ | PROT_WRITE, MAP_SHARED,
- buf_to_m2mctx(avbuf)->fd,
- avbuf->buf.m.planes[i].m.mem_offset);
+
+ if ((V4L2_TYPE_IS_OUTPUT(ctx->type) && buf_to_m2mctx(avbuf)->output_drm) ||
+ !buf_to_m2mctx(avbuf)->output_drm) {
+ avbuf->plane_info[i].mm_addr = mmap(NULL, avbuf->buf.m.planes[i].length,
+ PROT_READ | PROT_WRITE, MAP_SHARED,
+ buf_to_m2mctx(avbuf)->fd,
+ avbuf->buf.m.planes[i].m.mem_offset);
+ }
} else {
avbuf->plane_info[i].length = avbuf->buf.length;
- avbuf->plane_info[i].mm_addr = mmap(NULL, avbuf->buf.length,
- PROT_READ | PROT_WRITE, MAP_SHARED,
- buf_to_m2mctx(avbuf)->fd,
- avbuf->buf.m.offset);
+
+ if ((V4L2_TYPE_IS_OUTPUT(ctx->type) && buf_to_m2mctx(avbuf)->output_drm) ||
+ !buf_to_m2mctx(avbuf)->output_drm) {
+ avbuf->plane_info[i].mm_addr = mmap(NULL, avbuf->buf.length,
+ PROT_READ | PROT_WRITE, MAP_SHARED,
+ buf_to_m2mctx(avbuf)->fd,
+ avbuf->buf.m.offset);
+ }
}
if (avbuf->plane_info[i].mm_addr == MAP_FAILED)
--
2.24.1

View File

@ -1,42 +0,0 @@
From f3df44dbdf5e7ca66064c0ac9ae0f84bbcc245e9 Mon Sep 17 00:00:00 2001
From: Lukas Rusak <lorusak@gmail.com>
Date: Thu, 16 Aug 2018 21:11:38 -0700
Subject: [PATCH 08/14] libavcodec: v4l2m2m: allow using software pixel formats
---
libavcodec/v4l2_m2m_dec.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c
index fb5406a74e..8834b3d6fc 100644
--- a/libavcodec/v4l2_m2m_dec.c
+++ b/libavcodec/v4l2_m2m_dec.c
@@ -203,8 +203,16 @@ static av_cold int v4l2_decode_init(AVCodecContext *avctx)
* - the DRM frame format is passed in the DRM frame descriptor layer.
* check the v4l2_get_drm_frame function.
*/
- if (ff_get_format(avctx, avctx->codec->pix_fmts) == AV_PIX_FMT_DRM_PRIME)
+ switch (ff_get_format(avctx, avctx->codec->pix_fmts)) {
+ case AV_PIX_FMT_DRM_PRIME:
s->output_drm = 1;
+ break;
+ case AV_PIX_FMT_NONE:
+ return 0;
+ break;
+ default:
+ break;
+ }
ret = ff_v4l2_m2m_codec_init(avctx);
if (ret) {
@@ -255,6 +263,7 @@ static const AVCodecHWConfigInternal *v4l2_m2m_hw_configs[] = {
.receive_frame = v4l2_receive_frame, \
.close = ff_v4l2_m2m_codec_end, \
.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_DRM_PRIME, \
+ AV_PIX_FMT_NV12, \
AV_PIX_FMT_NONE}, \
.bsfs = bsf_name, \
.hw_configs = v4l2_m2m_hw_configs, \
--
2.24.1

View File

@ -1,26 +0,0 @@
From 3af2830856f4356acb9bf1655adf632759782aac Mon Sep 17 00:00:00 2001
From: Lukas Rusak <lorusak@gmail.com>
Date: Mon, 24 Sep 2018 13:38:46 -0700
Subject: [PATCH 09/14] libavcodec: v4l2m2m: fix decoder capabilities
---
libavcodec/v4l2_m2m_dec.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c
index 8834b3d6fc..0087de35d0 100644
--- a/libavcodec/v4l2_m2m_dec.c
+++ b/libavcodec/v4l2_m2m_dec.c
@@ -267,8 +267,7 @@ static const AVCodecHWConfigInternal *v4l2_m2m_hw_configs[] = {
AV_PIX_FMT_NONE}, \
.bsfs = bsf_name, \
.hw_configs = v4l2_m2m_hw_configs, \
- .capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY, \
- AV_CODEC_CAP_AVOID_PROBING, \
+ .capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING, \
.wrapper_name = "v4l2m2m", \
};
--
2.24.1

View File

@ -1,101 +0,0 @@
From 8b7ec4eae175835a806619b0bba98eb6d7252a13 Mon Sep 17 00:00:00 2001
From: Lukas Rusak <lorusak@gmail.com>
Date: Mon, 24 Sep 2018 13:39:31 -0700
Subject: [PATCH 10/14] libavcodec: v4l2m2m: implement hwcontext
---
libavcodec/v4l2_buffers.c | 22 ++++++++++++++++++++++
libavcodec/v4l2_context.h | 2 ++
libavcodec/v4l2_m2m.h | 2 ++
libavcodec/v4l2_m2m_dec.c | 9 +++++++++
4 files changed, 35 insertions(+)
diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c
index ee19bb5b6f..27820905b2 100644
--- a/libavcodec/v4l2_buffers.c
+++ b/libavcodec/v4l2_buffers.c
@@ -456,6 +456,7 @@ int ff_v4l2_buffer_buf_to_avframe(AVFrame *frame, V4L2Buffer *avbuf)
frame->data[0] = (uint8_t *) v4l2_get_drm_frame(avbuf);
frame->format = AV_PIX_FMT_DRM_PRIME;
+ frame->hw_frames_ctx = av_buffer_ref(avbuf->context->frames_ref);
} else {
/* 1. get references to the actual data */
for (i = 0; i < avbuf->num_planes; i++) {
@@ -555,6 +556,27 @@ int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index)
avbuf->buf.type = ctx->type;
avbuf->buf.index = index;
+ if (buf_to_m2mctx(avbuf)->output_drm) {
+ AVHWFramesContext *hwframes;
+
+ av_buffer_unref(&ctx->frames_ref);
+
+ ctx->frames_ref = av_hwframe_ctx_alloc(buf_to_m2mctx(avbuf)->device_ref);
+ if (!ctx->frames_ref) {
+ ret = AVERROR(ENOMEM);
+ return ret;
+ }
+
+ hwframes = (AVHWFramesContext*)ctx->frames_ref->data;
+ hwframes->format = AV_PIX_FMT_DRM_PRIME;
+ hwframes->sw_format = ctx->av_pix_fmt;
+ hwframes->width = ctx->width;
+ hwframes->height = ctx->height;
+ ret = av_hwframe_ctx_init(ctx->frames_ref);
+ if (ret < 0)
+ return ret;
+ }
+
if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type)) {
avbuf->buf.length = VIDEO_MAX_PLANES;
avbuf->buf.m.planes = avbuf->planes;
diff --git a/libavcodec/v4l2_context.h b/libavcodec/v4l2_context.h
index 632f1d0aac..9a1dbbea60 100644
--- a/libavcodec/v4l2_context.h
+++ b/libavcodec/v4l2_context.h
@@ -91,6 +91,8 @@ typedef struct V4L2Context {
*/
int done;
+ AVBufferRef *frames_ref;
+
} V4L2Context;
/**
diff --git a/libavcodec/v4l2_m2m.h b/libavcodec/v4l2_m2m.h
index 043a81a86a..4475618392 100644
--- a/libavcodec/v4l2_m2m.h
+++ b/libavcodec/v4l2_m2m.h
@@ -60,6 +60,8 @@ typedef struct V4L2m2mContext {
/* Reference to self; only valid while codec is active. */
AVBufferRef *self_ref;
+ AVBufferRef *device_ref;
+
/* generate DRM frames */
int output_drm;
} V4L2m2mContext;
diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c
index 0087de35d0..fffeb49092 100644
--- a/libavcodec/v4l2_m2m_dec.c
+++ b/libavcodec/v4l2_m2m_dec.c
@@ -214,6 +214,15 @@ static av_cold int v4l2_decode_init(AVCodecContext *avctx)
break;
}
+ s->device_ref = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_DRM);
+ if (!s->device_ref) {
+ ret = AVERROR(ENOMEM);
+ return ret;
+ }
+ ret = av_hwdevice_ctx_init(s->device_ref);
+ if (ret < 0)
+ return ret;
+
ret = ff_v4l2_m2m_codec_init(avctx);
if (ret) {
V4L2m2mPriv *priv = avctx->priv_data;
--
2.24.1

View File

@ -1,50 +0,0 @@
From 799aa17fbaa5a5dda7fd8a04c71df905e363f6f3 Mon Sep 17 00:00:00 2001
From: Lukas Rusak <lorusak@gmail.com>
Date: Mon, 24 Sep 2018 13:39:56 -0700
Subject: [PATCH 11/14] libavcodec: v4l2m2m: implement flush
---
libavcodec/v4l2_m2m_dec.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c
index fffeb49092..47ac53df00 100644
--- a/libavcodec/v4l2_m2m_dec.c
+++ b/libavcodec/v4l2_m2m_dec.c
@@ -236,6 +236,25 @@ static av_cold int v4l2_decode_init(AVCodecContext *avctx)
return v4l2_prepare_decoder(s);
}
+static void v4l2_flush(AVCodecContext *avctx)
+{
+ V4L2m2mPriv *priv = avctx->priv_data;
+ V4L2m2mContext* s = priv->context;
+ int ret;
+
+ /* wait for pending buffer references */
+ if (atomic_load(&s->refcount))
+ while(sem_wait(&s->refsync) == -1 && errno == EINTR);
+
+ ret = ff_v4l2_context_set_status(&s->output, VIDIOC_STREAMOFF);
+ if (ret)
+ av_log(avctx, AV_LOG_ERROR, "VIDIOC_STREAMOFF %s\n", s->output.name);
+
+ ret = ff_v4l2_context_set_status(&s->capture, VIDIOC_STREAMOFF);
+ if (ret)
+ av_log(avctx, AV_LOG_ERROR, "VIDIOC_STREAMOFF %s\n", s->capture.name);
+}
+
#define OFFSET(x) offsetof(V4L2m2mPriv, x)
#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
@@ -271,6 +290,7 @@ static const AVCodecHWConfigInternal *v4l2_m2m_hw_configs[] = {
.init = v4l2_decode_init, \
.receive_frame = v4l2_receive_frame, \
.close = ff_v4l2_m2m_codec_end, \
+ .flush = v4l2_flush, \
.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_DRM_PRIME, \
AV_PIX_FMT_NV12, \
AV_PIX_FMT_NONE}, \
--
2.24.1

View File

@ -1,63 +0,0 @@
From f91c0f01a4c563129acd388272e0ac4795b83435 Mon Sep 17 00:00:00 2001
From: Lukas Rusak <lorusak@gmail.com>
Date: Fri, 31 Jan 2020 08:33:02 -0800
Subject: [PATCH 12/14] libavcodec: v4l2m2m: aspect ratio
---
libavcodec/v4l2_context.c | 26 +++++++++++++++++++++++++-
1 file changed, 25 insertions(+), 1 deletion(-)
diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c
index 12d40d597e..5c51399a4c 100644
--- a/libavcodec/v4l2_context.c
+++ b/libavcodec/v4l2_context.c
@@ -539,6 +539,24 @@ static int v4l2_get_coded_format(V4L2Context* ctx, uint32_t *p)
return 0;
}
+static AVRational v4l2_get_sar(V4L2Context* ctx)
+{
+ struct AVRational sar = { 1, 1 };
+ struct v4l2_cropcap cropcap;
+ int ret;
+
+ memset(&cropcap, 0, sizeof(cropcap));
+ cropcap.type = ctx->type;
+
+ ret = ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_CROPCAP, &cropcap);
+ if (ret)
+ return sar;
+
+ sar.num = cropcap.pixelaspect.numerator;
+ sar.den = cropcap.pixelaspect.denominator;
+ return sar;
+}
+
/*****************************************************************************
*
* V4L2 Context Interface
@@ -612,6 +630,7 @@ int ff_v4l2_context_enqueue_packet(V4L2Context* ctx, const AVPacket* pkt)
int ff_v4l2_context_dequeue_frame(V4L2Context* ctx, AVFrame* frame)
{
V4L2Buffer* avbuf = NULL;
+ int ret;
/*
* blocks until:
@@ -626,7 +645,12 @@ int ff_v4l2_context_dequeue_frame(V4L2Context* ctx, AVFrame* frame)
return AVERROR(EAGAIN);
}
- return ff_v4l2_buffer_buf_to_avframe(frame, avbuf);
+ ret = ff_v4l2_buffer_buf_to_avframe(frame, avbuf);
+ if (ret)
+ return ret;
+
+ frame->sample_aspect_ratio = v4l2_get_sar(ctx);
+ return 0;
}
int ff_v4l2_context_dequeue_packet(V4L2Context* ctx, AVPacket* pkt)
--
2.24.1

View File

@ -1,62 +0,0 @@
From da24c4a08dd820804d9bd0709815d954836277d8 Mon Sep 17 00:00:00 2001
From: Lukas Rusak <lorusak@gmail.com>
Date: Fri, 31 Jan 2020 08:35:37 -0800
Subject: [PATCH 13/14] libavcodec: v4l2m2m: save pkt
---
libavcodec/v4l2_m2m_dec.c | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c
index 47ac53df00..cf48ff4b22 100644
--- a/libavcodec/v4l2_m2m_dec.c
+++ b/libavcodec/v4l2_m2m_dec.c
@@ -131,6 +131,8 @@ static int v4l2_prepare_decoder(V4L2m2mContext *s)
return 0;
}
+static AVPacket saved_avpkt = { 0 };
+
static int v4l2_receive_frame(AVCodecContext *avctx, AVFrame *frame)
{
V4L2m2mContext *s = ((V4L2m2mPriv*)avctx->priv_data)->context;
@@ -139,9 +141,14 @@ static int v4l2_receive_frame(AVCodecContext *avctx, AVFrame *frame)
AVPacket avpkt = {0};
int ret;
- ret = ff_decode_get_packet(avctx, &avpkt);
- if (ret < 0 && ret != AVERROR_EOF)
- return ret;
+ if (saved_avpkt.size) {
+ avpkt = saved_avpkt;
+ memset(&saved_avpkt, 0, sizeof(saved_avpkt));
+ } else {
+ ret = ff_decode_get_packet(avctx, &avpkt);
+ if (ret < 0 && ret != AVERROR_EOF)
+ return ret;
+ }
if (s->draining)
goto dequeue;
@@ -150,6 +157,8 @@ static int v4l2_receive_frame(AVCodecContext *avctx, AVFrame *frame)
if (ret < 0) {
if (ret != AVERROR(ENOMEM))
return ret;
+
+ saved_avpkt = avpkt;
/* no input buffers available, continue dequeing */
}
@@ -167,7 +176,8 @@ static int v4l2_receive_frame(AVCodecContext *avctx, AVFrame *frame)
}
dequeue:
- av_packet_unref(&avpkt);
+ if (!saved_avpkt.size)
+ av_packet_unref(&avpkt);
return ff_v4l2_context_dequeue_frame(capture, frame);
}
--
2.24.1

View File

@ -1,25 +0,0 @@
From d317cac9ec2470bcdb44f92a82b64e4d132aeb51 Mon Sep 17 00:00:00 2001
From: Lukas Rusak <lorusak@gmail.com>
Date: Fri, 31 Jan 2020 09:00:51 -0800
Subject: [PATCH 14/14] libavcodec: v4l2m2m: only use a few output buffers
---
libavcodec/v4l2_m2m.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libavcodec/v4l2_m2m.h b/libavcodec/v4l2_m2m.h
index 4475618392..7e075e7e80 100644
--- a/libavcodec/v4l2_m2m.h
+++ b/libavcodec/v4l2_m2m.h
@@ -38,7 +38,7 @@
#define V4L_M2M_DEFAULT_OPTS \
{ "num_output_buffers", "Number of buffers in the output context",\
- OFFSET(num_output_buffers), AV_OPT_TYPE_INT, { .i64 = 16 }, 6, INT_MAX, FLAGS }
+ OFFSET(num_output_buffers), AV_OPT_TYPE_INT, { .i64 = 2 }, 1, INT_MAX, FLAGS }
typedef struct V4L2m2mContext {
char devname[PATH_MAX];
--
2.24.1