* [FFmpeg-devel] [PATCH] Optimization: support for libx264's mb_info
@ 2023-05-19 10:19 Carotti, Elias
2023-05-21 23:17 ` Stefano Sabatini
0 siblings, 1 reply; 33+ messages in thread
From: Carotti, Elias @ 2023-05-19 10:19 UTC (permalink / raw)
To: ffmpeg-devel
[-- Attachment #1: Type: text/plain, Size: 915 bytes --]
Hi again,
I am sending this patch again (I had missed a check for NULL), could
somebody please have a look at it?
It is mainly an optimization when the encoder knows in advance that
only portions of the whole frame changed and which areas actually did.
The patch allows a user to pass down information to libx264 information
about which parts of a frame changed (with respect to the preceding
one) to be exploited as a hint for P_SKIP-ing macroblocks which didn't
change.
This information is encoded in the mb_info field of the x264_param_t
much like the quant_offsets which are already used for the
AV_FRAME_DATA_REGIONS_OF_INTEREST side information.
Best,
Elias
NICE SRL, viale Monte Grappa 3/5, 20124 Milano, Italia, Registro delle Imprese di Milano Monza Brianza Lodi REA n. 2096882, Capitale Sociale: 10.329,14 EUR i.v., Cod. Fisc. e P.IVA 01133050052, Societa con Socio Unico
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Add-support-for-x264-s-MB_INFO.patch --]
[-- Type: text/x-patch; name="0001-Add-support-for-x264-s-MB_INFO.patch", Size: 10851 bytes --]
diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c
index cfdd422236..55c64daafa 100644
--- a/libavcodec/libx264.c
+++ b/libavcodec/libx264.c
@@ -30,6 +30,7 @@
#include "libavutil/stereo3d.h"
#include "libavutil/time.h"
#include "libavutil/intreadwrite.h"
+#include "libavutil/mb_info.h"
#include "avcodec.h"
#include "codec_internal.h"
#include "encode.h"
@@ -48,6 +49,9 @@
// from x264.h, for quant_offsets, Macroblocks are 16x16
// blocks of pixels (with respect to the luma plane)
#define MB_SIZE 16
+#define MB_LSIZE 4
+#define MB_FLOOR(x) ((x) >> (MB_LSIZE))
+#define MB_CEIL(x) MB_FLOOR((x) + (MB_SIZE - 1))
typedef struct X264Opaque {
#if FF_API_REORDERED_OPAQUE
@@ -123,6 +127,8 @@ typedef struct X264Context {
* encounter a frame with ROI side data.
*/
int roi_warned;
+
+ int mb_info;
} X264Context;
static void X264_log(void *p, int level, const char *fmt, va_list args)
@@ -295,6 +301,7 @@ static void free_picture(x264_picture_t *pic)
av_free(pic->extra_sei.payloads[i].payload);
av_freep(&pic->extra_sei.payloads);
av_freep(&pic->prop.quant_offsets);
+ av_freep(&pic->prop.mb_info);
pic->extra_sei.num_payloads = 0;
}
@@ -320,6 +327,45 @@ static enum AVPixelFormat csp_to_pixfmt(int csp)
return AV_PIX_FMT_NONE;
}
+static int setup_mb_info(AVCodecContext *ctx, x264_picture_t *pic,
+ const AVFrame *frame, const uint8_t *data,
+ size_t size)
+{
+ int mb_width = (frame->width + MB_SIZE - 1) / MB_SIZE;
+ int mb_height = (frame->height + MB_SIZE - 1) / MB_SIZE;
+ const AVMBInfoRect *mbinfo_rects;
+ size_t mbinfo_count;
+ uint8_t *mbinfo;
+
+ mbinfo_rects = (const AVMBInfoRect *)data;
+ mbinfo_count = size / sizeof(AVMBInfoRect);
+
+ mbinfo = av_calloc(mb_width * mb_height, sizeof(*mbinfo));
+ if (!mbinfo)
+ return AVERROR(ENOMEM);
+
+ /* Sets the default as constant, i.e. P_SKIP-able, then selectively resets the flag */
+ memset(mbinfo, X264_MBINFO_CONSTANT, sizeof(*mbinfo) * mb_width * mb_height);
+
+ for (int i = 0; i < mbinfo_count; i++) {
+ int min_y = MB_FLOOR(mbinfo_rects->y);
+ int max_y = MB_CEIL(mbinfo_rects->y + mbinfo_rects->height);
+ int min_x = MB_FLOOR(mbinfo_rects->x);
+ int max_x = MB_CEIL(mbinfo_rects->x + mbinfo_rects->width);
+
+ for (int mb_y = min_y; mb_y < max_y; ++mb_y) {
+ memset(mbinfo + mb_y * mb_width + min_x, 0, max_x - min_x);
+ }
+
+ mbinfo_rects++;
+ }
+
+ pic->prop.mb_info = mbinfo;
+ pic->prop.mb_info_free = av_free;
+
+ return 0;
+}
+
static int setup_roi(AVCodecContext *ctx, x264_picture_t *pic, int bit_depth,
const AVFrame *frame, const uint8_t *data, size_t size)
{
@@ -404,6 +450,7 @@ static int setup_frame(AVCodecContext *ctx, const AVFrame *frame,
int64_t wallclock = 0;
int bit_depth, ret;
AVFrameSideData *sd;
+ AVFrameSideData *mbinfo_sd;
*ppic = NULL;
if (!frame)
@@ -499,6 +546,17 @@ FF_ENABLE_DEPRECATION_WARNINGS
goto fail;
}
+ mbinfo_sd = av_frame_get_side_data(frame, AV_FRAME_DATA_MB_INFO);
+ if (mbinfo_sd) {
+ int ret = setup_mb_info(ctx, pic, frame, mbinfo_sd->data, mbinfo_sd->size);
+ if (ret < 0) {
+ /* No need to fail here, this is not fatal. We just proceed with no
+ * mb_info and log a message */
+
+ av_log(ctx, AV_LOG_WARNING, "mb_info setup failure\n");
+ }
+ }
+
if (x4->udu_sei) {
for (int j = 0; j < frame->nb_side_data; j++) {
AVFrameSideData *side_data = frame->side_data[j];
@@ -1096,6 +1154,9 @@ static av_cold int X264_init(AVCodecContext *avctx)
}
}
+ x4->params.analyse.b_mb_info = x4->mb_info;
+ x4->params.analyse.b_fast_pskip = 1;
+
// update AVCodecContext with x264 parameters
avctx->has_b_frames = x4->params.i_bframe ?
x4->params.i_bframe_pyramid ? 2 : 1 : 0;
@@ -1305,6 +1366,7 @@ static const AVOption options[] = {
{ "noise_reduction", "Noise reduction", OFFSET(noise_reduction), AV_OPT_TYPE_INT, { .i64 = -1 }, INT_MIN, INT_MAX, VE },
{ "udu_sei", "Use user data unregistered SEI if available", OFFSET(udu_sei), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
{ "x264-params", "Override the x264 configuration using a :-separated list of key=value parameters", OFFSET(x264_params), AV_OPT_TYPE_DICT, { 0 }, 0, 0, VE },
+ { "mb_info", "Set mb_info data through AVSideData, only useful when used from the API", OFFSET(mb_info), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
{ NULL },
};
diff --git a/libavutil/Makefile b/libavutil/Makefile
index dc9012f9a8..e99f448213 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -91,6 +91,7 @@ HEADERS = adler32.h \
tea.h \
tx.h \
film_grain_params.h \
+ mb_info.h \
ARCH_HEADERS = bswap.h \
intmath.h \
@@ -196,6 +197,7 @@ OBJS-$(CONFIG_VAAPI) += hwcontext_vaapi.o
OBJS-$(CONFIG_VIDEOTOOLBOX) += hwcontext_videotoolbox.o
OBJS-$(CONFIG_VDPAU) += hwcontext_vdpau.o
OBJS-$(CONFIG_VULKAN) += hwcontext_vulkan.o
+OBJS-$(CONFIG_LIBX264) += mb_info.o
OBJS-$(!CONFIG_VULKAN) += hwcontext_stub.o
@@ -219,6 +221,8 @@ SKIPHEADERS-$(CONFIG_VULKAN) += hwcontext_vulkan.h vulkan.h \
vulkan_functions.h \
vulkan_loader.h
+SKIPHEADERS-$(CONFIG_LIBX264) += mb_info.h
+
TESTPROGS = adler32 \
aes \
aes_ctr \
diff --git a/libavutil/frame.h b/libavutil/frame.h
index f85d630c5c..9c0fdcf25d 100644
--- a/libavutil/frame.h
+++ b/libavutil/frame.h
@@ -214,6 +214,16 @@ enum AVFrameSideDataType {
* Ambient viewing environment metadata, as defined by H.274.
*/
AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT,
+
+ /**
+ * Provide macro block encoder-specific hinting information for the encoder
+ * processing. It can be used to pass information about which macroblock
+ * can be skipped because it hasn't changed from the corresponding one in
+ * the previous frame. This is useful for applications which know in
+ * advance this information to speed up real-time encoding. Currently only
+ * used by libx264.
+ */
+ AV_FRAME_DATA_MB_INFO,
};
enum AVActiveFormatDescription {
diff --git a/libavutil/mb_info.c b/libavutil/mb_info.c
new file mode 100644
index 0000000000..1e4a57b8d4
--- /dev/null
+++ b/libavutil/mb_info.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2023 Elias Carotti <eliascrt at amazon dot com>
+ *
+ * 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 <string.h>
+
+#include "avstring.h"
+#include "frame.h"
+#include "macros.h"
+#include "mem.h"
+#include "mb_info.h"
+
+
+AVMBInfoRect *av_mb_info_create_side_data(AVFrame *frame,
+ AVMBInfoRect *rects,
+ size_t num_rects)
+{
+ AVFrameSideData *side_data;
+ AVMBInfoRect *par;
+
+ side_data = av_frame_new_side_data(frame,
+ AV_FRAME_DATA_MB_INFO,
+ num_rects * sizeof(AVMBInfoRect));
+
+ if (!side_data)
+ return NULL;
+
+ par = (AVMBInfoRect *)side_data->data;
+
+ /* Just copies the rects over the newly allocated buffer */
+ memcpy(par, rects, sizeof(AVMBInfoRect) * num_rects);
+
+ return par;
+}
+
diff --git a/libavutil/mb_info.h b/libavutil/mb_info.h
new file mode 100644
index 0000000000..918cf167aa
--- /dev/null
+++ b/libavutil/mb_info.h
@@ -0,0 +1,46 @@
+/**
+ * Copyright 2023 Elias Carotti <eliascrt at amazon dot com>
+ *
+ * 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
+ */
+
+#ifndef AVUTIL_MB_INFO_H
+#define AVUTIL_MB_INFO_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include "libavutil/avassert.h"
+#include "libavutil/frame.h"
+
+typedef struct _AVMBInfoRect {
+ uint32_t x, y;
+ uint32_t width, height;
+} AVMBInfoRect;
+
+/**
+ * Allocate memory for a vector of AVMBInfoRect in the given AVFrame
+ * {@code frame} as AVFrameSideData of type AV_FRAME_DATA_MB_INFO.
+ * The side data contains a list of rectangles for the portions of the frame
+ * which changed from the last encoded one. The rest will be hinted to be
+ * P_SKIP-ped. Portions of the rects which are not on macroblock boundaries
+ * are not handled as P_SKIPS.
+ */
+AVMBInfoRect *av_mb_info_create_side_data(AVFrame *frame,
+ AVMBInfoRect *rects,
+ size_t num_rects);
+
+#endif /* AVUTIL_MB_INFO_H */
[-- Attachment #3: Type: text/plain, Size: 251 bytes --]
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [FFmpeg-devel] [PATCH] Optimization: support for libx264's mb_info
2023-05-19 10:19 [FFmpeg-devel] [PATCH] Optimization: support for libx264's mb_info Carotti, Elias
@ 2023-05-21 23:17 ` Stefano Sabatini
2023-05-22 9:19 ` Carotti, Elias
0 siblings, 1 reply; 33+ messages in thread
From: Stefano Sabatini @ 2023-05-21 23:17 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On date Friday 2023-05-19 10:19:03 +0000, Carotti, Elias wrote:
>
> Hi again,
> I am sending this patch again (I had missed a check for NULL), could
> somebody please have a look at it?
>
> It is mainly an optimization when the encoder knows in advance that
> only portions of the whole frame changed and which areas actually did.
>
> The patch allows a user to pass down information to libx264 information
> about which parts of a frame changed (with respect to the preceding
> one) to be exploited as a hint for P_SKIP-ing macroblocks which didn't
> change.
> This information is encoded in the mb_info field of the x264_param_t
> much like the quant_offsets which are already used for the
> AV_FRAME_DATA_REGIONS_OF_INTEREST side information.
Please send a git format-patch (complete with commit log information)
to simplify integration.
[...]
> diff --git a/libavutil/mb_info.h b/libavutil/mb_info.h
> new file mode 100644
> index 0000000000..918cf167aa
> --- /dev/null
> +++ b/libavutil/mb_info.h
> @@ -0,0 +1,46 @@
[...]
> +#ifndef AVUTIL_MB_INFO_H
> +#define AVUTIL_MB_INFO_H
> +
> +#include <stddef.h>
> +#include <stdint.h>
> +#include "libavutil/avassert.h"
> +#include "libavutil/frame.h"
> +
> +typedef struct _AVMBInfoRect {
nit: strip the _ before the struct name
> + uint32_t x, y;
> + uint32_t width, height;
> +} AVMBInfoRect;
> +
> +/**
> + * Allocate memory for a vector of AVMBInfoRect in the given AVFrame
> + * {@code frame} as AVFrameSideData of type AV_FRAME_DATA_MB_INFO.
> + * The side data contains a list of rectangles for the portions of the frame
> + * which changed from the last encoded one. The rest will be hinted to be
> + * P_SKIP-ped. Portions of the rects which are not on macroblock boundaries
> + * are not handled as P_SKIPS.
> + */
> +AVMBInfoRect *av_mb_info_create_side_data(AVFrame *frame,
> + AVMBInfoRect *rects,
> + size_t num_rects);
Probably this can be generalized with a flag defining the hinting type
(you might want either to specify the constant or non-constant rects),
in fact this data is pretty macro-block agnostic.
What about AVVideoHintInfo containing a hint (CONSTANT, VARIANT) and a
list of rects?
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [FFmpeg-devel] [PATCH] Optimization: support for libx264's mb_info
2023-05-21 23:17 ` Stefano Sabatini
@ 2023-05-22 9:19 ` Carotti, Elias
2023-05-29 17:56 ` Carotti, Elias
0 siblings, 1 reply; 33+ messages in thread
From: Carotti, Elias @ 2023-05-22 9:19 UTC (permalink / raw)
To: ffmpeg-devel
[-- Attachment #1: Type: text/plain, Size: 3459 bytes --]
Hi Stefano,
thanks for checking the patch.
Please find it attached in the required format.
Best,
Elias
On Mon, 2023-05-22 at 01:17 +0200, Stefano Sabatini wrote:
> CAUTION: This email originated from outside of the organization. Do
> not click links or open attachments unless you can confirm the sender
> and know the content is safe.
>
>
>
> On date Friday 2023-05-19 10:19:03 +0000, Carotti, Elias wrote:
> >
> > Hi again,
> > I am sending this patch again (I had missed a check for NULL),
> > could
> > somebody please have a look at it?
> >
> > It is mainly an optimization when the encoder knows in advance that
> > only portions of the whole frame changed and which areas actually
> > did.
> >
> > The patch allows a user to pass down information to libx264
> > information
> > about which parts of a frame changed (with respect to the preceding
> > one) to be exploited as a hint for P_SKIP-ing macroblocks which
> > didn't
> > change.
> > This information is encoded in the mb_info field of the
> > x264_param_t
> > much like the quant_offsets which are already used for the
> > AV_FRAME_DATA_REGIONS_OF_INTEREST side information.
>
> Please send a git format-patch (complete with commit log information)
> to simplify integration.
>
> [...]
> > diff --git a/libavutil/mb_info.h b/libavutil/mb_info.h
> > new file mode 100644
> > index 0000000000..918cf167aa
> > --- /dev/null
> > +++ b/libavutil/mb_info.h
> > @@ -0,0 +1,46 @@
> [...]
> > +#ifndef AVUTIL_MB_INFO_H
> > +#define AVUTIL_MB_INFO_H
> > +
> > +#include <stddef.h>
> > +#include <stdint.h>
> > +#include "libavutil/avassert.h"
> > +#include "libavutil/frame.h"
> > +
>
> > +typedef struct _AVMBInfoRect {
>
> nit: strip the _ before the struct name
>
> > + uint32_t x, y;
> > + uint32_t width, height;
> > +} AVMBInfoRect;
> > +
> > +/**
> > + * Allocate memory for a vector of AVMBInfoRect in the given
> > AVFrame
> > + * {@code frame} as AVFrameSideData of type AV_FRAME_DATA_MB_INFO.
>
> > + * The side data contains a list of rectangles for the portions of
> > the frame
> > + * which changed from the last encoded one. The rest will be
> > hinted to be
> > + * P_SKIP-ped. Portions of the rects which are not on macroblock
> > boundaries
> > + * are not handled as P_SKIPS.
> > + */
>
> > +AVMBInfoRect *av_mb_info_create_side_data(AVFrame *frame,
> > + AVMBInfoRect *rects,
> > + size_t num_rects);
>
> Probably this can be generalized with a flag defining the hinting
> type
> (you might want either to specify the constant or non-constant
> rects),
> in fact this data is pretty macro-block agnostic.
>
> What about AVVideoHintInfo containing a hint (CONSTANT, VARIANT) and
> a
> list of rects?
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
NICE SRL, viale Monte Grappa 3/5, 20124 Milano, Italia, Registro delle Imprese di Milano Monza Brianza Lodi REA n. 2096882, Capitale Sociale: 10.329,14 EUR i.v., Cod. Fisc. e P.IVA 01133050052, Societa con Socio Unico
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Add-support-for-libx264-s-MB_INFO.patch --]
[-- Type: text/x-patch; name="0001-Add-support-for-libx264-s-MB_INFO.patch", Size: 11672 bytes --]
From 9337a90552032069ae3b20371e657f698536d19b Mon Sep 17 00:00:00 2001
From: Elias Carotti <eliascrt at amazon dot it>
Date: Wed, 19 Apr 2023 11:49:39 +0200
Subject: [PATCH] Add support for libx264's MB_INFO
libx264's x264_image_properties_t, which is passed to the encoding function,
contains a field to pass down information on the portions of the frame which
changed with respect to the previous one (used for prediction) to mark
unchanged macroblocks P_SKIP.
---
libavcodec/libx264.c | 62 ++++++++++++++++++++++++++++++++++++++++++++
libavutil/Makefile | 4 +++
libavutil/frame.h | 10 +++++++
libavutil/mb_info.c | 51 ++++++++++++++++++++++++++++++++++++
libavutil/mb_info.h | 46 ++++++++++++++++++++++++++++++++
5 files changed, 173 insertions(+)
create mode 100644 libavutil/mb_info.c
create mode 100644 libavutil/mb_info.h
diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c
index 5736f1efa7..5953c4ce31 100644
--- a/libavcodec/libx264.c
+++ b/libavcodec/libx264.c
@@ -30,6 +30,7 @@
#include "libavutil/stereo3d.h"
#include "libavutil/time.h"
#include "libavutil/intreadwrite.h"
+#include "libavutil/mb_info.h"
#include "avcodec.h"
#include "codec_internal.h"
#include "encode.h"
@@ -48,6 +49,9 @@
// from x264.h, for quant_offsets, Macroblocks are 16x16
// blocks of pixels (with respect to the luma plane)
#define MB_SIZE 16
+#define MB_LSIZE 4
+#define MB_FLOOR(x) ((x) >> (MB_LSIZE))
+#define MB_CEIL(x) MB_FLOOR((x) + (MB_SIZE - 1))
typedef struct X264Opaque {
#if FF_API_REORDERED_OPAQUE
@@ -123,6 +127,8 @@ typedef struct X264Context {
* encounter a frame with ROI side data.
*/
int roi_warned;
+
+ int mb_info;
} X264Context;
static void X264_log(void *p, int level, const char *fmt, va_list args)
@@ -295,6 +301,7 @@ static void free_picture(x264_picture_t *pic)
av_free(pic->extra_sei.payloads[i].payload);
av_freep(&pic->extra_sei.payloads);
av_freep(&pic->prop.quant_offsets);
+ av_freep(&pic->prop.mb_info);
pic->extra_sei.num_payloads = 0;
}
@@ -320,6 +327,45 @@ static enum AVPixelFormat csp_to_pixfmt(int csp)
return AV_PIX_FMT_NONE;
}
+static int setup_mb_info(AVCodecContext *ctx, x264_picture_t *pic,
+ const AVFrame *frame, const uint8_t *data,
+ size_t size)
+{
+ int mb_width = (frame->width + MB_SIZE - 1) / MB_SIZE;
+ int mb_height = (frame->height + MB_SIZE - 1) / MB_SIZE;
+ const AVMBInfoRect *mbinfo_rects;
+ size_t mbinfo_count;
+ uint8_t *mbinfo;
+
+ mbinfo_rects = (const AVMBInfoRect *)data;
+ mbinfo_count = size / sizeof(AVMBInfoRect);
+
+ mbinfo = av_calloc(mb_width * mb_height, sizeof(*mbinfo));
+ if (!mbinfo)
+ return AVERROR(ENOMEM);
+
+ /* Sets the default as constant, i.e. P_SKIP-able, then selectively resets the flag */
+ memset(mbinfo, X264_MBINFO_CONSTANT, sizeof(*mbinfo) * mb_width * mb_height);
+
+ for (int i = 0; i < mbinfo_count; i++) {
+ int min_y = MB_FLOOR(mbinfo_rects->y);
+ int max_y = MB_CEIL(mbinfo_rects->y + mbinfo_rects->height);
+ int min_x = MB_FLOOR(mbinfo_rects->x);
+ int max_x = MB_CEIL(mbinfo_rects->x + mbinfo_rects->width);
+
+ for (int mb_y = min_y; mb_y < max_y; ++mb_y) {
+ memset(mbinfo + mb_y * mb_width + min_x, 0, max_x - min_x);
+ }
+
+ mbinfo_rects++;
+ }
+
+ pic->prop.mb_info = mbinfo;
+ pic->prop.mb_info_free = av_free;
+
+ return 0;
+}
+
static int setup_roi(AVCodecContext *ctx, x264_picture_t *pic, int bit_depth,
const AVFrame *frame, const uint8_t *data, size_t size)
{
@@ -404,6 +450,7 @@ static int setup_frame(AVCodecContext *ctx, const AVFrame *frame,
int64_t wallclock = 0;
int bit_depth, ret;
AVFrameSideData *sd;
+ AVFrameSideData *mbinfo_sd;
*ppic = NULL;
if (!frame)
@@ -499,6 +546,17 @@ FF_ENABLE_DEPRECATION_WARNINGS
goto fail;
}
+ mbinfo_sd = av_frame_get_side_data(frame, AV_FRAME_DATA_MB_INFO);
+ if (mbinfo_sd) {
+ int ret = setup_mb_info(ctx, pic, frame, mbinfo_sd->data, mbinfo_sd->size);
+ if (ret < 0) {
+ /* No need to fail here, this is not fatal. We just proceed with no
+ * mb_info and log a message */
+
+ av_log(ctx, AV_LOG_WARNING, "mb_info setup failure\n");
+ }
+ }
+
if (x4->udu_sei) {
for (int j = 0; j < frame->nb_side_data; j++) {
AVFrameSideData *side_data = frame->side_data[j];
@@ -1102,6 +1160,9 @@ FF_ENABLE_DEPRECATION_WARNINGS
}
}
+ x4->params.analyse.b_mb_info = x4->mb_info;
+ x4->params.analyse.b_fast_pskip = 1;
+
// update AVCodecContext with x264 parameters
avctx->has_b_frames = x4->params.i_bframe ?
x4->params.i_bframe_pyramid ? 2 : 1 : 0;
@@ -1311,6 +1372,7 @@ static const AVOption options[] = {
{ "noise_reduction", "Noise reduction", OFFSET(noise_reduction), AV_OPT_TYPE_INT, { .i64 = -1 }, INT_MIN, INT_MAX, VE },
{ "udu_sei", "Use user data unregistered SEI if available", OFFSET(udu_sei), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
{ "x264-params", "Override the x264 configuration using a :-separated list of key=value parameters", OFFSET(x264_params), AV_OPT_TYPE_DICT, { 0 }, 0, 0, VE },
+ { "mb_info", "Set mb_info data through AVSideData, only useful when used from the API", OFFSET(mb_info), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
{ NULL },
};
diff --git a/libavutil/Makefile b/libavutil/Makefile
index dc9012f9a8..e99f448213 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -91,6 +91,7 @@ HEADERS = adler32.h \
tea.h \
tx.h \
film_grain_params.h \
+ mb_info.h \
ARCH_HEADERS = bswap.h \
intmath.h \
@@ -196,6 +197,7 @@ OBJS-$(CONFIG_VAAPI) += hwcontext_vaapi.o
OBJS-$(CONFIG_VIDEOTOOLBOX) += hwcontext_videotoolbox.o
OBJS-$(CONFIG_VDPAU) += hwcontext_vdpau.o
OBJS-$(CONFIG_VULKAN) += hwcontext_vulkan.o
+OBJS-$(CONFIG_LIBX264) += mb_info.o
OBJS-$(!CONFIG_VULKAN) += hwcontext_stub.o
@@ -219,6 +221,8 @@ SKIPHEADERS-$(CONFIG_VULKAN) += hwcontext_vulkan.h vulkan.h \
vulkan_functions.h \
vulkan_loader.h
+SKIPHEADERS-$(CONFIG_LIBX264) += mb_info.h
+
TESTPROGS = adler32 \
aes \
aes_ctr \
diff --git a/libavutil/frame.h b/libavutil/frame.h
index a491315f25..e5d2b04784 100644
--- a/libavutil/frame.h
+++ b/libavutil/frame.h
@@ -214,6 +214,16 @@ enum AVFrameSideDataType {
* Ambient viewing environment metadata, as defined by H.274.
*/
AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT,
+
+ /**
+ * Provide macro block encoder-specific hinting information for the encoder
+ * processing. It can be used to pass information about which macroblock
+ * can be skipped because it hasn't changed from the corresponding one in
+ * the previous frame. This is useful for applications which know in
+ * advance this information to speed up real-time encoding. Currently only
+ * used by libx264.
+ */
+ AV_FRAME_DATA_MB_INFO,
};
enum AVActiveFormatDescription {
diff --git a/libavutil/mb_info.c b/libavutil/mb_info.c
new file mode 100644
index 0000000000..1e4a57b8d4
--- /dev/null
+++ b/libavutil/mb_info.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2023 Elias Carotti <eliascrt at amazon dot it>
+ *
+ * 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 <string.h>
+
+#include "avstring.h"
+#include "frame.h"
+#include "macros.h"
+#include "mem.h"
+#include "mb_info.h"
+
+
+AVMBInfoRect *av_mb_info_create_side_data(AVFrame *frame,
+ AVMBInfoRect *rects,
+ size_t num_rects)
+{
+ AVFrameSideData *side_data;
+ AVMBInfoRect *par;
+
+ side_data = av_frame_new_side_data(frame,
+ AV_FRAME_DATA_MB_INFO,
+ num_rects * sizeof(AVMBInfoRect));
+
+ if (!side_data)
+ return NULL;
+
+ par = (AVMBInfoRect *)side_data->data;
+
+ /* Just copies the rects over the newly allocated buffer */
+ memcpy(par, rects, sizeof(AVMBInfoRect) * num_rects);
+
+ return par;
+}
+
diff --git a/libavutil/mb_info.h b/libavutil/mb_info.h
new file mode 100644
index 0000000000..c63e0a691e
--- /dev/null
+++ b/libavutil/mb_info.h
@@ -0,0 +1,46 @@
+/**
+ * Copyright 2023 Elias Carotti <eliascrt at amazon dot it>
+ *
+ * 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
+ */
+
+#ifndef AVUTIL_MB_INFO_H
+#define AVUTIL_MB_INFO_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include "libavutil/avassert.h"
+#include "libavutil/frame.h"
+
+typedef struct AVMBInfoRect {
+ uint32_t x, y;
+ uint32_t width, height;
+} AVMBInfoRect;
+
+/**
+ * Allocate memory for a vector of AVMBInfoRect in the given AVFrame
+ * {@code frame} as AVFrameSideData of type AV_FRAME_DATA_MB_INFO.
+ * The side data contains a list of rectangles for the portions of the frame
+ * which changed from the last encoded one. The rest will be hinted to be
+ * P_SKIP-ped. Portions of the rects which are not on macroblock boundaries
+ * are not handled as P_SKIPS.
+ */
+AVMBInfoRect *av_mb_info_create_side_data(AVFrame *frame,
+ AVMBInfoRect *rects,
+ size_t num_rects);
+
+#endif /* AVUTIL_MB_INFO_H */
--
2.34.1
[-- Attachment #3: Type: text/plain, Size: 251 bytes --]
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [FFmpeg-devel] [PATCH] Optimization: support for libx264's mb_info
2023-05-22 9:19 ` Carotti, Elias
@ 2023-05-29 17:56 ` Carotti, Elias
2023-06-04 15:29 ` Stefano Sabatini
0 siblings, 1 reply; 33+ messages in thread
From: Carotti, Elias @ 2023-05-29 17:56 UTC (permalink / raw)
To: ffmpeg-devel
[-- Attachment #1: Type: text/plain, Size: 4529 bytes --]
Hi Stefano, hi all,
please find the updated patch according to the suggestions. Now it is
possible to specify whether the rectangles refer to the part we want to
hint as P_SKIP or to the rest portion of the frame.
Best,
Elias
On Mon, 2023-05-22 at 09:19 +0000, Carotti, Elias wrote:
> Hi Stefano,
> thanks for checking the patch.
> Please find it attached in the required format.
> Best,
> Elias
>
>
> On Mon, 2023-05-22 at 01:17 +0200, Stefano Sabatini wrote:
> > CAUTION: This email originated from outside of the organization. Do
> > not click links or open attachments unless you can confirm the
> > sender
> > and know the content is safe.
> >
> >
> >
> > On date Friday 2023-05-19 10:19:03 +0000, Carotti, Elias wrote:
> > >
> > > Hi again,
> > > I am sending this patch again (I had missed a check for NULL),
> > > could
> > > somebody please have a look at it?
> > >
> > > It is mainly an optimization when the encoder knows in advance
> > > that
> > > only portions of the whole frame changed and which areas actually
> > > did.
> > >
> > > The patch allows a user to pass down information to libx264
> > > information
> > > about which parts of a frame changed (with respect to the
> > > preceding
> > > one) to be exploited as a hint for P_SKIP-ing macroblocks which
> > > didn't
> > > change.
> > > This information is encoded in the mb_info field of the
> > > x264_param_t
> > > much like the quant_offsets which are already used for the
> > > AV_FRAME_DATA_REGIONS_OF_INTEREST side information.
> >
> > Please send a git format-patch (complete with commit log
> > information)
> > to simplify integration.
> >
> > [...]
> > > diff --git a/libavutil/mb_info.h b/libavutil/mb_info.h
> > > new file mode 100644
> > > index 0000000000..918cf167aa
> > > --- /dev/null
> > > +++ b/libavutil/mb_info.h
> > > @@ -0,0 +1,46 @@
> > [...]
> > > +#ifndef AVUTIL_MB_INFO_H
> > > +#define AVUTIL_MB_INFO_H
> > > +
> > > +#include <stddef.h>
> > > +#include <stdint.h>
> > > +#include "libavutil/avassert.h"
> > > +#include "libavutil/frame.h"
> > > +
> >
> > > +typedef struct _AVMBInfoRect {
> >
> > nit: strip the _ before the struct name
> >
> > > + uint32_t x, y;
> > > + uint32_t width, height;
> > > +} AVMBInfoRect;
> > > +
> > > +/**
> > > + * Allocate memory for a vector of AVMBInfoRect in the given
> > > AVFrame
> > > + * {@code frame} as AVFrameSideData of type
> > > AV_FRAME_DATA_MB_INFO.
> >
> > > + * The side data contains a list of rectangles for the portions
> > > of
> > > the frame
> > > + * which changed from the last encoded one. The rest will be
> > > hinted to be
> > > + * P_SKIP-ped. Portions of the rects which are not on
> > > macroblock
> > > boundaries
> > > + * are not handled as P_SKIPS.
> > > + */
> >
> > > +AVMBInfoRect *av_mb_info_create_side_data(AVFrame *frame,
> > > + AVMBInfoRect *rects,
> > > + size_t num_rects);
> >
> > Probably this can be generalized with a flag defining the hinting
> > type
> > (you might want either to specify the constant or non-constant
> > rects),
> > in fact this data is pretty macro-block agnostic.
> >
> > What about AVVideoHintInfo containing a hint (CONSTANT, VARIANT)
> > and
> > a
> > list of rects?
> > _______________________________________________
> > ffmpeg-devel mailing list
> > ffmpeg-devel@ffmpeg.org
> > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> >
> > To unsubscribe, visit link above, or email
> > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>
>
>
>
> NICE SRL, viale Monte Grappa 3/5, 20124 Milano, Italia, Registro
> delle Imprese di Milano Monza Brianza Lodi REA n. 2096882, Capitale
> Sociale: 10.329,14 EUR i.v., Cod. Fisc. e P.IVA 01133050052, Societa
> con Socio Unico
>
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
NICE SRL, viale Monte Grappa 3/5, 20124 Milano, Italia, Registro delle Imprese di Milano Monza Brianza Lodi REA n. 2096882, Capitale Sociale: 10.329,14 EUR i.v., Cod. Fisc. e P.IVA 01133050052, Societa con Socio Unico
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Add-support-for-libx264-s-MB_INFO.patch --]
[-- Type: text/x-patch; name="0001-Add-support-for-libx264-s-MB_INFO.patch", Size: 15021 bytes --]
From 7cb97ee977197e310a932b2d7a53bf5c6e99990e Mon Sep 17 00:00:00 2001
From: Elias Carotti <eliascrt@amazon.it>
Date: Wed, 19 Apr 2023 11:49:39 +0200
Subject: [PATCH] Add support for libx264's MB_INFO
libx264's x264_image_properties_t, which is passed to the encoding function,
contains a field to pass down information on the portions of the frame which
changed with respect to the previous one (used for prediction) to mark
unchanged macroblocks P_SKIP.
---
libavcodec/libx264.c | 81 +++++++++++++++++++++++++++++++++
libavutil/Makefile | 4 ++
libavutil/frame.h | 10 +++++
libavutil/video_hint_info.c | 89 +++++++++++++++++++++++++++++++++++++
libavutil/video_hint_info.h | 87 ++++++++++++++++++++++++++++++++++++
5 files changed, 271 insertions(+)
create mode 100644 libavutil/video_hint_info.c
create mode 100644 libavutil/video_hint_info.h
diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c
index 5736f1efa7..32fa80d0a1 100644
--- a/libavcodec/libx264.c
+++ b/libavcodec/libx264.c
@@ -30,6 +30,7 @@
#include "libavutil/stereo3d.h"
#include "libavutil/time.h"
#include "libavutil/intreadwrite.h"
+#include "libavutil/video_hint_info.h"
#include "avcodec.h"
#include "codec_internal.h"
#include "encode.h"
@@ -48,6 +49,9 @@
// from x264.h, for quant_offsets, Macroblocks are 16x16
// blocks of pixels (with respect to the luma plane)
#define MB_SIZE 16
+#define MB_LSIZE 4
+#define MB_FLOOR(x) ((x) >> (MB_LSIZE))
+#define MB_CEIL(x) MB_FLOOR((x) + (MB_SIZE - 1))
typedef struct X264Opaque {
#if FF_API_REORDERED_OPAQUE
@@ -123,6 +127,8 @@ typedef struct X264Context {
* encounter a frame with ROI side data.
*/
int roi_warned;
+
+ int mb_info;
} X264Context;
static void X264_log(void *p, int level, const char *fmt, va_list args)
@@ -295,6 +301,7 @@ static void free_picture(x264_picture_t *pic)
av_free(pic->extra_sei.payloads[i].payload);
av_freep(&pic->extra_sei.payloads);
av_freep(&pic->prop.quant_offsets);
+ av_freep(&pic->prop.mb_info);
pic->extra_sei.num_payloads = 0;
}
@@ -320,6 +327,64 @@ static enum AVPixelFormat csp_to_pixfmt(int csp)
return AV_PIX_FMT_NONE;
}
+static int setup_mb_info(AVCodecContext *ctx, x264_picture_t *pic,
+ const AVFrame *frame,
+ const AVVideoHint *info)
+{
+ int mb_width = (frame->width + MB_SIZE - 1) / MB_SIZE;
+ int mb_height = (frame->height + MB_SIZE - 1) / MB_SIZE;
+
+ const AVVideoRect *mbinfo_rects;
+ int nb_rects;
+ uint8_t *mbinfo;
+
+ mbinfo_rects = (const AVVideoRect *)av_video_hint_rects(info);
+ nb_rects = info->nb_rects;
+
+ mbinfo = av_calloc(mb_width * mb_height, sizeof(*mbinfo));
+ if (!mbinfo)
+ return AVERROR(ENOMEM);
+
+ if (info->type == AV_VIDEO_HINT_CHANGED) {
+ /* Sets the default as constant, i.e. P_SKIP-able, then selectively resets the flag */
+ memset(mbinfo, X264_MBINFO_CONSTANT, sizeof(*mbinfo) * mb_width * mb_height);
+
+ for (int i = 0; i < nb_rects; i++) {
+ int min_y = MB_FLOOR(mbinfo_rects->y);
+ int max_y = MB_CEIL(mbinfo_rects->y + mbinfo_rects->height);
+ int min_x = MB_FLOOR(mbinfo_rects->x);
+ int max_x = MB_CEIL(mbinfo_rects->x + mbinfo_rects->width);
+
+ for (int mb_y = min_y; mb_y < max_y; ++mb_y) {
+ memset(mbinfo + mb_y * mb_width + min_x, 0, max_x - min_x);
+ }
+
+ mbinfo_rects++;
+ }
+ } else {
+ /* Sets the default as changed, i.e. *not* P_SKIP-able, then selectively sets the flag */
+ memset(mbinfo, 0, sizeof(*mbinfo) * mb_width * mb_height);
+
+ for (int i = 0; i < nb_rects; i++) {
+ int min_y = MB_CEIL(mbinfo_rects->y);
+ int max_y = MB_FLOOR(mbinfo_rects->y + mbinfo_rects->height);
+ int min_x = MB_CEIL(mbinfo_rects->x);
+ int max_x = MB_FLOOR(mbinfo_rects->x + mbinfo_rects->width);
+
+ for (int mb_y = min_y; mb_y < max_y; ++mb_y) {
+ memset(mbinfo + mb_y * mb_width + min_x, X264_MBINFO_CONSTANT, max_x - min_x);
+ }
+
+ mbinfo_rects++;
+ }
+ }
+
+ pic->prop.mb_info = mbinfo;
+ pic->prop.mb_info_free = av_free;
+
+ return 0;
+}
+
static int setup_roi(AVCodecContext *ctx, x264_picture_t *pic, int bit_depth,
const AVFrame *frame, const uint8_t *data, size_t size)
{
@@ -404,6 +469,7 @@ static int setup_frame(AVCodecContext *ctx, const AVFrame *frame,
int64_t wallclock = 0;
int bit_depth, ret;
AVFrameSideData *sd;
+ AVFrameSideData *mbinfo_sd;
*ppic = NULL;
if (!frame)
@@ -499,6 +565,17 @@ FF_ENABLE_DEPRECATION_WARNINGS
goto fail;
}
+ mbinfo_sd = av_frame_get_side_data(frame, AV_FRAME_DATA_VIDEO_HINT);
+ if (mbinfo_sd) {
+ int ret = setup_mb_info(ctx, pic, frame, (const AVVideoHint *)mbinfo_sd->data);
+ if (ret < 0) {
+ /* No need to fail here, this is not fatal. We just proceed with no
+ * mb_info and log a message */
+
+ av_log(ctx, AV_LOG_WARNING, "mb_info setup failure\n");
+ }
+ }
+
if (x4->udu_sei) {
for (int j = 0; j < frame->nb_side_data; j++) {
AVFrameSideData *side_data = frame->side_data[j];
@@ -1102,6 +1179,9 @@ FF_ENABLE_DEPRECATION_WARNINGS
}
}
+ x4->params.analyse.b_mb_info = x4->mb_info;
+ x4->params.analyse.b_fast_pskip = 1;
+
// update AVCodecContext with x264 parameters
avctx->has_b_frames = x4->params.i_bframe ?
x4->params.i_bframe_pyramid ? 2 : 1 : 0;
@@ -1311,6 +1391,7 @@ static const AVOption options[] = {
{ "noise_reduction", "Noise reduction", OFFSET(noise_reduction), AV_OPT_TYPE_INT, { .i64 = -1 }, INT_MIN, INT_MAX, VE },
{ "udu_sei", "Use user data unregistered SEI if available", OFFSET(udu_sei), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
{ "x264-params", "Override the x264 configuration using a :-separated list of key=value parameters", OFFSET(x264_params), AV_OPT_TYPE_DICT, { 0 }, 0, 0, VE },
+ { "mb_info", "Set mb_info data through AVSideData, only useful when used from the API", OFFSET(mb_info), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
{ NULL },
};
diff --git a/libavutil/Makefile b/libavutil/Makefile
index dc9012f9a8..bb5ecc3235 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -91,6 +91,7 @@ HEADERS = adler32.h \
tea.h \
tx.h \
film_grain_params.h \
+ video_hint_info.h \
ARCH_HEADERS = bswap.h \
intmath.h \
@@ -196,6 +197,7 @@ OBJS-$(CONFIG_VAAPI) += hwcontext_vaapi.o
OBJS-$(CONFIG_VIDEOTOOLBOX) += hwcontext_videotoolbox.o
OBJS-$(CONFIG_VDPAU) += hwcontext_vdpau.o
OBJS-$(CONFIG_VULKAN) += hwcontext_vulkan.o
+OBJS-$(CONFIG_LIBX264) += video_hint_info.o
OBJS-$(!CONFIG_VULKAN) += hwcontext_stub.o
@@ -219,6 +221,8 @@ SKIPHEADERS-$(CONFIG_VULKAN) += hwcontext_vulkan.h vulkan.h \
vulkan_functions.h \
vulkan_loader.h
+SKIPHEADERS-$(CONFIG_LIBX264) += video_hint_info.h
+
TESTPROGS = adler32 \
aes \
aes_ctr \
diff --git a/libavutil/frame.h b/libavutil/frame.h
index a491315f25..0e765e5499 100644
--- a/libavutil/frame.h
+++ b/libavutil/frame.h
@@ -214,6 +214,16 @@ enum AVFrameSideDataType {
* Ambient viewing environment metadata, as defined by H.274.
*/
AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT,
+
+ /**
+ * Provide macro block encoder-specific hinting information for the encoder
+ * processing. It can be used to pass information about which macroblock
+ * can be skipped because it hasn't changed from the corresponding one in
+ * the previous frame. This is useful for applications which know in
+ * advance this information to speed up real-time encoding. Currently only
+ * used by libx264.
+ */
+ AV_FRAME_DATA_VIDEO_HINT,
};
enum AVActiveFormatDescription {
diff --git a/libavutil/video_hint_info.c b/libavutil/video_hint_info.c
new file mode 100644
index 0000000000..0a763962da
--- /dev/null
+++ b/libavutil/video_hint_info.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2023 Elias Carotti <eliascrt at amazon dot it>
+ *
+ * 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 <string.h>
+
+#include "avstring.h"
+#include "frame.h"
+#include "macros.h"
+#include "mem.h"
+#include "video_hint_info.h"
+
+AVVideoHint *av_video_hint_alloc(AVVideoRect *rects,
+ size_t nb_rects,
+ VideoHintType type,
+ size_t* out_size)
+{
+ struct TestStruct {
+ AVVideoHint p;
+ AVVideoRect b;
+ };
+ const size_t blocks_offset = offsetof(struct TestStruct, b);
+ size_t size = blocks_offset;
+ AVVideoHint *par;
+
+ *out_size = 0;
+ if (nb_rects > (SIZE_MAX - size) / sizeof(AVVideoRect))
+ return NULL;
+ size += sizeof(AVVideoRect) * nb_rects;
+
+ par = av_mallocz(size);
+ if (!par)
+ return NULL;
+
+ par->type = type;
+ par->nb_rects = nb_rects;
+ par->blocks_offset = blocks_offset;
+
+ /* Just copies the rects over the newly allocated buffer */
+ memcpy((uint8_t *)par + blocks_offset, rects, sizeof(AVVideoRect) * nb_rects);
+
+ *out_size = size;
+
+ return par;
+}
+
+AVVideoHint *av_video_hint_create_side_data(AVFrame *frame,
+ AVVideoRect *rects,
+ size_t num_rects,
+ VideoHintType type)
+{
+ AVVideoHint *par;
+ AVBufferRef *buf;
+ size_t size = 0;
+
+ par = av_video_hint_alloc(rects, num_rects, type, &size);
+ if (!par)
+ return NULL;
+
+ buf = av_buffer_create((uint8_t *)par, size, NULL, NULL, 0);
+ if (!buf) {
+ av_freep(&par);
+ return NULL;
+ }
+
+ if (!av_frame_new_side_data_from_buf(frame, AV_FRAME_DATA_VIDEO_HINT, buf)) {
+ av_buffer_unref(&buf);
+ return NULL;
+ }
+
+ return par;
+}
+
diff --git a/libavutil/video_hint_info.h b/libavutil/video_hint_info.h
new file mode 100644
index 0000000000..3b04e0c40e
--- /dev/null
+++ b/libavutil/video_hint_info.h
@@ -0,0 +1,87 @@
+/**
+ * Copyright 2023 Elias Carotti <eliascrt at amazon dot it>
+ *
+ * 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
+ */
+
+#ifndef AVUTIL_VIDEO_HINT_INFO_H
+#define AVUTIL_VIDEO_HINT_INFO_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include "libavutil/avassert.h"
+#include "libavutil/frame.h"
+
+typedef struct AVVideoRect {
+ uint32_t x, y;
+ uint32_t width, height;
+} AVVideoRect;
+
+typedef enum VideoHintType {
+ /* blocks delimit the constant areas (unchanged), default is changed */
+ AV_VIDEO_HINT_CONSTANT,
+
+ /* blocks delimit the constant areas (changed), default is not changed */
+ AV_VIDEO_HINT_CHANGED,
+} VideoHintType;
+
+typedef struct AVVideoHint {
+ /**
+ * Number of blocks in the array.
+ *
+ * May be 0, in which case no per-block information is present. In this case
+ * the values of blocks_offset / block_size are unspecified and should not
+ * be accessed.
+ */
+ int nb_rects;
+
+ /**
+ * Offset in bytes from the beginning of this structure at which the array
+ * of blocks starts.
+ */
+ size_t blocks_offset;
+
+ VideoHintType type;
+} AVVideoHint;
+
+static av_always_inline AVVideoRect*
+av_video_hint_rects(const AVVideoHint *par)
+{
+ return (AVVideoRect *)((uint8_t *)par + par->blocks_offset);
+}
+
+/**
+ * Allocate memory for a vector of AVVideoRect in the given AVFrame
+ * {@code frame} as AVFrameSideData of type AV_FRAME_DATA_VIDEO_HINT_INFO.
+ * The side data contains a list of rectangles for the portions of the frame
+ * which changed from the last encoded one (and the remainder are assumed to be
+ * changed), or, alternately (depending on the type parameter) the unchanged
+ * ones (and the remanining ones are those which changed).
+ * Macroblocks will thus be hinted either to be P_SKIP-ped or go through the
+ * regular encoding procedure.
+ */
+AVVideoHint *av_video_hint_create_side_data(AVFrame *frame,
+ AVVideoRect *rects,
+ size_t num_rects,
+ VideoHintType type);
+
+AVVideoHint *av_video_hint_alloc(AVVideoRect *rects,
+ size_t nb_rects,
+ VideoHintType type,
+ size_t *out_size);
+
+#endif /* AVUTIL__VIDEO_HINT_INFO_H */
--
2.34.1
[-- Attachment #3: Type: text/plain, Size: 251 bytes --]
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [FFmpeg-devel] [PATCH] Optimization: support for libx264's mb_info
2023-05-29 17:56 ` Carotti, Elias
@ 2023-06-04 15:29 ` Stefano Sabatini
2023-06-05 15:32 ` Carotti, Elias
0 siblings, 1 reply; 33+ messages in thread
From: Stefano Sabatini @ 2023-06-04 15:29 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On date Monday 2023-05-29 17:56:55 +0000, Carotti, Elias wrote:
[...]
> From 7cb97ee977197e310a932b2d7a53bf5c6e99990e Mon Sep 17 00:00:00 2001
> From: Elias Carotti <eliascrt@amazon.it>
> Date: Wed, 19 Apr 2023 11:49:39 +0200
> Subject: [PATCH] Add support for libx264's MB_INFO
>
> libx264's x264_image_properties_t, which is passed to the encoding function,
> contains a field to pass down information on the portions of the frame which
> changed with respect to the previous one (used for prediction) to mark
> unchanged macroblocks P_SKIP.
> ---
> libavcodec/libx264.c | 81 +++++++++++++++++++++++++++++++++
> libavutil/Makefile | 4 ++
> libavutil/frame.h | 10 +++++
> libavutil/video_hint_info.c | 89 +++++++++++++++++++++++++++++++++++++
> libavutil/video_hint_info.h | 87 ++++++++++++++++++++++++++++++++++++
> 5 files changed, 271 insertions(+)
> create mode 100644 libavutil/video_hint_info.c
> create mode 100644 libavutil/video_hint_info.h
>
> diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c
> index 5736f1efa7..32fa80d0a1 100644
> --- a/libavcodec/libx264.c
> +++ b/libavcodec/libx264.c
> @@ -30,6 +30,7 @@
> #include "libavutil/stereo3d.h"
> #include "libavutil/time.h"
> #include "libavutil/intreadwrite.h"
> +#include "libavutil/video_hint_info.h"
> #include "avcodec.h"
> #include "codec_internal.h"
> #include "encode.h"
> @@ -48,6 +49,9 @@
> // from x264.h, for quant_offsets, Macroblocks are 16x16
> // blocks of pixels (with respect to the luma plane)
> #define MB_SIZE 16
> +#define MB_LSIZE 4
> +#define MB_FLOOR(x) ((x) >> (MB_LSIZE))
> +#define MB_CEIL(x) MB_FLOOR((x) + (MB_SIZE - 1))
>
> typedef struct X264Opaque {
> #if FF_API_REORDERED_OPAQUE
> @@ -123,6 +127,8 @@ typedef struct X264Context {
> * encounter a frame with ROI side data.
> */
> int roi_warned;
> +
> + int mb_info;
> } X264Context;
>
> static void X264_log(void *p, int level, const char *fmt, va_list args)
> @@ -295,6 +301,7 @@ static void free_picture(x264_picture_t *pic)
> av_free(pic->extra_sei.payloads[i].payload);
> av_freep(&pic->extra_sei.payloads);
> av_freep(&pic->prop.quant_offsets);
> + av_freep(&pic->prop.mb_info);
> pic->extra_sei.num_payloads = 0;
> }
>
> @@ -320,6 +327,64 @@ static enum AVPixelFormat csp_to_pixfmt(int csp)
> return AV_PIX_FMT_NONE;
> }
>
> +static int setup_mb_info(AVCodecContext *ctx, x264_picture_t *pic,
> + const AVFrame *frame,
> + const AVVideoHint *info)
> +{
> + int mb_width = (frame->width + MB_SIZE - 1) / MB_SIZE;
> + int mb_height = (frame->height + MB_SIZE - 1) / MB_SIZE;
> +
> + const AVVideoRect *mbinfo_rects;
> + int nb_rects;
> + uint8_t *mbinfo;
> +
> + mbinfo_rects = (const AVVideoRect *)av_video_hint_rects(info);
> + nb_rects = info->nb_rects;
> +
> + mbinfo = av_calloc(mb_width * mb_height, sizeof(*mbinfo));
> + if (!mbinfo)
> + return AVERROR(ENOMEM);
> +
> + if (info->type == AV_VIDEO_HINT_CHANGED) {
> + /* Sets the default as constant, i.e. P_SKIP-able, then selectively resets the flag */
> + memset(mbinfo, X264_MBINFO_CONSTANT, sizeof(*mbinfo) * mb_width * mb_height);
> +
> + for (int i = 0; i < nb_rects; i++) {
> + int min_y = MB_FLOOR(mbinfo_rects->y);
> + int max_y = MB_CEIL(mbinfo_rects->y + mbinfo_rects->height);
> + int min_x = MB_FLOOR(mbinfo_rects->x);
> + int max_x = MB_CEIL(mbinfo_rects->x + mbinfo_rects->width);
> +
> + for (int mb_y = min_y; mb_y < max_y; ++mb_y) {
> + memset(mbinfo + mb_y * mb_width + min_x, 0, max_x - min_x);
> + }
> +
> + mbinfo_rects++;
> + }
> + } else {
> + /* Sets the default as changed, i.e. *not* P_SKIP-able, then selectively sets the flag */
> + memset(mbinfo, 0, sizeof(*mbinfo) * mb_width * mb_height);
> +
> + for (int i = 0; i < nb_rects; i++) {
> + int min_y = MB_CEIL(mbinfo_rects->y);
> + int max_y = MB_FLOOR(mbinfo_rects->y + mbinfo_rects->height);
> + int min_x = MB_CEIL(mbinfo_rects->x);
> + int max_x = MB_FLOOR(mbinfo_rects->x + mbinfo_rects->width);
> +
> + for (int mb_y = min_y; mb_y < max_y; ++mb_y) {
> + memset(mbinfo + mb_y * mb_width + min_x, X264_MBINFO_CONSTANT, max_x - min_x);
> + }
> +
> + mbinfo_rects++;
you can merge the two loops by adding an inline function to compute
the mins and maxs, and then setting:
mbinfo_filler = AV_VIDEO_HINT_CHANGED ? X264_MBINFO_CONSTANT : 0;
mbinfo_marker = AV_VIDEO_HINT_CHANGED ? 0 : X264_MBINFO_CONSTANT;
compute_coords_fn = AV_VIDEO_HINT_CHANGED ? compute_changed_coords : compute_constant_coords;
memset(mbinfo, mbinfo_filler, sizeof(*mbinfo) * mb_width * mb_height);
for (int i = 0; i < nb_rects; i++) {
compute_coords_fn...
for (int mb_y = min_y; mb_y < max_y; ++mb_y) {
memset(mbinfo + mb_y * mb_width + min_x, mbinfo_marker, max_x - min_x);
}
mbinfo_rects++;
}
> + }
> + }
> +
> + pic->prop.mb_info = mbinfo;
> + pic->prop.mb_info_free = av_free;
> +
> + return 0;
> +}
> +
> static int setup_roi(AVCodecContext *ctx, x264_picture_t *pic, int bit_depth,
> const AVFrame *frame, const uint8_t *data, size_t size)
> {
> @@ -404,6 +469,7 @@ static int setup_frame(AVCodecContext *ctx, const AVFrame *frame,
> int64_t wallclock = 0;
> int bit_depth, ret;
> AVFrameSideData *sd;
> + AVFrameSideData *mbinfo_sd;
>
> *ppic = NULL;
> if (!frame)
> @@ -499,6 +565,17 @@ FF_ENABLE_DEPRECATION_WARNINGS
> goto fail;
> }
>
> + mbinfo_sd = av_frame_get_side_data(frame, AV_FRAME_DATA_VIDEO_HINT);
> + if (mbinfo_sd) {
> + int ret = setup_mb_info(ctx, pic, frame, (const AVVideoHint *)mbinfo_sd->data);
> + if (ret < 0) {
> + /* No need to fail here, this is not fatal. We just proceed with no
> + * mb_info and log a message */
> +
> + av_log(ctx, AV_LOG_WARNING, "mb_info setup failure\n");
> + }
> + }
> +
> if (x4->udu_sei) {
> for (int j = 0; j < frame->nb_side_data; j++) {
> AVFrameSideData *side_data = frame->side_data[j];
> @@ -1102,6 +1179,9 @@ FF_ENABLE_DEPRECATION_WARNINGS
> }
> }
>
> + x4->params.analyse.b_mb_info = x4->mb_info;
> + x4->params.analyse.b_fast_pskip = 1;
> +
> // update AVCodecContext with x264 parameters
> avctx->has_b_frames = x4->params.i_bframe ?
> x4->params.i_bframe_pyramid ? 2 : 1 : 0;
> @@ -1311,6 +1391,7 @@ static const AVOption options[] = {
> { "noise_reduction", "Noise reduction", OFFSET(noise_reduction), AV_OPT_TYPE_INT, { .i64 = -1 }, INT_MIN, INT_MAX, VE },
> { "udu_sei", "Use user data unregistered SEI if available", OFFSET(udu_sei), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
> { "x264-params", "Override the x264 configuration using a :-separated list of key=value parameters", OFFSET(x264_params), AV_OPT_TYPE_DICT, { 0 }, 0, 0, VE },
> + { "mb_info", "Set mb_info data through AVSideData, only useful when used from the API", OFFSET(mb_info), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
> { NULL },
> };
>
> diff --git a/libavutil/Makefile b/libavutil/Makefile
> index dc9012f9a8..bb5ecc3235 100644
> --- a/libavutil/Makefile
> +++ b/libavutil/Makefile
> @@ -91,6 +91,7 @@ HEADERS = adler32.h \
> tea.h \
> tx.h \
> film_grain_params.h \
> + video_hint_info.h \
>
> ARCH_HEADERS = bswap.h \
> intmath.h \
> @@ -196,6 +197,7 @@ OBJS-$(CONFIG_VAAPI) += hwcontext_vaapi.o
> OBJS-$(CONFIG_VIDEOTOOLBOX) += hwcontext_videotoolbox.o
> OBJS-$(CONFIG_VDPAU) += hwcontext_vdpau.o
> OBJS-$(CONFIG_VULKAN) += hwcontext_vulkan.o
> +OBJS-$(CONFIG_LIBX264) += video_hint_info.o
order
>
> OBJS-$(!CONFIG_VULKAN) += hwcontext_stub.o
>
> @@ -219,6 +221,8 @@ SKIPHEADERS-$(CONFIG_VULKAN) += hwcontext_vulkan.h vulkan.h \
> vulkan_functions.h \
> vulkan_loader.h
>
> +SKIPHEADERS-$(CONFIG_LIBX264) += video_hint_info.h
> +
> TESTPROGS = adler32 \
> aes \
> aes_ctr \
> diff --git a/libavutil/frame.h b/libavutil/frame.h
> index a491315f25..0e765e5499 100644
> --- a/libavutil/frame.h
> +++ b/libavutil/frame.h
> @@ -214,6 +214,16 @@ enum AVFrameSideDataType {
> * Ambient viewing environment metadata, as defined by H.274.
> */
> AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT,
> +
> + /**
> + * Provide macro block encoder-specific hinting information for the encoder
> + * processing. It can be used to pass information about which macroblock
> + * can be skipped because it hasn't changed from the corresponding one in
> + * the previous frame. This is useful for applications which know in
> + * advance this information to speed up real-time encoding. Currently only
> + * used by libx264.
> + */
> + AV_FRAME_DATA_VIDEO_HINT,
> };
>
> enum AVActiveFormatDescription {
> diff --git a/libavutil/video_hint_info.c b/libavutil/video_hint_info.c
> new file mode 100644
> index 0000000000..0a763962da
> --- /dev/null
> +++ b/libavutil/video_hint_info.c
> @@ -0,0 +1,89 @@
> +/*
> + * Copyright 2023 Elias Carotti <eliascrt at amazon dot it>
> + *
> + * 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 <string.h>
> +
> +#include "avstring.h"
> +#include "frame.h"
> +#include "macros.h"
> +#include "mem.h"
> +#include "video_hint_info.h"
> +
> +AVVideoHint *av_video_hint_alloc(AVVideoRect *rects,
> + size_t nb_rects,
> + VideoHintType type,
> + size_t* out_size)
align to (
> +{
> + struct TestStruct {
> + AVVideoHint p;
> + AVVideoRect b;
> + };
nit: weird align (also use more meaningful names - e.g. hint and rect)
> + const size_t blocks_offset = offsetof(struct TestStruct, b);
> + size_t size = blocks_offset;
> + AVVideoHint *par;
AVVideoHint *hint?
> +
> + *out_size = 0;
> + if (nb_rects > (SIZE_MAX - size) / sizeof(AVVideoRect))
why SIZE_MAX - size?
> + return NULL;
> + size += sizeof(AVVideoRect) * nb_rects;
> +
> + par = av_mallocz(size);
> + if (!par)
> + return NULL;
> +
> + par->type = type;
> + par->nb_rects = nb_rects;
> + par->blocks_offset = blocks_offset;
> +
> + /* Just copies the rects over the newly allocated buffer */
> + memcpy((uint8_t *)par + blocks_offset, rects, sizeof(AVVideoRect) * nb_rects);
> +
> + *out_size = size;
> +
> + return par;
> +}
> +
> +AVVideoHint *av_video_hint_create_side_data(AVFrame *frame,
> + AVVideoRect *rects,
> + size_t num_rects,
> + VideoHintType type)
> +{
> + AVVideoHint *par;
use a more meaningful name (I think "par" is a leftover of an older
API)
> + AVBufferRef *buf;
> + size_t size = 0;
> +
> + par = av_video_hint_alloc(rects, num_rects, type, &size);
> + if (!par)
> + return NULL;
> +
> + buf = av_buffer_create((uint8_t *)par, size, NULL, NULL, 0);
> + if (!buf) {
> + av_freep(&par);
> + return NULL;
> + }
> +
> + if (!av_frame_new_side_data_from_buf(frame, AV_FRAME_DATA_VIDEO_HINT, buf)) {
> + av_buffer_unref(&buf);
> + return NULL;
> + }
> +
> + return par;
> +}
> +
> diff --git a/libavutil/video_hint_info.h b/libavutil/video_hint_info.h
> new file mode 100644
> index 0000000000..3b04e0c40e
> --- /dev/null
> +++ b/libavutil/video_hint_info.h
> @@ -0,0 +1,87 @@
> +/**
> + * Copyright 2023 Elias Carotti <eliascrt at amazon dot it>
> + *
> + * 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
> + */
> +
> +#ifndef AVUTIL_VIDEO_HINT_INFO_H
> +#define AVUTIL_VIDEO_HINT_INFO_H
> +
> +#include <stddef.h>
> +#include <stdint.h>
> +#include "libavutil/avassert.h"
> +#include "libavutil/frame.h"
> +
> +typedef struct AVVideoRect {
> + uint32_t x, y;
> + uint32_t width, height;
> +} AVVideoRect;
> +
> +typedef enum VideoHintType {
> + /* blocks delimit the constant areas (unchanged), default is changed */
> + AV_VIDEO_HINT_CONSTANT,
> +
> + /* blocks delimit the constant areas (changed), default is not changed */
> + AV_VIDEO_HINT_CHANGED,
> +} VideoHintType;
missing AV prefix
> +
> +typedef struct AVVideoHint {
> + /**
> + * Number of blocks in the array.
> + *
> + * May be 0, in which case no per-block information is present. In this case
> + * the values of blocks_offset / block_size are unspecified and should not
> + * be accessed.
> + */
> + int nb_rects;
> +
> + /**
> + * Offset in bytes from the beginning of this structure at which the array
> + * of blocks starts.
> + */
> + size_t blocks_offset;
> +
> + VideoHintType type;
> +} AVVideoHint;
> +
> +static av_always_inline AVVideoRect*
> +av_video_hint_rects(const AVVideoHint *par)
> +{
> + return (AVVideoRect *)((uint8_t *)par + par->blocks_offset);
> +}
> +
> +/**
> + * Allocate memory for a vector of AVVideoRect in the given AVFrame
> + * {@code frame} as AVFrameSideData of type AV_FRAME_DATA_VIDEO_HINT_INFO.
> + * The side data contains a list of rectangles for the portions of the frame
> + * which changed from the last encoded one (and the remainder are assumed to be
> + * changed), or, alternately (depending on the type parameter) the unchanged
> + * ones (and the remanining ones are those which changed).
> + * Macroblocks will thus be hinted either to be P_SKIP-ped or go through the
> + * regular encoding procedure.
> + */
> +AVVideoHint *av_video_hint_create_side_data(AVFrame *frame,
> + AVVideoRect *rects,
> + size_t num_rects,
> + VideoHintType type);
> +
> +AVVideoHint *av_video_hint_alloc(AVVideoRect *rects,
> + size_t nb_rects,
> + VideoHintType type,
> + size_t *out_size);
> +
> +#endif /* AVUTIL__VIDEO_HINT_INFO_H */
AVUTIL_VIDEO...
> --
> 2.34.1
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [FFmpeg-devel] [PATCH] Optimization: support for libx264's mb_info
2023-06-04 15:29 ` Stefano Sabatini
@ 2023-06-05 15:32 ` Carotti, Elias
2023-06-11 17:15 ` Stefano Sabatini
0 siblings, 1 reply; 33+ messages in thread
From: Carotti, Elias @ 2023-06-05 15:32 UTC (permalink / raw)
To: ffmpeg-devel
[-- Attachment #1: Type: text/plain, Size: 21478 bytes --]
Hi,
please find attached the patch which I updated according to your
suggestions.
Best,
Elias
On Sun, 2023-06-04 at 17:29 +0200, Stefano Sabatini wrote:
> CAUTION: This email originated from outside of the organization. Do
> not click links or open attachments unless you can confirm the sender
> and know the content is safe.
>
>
>
> On date Monday 2023-05-29 17:56:55 +0000, Carotti, Elias wrote:
> [...]
> > From 7cb97ee977197e310a932b2d7a53bf5c6e99990e Mon Sep 17 00:00:00
> > 2001
> > From: Elias Carotti <eliascrt@amazon.it>
> > Date: Wed, 19 Apr 2023 11:49:39 +0200
> > Subject: [PATCH] Add support for libx264's MB_INFO
> >
> > libx264's x264_image_properties_t, which is passed to the encoding
> > function,
> > contains a field to pass down information on the portions of the
> > frame which
> > changed with respect to the previous one (used for prediction) to
> > mark
> > unchanged macroblocks P_SKIP.
> > ---
> > libavcodec/libx264.c | 81 +++++++++++++++++++++++++++++++++
> > libavutil/Makefile | 4 ++
> > libavutil/frame.h | 10 +++++
> > libavutil/video_hint_info.c | 89
> > +++++++++++++++++++++++++++++++++++++
> > libavutil/video_hint_info.h | 87
> > ++++++++++++++++++++++++++++++++++++
> > 5 files changed, 271 insertions(+)
> > create mode 100644 libavutil/video_hint_info.c
> > create mode 100644 libavutil/video_hint_info.h
> >
> > diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c
> > index 5736f1efa7..32fa80d0a1 100644
> > --- a/libavcodec/libx264.c
> > +++ b/libavcodec/libx264.c
> > @@ -30,6 +30,7 @@
> > #include "libavutil/stereo3d.h"
> > #include "libavutil/time.h"
> > #include "libavutil/intreadwrite.h"
> > +#include "libavutil/video_hint_info.h"
> > #include "avcodec.h"
> > #include "codec_internal.h"
> > #include "encode.h"
> > @@ -48,6 +49,9 @@
> > // from x264.h, for quant_offsets, Macroblocks are 16x16
> > // blocks of pixels (with respect to the luma plane)
> > #define MB_SIZE 16
> > +#define MB_LSIZE 4
> > +#define MB_FLOOR(x) ((x) >> (MB_LSIZE))
> > +#define MB_CEIL(x) MB_FLOOR((x) + (MB_SIZE - 1))
> >
> > typedef struct X264Opaque {
> > #if FF_API_REORDERED_OPAQUE
> > @@ -123,6 +127,8 @@ typedef struct X264Context {
> > * encounter a frame with ROI side data.
> > */
> > int roi_warned;
> > +
> > + int mb_info;
> > } X264Context;
> >
> > static void X264_log(void *p, int level, const char *fmt, va_list
> > args)
> > @@ -295,6 +301,7 @@ static void free_picture(x264_picture_t *pic)
> > av_free(pic->extra_sei.payloads[i].payload);
> > av_freep(&pic->extra_sei.payloads);
> > av_freep(&pic->prop.quant_offsets);
> > + av_freep(&pic->prop.mb_info);
> > pic->extra_sei.num_payloads = 0;
> > }
> >
> > @@ -320,6 +327,64 @@ static enum AVPixelFormat csp_to_pixfmt(int
> > csp)
> > return AV_PIX_FMT_NONE;
> > }
> >
> > +static int setup_mb_info(AVCodecContext *ctx, x264_picture_t *pic,
> > + const AVFrame *frame,
> > + const AVVideoHint *info)
> > +{
>
> > + int mb_width = (frame->width + MB_SIZE - 1) / MB_SIZE;
> > + int mb_height = (frame->height + MB_SIZE - 1) / MB_SIZE;
>
>
> > +
> > + const AVVideoRect *mbinfo_rects;
> > + int nb_rects;
> > + uint8_t *mbinfo;
> > +
> > + mbinfo_rects = (const AVVideoRect *)av_video_hint_rects(info);
> > + nb_rects = info->nb_rects;
> > +
> > + mbinfo = av_calloc(mb_width * mb_height, sizeof(*mbinfo));
> > + if (!mbinfo)
> > + return AVERROR(ENOMEM);
> > +
>
> > + if (info->type == AV_VIDEO_HINT_CHANGED) {
> > + /* Sets the default as constant, i.e. P_SKIP-able, then
> > selectively resets the flag */
> > + memset(mbinfo, X264_MBINFO_CONSTANT, sizeof(*mbinfo) *
> > mb_width * mb_height);
> > +
> > + for (int i = 0; i < nb_rects; i++) {
> > + int min_y = MB_FLOOR(mbinfo_rects->y);
> > + int max_y = MB_CEIL(mbinfo_rects->y + mbinfo_rects-
> > >height);
> > + int min_x = MB_FLOOR(mbinfo_rects->x);
> > + int max_x = MB_CEIL(mbinfo_rects->x + mbinfo_rects-
> > >width);
> > +
> > + for (int mb_y = min_y; mb_y < max_y; ++mb_y) {
> > + memset(mbinfo + mb_y * mb_width + min_x, 0, max_x
> > - min_x);
> > + }
> > +
> > + mbinfo_rects++;
> > + }
> > + } else {
> > + /* Sets the default as changed, i.e. *not* P_SKIP-able,
> > then selectively sets the flag */
> > + memset(mbinfo, 0, sizeof(*mbinfo) * mb_width * mb_height);
> > +
> > + for (int i = 0; i < nb_rects; i++) {
> > + int min_y = MB_CEIL(mbinfo_rects->y);
> > + int max_y = MB_FLOOR(mbinfo_rects->y + mbinfo_rects-
> > >height);
> > + int min_x = MB_CEIL(mbinfo_rects->x);
> > + int max_x = MB_FLOOR(mbinfo_rects->x + mbinfo_rects-
> > >width);
> > +
> > + for (int mb_y = min_y; mb_y < max_y; ++mb_y) {
> > + memset(mbinfo + mb_y * mb_width + min_x,
> > X264_MBINFO_CONSTANT, max_x - min_x);
> > + }
> > +
> > + mbinfo_rects++;
>
> you can merge the two loops by adding an inline function to compute
> the mins and maxs, and then setting:
>
> mbinfo_filler = AV_VIDEO_HINT_CHANGED ? X264_MBINFO_CONSTANT : 0;
> mbinfo_marker = AV_VIDEO_HINT_CHANGED ? 0 : X264_MBINFO_CONSTANT;
> compute_coords_fn = AV_VIDEO_HINT_CHANGED ? compute_changed_coords :
> compute_constant_coords;
>
> memset(mbinfo, mbinfo_filler, sizeof(*mbinfo) * mb_width *
> mb_height);
> for (int i = 0; i < nb_rects; i++) {
> compute_coords_fn...
> for (int mb_y = min_y; mb_y < max_y; ++mb_y) {
> memset(mbinfo + mb_y * mb_width + min_x, mbinfo_marker, max_x
> - min_x);
> }
>
> mbinfo_rects++;
> }
>
> > + }
> > + }
> > +
> > + pic->prop.mb_info = mbinfo;
> > + pic->prop.mb_info_free = av_free;
> > +
> > + return 0;
> > +}
> > +
> > static int setup_roi(AVCodecContext *ctx, x264_picture_t *pic, int
> > bit_depth,
> > const AVFrame *frame, const uint8_t *data,
> > size_t size)
> > {
> > @@ -404,6 +469,7 @@ static int setup_frame(AVCodecContext *ctx,
> > const AVFrame *frame,
> > int64_t wallclock = 0;
> > int bit_depth, ret;
> > AVFrameSideData *sd;
> > + AVFrameSideData *mbinfo_sd;
> >
> > *ppic = NULL;
> > if (!frame)
> > @@ -499,6 +565,17 @@ FF_ENABLE_DEPRECATION_WARNINGS
> > goto fail;
> > }
> >
> > + mbinfo_sd = av_frame_get_side_data(frame,
> > AV_FRAME_DATA_VIDEO_HINT);
> > + if (mbinfo_sd) {
> > + int ret = setup_mb_info(ctx, pic, frame, (const
> > AVVideoHint *)mbinfo_sd->data);
> > + if (ret < 0) {
> > + /* No need to fail here, this is not fatal. We just
> > proceed with no
> > + * mb_info and log a message */
> > +
> > + av_log(ctx, AV_LOG_WARNING, "mb_info setup
> > failure\n");
> > + }
> > + }
> > +
> > if (x4->udu_sei) {
> > for (int j = 0; j < frame->nb_side_data; j++) {
> > AVFrameSideData *side_data = frame->side_data[j];
> > @@ -1102,6 +1179,9 @@ FF_ENABLE_DEPRECATION_WARNINGS
> > }
> > }
> >
> > + x4->params.analyse.b_mb_info = x4->mb_info;
> > + x4->params.analyse.b_fast_pskip = 1;
> > +
> > // update AVCodecContext with x264 parameters
> > avctx->has_b_frames = x4->params.i_bframe ?
> > x4->params.i_bframe_pyramid ? 2 : 1 : 0;
> > @@ -1311,6 +1391,7 @@ static const AVOption options[] = {
> > { "noise_reduction", "Noise
> > reduction", OFFSET(noise_reduction),
> > AV_OPT_TYPE_INT, { .i64 = -1 }, INT_MIN, INT_MAX, VE },
> > { "udu_sei", "Use user data unregistered SEI if
> > available", OFFSET(udu_sei), AV_OPT_TYPE_BOOL, { .i64 = 0
> > }, 0, 1, VE },
> > { "x264-params", "Override the x264 configuration using a :-
> > separated list of key=value parameters", OFFSET(x264_params),
> > AV_OPT_TYPE_DICT, { 0 }, 0, 0, VE },
> > + { "mb_info", "Set mb_info data through AVSideData, only
> > useful when used from the API", OFFSET(mb_info), AV_OPT_TYPE_BOOL,
> > { .i64 = 0 }, 0, 1, VE },
> > { NULL },
> > };
> >
> > diff --git a/libavutil/Makefile b/libavutil/Makefile
> > index dc9012f9a8..bb5ecc3235 100644
> > --- a/libavutil/Makefile
> > +++ b/libavutil/Makefile
> > @@ -91,6 +91,7 @@ HEADERS =
> > adler32.h \
> >
> > tea.h \
> >
> > tx.h \
> >
> > film_grain_params.h \
> > +
> > video_hint_info.h
> > \
>
> >
> > ARCH_HEADERS =
> > bswap.h \
> >
> > intmath.h \
> > @@ -196,6 +197,7 @@ OBJS-$(CONFIG_VAAPI) +=
> > hwcontext_vaapi.o
> > OBJS-$(CONFIG_VIDEOTOOLBOX) +=
> > hwcontext_videotoolbox.o
> > OBJS-$(CONFIG_VDPAU) += hwcontext_vdpau.o
> > OBJS-$(CONFIG_VULKAN) += hwcontext_vulkan.o
> > +OBJS-$(CONFIG_LIBX264) += video_hint_info.o
>
> order
>
> >
> > OBJS-$(!CONFIG_VULKAN) += hwcontext_stub.o
> >
> > @@ -219,6 +221,8 @@ SKIPHEADERS-$(CONFIG_VULKAN) +=
> > hwcontext_vulkan.h vulkan.h \
> >
> > vulkan_functions.h \
> > vulkan_loader.h
> >
> > +SKIPHEADERS-$(CONFIG_LIBX264) += video_hint_info.h
> > +
> > TESTPROGS =
> > adler32 \
> >
> > aes \
> >
> > aes_ctr \
> > diff --git a/libavutil/frame.h b/libavutil/frame.h
> > index a491315f25..0e765e5499 100644
> > --- a/libavutil/frame.h
> > +++ b/libavutil/frame.h
> > @@ -214,6 +214,16 @@ enum AVFrameSideDataType {
> > * Ambient viewing environment metadata, as defined by H.274.
> > */
> > AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT,
> > +
> > + /**
> > + * Provide macro block encoder-specific hinting information
> > for the encoder
> > + * processing. It can be used to pass information about which
> > macroblock
> > + * can be skipped because it hasn't changed from the
> > corresponding one in
> > + * the previous frame. This is useful for applications which
> > know in
> > + * advance this information to speed up real-time encoding.
> > Currently only
> > + * used by libx264.
> > + */
> > + AV_FRAME_DATA_VIDEO_HINT,
> > };
> >
> > enum AVActiveFormatDescription {
> > diff --git a/libavutil/video_hint_info.c
> > b/libavutil/video_hint_info.c
> > new file mode 100644
> > index 0000000000..0a763962da
> > --- /dev/null
> > +++ b/libavutil/video_hint_info.c
> > @@ -0,0 +1,89 @@
> > +/*
> > + * Copyright 2023 Elias Carotti <eliascrt at amazon dot it>
> > + *
> > + * 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 <string.h>
> > +
> > +#include "avstring.h"
> > +#include "frame.h"
> > +#include "macros.h"
> > +#include "mem.h"
> > +#include "video_hint_info.h"
> > +
> > +AVVideoHint *av_video_hint_alloc(AVVideoRect *rects,
>
> > + size_t nb_rects,
> > + VideoHintType type,
> > + size_t* out_size)
>
> align to (
>
> > +{
> > + struct TestStruct {
> > + AVVideoHint p;
> > + AVVideoRect b;
> > + };
>
> nit: weird align (also use more meaningful names - e.g. hint and
> rect)
>
> > + const size_t blocks_offset = offsetof(struct TestStruct, b);
> > + size_t size = blocks_offset;
>
> > + AVVideoHint *par;
>
> AVVideoHint *hint?
>
> > +
> > + *out_size = 0;
>
> > + if (nb_rects > (SIZE_MAX - size) / sizeof(AVVideoRect))
>
> why SIZE_MAX - size?
>
> > + return NULL;
>
> > + size += sizeof(AVVideoRect) * nb_rects;
> > +
> > + par = av_mallocz(size);
> > + if (!par)
> > + return NULL;
> > +
> > + par->type = type;
> > + par->nb_rects = nb_rects;
> > + par->blocks_offset = blocks_offset;
> > +
> > + /* Just copies the rects over the newly allocated buffer */
> > + memcpy((uint8_t *)par + blocks_offset, rects,
> > sizeof(AVVideoRect) * nb_rects);
> > +
> > + *out_size = size;
> > +
> > + return par;
> > +}
> > +
> > +AVVideoHint *av_video_hint_create_side_data(AVFrame *frame,
> > + AVVideoRect *rects,
> > + size_t num_rects,
> > + VideoHintType type)
> > +{
>
> > + AVVideoHint *par;
>
> use a more meaningful name (I think "par" is a leftover of an older
> API)
>
> > + AVBufferRef *buf;
> > + size_t size = 0;
> > +
> > + par = av_video_hint_alloc(rects, num_rects, type, &size);
> > + if (!par)
> > + return NULL;
> > +
> > + buf = av_buffer_create((uint8_t *)par, size, NULL, NULL, 0);
> > + if (!buf) {
> > + av_freep(&par);
> > + return NULL;
> > + }
> > +
> > + if (!av_frame_new_side_data_from_buf(frame,
> > AV_FRAME_DATA_VIDEO_HINT, buf)) {
> > + av_buffer_unref(&buf);
> > + return NULL;
> > + }
> > +
> > + return par;
> > +}
> > +
> > diff --git a/libavutil/video_hint_info.h
> > b/libavutil/video_hint_info.h
> > new file mode 100644
> > index 0000000000..3b04e0c40e
> > --- /dev/null
> > +++ b/libavutil/video_hint_info.h
> > @@ -0,0 +1,87 @@
> > +/**
> > + * Copyright 2023 Elias Carotti <eliascrt at amazon dot it>
> > + *
> > + * 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
> > + */
> > +
> > +#ifndef AVUTIL_VIDEO_HINT_INFO_H
> > +#define AVUTIL_VIDEO_HINT_INFO_H
> > +
> > +#include <stddef.h>
> > +#include <stdint.h>
> > +#include "libavutil/avassert.h"
> > +#include "libavutil/frame.h"
> > +
> > +typedef struct AVVideoRect {
> > + uint32_t x, y;
> > + uint32_t width, height;
> > +} AVVideoRect;
> > +
>
> > +typedef enum VideoHintType {
> > + /* blocks delimit the constant areas (unchanged), default is
> > changed */
> > + AV_VIDEO_HINT_CONSTANT,
> > +
> > + /* blocks delimit the constant areas (changed), default is not
> > changed */
> > + AV_VIDEO_HINT_CHANGED,
> > +} VideoHintType;
>
> missing AV prefix
>
> > +
> > +typedef struct AVVideoHint {
> > + /**
> > + * Number of blocks in the array.
> > + *
> > + * May be 0, in which case no per-block information is
> > present. In this case
> > + * the values of blocks_offset / block_size are unspecified
> > and should not
> > + * be accessed.
> > + */
> > + int nb_rects;
> > +
> > + /**
> > + * Offset in bytes from the beginning of this structure at
> > which the array
> > + * of blocks starts.
> > + */
> > + size_t blocks_offset;
> > +
> > + VideoHintType type;
> > +} AVVideoHint;
> > +
> > +static av_always_inline AVVideoRect*
> > +av_video_hint_rects(const AVVideoHint *par)
> > +{
> > + return (AVVideoRect *)((uint8_t *)par + par->blocks_offset);
> > +}
> > +
> > +/**
> > + * Allocate memory for a vector of AVVideoRect in the given
> > AVFrame
> > + * {@code frame} as AVFrameSideData of type
> > AV_FRAME_DATA_VIDEO_HINT_INFO.
> > + * The side data contains a list of rectangles for the portions of
> > the frame
> > + * which changed from the last encoded one (and the remainder are
> > assumed to be
> > + * changed), or, alternately (depending on the type parameter) the
> > unchanged
> > + * ones (and the remanining ones are those which changed).
> > + * Macroblocks will thus be hinted either to be P_SKIP-ped or go
> > through the
> > + * regular encoding procedure.
> > + */
> > +AVVideoHint *av_video_hint_create_side_data(AVFrame *frame,
> > + AVVideoRect *rects,
> > + size_t num_rects,
> > + VideoHintType type);
> > +
> > +AVVideoHint *av_video_hint_alloc(AVVideoRect *rects,
> > + size_t nb_rects,
> > + VideoHintType type,
> > + size_t *out_size);
> > +
>
> > +#endif /* AVUTIL__VIDEO_HINT_INFO_H */
>
> AVUTIL_VIDEO...
>
> > --
> > 2.34.1
> >
>
> > _______________________________________________
> > ffmpeg-devel mailing list
> > ffmpeg-devel@ffmpeg.org
> > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> >
> > To unsubscribe, visit link above, or email
> > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
NICE SRL, viale Monte Grappa 3/5, 20124 Milano, Italia, Registro delle Imprese di Milano Monza Brianza Lodi REA n. 2096882, Capitale Sociale: 10.329,14 EUR i.v., Cod. Fisc. e P.IVA 01133050052, Societa con Socio Unico
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Add-support-for-libx264-s-MB_INFO.patch --]
[-- Type: text/x-patch; name="0001-Add-support-for-libx264-s-MB_INFO.patch", Size: 15595 bytes --]
From 8288d2bd36ffed29140d46c42b6f5515a9058836 Mon Sep 17 00:00:00 2001
From: Elias Carotti <eliascr _at_ amazon _dot_ it>
Date: Wed, 19 Apr 2023 11:49:39 +0200
Subject: [PATCH] Add support for libx264's MB_INFO
libx264's x264_image_properties_t, which is passed to the encoding function,
contains a field to pass down information on the portions of the frame which
changed with respect to the previous one (used for prediction) to mark
unchanged macroblocks P_SKIP.
---
libavcodec/libx264.c | 94 +++++++++++++++++++++++++++++++++++++
libavutil/Makefile | 4 ++
libavutil/frame.h | 10 ++++
libavutil/video_hint_info.c | 89 +++++++++++++++++++++++++++++++++++
libavutil/video_hint_info.h | 87 ++++++++++++++++++++++++++++++++++
5 files changed, 284 insertions(+)
create mode 100644 libavutil/video_hint_info.c
create mode 100644 libavutil/video_hint_info.h
diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c
index 5736f1efa7..2cf7755eec 100644
--- a/libavcodec/libx264.c
+++ b/libavcodec/libx264.c
@@ -30,6 +30,7 @@
#include "libavutil/stereo3d.h"
#include "libavutil/time.h"
#include "libavutil/intreadwrite.h"
+#include "libavutil/video_hint_info.h"
#include "avcodec.h"
#include "codec_internal.h"
#include "encode.h"
@@ -48,6 +49,13 @@
// from x264.h, for quant_offsets, Macroblocks are 16x16
// blocks of pixels (with respect to the luma plane)
#define MB_SIZE 16
+#define MB_LSIZE 4
+#define MB_FLOOR(x) ((x) >> (MB_LSIZE))
+#define MB_CEIL(x) MB_FLOOR((x) + (MB_SIZE - 1))
+
+typedef void (*AVMBInfoComputeCoords)(const AVVideoRect *rect,
+ int *min_x, int *max_x,
+ int *min_y, int *max_y);
typedef struct X264Opaque {
#if FF_API_REORDERED_OPAQUE
@@ -123,6 +131,8 @@ typedef struct X264Context {
* encounter a frame with ROI side data.
*/
int roi_warned;
+
+ int mb_info;
} X264Context;
static void X264_log(void *p, int level, const char *fmt, va_list args)
@@ -295,6 +305,7 @@ static void free_picture(x264_picture_t *pic)
av_free(pic->extra_sei.payloads[i].payload);
av_freep(&pic->extra_sei.payloads);
av_freep(&pic->prop.quant_offsets);
+ av_freep(&pic->prop.mb_info);
pic->extra_sei.num_payloads = 0;
}
@@ -320,6 +331,73 @@ static enum AVPixelFormat csp_to_pixfmt(int csp)
return AV_PIX_FMT_NONE;
}
+static void mbinfo_compute_changed_coords(const AVVideoRect *rect,
+ int *min_x,
+ int *max_x,
+ int *min_y,
+ int *max_y)
+{
+ *min_y = MB_FLOOR(rect->y);
+ *max_y = MB_CEIL(rect->y + rect->height);
+ *min_x = MB_FLOOR(rect->x);
+ *max_x = MB_CEIL(rect->x + rect->width);
+}
+
+static void mbinfo_compute_constant_coords(const AVVideoRect *rect,
+ int *min_x,
+ int *max_x,
+ int *min_y,
+ int *max_y)
+{
+ *min_y = MB_CEIL(rect->y);
+ *max_y = MB_FLOOR(rect->y + rect->height);
+ *min_x = MB_CEIL(rect->x);
+ *max_x = MB_FLOOR(rect->x + rect->width);
+}
+
+static int setup_mb_info(AVCodecContext *ctx, x264_picture_t *pic,
+ const AVFrame *frame,
+ const AVVideoHint *info)
+{
+ int mb_width = (frame->width + MB_SIZE - 1) / MB_SIZE;
+ int mb_height = (frame->height + MB_SIZE - 1) / MB_SIZE;
+ int mbinfo_filler;
+ int mbinfo_marker;
+ AVMBInfoComputeCoords compute_coords_fn;
+
+ const AVVideoRect *mbinfo_rects;
+ int nb_rects;
+ uint8_t *mbinfo;
+
+ mbinfo_rects = (const AVVideoRect *)av_video_hint_rects(info);
+ nb_rects = info->nb_rects;
+
+ mbinfo = av_calloc(mb_width * mb_height, sizeof(*mbinfo));
+ if (!mbinfo)
+ return AVERROR(ENOMEM);
+
+ mbinfo_filler = (info->type == AV_VIDEO_HINT_CHANGED) ? X264_MBINFO_CONSTANT : 0;
+ mbinfo_marker = (info->type == AV_VIDEO_HINT_CHANGED) ? 0 : X264_MBINFO_CONSTANT;
+ compute_coords_fn = (info->type == AV_VIDEO_HINT_CHANGED) ? mbinfo_compute_changed_coords : mbinfo_compute_constant_coords;
+
+ memset(mbinfo, mbinfo_filler, sizeof(*mbinfo) * mb_width * mb_height);
+ for (int i = 0; i < nb_rects; i++) {
+ int min_x, max_x, min_y, max_y;
+
+ (*compute_coords_fn)(mbinfo_rects, &min_x, &max_x, &min_y, &max_y);
+ for (int mb_y = min_y; mb_y < max_y; ++mb_y) {
+ memset(mbinfo + mb_y * mb_width + min_x, mbinfo_marker, max_x - min_x);
+ }
+
+ mbinfo_rects++;
+ }
+
+ pic->prop.mb_info = mbinfo;
+ pic->prop.mb_info_free = av_free;
+
+ return 0;
+}
+
static int setup_roi(AVCodecContext *ctx, x264_picture_t *pic, int bit_depth,
const AVFrame *frame, const uint8_t *data, size_t size)
{
@@ -404,6 +482,7 @@ static int setup_frame(AVCodecContext *ctx, const AVFrame *frame,
int64_t wallclock = 0;
int bit_depth, ret;
AVFrameSideData *sd;
+ AVFrameSideData *mbinfo_sd;
*ppic = NULL;
if (!frame)
@@ -499,6 +578,17 @@ FF_ENABLE_DEPRECATION_WARNINGS
goto fail;
}
+ mbinfo_sd = av_frame_get_side_data(frame, AV_FRAME_DATA_VIDEO_HINT);
+ if (mbinfo_sd) {
+ int ret = setup_mb_info(ctx, pic, frame, (const AVVideoHint *)mbinfo_sd->data);
+ if (ret < 0) {
+ /* No need to fail here, this is not fatal. We just proceed with no
+ * mb_info and log a message */
+
+ av_log(ctx, AV_LOG_WARNING, "mb_info setup failure\n");
+ }
+ }
+
if (x4->udu_sei) {
for (int j = 0; j < frame->nb_side_data; j++) {
AVFrameSideData *side_data = frame->side_data[j];
@@ -1102,6 +1192,9 @@ FF_ENABLE_DEPRECATION_WARNINGS
}
}
+ x4->params.analyse.b_mb_info = x4->mb_info;
+ x4->params.analyse.b_fast_pskip = 1;
+
// update AVCodecContext with x264 parameters
avctx->has_b_frames = x4->params.i_bframe ?
x4->params.i_bframe_pyramid ? 2 : 1 : 0;
@@ -1311,6 +1404,7 @@ static const AVOption options[] = {
{ "noise_reduction", "Noise reduction", OFFSET(noise_reduction), AV_OPT_TYPE_INT, { .i64 = -1 }, INT_MIN, INT_MAX, VE },
{ "udu_sei", "Use user data unregistered SEI if available", OFFSET(udu_sei), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
{ "x264-params", "Override the x264 configuration using a :-separated list of key=value parameters", OFFSET(x264_params), AV_OPT_TYPE_DICT, { 0 }, 0, 0, VE },
+ { "mb_info", "Set mb_info data through AVSideData, only useful when used from the API", OFFSET(mb_info), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
{ NULL },
};
diff --git a/libavutil/Makefile b/libavutil/Makefile
index dc9012f9a8..1dad526946 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -91,6 +91,7 @@ HEADERS = adler32.h \
tea.h \
tx.h \
film_grain_params.h \
+ video_hint_info.h
ARCH_HEADERS = bswap.h \
intmath.h \
@@ -188,6 +189,7 @@ OBJS-$(CONFIG_CUDA) += hwcontext_cuda.o
OBJS-$(CONFIG_D3D11VA) += hwcontext_d3d11va.o
OBJS-$(CONFIG_DXVA2) += hwcontext_dxva2.o
OBJS-$(CONFIG_LIBDRM) += hwcontext_drm.o
+OBJS-$(CONFIG_LIBX264) += video_hint_info.o
OBJS-$(CONFIG_MACOS_KPERF) += macos_kperf.o
OBJS-$(CONFIG_MEDIACODEC) += hwcontext_mediacodec.o
OBJS-$(CONFIG_OPENCL) += hwcontext_opencl.o
@@ -219,6 +221,8 @@ SKIPHEADERS-$(CONFIG_VULKAN) += hwcontext_vulkan.h vulkan.h \
vulkan_functions.h \
vulkan_loader.h
+SKIPHEADERS-$(CONFIG_LIBX264) += video_hint_info.h
+
TESTPROGS = adler32 \
aes \
aes_ctr \
diff --git a/libavutil/frame.h b/libavutil/frame.h
index a491315f25..0e765e5499 100644
--- a/libavutil/frame.h
+++ b/libavutil/frame.h
@@ -214,6 +214,16 @@ enum AVFrameSideDataType {
* Ambient viewing environment metadata, as defined by H.274.
*/
AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT,
+
+ /**
+ * Provide macro block encoder-specific hinting information for the encoder
+ * processing. It can be used to pass information about which macroblock
+ * can be skipped because it hasn't changed from the corresponding one in
+ * the previous frame. This is useful for applications which know in
+ * advance this information to speed up real-time encoding. Currently only
+ * used by libx264.
+ */
+ AV_FRAME_DATA_VIDEO_HINT,
};
enum AVActiveFormatDescription {
diff --git a/libavutil/video_hint_info.c b/libavutil/video_hint_info.c
new file mode 100644
index 0000000000..c920bd6232
--- /dev/null
+++ b/libavutil/video_hint_info.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2023 Elias Carotti <eliascrt at amazon dot it>
+ *
+ * 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 <string.h>
+
+#include "avstring.h"
+#include "frame.h"
+#include "macros.h"
+#include "mem.h"
+#include "video_hint_info.h"
+
+AVVideoHint *av_video_hint_alloc(AVVideoRect *rects,
+ size_t nb_rects,
+ AVVideoHintType type,
+ size_t* out_size)
+{
+ struct TestStruct {
+ AVVideoHint hint;
+ AVVideoRect rect;
+ };
+ const size_t blocks_offset = offsetof(struct TestStruct, rect);
+ size_t size = blocks_offset;
+ AVVideoHint *hint;
+
+ *out_size = 0;
+ if (nb_rects > (SIZE_MAX - size) / sizeof(AVVideoRect))
+ return NULL;
+ size += sizeof(AVVideoRect) * nb_rects;
+
+ hint = av_mallocz(size);
+ if (!hint)
+ return NULL;
+
+ hint->type = type;
+ hint->nb_rects = nb_rects;
+ hint->blocks_offset = blocks_offset;
+
+ /* Just copies the rects over the newly allocated buffer */
+ memcpy((uint8_t *)hint + blocks_offset, rects, sizeof(AVVideoRect) * nb_rects);
+
+ *out_size = size;
+
+ return hint;
+}
+
+AVVideoHint *av_video_hint_create_side_data(AVFrame *frame,
+ AVVideoRect *rects,
+ size_t num_rects,
+ AVVideoHintType type)
+{
+ AVVideoHint *hint;
+ AVBufferRef *buf;
+ size_t size = 0;
+
+ hint = av_video_hint_alloc(rects, num_rects, type, &size);
+ if (!hint)
+ return NULL;
+
+ buf = av_buffer_create((uint8_t *)hint, size, NULL, NULL, 0);
+ if (!buf) {
+ av_freep(&hint);
+ return NULL;
+ }
+
+ if (!av_frame_new_side_data_from_buf(frame, AV_FRAME_DATA_VIDEO_HINT, buf)) {
+ av_buffer_unref(&buf);
+ return NULL;
+ }
+
+ return hint;
+}
+
diff --git a/libavutil/video_hint_info.h b/libavutil/video_hint_info.h
new file mode 100644
index 0000000000..2844398d18
--- /dev/null
+++ b/libavutil/video_hint_info.h
@@ -0,0 +1,87 @@
+/**
+ * Copyright 2023 Elias Carotti <eliascrt at amazon dot it>
+ *
+ * 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
+ */
+
+#ifndef AVUTIL_VIDEO_HINT_INFO_H
+#define AVUTIL_VIDEO_HINT_INFO_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include "libavutil/avassert.h"
+#include "libavutil/frame.h"
+
+typedef struct AVVideoRect {
+ uint32_t x, y;
+ uint32_t width, height;
+} AVVideoRect;
+
+typedef enum AVVideoHintType {
+ /* blocks delimit the constant areas (unchanged), default is changed */
+ AV_VIDEO_HINT_CONSTANT,
+
+ /* blocks delimit the constant areas (changed), default is not changed */
+ AV_VIDEO_HINT_CHANGED,
+} AVVideoHintType;
+
+typedef struct AVVideoHint {
+ /**
+ * Number of blocks in the array.
+ *
+ * May be 0, in which case no per-block information is present. In this case
+ * the values of blocks_offset / block_size are unspecified and should not
+ * be accessed.
+ */
+ int nb_rects;
+
+ /**
+ * Offset in bytes from the beginning of this structure at which the array
+ * of blocks starts.
+ */
+ size_t blocks_offset;
+
+ AVVideoHintType type;
+} AVVideoHint;
+
+static av_always_inline AVVideoRect*
+av_video_hint_rects(const AVVideoHint *par)
+{
+ return (AVVideoRect *)((uint8_t *)par + par->blocks_offset);
+}
+
+/**
+ * Allocate memory for a vector of AVVideoRect in the given AVFrame
+ * {@code frame} as AVFrameSideData of type AV_FRAME_DATA_VIDEO_HINT_INFO.
+ * The side data contains a list of rectangles for the portions of the frame
+ * which changed from the last encoded one (and the remainder are assumed to be
+ * changed), or, alternately (depending on the type parameter) the unchanged
+ * ones (and the remanining ones are those which changed).
+ * Macroblocks will thus be hinted either to be P_SKIP-ped or go through the
+ * regular encoding procedure.
+ */
+AVVideoHint *av_video_hint_create_side_data(AVFrame *frame,
+ AVVideoRect *rects,
+ size_t num_rects,
+ AVVideoHintType type);
+
+AVVideoHint *av_video_hint_alloc(AVVideoRect *rects,
+ size_t nb_rects,
+ AVVideoHintType type,
+ size_t *out_size);
+
+#endif /* AVUTIL_VIDEO_HINT_INFO_H */
--
2.34.1
[-- Attachment #3: Type: text/plain, Size: 251 bytes --]
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [FFmpeg-devel] [PATCH] Optimization: support for libx264's mb_info
2023-06-05 15:32 ` Carotti, Elias
@ 2023-06-11 17:15 ` Stefano Sabatini
2023-06-12 8:23 ` Kieran Kunhya
2023-06-12 17:28 ` Carotti, Elias
0 siblings, 2 replies; 33+ messages in thread
From: Stefano Sabatini @ 2023-06-11 17:15 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On date Monday 2023-06-05 15:32:35 +0000, Carotti, Elias wrote:
> Hi,
> please find attached the patch which I updated according to your
> suggestions.
> Best,
> Elias
[...]
> From 8288d2bd36ffed29140d46c42b6f5515a9058836 Mon Sep 17 00:00:00 2001
> From: Elias Carotti <eliascr _at_ amazon _dot_ it>
> Date: Wed, 19 Apr 2023 11:49:39 +0200
> Subject: [PATCH] Add support for libx264's MB_INFO
>
> libx264's x264_image_properties_t, which is passed to the encoding function,
> contains a field to pass down information on the portions of the frame which
> changed with respect to the previous one (used for prediction) to mark
> unchanged macroblocks P_SKIP.
> ---
> libavcodec/libx264.c | 94 +++++++++++++++++++++++++++++++++++++
> libavutil/Makefile | 4 ++
> libavutil/frame.h | 10 ++++
> libavutil/video_hint_info.c | 89 +++++++++++++++++++++++++++++++++++
> libavutil/video_hint_info.h | 87 ++++++++++++++++++++++++++++++++++
> 5 files changed, 284 insertions(+)
> create mode 100644 libavutil/video_hint_info.c
> create mode 100644 libavutil/video_hint_info.h
>
> diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c
> index 5736f1efa7..2cf7755eec 100644
> --- a/libavcodec/libx264.c
> +++ b/libavcodec/libx264.c
> @@ -30,6 +30,7 @@
> #include "libavutil/stereo3d.h"
> #include "libavutil/time.h"
> #include "libavutil/intreadwrite.h"
> +#include "libavutil/video_hint_info.h"
> #include "avcodec.h"
> #include "codec_internal.h"
> #include "encode.h"
> @@ -48,6 +49,13 @@
> // from x264.h, for quant_offsets, Macroblocks are 16x16
> // blocks of pixels (with respect to the luma plane)
> #define MB_SIZE 16
> +#define MB_LSIZE 4
> +#define MB_FLOOR(x) ((x) >> (MB_LSIZE))
> +#define MB_CEIL(x) MB_FLOOR((x) + (MB_SIZE - 1))
> +
> +typedef void (*AVMBInfoComputeCoords)(const AVVideoRect *rect,
> + int *min_x, int *max_x,
> + int *min_y, int *max_y);
>
> typedef struct X264Opaque {
> #if FF_API_REORDERED_OPAQUE
> @@ -123,6 +131,8 @@ typedef struct X264Context {
> * encounter a frame with ROI side data.
> */
> int roi_warned;
> +
> + int mb_info;
> } X264Context;
>
> static void X264_log(void *p, int level, const char *fmt, va_list args)
> @@ -295,6 +305,7 @@ static void free_picture(x264_picture_t *pic)
> av_free(pic->extra_sei.payloads[i].payload);
> av_freep(&pic->extra_sei.payloads);
> av_freep(&pic->prop.quant_offsets);
> + av_freep(&pic->prop.mb_info);
> pic->extra_sei.num_payloads = 0;
> }
>
> @@ -320,6 +331,73 @@ static enum AVPixelFormat csp_to_pixfmt(int csp)
> return AV_PIX_FMT_NONE;
> }
>
> +static void mbinfo_compute_changed_coords(const AVVideoRect *rect,
> + int *min_x,
> + int *max_x,
> + int *min_y,
> + int *max_y)
> +{
> + *min_y = MB_FLOOR(rect->y);
> + *max_y = MB_CEIL(rect->y + rect->height);
> + *min_x = MB_FLOOR(rect->x);
> + *max_x = MB_CEIL(rect->x + rect->width);
> +}
> +
> +static void mbinfo_compute_constant_coords(const AVVideoRect *rect,
> + int *min_x,
> + int *max_x,
> + int *min_y,
> + int *max_y)
> +{
> + *min_y = MB_CEIL(rect->y);
> + *max_y = MB_FLOOR(rect->y + rect->height);
> + *min_x = MB_CEIL(rect->x);
> + *max_x = MB_FLOOR(rect->x + rect->width);
> +}
> +
> +static int setup_mb_info(AVCodecContext *ctx, x264_picture_t *pic,
> + const AVFrame *frame,
> + const AVVideoHint *info)
> +{
> + int mb_width = (frame->width + MB_SIZE - 1) / MB_SIZE;
> + int mb_height = (frame->height + MB_SIZE - 1) / MB_SIZE;
> + int mbinfo_filler;
> + int mbinfo_marker;
> + AVMBInfoComputeCoords compute_coords_fn;
> +
> + const AVVideoRect *mbinfo_rects;
> + int nb_rects;
> + uint8_t *mbinfo;
> +
> + mbinfo_rects = (const AVVideoRect *)av_video_hint_rects(info);
> + nb_rects = info->nb_rects;
> +
> + mbinfo = av_calloc(mb_width * mb_height, sizeof(*mbinfo));
> + if (!mbinfo)
> + return AVERROR(ENOMEM);
> +
> + mbinfo_filler = (info->type == AV_VIDEO_HINT_CHANGED) ? X264_MBINFO_CONSTANT : 0;
> + mbinfo_marker = (info->type == AV_VIDEO_HINT_CHANGED) ? 0 : X264_MBINFO_CONSTANT;
> + compute_coords_fn = (info->type == AV_VIDEO_HINT_CHANGED) ? mbinfo_compute_changed_coords : mbinfo_compute_constant_coords;
> +
> + memset(mbinfo, mbinfo_filler, sizeof(*mbinfo) * mb_width * mb_height);
> + for (int i = 0; i < nb_rects; i++) {
> + int min_x, max_x, min_y, max_y;
> +
> + (*compute_coords_fn)(mbinfo_rects, &min_x, &max_x, &min_y, &max_y);
> + for (int mb_y = min_y; mb_y < max_y; ++mb_y) {
> + memset(mbinfo + mb_y * mb_width + min_x, mbinfo_marker, max_x - min_x);
> + }
> +
> + mbinfo_rects++;
> + }
maybe
#define COMPUTE_MBINFO(mbinfo_filler_, mbinfo_marker_, compute_coords_fn_) \
memset(mbinfo, mbinfo_filler_, sizeof(*mbinfo) * mb_width * mb_height); \
\
for (int i = 0; i < nb_rects; i++) { \
int min_x, max_x, min_y, max_y; \
\
compute_coords_fn_(mbinfo_rects, &min_x, &max_x, &min_y, &max_y); \
for (int mb_y = min_y; mb_y < max_y; ++mb_y) { \
memset(mbinfo + mb_y * mb_width + min_x, mbinfo_marker_, max_x - min_x); \
} \
\
mbinfo_rects++; \
} \
if (info->type == AV_VIDEO_HINT_CHANGED) {
COMPUTE_MBINFO(X264_MBINFO_CONSTANT, 0, mbinfo_compute_changed_coords);
} else /* if (info->type == AV_VIDEO_HINT_CHANGED) */ {
COMPUTE_MBINFO(0, X264_MBINFO_CONSTANT, mbinfo_compute_constant_coords);
}
this adds to spatial complexity but enables the use of inlined
functions to avoid the function call in the loop
> + pic->prop.mb_info = mbinfo;
> + pic->prop.mb_info_free = av_free;
> +
> + return 0;
> +}
> +
> static int setup_roi(AVCodecContext *ctx, x264_picture_t *pic, int bit_depth,
> const AVFrame *frame, const uint8_t *data, size_t size)
> {
> @@ -404,6 +482,7 @@ static int setup_frame(AVCodecContext *ctx, const AVFrame *frame,
> int64_t wallclock = 0;
> int bit_depth, ret;
> AVFrameSideData *sd;
> + AVFrameSideData *mbinfo_sd;
>
> *ppic = NULL;
> if (!frame)
> @@ -499,6 +578,17 @@ FF_ENABLE_DEPRECATION_WARNINGS
> goto fail;
> }
>
> + mbinfo_sd = av_frame_get_side_data(frame, AV_FRAME_DATA_VIDEO_HINT);
> + if (mbinfo_sd) {
> + int ret = setup_mb_info(ctx, pic, frame, (const AVVideoHint *)mbinfo_sd->data);
> + if (ret < 0) {
> + /* No need to fail here, this is not fatal. We just proceed with no
> + * mb_info and log a message */
> +
> + av_log(ctx, AV_LOG_WARNING, "mb_info setup failure\n");
nit to provide more context: "setup_mb_info failed with error: %s\n", av_strerror(ret)
> + }
> + }
> +
> if (x4->udu_sei) {
> for (int j = 0; j < frame->nb_side_data; j++) {
> AVFrameSideData *side_data = frame->side_data[j];
> @@ -1102,6 +1192,9 @@ FF_ENABLE_DEPRECATION_WARNINGS
> }
> }
>
> + x4->params.analyse.b_mb_info = x4->mb_info;
> + x4->params.analyse.b_fast_pskip = 1;
> +
> // update AVCodecContext with x264 parameters
> avctx->has_b_frames = x4->params.i_bframe ?
> x4->params.i_bframe_pyramid ? 2 : 1 : 0;
> @@ -1311,6 +1404,7 @@ static const AVOption options[] = {
> { "noise_reduction", "Noise reduction", OFFSET(noise_reduction), AV_OPT_TYPE_INT, { .i64 = -1 }, INT_MIN, INT_MAX, VE },
> { "udu_sei", "Use user data unregistered SEI if available", OFFSET(udu_sei), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
> { "x264-params", "Override the x264 configuration using a :-separated list of key=value parameters", OFFSET(x264_params), AV_OPT_TYPE_DICT, { 0 }, 0, 0, VE },
> + { "mb_info", "Set mb_info data through AVSideData, only useful when used from the API", OFFSET(mb_info), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
> { NULL },
> };
[...]
> enum AVActiveFormatDescription {
> diff --git a/libavutil/video_hint_info.c b/libavutil/video_hint_info.c
> new file mode 100644
> index 0000000000..c920bd6232
> --- /dev/null
> +++ b/libavutil/video_hint_info.c
> @@ -0,0 +1,89 @@
> +/*
> + * Copyright 2023 Elias Carotti <eliascrt at amazon dot it>
> + *
> + * 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 <string.h>
> +
> +#include "avstring.h"
> +#include "frame.h"
> +#include "macros.h"
> +#include "mem.h"
> +#include "video_hint_info.h"
> +
> +AVVideoHint *av_video_hint_alloc(AVVideoRect *rects,
> + size_t nb_rects,
> + AVVideoHintType type,
> + size_t* out_size)
> +{
> + struct TestStruct {
> + AVVideoHint hint;
> + AVVideoRect rect;
> + };
> + const size_t blocks_offset = offsetof(struct TestStruct, rect);
> + size_t size = blocks_offset;
> + AVVideoHint *hint;
> +
> + *out_size = 0;
> + if (nb_rects > (SIZE_MAX - size) / sizeof(AVVideoRect))
> + return NULL;
> + size += sizeof(AVVideoRect) * nb_rects;
> +
> + hint = av_mallocz(size);
> + if (!hint)
> + return NULL;
> +
> + hint->type = type;
> + hint->nb_rects = nb_rects;
> + hint->blocks_offset = blocks_offset;
> +
> + /* Just copies the rects over the newly allocated buffer */
> + memcpy((uint8_t *)hint + blocks_offset, rects, sizeof(AVVideoRect) * nb_rects);
> +
> + *out_size = size;
> +
> + return hint;
> +}
> +
> +AVVideoHint *av_video_hint_create_side_data(AVFrame *frame,
> + AVVideoRect *rects,
> + size_t num_rects,
> + AVVideoHintType type)
> +{
> + AVVideoHint *hint;
> + AVBufferRef *buf;
> + size_t size = 0;
> +
> + hint = av_video_hint_alloc(rects, num_rects, type, &size);
> + if (!hint)
> + return NULL;
> +
> + buf = av_buffer_create((uint8_t *)hint, size, NULL, NULL, 0);
> + if (!buf) {
> + av_freep(&hint);
> + return NULL;
> + }
> +
> + if (!av_frame_new_side_data_from_buf(frame, AV_FRAME_DATA_VIDEO_HINT, buf)) {
> + av_buffer_unref(&buf);
> + return NULL;
> + }
> +
> + return hint;
> +}
> +
> diff --git a/libavutil/video_hint_info.h b/libavutil/video_hint_info.h
> new file mode 100644
> index 0000000000..2844398d18
> --- /dev/null
> +++ b/libavutil/video_hint_info.h
strip the _info part since to have simple mapping between data
structure and file names
[...]
Looks good to me otherwise, maybe Michael/Anton or someone else want
to have a look?
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [FFmpeg-devel] [PATCH] Optimization: support for libx264's mb_info
2023-06-11 17:15 ` Stefano Sabatini
@ 2023-06-12 8:23 ` Kieran Kunhya
2023-06-12 17:38 ` Carotti, Elias
2023-06-12 17:28 ` Carotti, Elias
1 sibling, 1 reply; 33+ messages in thread
From: Kieran Kunhya @ 2023-06-12 8:23 UTC (permalink / raw)
To: FFmpeg development discussions and patches
>
> Looks good to me otherwise, maybe Michael/Anton or someone else want
> to have a look?
>
I don't think we should be adding what is essentially libx264 specific code
to the public libavutil API.
Kieran
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [FFmpeg-devel] [PATCH] Optimization: support for libx264's mb_info
2023-06-11 17:15 ` Stefano Sabatini
2023-06-12 8:23 ` Kieran Kunhya
@ 2023-06-12 17:28 ` Carotti, Elias
2023-06-18 10:18 ` Stefano Sabatini
1 sibling, 1 reply; 33+ messages in thread
From: Carotti, Elias @ 2023-06-12 17:28 UTC (permalink / raw)
To: ffmpeg-devel
[-- Attachment #1: Type: text/plain, Size: 16019 bytes --]
Hi Stefano,
Here is the revised patch according to your suggestions. This should
allow for efficient inlining of the methods computing the map of
skipped macrobloks.
Best,
Elias
On Sun, 2023-06-11 at 19:15 +0200, Stefano Sabatini wrote:
> CAUTION: This email originated from outside of the organization. Do
> not click links or open attachments unless you can confirm the sender
> and know the content is safe.
>
>
>
> On date Monday 2023-06-05 15:32:35 +0000, Carotti, Elias wrote:
> > Hi,
> > please find attached the patch which I updated according to your
> > suggestions.
> > Best,
> > Elias
> [...]
>
> > From 8288d2bd36ffed29140d46c42b6f5515a9058836 Mon Sep 17 00:00:00
> > 2001
> > From: Elias Carotti <eliascr _at_ amazon _dot_ it>
> > Date: Wed, 19 Apr 2023 11:49:39 +0200
> > Subject: [PATCH] Add support for libx264's MB_INFO
> >
> > libx264's x264_image_properties_t, which is passed to the encoding
> > function,
> > contains a field to pass down information on the portions of the
> > frame which
> > changed with respect to the previous one (used for prediction) to
> > mark
> > unchanged macroblocks P_SKIP.
> > ---
> > libavcodec/libx264.c | 94
> > +++++++++++++++++++++++++++++++++++++
> > libavutil/Makefile | 4 ++
> > libavutil/frame.h | 10 ++++
> > libavutil/video_hint_info.c | 89
> > +++++++++++++++++++++++++++++++++++
> > libavutil/video_hint_info.h | 87
> > ++++++++++++++++++++++++++++++++++
> > 5 files changed, 284 insertions(+)
> > create mode 100644 libavutil/video_hint_info.c
> > create mode 100644 libavutil/video_hint_info.h
> >
> > diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c
> > index 5736f1efa7..2cf7755eec 100644
> > --- a/libavcodec/libx264.c
> > +++ b/libavcodec/libx264.c
> > @@ -30,6 +30,7 @@
> > #include "libavutil/stereo3d.h"
> > #include "libavutil/time.h"
> > #include "libavutil/intreadwrite.h"
> > +#include "libavutil/video_hint_info.h"
> > #include "avcodec.h"
> > #include "codec_internal.h"
> > #include "encode.h"
> > @@ -48,6 +49,13 @@
> > // from x264.h, for quant_offsets, Macroblocks are 16x16
> > // blocks of pixels (with respect to the luma plane)
> > #define MB_SIZE 16
> > +#define MB_LSIZE 4
> > +#define MB_FLOOR(x) ((x) >> (MB_LSIZE))
> > +#define MB_CEIL(x) MB_FLOOR((x) + (MB_SIZE - 1))
> > +
> > +typedef void (*AVMBInfoComputeCoords)(const AVVideoRect *rect,
> > + int *min_x, int *max_x,
> > + int *min_y, int *max_y);
> >
> > typedef struct X264Opaque {
> > #if FF_API_REORDERED_OPAQUE
> > @@ -123,6 +131,8 @@ typedef struct X264Context {
> > * encounter a frame with ROI side data.
> > */
> > int roi_warned;
> > +
> > + int mb_info;
> > } X264Context;
> >
> > static void X264_log(void *p, int level, const char *fmt, va_list
> > args)
> > @@ -295,6 +305,7 @@ static void free_picture(x264_picture_t *pic)
> > av_free(pic->extra_sei.payloads[i].payload);
> > av_freep(&pic->extra_sei.payloads);
> > av_freep(&pic->prop.quant_offsets);
> > + av_freep(&pic->prop.mb_info);
> > pic->extra_sei.num_payloads = 0;
> > }
> >
> > @@ -320,6 +331,73 @@ static enum AVPixelFormat csp_to_pixfmt(int
> > csp)
> > return AV_PIX_FMT_NONE;
> > }
> >
> > +static void mbinfo_compute_changed_coords(const AVVideoRect *rect,
> > + int *min_x,
> > + int *max_x,
> > + int *min_y,
> > + int *max_y)
> > +{
> > + *min_y = MB_FLOOR(rect->y);
> > + *max_y = MB_CEIL(rect->y + rect->height);
> > + *min_x = MB_FLOOR(rect->x);
> > + *max_x = MB_CEIL(rect->x + rect->width);
> > +}
> > +
> > +static void mbinfo_compute_constant_coords(const AVVideoRect
> > *rect,
> > + int *min_x,
> > + int *max_x,
> > + int *min_y,
> > + int *max_y)
> > +{
> > + *min_y = MB_CEIL(rect->y);
> > + *max_y = MB_FLOOR(rect->y + rect->height);
> > + *min_x = MB_CEIL(rect->x);
> > + *max_x = MB_FLOOR(rect->x + rect->width);
> > +}
> > +
> > +static int setup_mb_info(AVCodecContext *ctx, x264_picture_t *pic,
> > + const AVFrame *frame,
> > + const AVVideoHint *info)
> > +{
> > + int mb_width = (frame->width + MB_SIZE - 1) / MB_SIZE;
> > + int mb_height = (frame->height + MB_SIZE - 1) / MB_SIZE;
> > + int mbinfo_filler;
> > + int mbinfo_marker;
> > + AVMBInfoComputeCoords compute_coords_fn;
> > +
> > + const AVVideoRect *mbinfo_rects;
> > + int nb_rects;
> > + uint8_t *mbinfo;
> > +
> > + mbinfo_rects = (const AVVideoRect *)av_video_hint_rects(info);
> > + nb_rects = info->nb_rects;
> > +
> > + mbinfo = av_calloc(mb_width * mb_height, sizeof(*mbinfo));
> > + if (!mbinfo)
> > + return AVERROR(ENOMEM);
> > +
>
> > + mbinfo_filler = (info->type == AV_VIDEO_HINT_CHANGED) ?
> > X264_MBINFO_CONSTANT : 0;
> > + mbinfo_marker = (info->type == AV_VIDEO_HINT_CHANGED) ? 0
> > : X264_MBINFO_CONSTANT;
> > + compute_coords_fn = (info->type == AV_VIDEO_HINT_CHANGED) ?
> > mbinfo_compute_changed_coords : mbinfo_compute_constant_coords;
> > +
> > + memset(mbinfo, mbinfo_filler, sizeof(*mbinfo) * mb_width *
> > mb_height);
> > + for (int i = 0; i < nb_rects; i++) {
> > + int min_x, max_x, min_y, max_y;
> > +
> > + (*compute_coords_fn)(mbinfo_rects, &min_x, &max_x, &min_y,
> > &max_y);
> > + for (int mb_y = min_y; mb_y < max_y; ++mb_y) {
> > + memset(mbinfo + mb_y * mb_width + min_x,
> > mbinfo_marker, max_x - min_x);
> > + }
> > +
> > + mbinfo_rects++;
> > + }
>
> maybe
>
> #define COMPUTE_MBINFO(mbinfo_filler_, mbinfo_marker_,
> compute_coords_fn_) \
> memset(mbinfo, mbinfo_filler_, sizeof(*mbinfo) * mb_width *
> mb_height); \
>
> \
> for (int i = 0; i < nb_rects; i++)
> { \
> int min_x, max_x, min_y,
> max_y; \
>
> \
> compute_coords_fn_(mbinfo_rects, &min_x, &max_x, &min_y,
> &max_y); \
> for (int mb_y = min_y; mb_y < max_y; ++mb_y)
> { \
> memset(mbinfo + mb_y * mb_width + min_x, mbinfo_marker_,
> max_x - min_x); \
>
> } \
>
> \
>
> mbinfo_rects++; \
>
> } \
>
> if (info->type == AV_VIDEO_HINT_CHANGED) {
> COMPUTE_MBINFO(X264_MBINFO_CONSTANT, 0,
> mbinfo_compute_changed_coords);
> } else /* if (info->type == AV_VIDEO_HINT_CHANGED) */ {
> COMPUTE_MBINFO(0, X264_MBINFO_CONSTANT,
> mbinfo_compute_constant_coords);
> }
>
> this adds to spatial complexity but enables the use of inlined
> functions to avoid the function call in the loop
>
> > + pic->prop.mb_info = mbinfo;
> > + pic->prop.mb_info_free = av_free;
> > +
> > + return 0;
> > +}
> > +
> > static int setup_roi(AVCodecContext *ctx, x264_picture_t *pic, int
> > bit_depth,
> > const AVFrame *frame, const uint8_t *data,
> > size_t size)
> > {
> > @@ -404,6 +482,7 @@ static int setup_frame(AVCodecContext *ctx,
> > const AVFrame *frame,
> > int64_t wallclock = 0;
> > int bit_depth, ret;
> > AVFrameSideData *sd;
> > + AVFrameSideData *mbinfo_sd;
> >
> > *ppic = NULL;
> > if (!frame)
> > @@ -499,6 +578,17 @@ FF_ENABLE_DEPRECATION_WARNINGS
> > goto fail;
> > }
> >
> > + mbinfo_sd = av_frame_get_side_data(frame,
> > AV_FRAME_DATA_VIDEO_HINT);
> > + if (mbinfo_sd) {
> > + int ret = setup_mb_info(ctx, pic, frame, (const
> > AVVideoHint *)mbinfo_sd->data);
> > + if (ret < 0) {
> > + /* No need to fail here, this is not fatal. We just
> > proceed with no
> > + * mb_info and log a message */
> > +
>
> > + av_log(ctx, AV_LOG_WARNING, "mb_info setup
> > failure\n");
>
> nit to provide more context: "setup_mb_info failed with error: %s\n",
> av_strerror(ret)
>
> > + }
> > + }
> > +
> > if (x4->udu_sei) {
> > for (int j = 0; j < frame->nb_side_data; j++) {
> > AVFrameSideData *side_data = frame->side_data[j];
> > @@ -1102,6 +1192,9 @@ FF_ENABLE_DEPRECATION_WARNINGS
> > }
> > }
> >
> > + x4->params.analyse.b_mb_info = x4->mb_info;
> > + x4->params.analyse.b_fast_pskip = 1;
> > +
> > // update AVCodecContext with x264 parameters
> > avctx->has_b_frames = x4->params.i_bframe ?
> > x4->params.i_bframe_pyramid ? 2 : 1 : 0;
> > @@ -1311,6 +1404,7 @@ static const AVOption options[] = {
> > { "noise_reduction", "Noise
> > reduction", OFFSET(noise_reduction),
> > AV_OPT_TYPE_INT, { .i64 = -1 }, INT_MIN, INT_MAX, VE },
> > { "udu_sei", "Use user data unregistered SEI if
> > available", OFFSET(udu_sei), AV_OPT_TYPE_BOOL, { .i64 = 0
> > }, 0, 1, VE },
> > { "x264-params", "Override the x264 configuration using a :-
> > separated list of key=value parameters", OFFSET(x264_params),
> > AV_OPT_TYPE_DICT, { 0 }, 0, 0, VE },
> > + { "mb_info", "Set mb_info data through AVSideData, only
> > useful when used from the API", OFFSET(mb_info), AV_OPT_TYPE_BOOL,
> > { .i64 = 0 }, 0, 1, VE },
> > { NULL },
> > };
> [...]
> > enum AVActiveFormatDescription {
> > diff --git a/libavutil/video_hint_info.c
> > b/libavutil/video_hint_info.c
> > new file mode 100644
> > index 0000000000..c920bd6232
> > --- /dev/null
> > +++ b/libavutil/video_hint_info.c
> > @@ -0,0 +1,89 @@
> > +/*
> > + * Copyright 2023 Elias Carotti <eliascrt at amazon dot it>
> > + *
> > + * 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 <string.h>
> > +
> > +#include "avstring.h"
> > +#include "frame.h"
> > +#include "macros.h"
> > +#include "mem.h"
> > +#include "video_hint_info.h"
> > +
> > +AVVideoHint *av_video_hint_alloc(AVVideoRect *rects,
> > + size_t nb_rects,
> > + AVVideoHintType type,
> > + size_t* out_size)
> > +{
> > + struct TestStruct {
> > + AVVideoHint hint;
> > + AVVideoRect rect;
> > + };
>
> > + const size_t blocks_offset = offsetof(struct TestStruct,
> > rect);
> > + size_t size = blocks_offset;
> > + AVVideoHint *hint;
> > +
> > + *out_size = 0;
> > + if (nb_rects > (SIZE_MAX - size) / sizeof(AVVideoRect))
> > + return NULL;
> > + size += sizeof(AVVideoRect) * nb_rects;
> > +
> > + hint = av_mallocz(size);
> > + if (!hint)
> > + return NULL;
> > +
> > + hint->type = type;
> > + hint->nb_rects = nb_rects;
> > + hint->blocks_offset = blocks_offset;
> > +
> > + /* Just copies the rects over the newly allocated buffer */
> > + memcpy((uint8_t *)hint + blocks_offset, rects,
> > sizeof(AVVideoRect) * nb_rects);
> > +
> > + *out_size = size;
> > +
> > + return hint;
> > +}
> > +
> > +AVVideoHint *av_video_hint_create_side_data(AVFrame *frame,
> > + AVVideoRect *rects,
> > + size_t num_rects,
> > + AVVideoHintType type)
> > +{
> > + AVVideoHint *hint;
> > + AVBufferRef *buf;
> > + size_t size = 0;
> > +
> > + hint = av_video_hint_alloc(rects, num_rects, type, &size);
> > + if (!hint)
> > + return NULL;
> > +
> > + buf = av_buffer_create((uint8_t *)hint, size, NULL, NULL, 0);
> > + if (!buf) {
> > + av_freep(&hint);
> > + return NULL;
> > + }
> > +
> > + if (!av_frame_new_side_data_from_buf(frame,
> > AV_FRAME_DATA_VIDEO_HINT, buf)) {
> > + av_buffer_unref(&buf);
> > + return NULL;
> > + }
> > +
> > + return hint;
> > +}
> > +
> > diff --git a/libavutil/video_hint_info.h
> > b/libavutil/video_hint_info.h
> > new file mode 100644
> > index 0000000000..2844398d18
> > --- /dev/null
>
> > +++ b/libavutil/video_hint_info.h
>
> strip the _info part since to have simple mapping between data
> structure and file names
>
> [...]
>
> Looks good to me otherwise, maybe Michael/Anton or someone else want
> to have a look?
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
NICE SRL, viale Monte Grappa 3/5, 20124 Milano, Italia, Registro delle Imprese di Milano Monza Brianza Lodi REA n. 2096882, Capitale Sociale: 10.329,14 EUR i.v., Cod. Fisc. e P.IVA 01133050052, Societa con Socio Unico
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Add-support-for-libx264-s-MB_INFO.patch --]
[-- Type: text/x-patch; name="0001-Add-support-for-libx264-s-MB_INFO.patch", Size: 15963 bytes --]
From 0e7979250231edbe0b845cee96c473bc6e07d46b Mon Sep 17 00:00:00 2001
From: Elias Carotti <eliascrt _at_ amazon _dot_ it>
Date: Wed, 19 Apr 2023 11:49:39 +0200
Subject: [PATCH] Add support for libx264's MB_INFO
libx264's x264_image_properties_t, which is passed to the encoding function,
contains a field to pass down information on the portions of the frame which
changed with respect to the previous one (used for prediction) to mark
unchanged macroblocks P_SKIP.
---
libavcodec/libx264.c | 91 ++++++++++++++++++++++++++++++++++++++++++
libavutil/Makefile | 4 ++
libavutil/frame.h | 10 +++++
libavutil/video_hint.c | 89 +++++++++++++++++++++++++++++++++++++++++
libavutil/video_hint.h | 87 ++++++++++++++++++++++++++++++++++++++++
5 files changed, 281 insertions(+)
create mode 100644 libavutil/video_hint.c
create mode 100644 libavutil/video_hint.h
diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c
index 5736f1efa7..c42e7ad39d 100644
--- a/libavcodec/libx264.c
+++ b/libavcodec/libx264.c
@@ -30,6 +30,7 @@
#include "libavutil/stereo3d.h"
#include "libavutil/time.h"
#include "libavutil/intreadwrite.h"
+#include "libavutil/video_hint.h"
#include "avcodec.h"
#include "codec_internal.h"
#include "encode.h"
@@ -48,6 +49,9 @@
// from x264.h, for quant_offsets, Macroblocks are 16x16
// blocks of pixels (with respect to the luma plane)
#define MB_SIZE 16
+#define MB_LSIZE 4
+#define MB_FLOOR(x) ((x) >> (MB_LSIZE))
+#define MB_CEIL(x) MB_FLOOR((x) + (MB_SIZE - 1))
typedef struct X264Opaque {
#if FF_API_REORDERED_OPAQUE
@@ -123,6 +127,8 @@ typedef struct X264Context {
* encounter a frame with ROI side data.
*/
int roi_warned;
+
+ int mb_info;
} X264Context;
static void X264_log(void *p, int level, const char *fmt, va_list args)
@@ -295,6 +301,7 @@ static void free_picture(x264_picture_t *pic)
av_free(pic->extra_sei.payloads[i].payload);
av_freep(&pic->extra_sei.payloads);
av_freep(&pic->prop.quant_offsets);
+ av_freep(&pic->prop.mb_info);
pic->extra_sei.num_payloads = 0;
}
@@ -320,6 +327,74 @@ static enum AVPixelFormat csp_to_pixfmt(int csp)
return AV_PIX_FMT_NONE;
}
+static void av_always_inline mbinfo_compute_changed_coords(const AVVideoRect *rect,
+ int *min_x,
+ int *max_x,
+ int *min_y,
+ int *max_y)
+{
+ *min_y = MB_FLOOR(rect->y);
+ *max_y = MB_CEIL(rect->y + rect->height);
+ *min_x = MB_FLOOR(rect->x);
+ *max_x = MB_CEIL(rect->x + rect->width);
+}
+
+static void av_always_inline mbinfo_compute_constant_coords(const AVVideoRect *rect,
+ int *min_x,
+ int *max_x,
+ int *min_y,
+ int *max_y)
+{
+ *min_y = MB_CEIL(rect->y);
+ *max_y = MB_FLOOR(rect->y + rect->height);
+ *min_x = MB_CEIL(rect->x);
+ *max_x = MB_FLOOR(rect->x + rect->width);
+}
+
+static int setup_mb_info(AVCodecContext *ctx, x264_picture_t *pic,
+ const AVFrame *frame,
+ const AVVideoHint *info)
+{
+ int mb_width = (frame->width + MB_SIZE - 1) / MB_SIZE;
+ int mb_height = (frame->height + MB_SIZE - 1) / MB_SIZE;
+
+ const AVVideoRect *mbinfo_rects;
+ int nb_rects;
+ uint8_t *mbinfo;
+
+ mbinfo_rects = (const AVVideoRect *)av_video_hint_rects(info);
+ nb_rects = info->nb_rects;
+
+ mbinfo = av_calloc(mb_width * mb_height, sizeof(*mbinfo));
+ if (!mbinfo)
+ return AVERROR(ENOMEM);
+
+#define COMPUTE_MBINFO(mbinfo_filler_, mbinfo_marker_, compute_coords_fn_) \
+ memset(mbinfo, mbinfo_filler_, sizeof(*mbinfo) * mb_width * mb_height); \
+ \
+ for (int i = 0; i < nb_rects; i++) { \
+ int min_x, max_x, min_y, max_y; \
+ \
+ compute_coords_fn_(mbinfo_rects, &min_x, &max_x, &min_y, &max_y); \
+ for (int mb_y = min_y; mb_y < max_y; ++mb_y) { \
+ memset(mbinfo + mb_y * mb_width + min_x, mbinfo_marker_, max_x - min_x); \
+ } \
+ \
+ mbinfo_rects++; \
+ } \
+
+ if (info->type == AV_VIDEO_HINT_CHANGED) {
+ COMPUTE_MBINFO(X264_MBINFO_CONSTANT, 0, mbinfo_compute_changed_coords);
+ } else /* if (info->type == AV_VIDEO_HINT_CHANGED) */ {
+ COMPUTE_MBINFO(0, X264_MBINFO_CONSTANT, mbinfo_compute_constant_coords);
+ }
+
+ pic->prop.mb_info = mbinfo;
+ pic->prop.mb_info_free = av_free;
+
+ return 0;
+}
+
static int setup_roi(AVCodecContext *ctx, x264_picture_t *pic, int bit_depth,
const AVFrame *frame, const uint8_t *data, size_t size)
{
@@ -404,6 +479,7 @@ static int setup_frame(AVCodecContext *ctx, const AVFrame *frame,
int64_t wallclock = 0;
int bit_depth, ret;
AVFrameSideData *sd;
+ AVFrameSideData *mbinfo_sd;
*ppic = NULL;
if (!frame)
@@ -499,6 +575,17 @@ FF_ENABLE_DEPRECATION_WARNINGS
goto fail;
}
+ mbinfo_sd = av_frame_get_side_data(frame, AV_FRAME_DATA_VIDEO_HINT);
+ if (mbinfo_sd) {
+ int ret = setup_mb_info(ctx, pic, frame, (const AVVideoHint *)mbinfo_sd->data);
+ if (ret < 0) {
+ /* No need to fail here, this is not fatal. We just proceed with no
+ * mb_info and log a message */
+
+ av_log(ctx, AV_LOG_WARNING, "setup_mb_info failed with error: %s\n", av_err2str(ret));
+ }
+ }
+
if (x4->udu_sei) {
for (int j = 0; j < frame->nb_side_data; j++) {
AVFrameSideData *side_data = frame->side_data[j];
@@ -1102,6 +1189,9 @@ FF_ENABLE_DEPRECATION_WARNINGS
}
}
+ x4->params.analyse.b_mb_info = x4->mb_info;
+ x4->params.analyse.b_fast_pskip = 1;
+
// update AVCodecContext with x264 parameters
avctx->has_b_frames = x4->params.i_bframe ?
x4->params.i_bframe_pyramid ? 2 : 1 : 0;
@@ -1311,6 +1401,7 @@ static const AVOption options[] = {
{ "noise_reduction", "Noise reduction", OFFSET(noise_reduction), AV_OPT_TYPE_INT, { .i64 = -1 }, INT_MIN, INT_MAX, VE },
{ "udu_sei", "Use user data unregistered SEI if available", OFFSET(udu_sei), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
{ "x264-params", "Override the x264 configuration using a :-separated list of key=value parameters", OFFSET(x264_params), AV_OPT_TYPE_DICT, { 0 }, 0, 0, VE },
+ { "mb_info", "Set mb_info data through AVSideData, only useful when used from the API", OFFSET(mb_info), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
{ NULL },
};
diff --git a/libavutil/Makefile b/libavutil/Makefile
index dc9012f9a8..0ef2b4064d 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -91,6 +91,7 @@ HEADERS = adler32.h \
tea.h \
tx.h \
film_grain_params.h \
+ video_hint.h
ARCH_HEADERS = bswap.h \
intmath.h \
@@ -188,6 +189,7 @@ OBJS-$(CONFIG_CUDA) += hwcontext_cuda.o
OBJS-$(CONFIG_D3D11VA) += hwcontext_d3d11va.o
OBJS-$(CONFIG_DXVA2) += hwcontext_dxva2.o
OBJS-$(CONFIG_LIBDRM) += hwcontext_drm.o
+OBJS-$(CONFIG_LIBX264) += video_hint.o
OBJS-$(CONFIG_MACOS_KPERF) += macos_kperf.o
OBJS-$(CONFIG_MEDIACODEC) += hwcontext_mediacodec.o
OBJS-$(CONFIG_OPENCL) += hwcontext_opencl.o
@@ -219,6 +221,8 @@ SKIPHEADERS-$(CONFIG_VULKAN) += hwcontext_vulkan.h vulkan.h \
vulkan_functions.h \
vulkan_loader.h
+SKIPHEADERS-$(CONFIG_LIBX264) += video_hint.h
+
TESTPROGS = adler32 \
aes \
aes_ctr \
diff --git a/libavutil/frame.h b/libavutil/frame.h
index a491315f25..0e765e5499 100644
--- a/libavutil/frame.h
+++ b/libavutil/frame.h
@@ -214,6 +214,16 @@ enum AVFrameSideDataType {
* Ambient viewing environment metadata, as defined by H.274.
*/
AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT,
+
+ /**
+ * Provide macro block encoder-specific hinting information for the encoder
+ * processing. It can be used to pass information about which macroblock
+ * can be skipped because it hasn't changed from the corresponding one in
+ * the previous frame. This is useful for applications which know in
+ * advance this information to speed up real-time encoding. Currently only
+ * used by libx264.
+ */
+ AV_FRAME_DATA_VIDEO_HINT,
};
enum AVActiveFormatDescription {
diff --git a/libavutil/video_hint.c b/libavutil/video_hint.c
new file mode 100644
index 0000000000..a638891d45
--- /dev/null
+++ b/libavutil/video_hint.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2023 Elias Carotti <eliascrt at amazon dot it>
+ *
+ * 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 <string.h>
+
+#include "avstring.h"
+#include "frame.h"
+#include "macros.h"
+#include "mem.h"
+#include "video_hint.h"
+
+AVVideoHint *av_video_hint_alloc(AVVideoRect *rects,
+ size_t nb_rects,
+ AVVideoHintType type,
+ size_t* out_size)
+{
+ struct TestStruct {
+ AVVideoHint hint;
+ AVVideoRect rect;
+ };
+ const size_t blocks_offset = offsetof(struct TestStruct, rect);
+ size_t size = blocks_offset;
+ AVVideoHint *hint;
+
+ *out_size = 0;
+ if (nb_rects > (SIZE_MAX - size) / sizeof(AVVideoRect))
+ return NULL;
+ size += sizeof(AVVideoRect) * nb_rects;
+
+ hint = av_mallocz(size);
+ if (!hint)
+ return NULL;
+
+ hint->type = type;
+ hint->nb_rects = nb_rects;
+ hint->blocks_offset = blocks_offset;
+
+ /* Just copies the rects over the newly allocated buffer */
+ memcpy((uint8_t *)hint + blocks_offset, rects, sizeof(AVVideoRect) * nb_rects);
+
+ *out_size = size;
+
+ return hint;
+}
+
+AVVideoHint *av_video_hint_create_side_data(AVFrame *frame,
+ AVVideoRect *rects,
+ size_t num_rects,
+ AVVideoHintType type)
+{
+ AVVideoHint *hint;
+ AVBufferRef *buf;
+ size_t size = 0;
+
+ hint = av_video_hint_alloc(rects, num_rects, type, &size);
+ if (!hint)
+ return NULL;
+
+ buf = av_buffer_create((uint8_t *)hint, size, NULL, NULL, 0);
+ if (!buf) {
+ av_freep(&hint);
+ return NULL;
+ }
+
+ if (!av_frame_new_side_data_from_buf(frame, AV_FRAME_DATA_VIDEO_HINT, buf)) {
+ av_buffer_unref(&buf);
+ return NULL;
+ }
+
+ return hint;
+}
+
diff --git a/libavutil/video_hint.h b/libavutil/video_hint.h
new file mode 100644
index 0000000000..f7d113fb90
--- /dev/null
+++ b/libavutil/video_hint.h
@@ -0,0 +1,87 @@
+/**
+ * Copyright 2023 Elias Carotti <eliascrt at amazon dot it>
+ *
+ * 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
+ */
+
+#ifndef AVUTIL_VIDEO_HINT_H
+#define AVUTIL_VIDEO_HINT_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include "libavutil/avassert.h"
+#include "libavutil/frame.h"
+
+typedef struct AVVideoRect {
+ uint32_t x, y;
+ uint32_t width, height;
+} AVVideoRect;
+
+typedef enum AVVideoHintType {
+ /* blocks delimit the constant areas (unchanged), default is changed */
+ AV_VIDEO_HINT_CONSTANT,
+
+ /* blocks delimit the constant areas (changed), default is not changed */
+ AV_VIDEO_HINT_CHANGED,
+} AVVideoHintType;
+
+typedef struct AVVideoHint {
+ /**
+ * Number of blocks in the array.
+ *
+ * May be 0, in which case no per-block information is present. In this case
+ * the values of blocks_offset / block_size are unspecified and should not
+ * be accessed.
+ */
+ int nb_rects;
+
+ /**
+ * Offset in bytes from the beginning of this structure at which the array
+ * of blocks starts.
+ */
+ size_t blocks_offset;
+
+ AVVideoHintType type;
+} AVVideoHint;
+
+static av_always_inline AVVideoRect*
+av_video_hint_rects(const AVVideoHint *par)
+{
+ return (AVVideoRect *)((uint8_t *)par + par->blocks_offset);
+}
+
+/**
+ * Allocate memory for a vector of AVVideoRect in the given AVFrame
+ * {@code frame} as AVFrameSideData of type AV_FRAME_DATA_VIDEO_HINT_INFO.
+ * The side data contains a list of rectangles for the portions of the frame
+ * which changed from the last encoded one (and the remainder are assumed to be
+ * changed), or, alternately (depending on the type parameter) the unchanged
+ * ones (and the remanining ones are those which changed).
+ * Macroblocks will thus be hinted either to be P_SKIP-ped or go through the
+ * regular encoding procedure.
+ */
+AVVideoHint *av_video_hint_create_side_data(AVFrame *frame,
+ AVVideoRect *rects,
+ size_t num_rects,
+ AVVideoHintType type);
+
+AVVideoHint *av_video_hint_alloc(AVVideoRect *rects,
+ size_t nb_rects,
+ AVVideoHintType type,
+ size_t *out_size);
+
+#endif /* AVUTIL_VIDEO_HINT_H */
--
2.34.1
[-- Attachment #3: Type: text/plain, Size: 251 bytes --]
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [FFmpeg-devel] [PATCH] Optimization: support for libx264's mb_info
2023-06-12 8:23 ` Kieran Kunhya
@ 2023-06-12 17:38 ` Carotti, Elias
2023-06-18 10:04 ` Stefano Sabatini
0 siblings, 1 reply; 33+ messages in thread
From: Carotti, Elias @ 2023-06-12 17:38 UTC (permalink / raw)
To: ffmpeg-devel
On Mon, 2023-06-12 at 18:23 +1000, Kieran Kunhya wrote:
> CAUTION: This email originated from outside of the organization. Do
> not click links or open attachments unless you can confirm the sender
> and know the content is safe.
>
>
>
> >
> > Looks good to me otherwise, maybe Michael/Anton or someone else
> > want
> > to have a look?
> >
>
> I don't think we should be adding what is essentially libx264
> specific code
> to the public libavutil API.
>
> Kieran
Hi Kieran,
I disagree: this is not more libx264-specific than most other code in
libavutil/libx264.c, like, say, the region of interest code.
P_SKIPs are in the standard and this API is designed to provide a
generic way to generate them when the changing portion of a frame is
known in advance.
Should other encoders (and I mean it in the broadest sense, not
specifically h.264 ones) support a method for feeding in hints about
unchanged portions of a frame, it shouldn't be hard to write the
encoder-specific code for them in the respective encoder-specific file.
In fact, the public api provided only allows to specify as side data a
list of rectangles (in pixels' space) on the frame (just like it's done
for the region of interest) which is then translated into the specific
libx264 hinting mechanism (in macroblock space.)
Best,
Elias
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
NICE SRL, viale Monte Grappa 3/5, 20124 Milano, Italia, Registro delle Imprese di Milano Monza Brianza Lodi REA n. 2096882, Capitale Sociale: 10.329,14 EUR i.v., Cod. Fisc. e P.IVA 01133050052, Societa con Socio Unico
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [FFmpeg-devel] [PATCH] Optimization: support for libx264's mb_info
2023-06-12 17:38 ` Carotti, Elias
@ 2023-06-18 10:04 ` Stefano Sabatini
0 siblings, 0 replies; 33+ messages in thread
From: Stefano Sabatini @ 2023-06-18 10:04 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On date Monday 2023-06-12 17:38:43 +0000, Carotti, Elias wrote:
> On Mon, 2023-06-12 at 18:23 +1000, Kieran Kunhya wrote:
> > CAUTION: This email originated from outside of the organization. Do
> > not click links or open attachments unless you can confirm the sender
> > and know the content is safe.
> >
> > >
> > > Looks good to me otherwise, maybe Michael/Anton or someone else
> > > want
> > > to have a look?
> > >
> >
> > I don't think we should be adding what is essentially libx264
> > specific code
> > to the public libavutil API.
> >
> > Kieran
>
> Hi Kieran,
> I disagree: this is not more libx264-specific than most other code in
> libavutil/libx264.c, like, say, the region of interest code.
>
> P_SKIPs are in the standard and this API is designed to provide a
> generic way to generate them when the changing portion of a frame is
> known in advance.
>
> Should other encoders (and I mean it in the broadest sense, not
> specifically h.264 ones) support a method for feeding in hints about
> unchanged portions of a frame, it shouldn't be hard to write the
> encoder-specific code for them in the respective encoder-specific file.
>
> In fact, the public api provided only allows to specify as side data a
> list of rectangles (in pixels' space) on the frame (just like it's done
> for the region of interest) which is then translated into the specific
> libx264 hinting mechanism (in macroblock space.)
+1, I don't think there is anything specific for x264 here.
In fact, we could even add a filter to compute the hinting data and
export it in the side data. If you think this is a good idea, we could
split the patches in two parts to make this more apparent.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [FFmpeg-devel] [PATCH] Optimization: support for libx264's mb_info
2023-06-12 17:28 ` Carotti, Elias
@ 2023-06-18 10:18 ` Stefano Sabatini
2023-06-21 15:53 ` Carotti, Elias
0 siblings, 1 reply; 33+ messages in thread
From: Stefano Sabatini @ 2023-06-18 10:18 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On date Monday 2023-06-12 17:28:10 +0000, Carotti, Elias wrote:
> Hi Stefano,
> Here is the revised patch according to your suggestions. This should
> allow for efficient inlining of the methods computing the map of
> skipped macrobloks.
> Best,
> Elias
[...]
>
> From 0e7979250231edbe0b845cee96c473bc6e07d46b Mon Sep 17 00:00:00 2001
> From: Elias Carotti <eliascrt _at_ amazon _dot_ it>
> Date: Wed, 19 Apr 2023 11:49:39 +0200
> Subject: [PATCH] Add support for libx264's MB_INFO
>
> libx264's x264_image_properties_t, which is passed to the encoding function,
> contains a field to pass down information on the portions of the frame which
> changed with respect to the previous one (used for prediction) to mark
> unchanged macroblocks P_SKIP.
> ---
> libavcodec/libx264.c | 91 ++++++++++++++++++++++++++++++++++++++++++
> libavutil/Makefile | 4 ++
> libavutil/frame.h | 10 +++++
> libavutil/video_hint.c | 89 +++++++++++++++++++++++++++++++++++++++++
> libavutil/video_hint.h | 87 ++++++++++++++++++++++++++++++++++++++++
> 5 files changed, 281 insertions(+)
> create mode 100644 libavutil/video_hint.c
> create mode 100644 libavutil/video_hint.h
Note: maybe this should be split in two parts, one about libavutil and
one about libx264. The libavutil part should also contain a minor bump
for the new feature, same for libavcodec (with corresponding changes
in doc/APIchanges).
I don't know if we track internal dependencies (to define the minor
libavutil version needed for the new libx264 feature in
libavcodec). What's the current practice here?
Looks good to me otherwise (still it would be good if someone else can
have a look at it).
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [FFmpeg-devel] [PATCH] Optimization: support for libx264's mb_info
2023-06-18 10:18 ` Stefano Sabatini
@ 2023-06-21 15:53 ` Carotti, Elias
2023-06-22 8:44 ` Anton Khirnov
0 siblings, 1 reply; 33+ messages in thread
From: Carotti, Elias @ 2023-06-21 15:53 UTC (permalink / raw)
To: ffmpeg-devel
[-- Attachment #1: Type: text/plain, Size: 2587 bytes --]
On Sun, 2023-06-18 at 12:18 +0200, Stefano Sabatini wrote:
> CAUTION: This email originated from outside of the organization. Do
> not click links or open attachments unless you can confirm the sender
> and know the content is safe.
>
>
>
> On date Monday 2023-06-12 17:28:10 +0000, Carotti, Elias wrote:
> > Hi Stefano,
> > Here is the revised patch according to your suggestions. This
> > should
> > allow for efficient inlining of the methods computing the map of
> > skipped macrobloks.
> > Best,
> > Elias
> [...]
> >
> > From 0e7979250231edbe0b845cee96c473bc6e07d46b Mon Sep 17 00:00:00
> > 2001
> > From: Elias Carotti <eliascrt _at_ amazon _dot_ it>
> > Date: Wed, 19 Apr 2023 11:49:39 +0200
> > Subject: [PATCH] Add support for libx264's MB_INFO
> >
> > libx264's x264_image_properties_t, which is passed to the encoding
> > function,
> > contains a field to pass down information on the portions of the
> > frame which
> > changed with respect to the previous one (used for prediction) to
> > mark
> > unchanged macroblocks P_SKIP.
> > ---
> > libavcodec/libx264.c | 91
> > ++++++++++++++++++++++++++++++++++++++++++
> > libavutil/Makefile | 4 ++
> > libavutil/frame.h | 10 +++++
> > libavutil/video_hint.c | 89
> > +++++++++++++++++++++++++++++++++++++++++
> > libavutil/video_hint.h | 87
> > ++++++++++++++++++++++++++++++++++++++++
> > 5 files changed, 281 insertions(+)
> > create mode 100644 libavutil/video_hint.c
> > create mode 100644 libavutil/video_hint.h
>
> Note: maybe this should be split in two parts, one about libavutil
> and
> one about libx264. The libavutil part should also contain a minor
> bump
> for the new feature, same for libavcodec (with corresponding changes
> in doc/APIchanges).
>
> I don't know if we track internal dependencies (to define the minor
> libavutil version needed for the new libx264 feature in
> libavcodec). What's the current practice here?
>
> Looks good to me otherwise (still it would be good if someone else
> can
> have a look at it).
....
Hi all,
please find the updated patch split into two parts. The first part with
the changes to libavutil is appended at the end of this email, while
the second patch with the changes to libavcodec will be in a separate
mail.
Best,
Elias
NICE SRL, viale Monte Grappa 3/5, 20124 Milano, Italia, Registro delle Imprese di Milano Monza Brianza Lodi REA n. 2096882, Capitale Sociale: 10.329,14 EUR i.v., Cod. Fisc. e P.IVA 01133050052, Societa con Socio Unico
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-lavu-add-AVVideoHint-API.patch --]
[-- Type: text/x-patch; name="0001-lavu-add-AVVideoHint-API.patch", Size: 10310 bytes --]
From d4b00df7b07447fccd7f5b5c2005fcdb7383717d Mon Sep 17 00:00:00 2001
From: Elias Carotti <eliascrt _at_ amazon _dot_ it>
Date: Tue, 20 Jun 2023 19:28:04 +0200
Subject: [PATCH 1/2] lavu: add AVVideoHint API
Add side data type to provide hint to the video encoders about unchanged
portions of each frame.
---
doc/APIchanges | 3 ++
libavutil/Makefile | 4 ++
libavutil/frame.h | 10 +++++
libavutil/version.h | 4 +-
libavutil/video_hint.c | 89 ++++++++++++++++++++++++++++++++++++++++++
libavutil/video_hint.h | 87 +++++++++++++++++++++++++++++++++++++++++
6 files changed, 195 insertions(+), 2 deletions(-)
create mode 100644 libavutil/video_hint.c
create mode 100644 libavutil/video_hint.h
diff --git a/doc/APIchanges b/doc/APIchanges
index f040211f7d..bfe04556d2 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -2,6 +2,9 @@ The last version increases of all libraries were on 2023-02-09
API changes, most recent first:
+2023-06-21 - xxxxxxxxxx - lavu 58.14.100 - video_hint.h
+ Add AVVideoHint API.
+
2023-05-29 - xxxxxxxxxx - lavc 60.16.100 - avcodec.h codec_id.h
Add AV_CODEC_ID_EVC, FF_PROFILE_EVC_BASELINE, and FF_PROFILE_EVC_MAIN.
diff --git a/libavutil/Makefile b/libavutil/Makefile
index bd9c6f9e32..a0b43faa9f 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -91,6 +91,7 @@ HEADERS = adler32.h \
tea.h \
tx.h \
film_grain_params.h \
+ video_hint.h
ARCH_HEADERS = bswap.h \
intmath.h \
@@ -188,6 +189,7 @@ OBJS-$(CONFIG_CUDA) += hwcontext_cuda.o
OBJS-$(CONFIG_D3D11VA) += hwcontext_d3d11va.o
OBJS-$(CONFIG_DXVA2) += hwcontext_dxva2.o
OBJS-$(CONFIG_LIBDRM) += hwcontext_drm.o
+OBJS-$(CONFIG_LIBX264) += video_hint.o
OBJS-$(CONFIG_MACOS_KPERF) += macos_kperf.o
OBJS-$(CONFIG_MEDIACODEC) += hwcontext_mediacodec.o
OBJS-$(CONFIG_OPENCL) += hwcontext_opencl.o
@@ -219,6 +221,8 @@ SKIPHEADERS-$(CONFIG_VULKAN) += hwcontext_vulkan.h vulkan.h \
vulkan_functions.h \
vulkan_loader.h
+SKIPHEADERS-$(CONFIG_LIBX264) += video_hint.h
+
TESTPROGS = adler32 \
aes \
aes_ctr \
diff --git a/libavutil/frame.h b/libavutil/frame.h
index a491315f25..0e765e5499 100644
--- a/libavutil/frame.h
+++ b/libavutil/frame.h
@@ -214,6 +214,16 @@ enum AVFrameSideDataType {
* Ambient viewing environment metadata, as defined by H.274.
*/
AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT,
+
+ /**
+ * Provide macro block encoder-specific hinting information for the encoder
+ * processing. It can be used to pass information about which macroblock
+ * can be skipped because it hasn't changed from the corresponding one in
+ * the previous frame. This is useful for applications which know in
+ * advance this information to speed up real-time encoding. Currently only
+ * used by libx264.
+ */
+ AV_FRAME_DATA_VIDEO_HINT,
};
enum AVActiveFormatDescription {
diff --git a/libavutil/version.h b/libavutil/version.h
index 17a6d296a6..24af520e08 100644
--- a/libavutil/version.h
+++ b/libavutil/version.h
@@ -79,8 +79,8 @@
*/
#define LIBAVUTIL_VERSION_MAJOR 58
-#define LIBAVUTIL_VERSION_MINOR 13
-#define LIBAVUTIL_VERSION_MICRO 101
+#define LIBAVUTIL_VERSION_MINOR 14
+#define LIBAVUTIL_VERSION_MICRO 100
#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
LIBAVUTIL_VERSION_MINOR, \
diff --git a/libavutil/video_hint.c b/libavutil/video_hint.c
new file mode 100644
index 0000000000..a638891d45
--- /dev/null
+++ b/libavutil/video_hint.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2023 Elias Carotti <eliascrt at amazon dot it>
+ *
+ * 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 <string.h>
+
+#include "avstring.h"
+#include "frame.h"
+#include "macros.h"
+#include "mem.h"
+#include "video_hint.h"
+
+AVVideoHint *av_video_hint_alloc(AVVideoRect *rects,
+ size_t nb_rects,
+ AVVideoHintType type,
+ size_t* out_size)
+{
+ struct TestStruct {
+ AVVideoHint hint;
+ AVVideoRect rect;
+ };
+ const size_t blocks_offset = offsetof(struct TestStruct, rect);
+ size_t size = blocks_offset;
+ AVVideoHint *hint;
+
+ *out_size = 0;
+ if (nb_rects > (SIZE_MAX - size) / sizeof(AVVideoRect))
+ return NULL;
+ size += sizeof(AVVideoRect) * nb_rects;
+
+ hint = av_mallocz(size);
+ if (!hint)
+ return NULL;
+
+ hint->type = type;
+ hint->nb_rects = nb_rects;
+ hint->blocks_offset = blocks_offset;
+
+ /* Just copies the rects over the newly allocated buffer */
+ memcpy((uint8_t *)hint + blocks_offset, rects, sizeof(AVVideoRect) * nb_rects);
+
+ *out_size = size;
+
+ return hint;
+}
+
+AVVideoHint *av_video_hint_create_side_data(AVFrame *frame,
+ AVVideoRect *rects,
+ size_t num_rects,
+ AVVideoHintType type)
+{
+ AVVideoHint *hint;
+ AVBufferRef *buf;
+ size_t size = 0;
+
+ hint = av_video_hint_alloc(rects, num_rects, type, &size);
+ if (!hint)
+ return NULL;
+
+ buf = av_buffer_create((uint8_t *)hint, size, NULL, NULL, 0);
+ if (!buf) {
+ av_freep(&hint);
+ return NULL;
+ }
+
+ if (!av_frame_new_side_data_from_buf(frame, AV_FRAME_DATA_VIDEO_HINT, buf)) {
+ av_buffer_unref(&buf);
+ return NULL;
+ }
+
+ return hint;
+}
+
diff --git a/libavutil/video_hint.h b/libavutil/video_hint.h
new file mode 100644
index 0000000000..f7d113fb90
--- /dev/null
+++ b/libavutil/video_hint.h
@@ -0,0 +1,87 @@
+/**
+ * Copyright 2023 Elias Carotti <eliascrt at amazon dot it>
+ *
+ * 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
+ */
+
+#ifndef AVUTIL_VIDEO_HINT_H
+#define AVUTIL_VIDEO_HINT_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include "libavutil/avassert.h"
+#include "libavutil/frame.h"
+
+typedef struct AVVideoRect {
+ uint32_t x, y;
+ uint32_t width, height;
+} AVVideoRect;
+
+typedef enum AVVideoHintType {
+ /* blocks delimit the constant areas (unchanged), default is changed */
+ AV_VIDEO_HINT_CONSTANT,
+
+ /* blocks delimit the constant areas (changed), default is not changed */
+ AV_VIDEO_HINT_CHANGED,
+} AVVideoHintType;
+
+typedef struct AVVideoHint {
+ /**
+ * Number of blocks in the array.
+ *
+ * May be 0, in which case no per-block information is present. In this case
+ * the values of blocks_offset / block_size are unspecified and should not
+ * be accessed.
+ */
+ int nb_rects;
+
+ /**
+ * Offset in bytes from the beginning of this structure at which the array
+ * of blocks starts.
+ */
+ size_t blocks_offset;
+
+ AVVideoHintType type;
+} AVVideoHint;
+
+static av_always_inline AVVideoRect*
+av_video_hint_rects(const AVVideoHint *par)
+{
+ return (AVVideoRect *)((uint8_t *)par + par->blocks_offset);
+}
+
+/**
+ * Allocate memory for a vector of AVVideoRect in the given AVFrame
+ * {@code frame} as AVFrameSideData of type AV_FRAME_DATA_VIDEO_HINT_INFO.
+ * The side data contains a list of rectangles for the portions of the frame
+ * which changed from the last encoded one (and the remainder are assumed to be
+ * changed), or, alternately (depending on the type parameter) the unchanged
+ * ones (and the remanining ones are those which changed).
+ * Macroblocks will thus be hinted either to be P_SKIP-ped or go through the
+ * regular encoding procedure.
+ */
+AVVideoHint *av_video_hint_create_side_data(AVFrame *frame,
+ AVVideoRect *rects,
+ size_t num_rects,
+ AVVideoHintType type);
+
+AVVideoHint *av_video_hint_alloc(AVVideoRect *rects,
+ size_t nb_rects,
+ AVVideoHintType type,
+ size_t *out_size);
+
+#endif /* AVUTIL_VIDEO_HINT_H */
--
2.34.1
[-- Attachment #3: Type: text/plain, Size: 251 bytes --]
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [FFmpeg-devel] [PATCH] Optimization: support for libx264's mb_info
2023-06-21 15:53 ` Carotti, Elias
@ 2023-06-22 8:44 ` Anton Khirnov
2023-06-22 17:23 ` Carotti, Elias
0 siblings, 1 reply; 33+ messages in thread
From: Anton Khirnov @ 2023-06-22 8:44 UTC (permalink / raw)
To: ffmpeg-devel
Quoting Carotti, Elias (2023-06-21 17:53:09)
> +
> + /**
> + * Provide macro block encoder-specific hinting information for the encoder
> + * processing. It can be used to pass information about which macroblock
> + * can be skipped because it hasn't changed from the corresponding one in
> + * the previous frame. This is useful for applications which know in
> + * advance this information to speed up real-time encoding. Currently only
> + * used by libx264.
I'd avoid any such claims here, because this comment will certainly not
be kept up to date.
> +/**
> + * Allocate memory for a vector of AVVideoRect in the given AVFrame
> + * {@code frame} as AVFrameSideData of type AV_FRAME_DATA_VIDEO_HINT_INFO.
> + * The side data contains a list of rectangles for the portions of the frame
> + * which changed from the last encoded one (and the remainder are assumed to be
> + * changed), or, alternately (depending on the type parameter) the unchanged
> + * ones (and the remanining ones are those which changed).
> + * Macroblocks will thus be hinted either to be P_SKIP-ped or go through the
> + * regular encoding procedure.
> + */
> +AVVideoHint *av_video_hint_create_side_data(AVFrame *frame,
> + AVVideoRect *rects,
> + size_t num_rects,
> + AVVideoHintType type);
> +
> +AVVideoHint *av_video_hint_alloc(AVVideoRect *rects,
> + size_t nb_rects,
> + AVVideoHintType type,
> + size_t *out_size);
If AVVideoHint is extended in the future, you will have a weird
situation where some fields are set by the allocation function, while
others have to be set manually by the caller.
You're also assuming the caller has an explicit array of AVVideoRect,
while they may actually want to fill them in through some other means.
Finally, it still seems to me this is largely duplicating
AVVideoEncParams and you could get your functionality by adding your
AVVideoHintType there.
--
Anton Khirnov
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [FFmpeg-devel] [PATCH] Optimization: support for libx264's mb_info
2023-06-22 8:44 ` Anton Khirnov
@ 2023-06-22 17:23 ` Carotti, Elias
2023-06-24 11:01 ` Anton Khirnov
0 siblings, 1 reply; 33+ messages in thread
From: Carotti, Elias @ 2023-06-22 17:23 UTC (permalink / raw)
To: ffmpeg-devel
On Thu, 2023-06-22 at 10:44 +0200, Anton Khirnov wrote:
> CAUTION: This email originated from outside of the organization. Do
> not click links or open attachments unless you can confirm the sender
> and know the content is safe.
>
>
>
> Quoting Carotti, Elias (2023-06-21 17:53:09)
> > +
> > + /**
> > + * Provide macro block encoder-specific hinting information
> > for the encoder
> > + * processing. It can be used to pass information about which
> > macroblock
> > + * can be skipped because it hasn't changed from the
> > corresponding one in
> > + * the previous frame. This is useful for applications which
> > know in
> > + * advance this information to speed up real-time encoding.
> > Currently only
> > + * used by libx264.
>
> I'd avoid any such claims here, because this comment will certainly
> not
> be kept up to date.
Agreed. It was more a statement than a claim, since I only implemented
that :-)
>
> > +/**
> > + * Allocate memory for a vector of AVVideoRect in the given
> > AVFrame
> > + * {@code frame} as AVFrameSideData of type
> > AV_FRAME_DATA_VIDEO_HINT_INFO.
> > + * The side data contains a list of rectangles for the portions of
> > the frame
> > + * which changed from the last encoded one (and the remainder are
> > assumed to be
> > + * changed), or, alternately (depending on the type parameter) the
> > unchanged
> > + * ones (and the remanining ones are those which changed).
> > + * Macroblocks will thus be hinted either to be P_SKIP-ped or go
> > through the
> > + * regular encoding procedure.
> > + */
> > +AVVideoHint *av_video_hint_create_side_data(AVFrame *frame,
> > + AVVideoRect *rects,
> > + size_t num_rects,
> > + AVVideoHintType type);
> > +
> > +AVVideoHint *av_video_hint_alloc(AVVideoRect *rects,
> > + size_t nb_rects,
> > + AVVideoHintType type,
> > + size_t *out_size);
>
> If AVVideoHint is extended in the future, you will have a weird
> situation where some fields are set by the allocation function, while
> others have to be set manually by the caller.
>
> You're also assuming the caller has an explicit array of AVVideoRect,
> while they may actually want to fill them in through some other
> means.
I agree on the first issue, and yes, it would be wiser to split the
allocation function from a the setting function.
Would a simple append_rectangles (the name may be different) API work
for you?
I am not clear on the second issue you raise though: the thing is that
this side information is only needed per frame and before encoding, so
I do not see a use case where you keep adding rectangles to this side
data. The use case I see is where you accumulate the rectangles and
then feed them to the encoding function and forget about them, however,
again, if we add an append_rectangles we could easily extend it to the
use case you're hinting at.
>
> Finally, it still seems to me this is largely duplicating
> AVVideoEncParams and you could get your functionality by adding your
> AVVideoHintType there.
>
I disagree on this last point. My first idea to avoid duplicating or
adding unnecessary code was indeed to extend AVVideoEncParams. However,
(please correct me if I am wrong,) to my undestanding the
AVVideoEncParams are currently only used at the *decoder* side to
convey the encoding parameters (extracted from the bitstream) used by
the encoder to produce a stream while here we want to work the other
way around: at the encoder's side to provide hints on how to encode a
frame but won't affect the bitstream (aside from inducing faster
P_SKIPs generation.) and won't be known at the decoder's side.
So it seems to me it's a different semantics for which it's better to
have an appropriate side information.
Best,
Elias
> --
> Anton Khirnov
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
NICE SRL, viale Monte Grappa 3/5, 20124 Milano, Italia, Registro delle Imprese di Milano Monza Brianza Lodi REA n. 2096882, Capitale Sociale: 10.329,14 EUR i.v., Cod. Fisc. e P.IVA 01133050052, Societa con Socio Unico
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [FFmpeg-devel] [PATCH] Optimization: support for libx264's mb_info
2023-06-22 17:23 ` Carotti, Elias
@ 2023-06-24 11:01 ` Anton Khirnov
2023-06-26 9:50 ` Carotti, Elias
0 siblings, 1 reply; 33+ messages in thread
From: Anton Khirnov @ 2023-06-24 11:01 UTC (permalink / raw)
To: ffmpeg-devel
Quoting Carotti, Elias (2023-06-22 19:23:05)
> On Thu, 2023-06-22 at 10:44 +0200, Anton Khirnov wrote:
> > CAUTION: This email originated from outside of the organization. Do
> > not click links or open attachments unless you can confirm the sender
> > and know the content is safe.
> >
> >
> >
> > Quoting Carotti, Elias (2023-06-21 17:53:09)
> > > +
> > > + /**
> > > + * Provide macro block encoder-specific hinting information
> > > for the encoder
> > > + * processing. It can be used to pass information about which
> > > macroblock
> > > + * can be skipped because it hasn't changed from the
> > > corresponding one in
> > > + * the previous frame. This is useful for applications which
> > > know in
> > > + * advance this information to speed up real-time encoding.
> > > Currently only
> > > + * used by libx264.
> >
> > I'd avoid any such claims here, because this comment will certainly
> > not
> > be kept up to date.
>
>
> Agreed. It was more a statement than a claim, since I only implemented
> that :-)
>
> >
> > > +/**
> > > + * Allocate memory for a vector of AVVideoRect in the given
> > > AVFrame
> > > + * {@code frame} as AVFrameSideData of type
> > > AV_FRAME_DATA_VIDEO_HINT_INFO.
> > > + * The side data contains a list of rectangles for the portions of
> > > the frame
> > > + * which changed from the last encoded one (and the remainder are
> > > assumed to be
> > > + * changed), or, alternately (depending on the type parameter) the
> > > unchanged
> > > + * ones (and the remanining ones are those which changed).
> > > + * Macroblocks will thus be hinted either to be P_SKIP-ped or go
> > > through the
> > > + * regular encoding procedure.
> > > + */
> > > +AVVideoHint *av_video_hint_create_side_data(AVFrame *frame,
> > > + AVVideoRect *rects,
> > > + size_t num_rects,
> > > + AVVideoHintType type);
> > > +
> > > +AVVideoHint *av_video_hint_alloc(AVVideoRect *rects,
> > > + size_t nb_rects,
> > > + AVVideoHintType type,
> > > + size_t *out_size);
> >
> > If AVVideoHint is extended in the future, you will have a weird
> > situation where some fields are set by the allocation function, while
> > others have to be set manually by the caller.
> >
> > You're also assuming the caller has an explicit array of AVVideoRect,
> > while they may actually want to fill them in through some other
> > means.
>
> I agree on the first issue, and yes, it would be wiser to split the
> allocation function from a the setting function.
> Would a simple append_rectangles (the name may be different) API work
> for you?
I don't see why does there need to be a setting function. The caller can
directly assign or memcpy the values, it seems just as easy to me.
> I am not clear on the second issue you raise though: the thing is that
> this side information is only needed per frame and before encoding, so
> I do not see a use case where you keep adding rectangles to this side
> data. The use case I see is where you accumulate the rectangles and
> then feed them to the encoding function and forget about them, however,
> again, if we add an append_rectangles we could easily extend it to the
> use case you're hinting at.
The case I have in mind is not modifying the data at some later point,
but rather that the user has the data in some more complex structure. So
in order to fill it here, they'd have to explicitly construct an array
of AVVideoRect, which is an extra step.
>
> >
> > Finally, it still seems to me this is largely duplicating
> > AVVideoEncParams and you could get your functionality by adding your
> > AVVideoHintType there.
> >
>
> I disagree on this last point. My first idea to avoid duplicating or
> adding unnecessary code was indeed to extend AVVideoEncParams. However,
> (please correct me if I am wrong,) to my undestanding the
> AVVideoEncParams are currently only used at the *decoder* side to
> convey the encoding parameters (extracted from the bitstream) used by
> the encoder to produce a stream while here we want to work the other
> way around: at the encoder's side to provide hints on how to encode a
> frame but won't affect the bitstream (aside from inducing faster
> P_SKIPs generation.) and won't be known at the decoder's side.
>
> So it seems to me it's a different semantics for which it's better to
> have an appropriate side information.
AVVideoEncParams describes the block-level parameters of an encoded
bitstream. Yes, it is currently used to export coded bitstream
information from decoders. But there is no restriction or assumption in
the API itself that it will be used in this way and it can just as well
describe the information you want a coded bitstream to have.
--
Anton Khirnov
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [FFmpeg-devel] [PATCH] Optimization: support for libx264's mb_info
2023-06-24 11:01 ` Anton Khirnov
@ 2023-06-26 9:50 ` Carotti, Elias
2023-06-28 12:55 ` Anton Khirnov
0 siblings, 1 reply; 33+ messages in thread
From: Carotti, Elias @ 2023-06-26 9:50 UTC (permalink / raw)
To: ffmpeg-devel
On Sat, 2023-06-24 at 13:01 +0200, Anton Khirnov wrote:
> CAUTION: This email originated from outside of the organization. Do
> not click links or open attachments unless you can confirm the sender
> and know the content is safe.
>
>
>
> Quoting Carotti, Elias (2023-06-22 19:23:05)
> > On Thu, 2023-06-22 at 10:44 +0200, Anton Khirnov wrote:
> > > CAUTION: This email originated from outside of the organization.
> > > Do
> > > not click links or open attachments unless you can confirm the
> > > sender
> > > and know the content is safe.
> > >
> > >
> > >
> > > Quoting Carotti, Elias (2023-06-21 17:53:09)
> > > > +
> > > > + /**
> > > > + * Provide macro block encoder-specific hinting
> > > > information
> > > > for the encoder
> > > > + * processing. It can be used to pass information about
> > > > which
> > > > macroblock
> > > > + * can be skipped because it hasn't changed from the
> > > > corresponding one in
> > > > + * the previous frame. This is useful for applications
> > > > which
> > > > know in
> > > > + * advance this information to speed up real-time
> > > > encoding.
> > > > Currently only
> > > > + * used by libx264.
> > >
> > > I'd avoid any such claims here, because this comment will
> > > certainly
> > > not
> > > be kept up to date.
> >
> >
> > Agreed. It was more a statement than a claim, since I only
> > implemented
> > that :-)
> >
> > >
> > > > +/**
> > > > + * Allocate memory for a vector of AVVideoRect in the given
> > > > AVFrame
> > > > + * {@code frame} as AVFrameSideData of type
> > > > AV_FRAME_DATA_VIDEO_HINT_INFO.
> > > > + * The side data contains a list of rectangles for the
> > > > portions of
> > > > the frame
> > > > + * which changed from the last encoded one (and the remainder
> > > > are
> > > > assumed to be
> > > > + * changed), or, alternately (depending on the type parameter)
> > > > the
> > > > unchanged
> > > > + * ones (and the remanining ones are those which changed).
> > > > + * Macroblocks will thus be hinted either to be P_SKIP-ped or
> > > > go
> > > > through the
> > > > + * regular encoding procedure.
> > > > + */
> > > > +AVVideoHint *av_video_hint_create_side_data(AVFrame *frame,
> > > > + AVVideoRect
> > > > *rects,
> > > > + size_t num_rects,
> > > > + AVVideoHintType
> > > > type);
> > > > +
> > > > +AVVideoHint *av_video_hint_alloc(AVVideoRect *rects,
> > > > + size_t nb_rects,
> > > > + AVVideoHintType type,
> > > > + size_t *out_size);
> > >
> > > If AVVideoHint is extended in the future, you will have a weird
> > > situation where some fields are set by the allocation function,
> > > while
> > > others have to be set manually by the caller.
> > >
> > > You're also assuming the caller has an explicit array of
> > > AVVideoRect,
> > > while they may actually want to fill them in through some other
> > > means.
> >
> > I agree on the first issue, and yes, it would be wiser to split the
> > allocation function from a the setting function.
> > Would a simple append_rectangles (the name may be different) API
> > work
> > for you?
>
> I don't see why does there need to be a setting function. The caller
> can
> directly assign or memcpy the values, it seems just as easy to me.
We can do whatever you want. However I am not clear on how that<br>
would work.
We could have a side data creation api with the standard parameters and
another method to allocate memory so that ownership is kept by
libavutil returns a pointer to the rectangles (with bounds checking and
so on on the caller):
av_video_hint_create_side_data(AVFrame *frame, AVVideoHintType type);
AVVideoRect* av_video_hint_set_number_of_rectangles(
AVVideoHint *video_hint,
size_t n_rects,
AVVideoHintType changed_flag);
(Names can change I just want to convey a possible api).
Would that work for you?
Or, do you prefer a creation api which already allocates memory and
sets the number of rectangles but doesn't copy them and that's
responsibility on the caller?
What I'd like in this latter case is that (like now) memory would be
flat with no need for specific custom deallocators.
Something along the lines:
AVVideoHint *av_video_hint_create_side_data(AVFrame *frame,
size_t n_rects,
AVVideoHintType type);
AVVideoRect *av_video_hint_get_rects(AVVideoHint *video_hint);
Third option: side information creation api and the caller has to
alloc/realloc the rectangle buffer and hand out ownership to libavutil,
but I guess this is the worst one for various reasons.
I do not see any further option.
>
> > I am not clear on the second issue you raise though: the thing is
> > that
> > this side information is only needed per frame and before encoding,
> > so
> > I do not see a use case where you keep adding rectangles to this
> > side
> > data. The use case I see is where you accumulate the rectangles and
> > then feed them to the encoding function and forget about them,
> > however,
> > again, if we add an append_rectangles we could easily extend it to
> > the
> > use case you're hinting at.
>
> The case I have in mind is not modifying the data at some later
> point,
> but rather that the user has the data in some more complex structure.
> So
> in order to fill it here, they'd have to explicitly construct an
> array
> of AVVideoRect, which is an extra step.
>
> >
> > >
> > > Finally, it still seems to me this is largely duplicating
> > > AVVideoEncParams and you could get your functionality by adding
> > > your
> > > AVVideoHintType there.
> > >
> >
> > I disagree on this last point. My first idea to avoid duplicating
> > or
> > adding unnecessary code was indeed to extend AVVideoEncParams.
> > However,
> > (please correct me if I am wrong,) to my undestanding the
> > AVVideoEncParams are currently only used at the *decoder* side to
> > convey the encoding parameters (extracted from the bitstream) used
> > by
> > the encoder to produce a stream while here we want to work the
> > other
> > way around: at the encoder's side to provide hints on how to encode
> > a
> > frame but won't affect the bitstream (aside from inducing faster
> > P_SKIPs generation.) and won't be known at the decoder's side.
> >
> > So it seems to me it's a different semantics for which it's better
> > to
> > have an appropriate side information.
>
> AVVideoEncParams describes the block-level parameters of an encoded
> bitstream. Yes, it is currently used to export coded bitstream
> information from decoders. But there is no restriction or assumption
> in
> the API itself that it will be used in this way and it can just as
> well
> describe the information you want a coded bitstream to have.
>
Right, but in this case it's not something which is going to end up
into the bitstream, since this is *not* and api to set some bitstream
properties but really just provide some information which the encoder
can exploit.
So it's definitely a different semantics and I do not think it fits
well into AVVideoEncParams (frankly I think it's wrong), however if we
are clear on this and that's what you really want and that's what we
need to do to get the patch in, well I have no issue changing the code.
Best
Elias
> --
> Anton Khirnov
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
NICE SRL, viale Monte Grappa 3/5, 20124 Milano, Italia, Registro delle Imprese di Milano Monza Brianza Lodi REA n. 2096882, Capitale Sociale: 10.329,14 EUR i.v., Cod. Fisc. e P.IVA 01133050052, Societa con Socio Unico
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [FFmpeg-devel] [PATCH] Optimization: support for libx264's mb_info
2023-06-26 9:50 ` Carotti, Elias
@ 2023-06-28 12:55 ` Anton Khirnov
2023-06-30 17:40 ` Carotti, Elias
0 siblings, 1 reply; 33+ messages in thread
From: Anton Khirnov @ 2023-06-28 12:55 UTC (permalink / raw)
To: ffmpeg-devel
Quoting Carotti, Elias (2023-06-26 11:50:59)
> We can do whatever you want. However I am not clear on how that<br>
> would work.
>
> We could have a side data creation api with the standard parameters and
> another method to allocate memory so that ownership is kept by
> libavutil returns a pointer to the rectangles (with bounds checking and
> so on on the caller):
>
>
>
> av_video_hint_create_side_data(AVFrame *frame, AVVideoHintType type);
>
> AVVideoRect* av_video_hint_set_number_of_rectangles(
> AVVideoHint *video_hint,
> size_t n_rects,
> AVVideoHintType changed_flag);
> (Names can change I just want to convey a possible api).
>
> Would that work for you?
>
> Or, do you prefer a creation api which already allocates memory and
> sets the number of rectangles but doesn't copy them and that's
> responsibility on the caller?
> What I'd like in this latter case is that (like now) memory would be
> flat with no need for specific custom deallocators.
> Something along the lines:
>
>
> AVVideoHint *av_video_hint_create_side_data(AVFrame *frame,
> size_t n_rects,
> AVVideoHintType type);
>
> AVVideoRect *av_video_hint_get_rects(AVVideoHint *video_hint);
>
>
> Third option: side information creation api and the caller has to
> alloc/realloc the rectangle buffer and hand out ownership to libavutil,
> but I guess this is the worst one for various reasons.
>
> I do not see any further option.
What I'm proposing is this:
AVVideoHint *av_video_hint_create_side_data(AVFrame *frame, size_t num_rects);
AVVideoHint *av_video_hint_alloc(size_t nb_rects, size_t *out_size);
The caller filles the type and the rectangles manually.
> > AVVideoEncParams describes the block-level parameters of an encoded
> > bitstream. Yes, it is currently used to export coded bitstream
> > information from decoders. But there is no restriction or assumption
> > in
> > the API itself that it will be used in this way and it can just as
> > well
> > describe the information you want a coded bitstream to have.
> >
>
>
> Right, but in this case it's not something which is going to end up
> into the bitstream, since this is *not* and api to set some bitstream
> properties but really just provide some information which the encoder
> can exploit.
>
> So it's definitely a different semantics and I do not think it fits
> well into AVVideoEncParams (frankly I think it's wrong), however if we
> are clear on this and that's what you really want and that's what we
> need to do to get the patch in, well I have no issue changing the code.
Ok, I see your point and drop my objection.
--
Anton Khirnov
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [FFmpeg-devel] [PATCH] Optimization: support for libx264's mb_info
2023-06-28 12:55 ` Anton Khirnov
@ 2023-06-30 17:40 ` Carotti, Elias
2023-07-01 8:33 ` Anton Khirnov
0 siblings, 1 reply; 33+ messages in thread
From: Carotti, Elias @ 2023-06-30 17:40 UTC (permalink / raw)
To: ffmpeg-devel
[-- Attachment #1: Type: text/plain, Size: 3008 bytes --]
On Wed, 2023-06-28 at 14:55 +0200, Anton Khirnov wrote:
> CAUTION: This email originated from outside of the organization. Do
> not click links or open attachments unless you can confirm the sender
> and know the content is safe.
>
>
>
> Quoting Carotti, Elias (2023-06-26 11:50:59)
> > We can do whatever you want. However I am not clear on how that<br>
> > would work.
> >
> > We could have a side data creation api with the standard parameters
> > and
> > another method to allocate memory so that ownership is kept by
> > libavutil returns a pointer to the rectangles (with bounds checking
> > and
> > so on on the caller):
> >
> >
> >
> > av_video_hint_create_side_data(AVFrame *frame, AVVideoHintType
> > type);
> >
> > AVVideoRect* av_video_hint_set_number_of_rectangles(
> > AVVideoHint *video_hint,
> > size_t n_rects,
> > AVVideoHintType
> > changed_flag);
> > (Names can change I just want to convey a possible api).
> >
> > Would that work for you?
> >
> > Or, do you prefer a creation api which already allocates memory and
> > sets the number of rectangles but doesn't copy them and that's
> > responsibility on the caller?
> > What I'd like in this latter case is that (like now) memory would
> > be
> > flat with no need for specific custom deallocators.
> > Something along the lines:
> >
> >
> > AVVideoHint *av_video_hint_create_side_data(AVFrame *frame,
> > size_t n_rects,
> > AVVideoHintType type);
> >
> > AVVideoRect *av_video_hint_get_rects(AVVideoHint *video_hint);
> >
> >
> > Third option: side information creation api and the caller has to
> > alloc/realloc the rectangle buffer and hand out ownership to
> > libavutil,
> > but I guess this is the worst one for various reasons.
> >
> > I do not see any further option.
>
> What I'm proposing is this:
> AVVideoHint *av_video_hint_create_side_data(AVFrame *frame, size_t
> num_rects);
> AVVideoHint *av_video_hint_alloc(size_t nb_rects, size_t *out_size);
>
> The caller filles the type and the rectangles manually.
>
I implemented the changes, I hope it is better now. The libavcodec part
remains unchanged and only this part was affected by the change.
Best,
Elias
> > > AVVideoEncParams describes the block-level parameters of an
> > > encoded
<snip>
> > code.
>
> Ok, I see your point and drop my objection.
NICE SRL, viale Monte Grappa 3/5, 20124 Milano, Italia, Registro delle Imprese di Milano Monza Brianza Lodi REA n. 2096882, Capitale Sociale: 10.329,14 EUR i.v., Cod. Fisc. e P.IVA 01133050052, Societa con Socio Unico
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-lavu-add-AVVideoHint-API.patch --]
[-- Type: text/x-patch; name="0001-lavu-add-AVVideoHint-API.patch", Size: 9727 bytes --]
From 436f87f150ea122a57f610def94be07eb7286213 Mon Sep 17 00:00:00 2001
From: Elias Carotti <eliascrt _at_ amazon _dot_ it>
Date: Tue, 20 Jun 2023 19:28:04 +0200
Subject: [PATCH 1/2] lavu: add AVVideoHint API
Add side data type to provide hint to the video encoders about unchanged
portions of each frame.
---
doc/APIchanges | 3 ++
libavutil/Makefile | 4 ++
libavutil/frame.h | 10 +++++
libavutil/version.h | 4 +-
libavutil/video_hint.c | 81 +++++++++++++++++++++++++++++++++++++++
libavutil/video_hint.h | 86 ++++++++++++++++++++++++++++++++++++++++++
6 files changed, 186 insertions(+), 2 deletions(-)
create mode 100644 libavutil/video_hint.c
create mode 100644 libavutil/video_hint.h
diff --git a/doc/APIchanges b/doc/APIchanges
index f040211f7d..bfe04556d2 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -2,6 +2,9 @@ The last version increases of all libraries were on 2023-02-09
API changes, most recent first:
+2023-06-21 - xxxxxxxxxx - lavu 58.14.100 - video_hint.h
+ Add AVVideoHint API.
+
2023-05-29 - xxxxxxxxxx - lavc 60.16.100 - avcodec.h codec_id.h
Add AV_CODEC_ID_EVC, FF_PROFILE_EVC_BASELINE, and FF_PROFILE_EVC_MAIN.
diff --git a/libavutil/Makefile b/libavutil/Makefile
index bd9c6f9e32..a0b43faa9f 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -91,6 +91,7 @@ HEADERS = adler32.h \
tea.h \
tx.h \
film_grain_params.h \
+ video_hint.h
ARCH_HEADERS = bswap.h \
intmath.h \
@@ -188,6 +189,7 @@ OBJS-$(CONFIG_CUDA) += hwcontext_cuda.o
OBJS-$(CONFIG_D3D11VA) += hwcontext_d3d11va.o
OBJS-$(CONFIG_DXVA2) += hwcontext_dxva2.o
OBJS-$(CONFIG_LIBDRM) += hwcontext_drm.o
+OBJS-$(CONFIG_LIBX264) += video_hint.o
OBJS-$(CONFIG_MACOS_KPERF) += macos_kperf.o
OBJS-$(CONFIG_MEDIACODEC) += hwcontext_mediacodec.o
OBJS-$(CONFIG_OPENCL) += hwcontext_opencl.o
@@ -219,6 +221,8 @@ SKIPHEADERS-$(CONFIG_VULKAN) += hwcontext_vulkan.h vulkan.h \
vulkan_functions.h \
vulkan_loader.h
+SKIPHEADERS-$(CONFIG_LIBX264) += video_hint.h
+
TESTPROGS = adler32 \
aes \
aes_ctr \
diff --git a/libavutil/frame.h b/libavutil/frame.h
index a491315f25..c0c1b23db7 100644
--- a/libavutil/frame.h
+++ b/libavutil/frame.h
@@ -214,6 +214,16 @@ enum AVFrameSideDataType {
* Ambient viewing environment metadata, as defined by H.274.
*/
AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT,
+
+ /**
+ * Provide encoder-specific hinting information about changed/unchanged
+ * portions of a frame. It can be used to pass information about which
+ * macroblocks can be skipped because they didn't change from the
+ * corresponding ones in the previous frame. This could be useful for
+ * applications which know this information in advance to speed up
+ * encoding.
+ */
+ AV_FRAME_DATA_VIDEO_HINT,
};
enum AVActiveFormatDescription {
diff --git a/libavutil/version.h b/libavutil/version.h
index 17a6d296a6..24af520e08 100644
--- a/libavutil/version.h
+++ b/libavutil/version.h
@@ -79,8 +79,8 @@
*/
#define LIBAVUTIL_VERSION_MAJOR 58
-#define LIBAVUTIL_VERSION_MINOR 13
-#define LIBAVUTIL_VERSION_MICRO 101
+#define LIBAVUTIL_VERSION_MINOR 14
+#define LIBAVUTIL_VERSION_MICRO 100
#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
LIBAVUTIL_VERSION_MINOR, \
diff --git a/libavutil/video_hint.c b/libavutil/video_hint.c
new file mode 100644
index 0000000000..040b4b5f25
--- /dev/null
+++ b/libavutil/video_hint.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2023 Elias Carotti <eliascrt at amazon dot it>
+ *
+ * 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 <string.h>
+
+#include "avstring.h"
+#include "frame.h"
+#include "macros.h"
+#include "mem.h"
+#include "video_hint.h"
+
+AVVideoHint *av_video_hint_alloc(size_t nb_rects,
+ size_t* out_size)
+{
+ struct TestStruct {
+ AVVideoHint hint;
+ AVVideoRect rect;
+ };
+ const size_t blocks_offset = offsetof(struct TestStruct, rect);
+ size_t size = blocks_offset;
+ AVVideoHint *hint;
+
+ *out_size = 0;
+ if (nb_rects > (SIZE_MAX - size) / sizeof(AVVideoRect))
+ return NULL;
+ size += sizeof(AVVideoRect) * nb_rects;
+
+ hint = av_mallocz(size);
+ if (!hint)
+ return NULL;
+
+ hint->nb_rects = nb_rects;
+ hint->blocks_offset = blocks_offset;
+
+ *out_size = size;
+
+ return hint;
+}
+
+AVVideoHint *av_video_hint_create_side_data(AVFrame *frame,
+ size_t num_rects)
+{
+ AVVideoHint *hint;
+ AVBufferRef *buf;
+ size_t size = 0;
+
+ hint = av_video_hint_alloc(num_rects, &size);
+ if (!hint)
+ return NULL;
+
+ buf = av_buffer_create((uint8_t *)hint, size, NULL, NULL, 0);
+ if (!buf) {
+ av_freep(&hint);
+ return NULL;
+ }
+
+ if (!av_frame_new_side_data_from_buf(frame, AV_FRAME_DATA_VIDEO_HINT, buf)) {
+ av_buffer_unref(&buf);
+ return NULL;
+ }
+
+ return hint;
+}
+
diff --git a/libavutil/video_hint.h b/libavutil/video_hint.h
new file mode 100644
index 0000000000..e0823ef09a
--- /dev/null
+++ b/libavutil/video_hint.h
@@ -0,0 +1,86 @@
+/**
+ * Copyright 2023 Elias Carotti <eliascrt at amazon dot it>
+ *
+ * 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
+ */
+
+#ifndef AVUTIL_VIDEO_HINT_H
+#define AVUTIL_VIDEO_HINT_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include "libavutil/avassert.h"
+#include "libavutil/frame.h"
+
+typedef struct AVVideoRect {
+ uint32_t x, y;
+ uint32_t width, height;
+} AVVideoRect;
+
+typedef enum AVVideoHintType {
+ /* blocks delimit the constant areas (unchanged), default is changed */
+ AV_VIDEO_HINT_CONSTANT,
+
+ /* blocks delimit the constant areas (changed), default is not changed */
+ AV_VIDEO_HINT_CHANGED,
+} AVVideoHintType;
+
+typedef struct AVVideoHint {
+ /**
+ * Number of blocks in the array.
+ *
+ * May be 0, in which case no per-block information is present. In this case
+ * the values of blocks_offset / block_size are unspecified and should not
+ * be accessed.
+ */
+ int nb_rects;
+
+ /**
+ * Offset in bytes from the beginning of this structure at which the array
+ * of blocks starts.
+ */
+ size_t blocks_offset;
+
+ AVVideoHintType type;
+} AVVideoHint;
+
+static av_always_inline AVVideoRect*
+av_video_hint_rects(const AVVideoHint *hints)
+{
+ return (AVVideoRect *)((uint8_t *)hints + hints->blocks_offset);
+}
+
+/**
+ * Allocate memory for a vector of AVVideoRect in the given AVFrame
+ * {@code frame} as AVFrameSideData of type AV_FRAME_DATA_VIDEO_HINT_INFO.
+ * The side data contains a list of rectangles for the portions of the frame
+ * which changed from the last encoded one (and the remainder are assumed to be
+ * changed), or, alternately (depending on the type parameter) the unchanged
+ * ones (and the remanining ones are those which changed).
+ * Macroblocks will thus be hinted either to be P_SKIP-ped or go through the
+ * regular encoding procedure.
+ *
+ * It's responsibility of the caller to fill the AVRects accordingly, and to set
+ * the proper AVVideoHintType field.
+ */
+AVVideoHint *av_video_hint_create_side_data(AVFrame *frame,
+ size_t num_rects);
+
+AVVideoHint *av_video_hint_alloc(size_t nb_rects,
+ size_t *out_size);
+
+#endif /* AVUTIL_VIDEO_HINT_H */
--
2.34.1
[-- Attachment #3: Type: text/plain, Size: 251 bytes --]
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [FFmpeg-devel] [PATCH] Optimization: support for libx264's mb_info
2023-06-30 17:40 ` Carotti, Elias
@ 2023-07-01 8:33 ` Anton Khirnov
2023-07-03 15:51 ` Carotti, Elias
0 siblings, 1 reply; 33+ messages in thread
From: Anton Khirnov @ 2023-07-01 8:33 UTC (permalink / raw)
To: ffmpeg-devel
Sorry to still nag you, but I just noticed that unlike video_enc_params,
you do not store AVVideoRect size in AVVideoHint. This means that
no new fields can be added to AVVideoRect without an ABI break. This
seems suboptimal, since I do see potential use for per-block
information.
--
Anton Khirnov
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [FFmpeg-devel] [PATCH] Optimization: support for libx264's mb_info
2023-07-01 8:33 ` Anton Khirnov
@ 2023-07-03 15:51 ` Carotti, Elias
2023-07-07 16:27 ` Carotti, Elias
0 siblings, 1 reply; 33+ messages in thread
From: Carotti, Elias @ 2023-07-03 15:51 UTC (permalink / raw)
To: ffmpeg-devel
[-- Attachment #1: Type: text/plain, Size: 1705 bytes --]
On Sat, 2023-07-01 at 10:33 +0200, Anton Khirnov wrote:
> CAUTION: This email originated from outside of the organization. Do
> not click links or open attachments unless you can confirm the sender
> and know the content is safe.
>
>
>
> Sorry to still nag you, but I just noticed that unlike
> video_enc_params,
> you do not store AVVideoRect size in AVVideoHint. This means that
> no new fields can be added to AVVideoRect without an ABI break. This
> seems suboptimal, since I do see potential use for per-block
> information.
>
Hi Anton,
I do agree with you.
Please find the updated (and rebased) patch attached to this email.
Best,
Elias
P.S. By the way, I would be tempted (I didn't do that here) to declare
the block_size field as
const size_t block_size;
and then when setting it into av_video_hint_alloc(...) cast away the
const (it has to be assigned only once, upon allocation of the struct),
just to enforce compiler checking against accidental assignments and
for better clarity that this is a read-only field, in the general case.
P.P.S.: I'm sending the second part of the patch for libavcodec as a
separate email.
> --
> Anton Khirnov
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
NICE SRL, viale Monte Grappa 3/5, 20124 Milano, Italia, Registro delle Imprese di Milano Monza Brianza Lodi REA n. 2096882, Capitale Sociale: 10.329,14 EUR i.v., Cod. Fisc. e P.IVA 01133050052, Societa con Socio Unico
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-lavu-add-AVVideoHint-API.patch --]
[-- Type: text/x-patch; name="0001-lavu-add-AVVideoHint-API.patch", Size: 10002 bytes --]
From b0fb79736c082d4c6c8bfd698f8f76a835d41770 Mon Sep 17 00:00:00 2001
From: Elias Carotti <eliascrt _at_ amazon _dot_ it>
Date: Tue, 20 Jun 2023 19:28:04 +0200
Subject: [PATCH 1/2] lavu: add AVVideoHint API
Add side data type to provide hint to the video encoders about unchanged
portions of each frame.
---
doc/APIchanges | 3 ++
libavutil/Makefile | 4 ++
libavutil/frame.h | 10 +++++
libavutil/version.h | 4 +-
libavutil/video_hint.c | 82 ++++++++++++++++++++++++++++++++++++
libavutil/video_hint.h | 94 ++++++++++++++++++++++++++++++++++++++++++
6 files changed, 195 insertions(+), 2 deletions(-)
create mode 100644 libavutil/video_hint.c
create mode 100644 libavutil/video_hint.h
diff --git a/doc/APIchanges b/doc/APIchanges
index f040211f7d..bfe04556d2 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -2,6 +2,9 @@ The last version increases of all libraries were on 2023-02-09
API changes, most recent first:
+2023-06-21 - xxxxxxxxxx - lavu 58.14.100 - video_hint.h
+ Add AVVideoHint API.
+
2023-05-29 - xxxxxxxxxx - lavc 60.16.100 - avcodec.h codec_id.h
Add AV_CODEC_ID_EVC, FF_PROFILE_EVC_BASELINE, and FF_PROFILE_EVC_MAIN.
diff --git a/libavutil/Makefile b/libavutil/Makefile
index bd9c6f9e32..a0b43faa9f 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -91,6 +91,7 @@ HEADERS = adler32.h \
tea.h \
tx.h \
film_grain_params.h \
+ video_hint.h
ARCH_HEADERS = bswap.h \
intmath.h \
@@ -188,6 +189,7 @@ OBJS-$(CONFIG_CUDA) += hwcontext_cuda.o
OBJS-$(CONFIG_D3D11VA) += hwcontext_d3d11va.o
OBJS-$(CONFIG_DXVA2) += hwcontext_dxva2.o
OBJS-$(CONFIG_LIBDRM) += hwcontext_drm.o
+OBJS-$(CONFIG_LIBX264) += video_hint.o
OBJS-$(CONFIG_MACOS_KPERF) += macos_kperf.o
OBJS-$(CONFIG_MEDIACODEC) += hwcontext_mediacodec.o
OBJS-$(CONFIG_OPENCL) += hwcontext_opencl.o
@@ -219,6 +221,8 @@ SKIPHEADERS-$(CONFIG_VULKAN) += hwcontext_vulkan.h vulkan.h \
vulkan_functions.h \
vulkan_loader.h
+SKIPHEADERS-$(CONFIG_LIBX264) += video_hint.h
+
TESTPROGS = adler32 \
aes \
aes_ctr \
diff --git a/libavutil/frame.h b/libavutil/frame.h
index a491315f25..c0c1b23db7 100644
--- a/libavutil/frame.h
+++ b/libavutil/frame.h
@@ -214,6 +214,16 @@ enum AVFrameSideDataType {
* Ambient viewing environment metadata, as defined by H.274.
*/
AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT,
+
+ /**
+ * Provide encoder-specific hinting information about changed/unchanged
+ * portions of a frame. It can be used to pass information about which
+ * macroblocks can be skipped because they didn't change from the
+ * corresponding ones in the previous frame. This could be useful for
+ * applications which know this information in advance to speed up
+ * encoding.
+ */
+ AV_FRAME_DATA_VIDEO_HINT,
};
enum AVActiveFormatDescription {
diff --git a/libavutil/version.h b/libavutil/version.h
index 17a6d296a6..24af520e08 100644
--- a/libavutil/version.h
+++ b/libavutil/version.h
@@ -79,8 +79,8 @@
*/
#define LIBAVUTIL_VERSION_MAJOR 58
-#define LIBAVUTIL_VERSION_MINOR 13
-#define LIBAVUTIL_VERSION_MICRO 101
+#define LIBAVUTIL_VERSION_MINOR 14
+#define LIBAVUTIL_VERSION_MICRO 100
#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
LIBAVUTIL_VERSION_MINOR, \
diff --git a/libavutil/video_hint.c b/libavutil/video_hint.c
new file mode 100644
index 0000000000..0ea495debe
--- /dev/null
+++ b/libavutil/video_hint.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2023 Elias Carotti <eliascrt at amazon dot it>
+ *
+ * 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 <string.h>
+
+#include "avstring.h"
+#include "frame.h"
+#include "macros.h"
+#include "mem.h"
+#include "video_hint.h"
+
+AVVideoHint *av_video_hint_alloc(size_t nb_rects,
+ size_t* out_size)
+{
+ struct TestStruct {
+ AVVideoHint hint;
+ AVVideoRect rect;
+ };
+ const size_t blocks_offset = offsetof(struct TestStruct, rect);
+ size_t size = blocks_offset;
+ AVVideoHint *hint;
+
+ *out_size = 0;
+ if (nb_rects > (SIZE_MAX - size) / sizeof(AVVideoRect))
+ return NULL;
+ size += sizeof(AVVideoRect) * nb_rects;
+
+ hint = av_mallocz(size);
+ if (!hint)
+ return NULL;
+
+ hint->nb_rects = nb_rects;
+ hint->blocks_offset = blocks_offset;
+ hint->block_size = sizeof(AVVideoRect);
+
+ *out_size = size;
+
+ return hint;
+}
+
+AVVideoHint *av_video_hint_create_side_data(AVFrame *frame,
+ size_t num_rects)
+{
+ AVVideoHint *hint;
+ AVBufferRef *buf;
+ size_t size = 0;
+
+ hint = av_video_hint_alloc(num_rects, &size);
+ if (!hint)
+ return NULL;
+
+ buf = av_buffer_create((uint8_t *)hint, size, NULL, NULL, 0);
+ if (!buf) {
+ av_freep(&hint);
+ return NULL;
+ }
+
+ if (!av_frame_new_side_data_from_buf(frame, AV_FRAME_DATA_VIDEO_HINT, buf)) {
+ av_buffer_unref(&buf);
+ return NULL;
+ }
+
+ return hint;
+}
+
diff --git a/libavutil/video_hint.h b/libavutil/video_hint.h
new file mode 100644
index 0000000000..469336e90d
--- /dev/null
+++ b/libavutil/video_hint.h
@@ -0,0 +1,94 @@
+/**
+ * Copyright 2023 Elias Carotti <eliascrt at amazon dot it>
+ *
+ * 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
+ */
+
+#ifndef AVUTIL_VIDEO_HINT_H
+#define AVUTIL_VIDEO_HINT_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include "libavutil/avassert.h"
+#include "libavutil/frame.h"
+
+typedef struct AVVideoRect {
+ uint32_t x, y;
+ uint32_t width, height;
+} AVVideoRect;
+
+typedef enum AVVideoHintType {
+ /* blocks delimit the constant areas (unchanged), default is changed */
+ AV_VIDEO_HINT_CONSTANT,
+
+ /* blocks delimit the constant areas (changed), default is not changed */
+ AV_VIDEO_HINT_CHANGED,
+} AVVideoHintType;
+
+typedef struct AVVideoHint {
+ /**
+ * Number of blocks in the array.
+ *
+ * May be 0, in which case no per-block information is present. In this case
+ * the values of blocks_offset / block_size are unspecified and should not
+ * be accessed.
+ */
+ int nb_rects;
+
+ /**
+ * Offset in bytes from the beginning of this structure at which the array
+ * of blocks starts.
+ */
+ size_t blocks_offset;
+
+ size_t block_size;
+
+ AVVideoHintType type;
+} AVVideoHint;
+
+static av_always_inline AVVideoRect*
+av_video_hint_rects(const AVVideoHint *hints)
+{
+ return (AVVideoRect *)((uint8_t *)hints + hints->blocks_offset);
+}
+
+static av_always_inline AVVideoRect*
+av_video_hint_get_rect(const AVVideoHint *hints, size_t idx)
+{
+ return (AVVideoRect *)((uint8_t *)hints + hints->blocks_offset + idx * hints->block_size);
+}
+
+/**
+ * Allocate memory for a vector of AVVideoRect in the given AVFrame
+ * {@code frame} as AVFrameSideData of type AV_FRAME_DATA_VIDEO_HINT_INFO.
+ * The side data contains a list of rectangles for the portions of the frame
+ * which changed from the last encoded one (and the remainder are assumed to be
+ * changed), or, alternately (depending on the type parameter) the unchanged
+ * ones (and the remanining ones are those which changed).
+ * Macroblocks will thus be hinted either to be P_SKIP-ped or go through the
+ * regular encoding procedure.
+ *
+ * It's responsibility of the caller to fill the AVRects accordingly, and to set
+ * the proper AVVideoHintType field.
+ */
+AVVideoHint *av_video_hint_create_side_data(AVFrame *frame,
+ size_t num_rects);
+
+AVVideoHint *av_video_hint_alloc(size_t nb_rects,
+ size_t *out_size);
+
+#endif /* AVUTIL_VIDEO_HINT_H */
--
2.34.1
[-- Attachment #3: Type: text/plain, Size: 251 bytes --]
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [FFmpeg-devel] [PATCH] Optimization: support for libx264's mb_info
2023-07-03 15:51 ` Carotti, Elias
@ 2023-07-07 16:27 ` Carotti, Elias
2023-07-09 11:05 ` [FFmpeg-devel] [PATCH] lavu: add AVVideoHint API Anton Khirnov
0 siblings, 1 reply; 33+ messages in thread
From: Carotti, Elias @ 2023-07-07 16:27 UTC (permalink / raw)
To: ffmpeg-devel
On Mon, 2023-07-03 at 15:51 +0000, Carotti, Elias wrote:
> On Sat, 2023-07-01 at 10:33 +0200, Anton Khirnov wrote:
> > CAUTION: This email originated from outside of the organization. Do
> > not click links or open attachments unless you can confirm the
> > sender
> > and know the content is safe.
> >
> >
> >
> > Sorry to still nag you, but I just noticed that unlike
> > video_enc_params,
> > you do not store AVVideoRect size in AVVideoHint. This means that
> > no new fields can be added to AVVideoRect without an ABI break.
> > This
> > seems suboptimal, since I do see potential use for per-block
> > information.
> >
>
> Hi Anton,
> I do agree with you.
> Please find the updated (and rebased) patch attached to this email.
>
> Best,
> Elias
>
> P.S. By the way, I would be tempted (I didn't do that here) to
> declare
> the block_size field as
>
> const size_t block_size;
>
> and then when setting it into av_video_hint_alloc(...) cast away the
> const (it has to be assigned only once, upon allocation of the
> struct),
> just to enforce compiler checking against accidental assignments and
> for better clarity that this is a read-only field, in the general
> case.
>
> P.P.S.: I'm sending the second part of the patch for libavcodec as a
> separate email.
Hi Anton, Hi Stefano,
do you think this solves the issue?
Best
Elias
NICE SRL, viale Monte Grappa 3/5, 20124 Milano, Italia, Registro delle Imprese di Milano Monza Brianza Lodi REA n. 2096882, Capitale Sociale: 10.329,14 EUR i.v., Cod. Fisc. e P.IVA 01133050052, Societa con Socio Unico
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 33+ messages in thread
* [FFmpeg-devel] [PATCH] lavu: add AVVideoHint API
2023-07-07 16:27 ` Carotti, Elias
@ 2023-07-09 11:05 ` Anton Khirnov
2023-07-09 13:10 ` Lynne
2023-07-10 8:09 ` Carotti, Elias
0 siblings, 2 replies; 33+ messages in thread
From: Anton Khirnov @ 2023-07-09 11:05 UTC (permalink / raw)
To: ffmpeg-devel
From: Elias Carotti <eliascrt _at_ amazon _dot_ it>
Add side data type to provide hint to the video encoders about unchanged
portions of each frame.
Signed-off-by: Anton Khirnov <anton@khirnov.net>
---
I've made couple small changes:
* rebased against current master
* consistently refer to rectangles or AVVideoRect, not blocks
* use size_t instead of int for AVVideoHint.nb_rects
* build unconditionally -- this is public API, it must always be
available regardless of what encoders are or are not available
* tweaked documentation
If you have no objections to the changes, I'll push this in a few days.
---
doc/APIchanges | 3 ++
libavutil/Makefile | 2 +
libavutil/frame.h | 10 ++++
libavutil/version.h | 2 +-
libavutil/video_hint.c | 82 +++++++++++++++++++++++++++++++
libavutil/video_hint.h | 108 +++++++++++++++++++++++++++++++++++++++++
6 files changed, 206 insertions(+), 1 deletion(-)
create mode 100644 libavutil/video_hint.c
create mode 100644 libavutil/video_hint.h
diff --git a/doc/APIchanges b/doc/APIchanges
index 27f835cfce..0cda51fdee 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -2,6 +2,9 @@ The last version increases of all libraries were on 2023-02-09
API changes, most recent first:
+2023-07-xx - xxxxxxxxxx - lavu 58.15.100 - video_hint.h
+ Add AVVideoHint API.
+
2023-07-05 - xxxxxxxxxx - lavu 58.14.100 - random_seed.h
Add av_random_bytes()
diff --git a/libavutil/Makefile b/libavutil/Makefile
index bd9c6f9e32..7828c94dc5 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -91,6 +91,7 @@ HEADERS = adler32.h \
tea.h \
tx.h \
film_grain_params.h \
+ video_hint.h
ARCH_HEADERS = bswap.h \
intmath.h \
@@ -181,6 +182,7 @@ OBJS = adler32.o \
uuid.o \
version.o \
video_enc_params.o \
+ video_hint.o \
film_grain_params.o \
diff --git a/libavutil/frame.h b/libavutil/frame.h
index a491315f25..c0c1b23db7 100644
--- a/libavutil/frame.h
+++ b/libavutil/frame.h
@@ -214,6 +214,16 @@ enum AVFrameSideDataType {
* Ambient viewing environment metadata, as defined by H.274.
*/
AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT,
+
+ /**
+ * Provide encoder-specific hinting information about changed/unchanged
+ * portions of a frame. It can be used to pass information about which
+ * macroblocks can be skipped because they didn't change from the
+ * corresponding ones in the previous frame. This could be useful for
+ * applications which know this information in advance to speed up
+ * encoding.
+ */
+ AV_FRAME_DATA_VIDEO_HINT,
};
enum AVActiveFormatDescription {
diff --git a/libavutil/version.h b/libavutil/version.h
index 24af520e08..9e798b0e3f 100644
--- a/libavutil/version.h
+++ b/libavutil/version.h
@@ -79,7 +79,7 @@
*/
#define LIBAVUTIL_VERSION_MAJOR 58
-#define LIBAVUTIL_VERSION_MINOR 14
+#define LIBAVUTIL_VERSION_MINOR 15
#define LIBAVUTIL_VERSION_MICRO 100
#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
diff --git a/libavutil/video_hint.c b/libavutil/video_hint.c
new file mode 100644
index 0000000000..5730ed6cfb
--- /dev/null
+++ b/libavutil/video_hint.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2023 Elias Carotti <eliascrt at amazon dot it>
+ *
+ * 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 <string.h>
+
+#include "avstring.h"
+#include "frame.h"
+#include "macros.h"
+#include "mem.h"
+#include "video_hint.h"
+
+AVVideoHint *av_video_hint_alloc(size_t nb_rects,
+ size_t *out_size)
+{
+ struct TestStruct {
+ AVVideoHint hint;
+ AVVideoRect rect;
+ };
+ const size_t rect_offset = offsetof(struct TestStruct, rect);
+ size_t size = rect_offset;
+ AVVideoHint *hint;
+
+ *out_size = 0;
+ if (nb_rects > (SIZE_MAX - size) / sizeof(AVVideoRect))
+ return NULL;
+ size += sizeof(AVVideoRect) * nb_rects;
+
+ hint = av_mallocz(size);
+ if (!hint)
+ return NULL;
+
+ hint->nb_rects = nb_rects;
+ hint->rect_offset = rect_offset;
+ hint->rect_size = sizeof(AVVideoRect);
+
+ *out_size = size;
+
+ return hint;
+}
+
+AVVideoHint *av_video_hint_create_side_data(AVFrame *frame,
+ size_t nb_rects)
+{
+ AVVideoHint *hint;
+ AVBufferRef *buf;
+ size_t size = 0;
+
+ hint = av_video_hint_alloc(nb_rects, &size);
+ if (!hint)
+ return NULL;
+
+ buf = av_buffer_create((uint8_t *)hint, size, NULL, NULL, 0);
+ if (!buf) {
+ av_freep(&hint);
+ return NULL;
+ }
+
+ if (!av_frame_new_side_data_from_buf(frame, AV_FRAME_DATA_VIDEO_HINT, buf)) {
+ av_buffer_unref(&buf);
+ return NULL;
+ }
+
+ return hint;
+}
+
diff --git a/libavutil/video_hint.h b/libavutil/video_hint.h
new file mode 100644
index 0000000000..86addf5ceb
--- /dev/null
+++ b/libavutil/video_hint.h
@@ -0,0 +1,108 @@
+/**
+ * Copyright 2023 Elias Carotti <eliascrt at amazon dot it>
+ *
+ * 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
+ */
+
+#ifndef AVUTIL_VIDEO_HINT_H
+#define AVUTIL_VIDEO_HINT_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include "libavutil/avassert.h"
+#include "libavutil/frame.h"
+
+typedef struct AVVideoRect {
+ uint32_t x, y;
+ uint32_t width, height;
+} AVVideoRect;
+
+typedef enum AVVideoHintType {
+ /* rectangled delimit the constant areas (unchanged), default is changed */
+ AV_VIDEO_HINT_CONSTANT,
+
+ /* rectangled delimit the constant areas (changed), default is not changed */
+ AV_VIDEO_HINT_CHANGED,
+} AVVideoHintType;
+
+typedef struct AVVideoHint {
+ /**
+ * Number of AVVideoRect present.
+ *
+ * May be 0, in which case no per-rectangle information is present. In this
+ * case the values of rect_offset / rect_size are unspecified and should
+ * not be accessed.
+ */
+ size_t nb_rects;
+
+ /**
+ * Offset in bytes from the beginning of this structure at which the array
+ * of AVVideoRect starts.
+ */
+ size_t rect_offset;
+
+ /**
+ * Size in bytes of AVVideoRect.
+ */
+ size_t rect_size;
+
+ AVVideoHintType type;
+} AVVideoHint;
+
+static av_always_inline AVVideoRect*
+av_video_hint_rects(const AVVideoHint *hints)
+{
+ return (AVVideoRect *)((uint8_t *)hints + hints->rect_offset);
+}
+
+static av_always_inline AVVideoRect*
+av_video_hint_get_rect(const AVVideoHint *hints, size_t idx)
+{
+ return (AVVideoRect *)((uint8_t *)hints + hints->rect_offset + idx * hints->rect_size);
+}
+
+/**
+ * Allocate memory for the AVVideoHint struct along with an nb_rects-sized
+ * arrays of AVVideoRect.
+ *
+ * The side data contains a list of rectangles for the portions of the frame
+ * which changed from the last encoded one (and the remainder are assumed to be
+ * changed), or, alternately (depending on the type parameter) the unchanged
+ * ones (and the remanining ones are those which changed).
+ * Macroblocks will thus be hinted either to be P_SKIP-ped or go through the
+ * regular encoding procedure.
+ *
+ * It's responsibility of the caller to fill the AVRects accordingly, and to set
+ * the proper AVVideoHintType field.
+ *
+ * @param out_size if non-NULL, the size in bytes of the resulting data array is
+ * written here
+ *
+ * @return newly allocated AVVideoHint struct (must be freed by the caller using
+ * av_free()) on success, NULL on memory allocation failure
+ */
+AVVideoHint *av_video_hint_alloc(size_t nb_rects,
+ size_t *out_size);
+/**
+ * Same as av_video_hint_alloc(), except newly-allocated AVVideoHint is attached
+ * as side data of type AV_FRAME_DATA_VIDEO_HINT_INFO to frame.
+ */
+AVVideoHint *av_video_hint_create_side_data(AVFrame *frame,
+ size_t nb_rects);
+
+
+#endif /* AVUTIL_VIDEO_HINT_H */
--
2.40.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [FFmpeg-devel] [PATCH] lavu: add AVVideoHint API
2023-07-09 11:05 ` [FFmpeg-devel] [PATCH] lavu: add AVVideoHint API Anton Khirnov
@ 2023-07-09 13:10 ` Lynne
2023-07-10 8:13 ` Carotti, Elias
2023-07-10 8:09 ` Carotti, Elias
1 sibling, 1 reply; 33+ messages in thread
From: Lynne @ 2023-07-09 13:10 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Jul 9, 2023, 13:05 by anton@khirnov.net:
> From: Elias Carotti <eliascrt _at_ amazon _dot_ it>
>
> Add side data type to provide hint to the video encoders about unchanged
> portions of each frame.
>
> Signed-off-by: Anton Khirnov <anton@khirnov.net>
> ---
> I've made couple small changes:
> * rebased against current master
> * consistently refer to rectangles or AVVideoRect, not blocks
> * use size_t instead of int for AVVideoHint.nb_rects
> * build unconditionally -- this is public API, it must always be
> available regardless of what encoders are or are not available
> * tweaked documentation
>
> If you have no objections to the changes, I'll push this in a few days.
> ---
> doc/APIchanges | 3 ++
> libavutil/Makefile | 2 +
> libavutil/frame.h | 10 ++++
> libavutil/version.h | 2 +-
> libavutil/video_hint.c | 82 +++++++++++++++++++++++++++++++
> libavutil/video_hint.h | 108 +++++++++++++++++++++++++++++++++++++++++
> 6 files changed, 206 insertions(+), 1 deletion(-)
> create mode 100644 libavutil/video_hint.c
> create mode 100644 libavutil/video_hint.h
>
AVVideoHint is a bad name for something like this.
Could you borrow some wording from graphics and call it
AVVideoDamagedHint or maybe AVVideoChangedAreaHint
or a combination of both?
I'd prefer the former, damage is standard language in graphics
circles about what has changed since the last frame.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [FFmpeg-devel] [PATCH] lavu: add AVVideoHint API
2023-07-09 11:05 ` [FFmpeg-devel] [PATCH] lavu: add AVVideoHint API Anton Khirnov
2023-07-09 13:10 ` Lynne
@ 2023-07-10 8:09 ` Carotti, Elias
1 sibling, 0 replies; 33+ messages in thread
From: Carotti, Elias @ 2023-07-10 8:09 UTC (permalink / raw)
To: FFmpeg development discussions and patches
-----Original Message-----
From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of Anton Khirnov
Sent: Sunday, July 9, 2023 1:05 PM
To: ffmpeg-devel@ffmpeg.org
Subject: [EXTERNAL] [FFmpeg-devel] [PATCH] lavu: add AVVideoHint API
CAUTION: This email originated from outside of the organization. Do not click links or open attachments unless you can confirm the sender and know the content is safe.
From: Elias Carotti <eliascrt _at_ amazon _dot_ it>
Add side data type to provide hint to the video encoders about unchanged portions of each frame.
Signed-off-by: Anton Khirnov <anton@khirnov.net>
---
I've made couple small changes:
* rebased against current master
* consistently refer to rectangles or AVVideoRect, not blocks
* use size_t instead of int for AVVideoHint.nb_rects
* build unconditionally -- this is public API, it must always be
available regardless of what encoders are or are not available
* tweaked documentation
If you have no objections to the changes, I'll push this in a few days.
Hi Anton,
I'm perfectly fine with all the changes, so feel free to proceed.
Best,
Elias
---
doc/APIchanges | 3 ++
libavutil/Makefile | 2 +
libavutil/frame.h | 10 ++++
libavutil/version.h | 2 +-
libavutil/video_hint.c | 82 +++++++++++++++++++++++++++++++ libavutil/video_hint.h | 108 +++++++++++++++++++++++++++++++++++++++++
6 files changed, 206 insertions(+), 1 deletion(-) create mode 100644 libavutil/video_hint.c create mode 100644 libavutil/video_hint.h
diff --git a/doc/APIchanges b/doc/APIchanges index 27f835cfce..0cda51fdee 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -2,6 +2,9 @@ The last version increases of all libraries were on 2023-02-09
API changes, most recent first:
+2023-07-xx - xxxxxxxxxx - lavu 58.15.100 - video_hint.h
+ Add AVVideoHint API.
+
2023-07-05 - xxxxxxxxxx - lavu 58.14.100 - random_seed.h
Add av_random_bytes()
diff --git a/libavutil/Makefile b/libavutil/Makefile index bd9c6f9e32..7828c94dc5 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -91,6 +91,7 @@ HEADERS = adler32.h \
tea.h \
tx.h \
film_grain_params.h \
+ video_hint.h
ARCH_HEADERS = bswap.h \
intmath.h \
@@ -181,6 +182,7 @@ OBJS = adler32.o \
uuid.o \
version.o \
video_enc_params.o \
+ video_hint.o \
film_grain_params.o \
diff --git a/libavutil/frame.h b/libavutil/frame.h index a491315f25..c0c1b23db7 100644
--- a/libavutil/frame.h
+++ b/libavutil/frame.h
@@ -214,6 +214,16 @@ enum AVFrameSideDataType {
* Ambient viewing environment metadata, as defined by H.274.
*/
AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT,
+
+ /**
+ * Provide encoder-specific hinting information about changed/unchanged
+ * portions of a frame. It can be used to pass information about which
+ * macroblocks can be skipped because they didn't change from the
+ * corresponding ones in the previous frame. This could be useful for
+ * applications which know this information in advance to speed up
+ * encoding.
+ */
+ AV_FRAME_DATA_VIDEO_HINT,
};
enum AVActiveFormatDescription {
diff --git a/libavutil/version.h b/libavutil/version.h index 24af520e08..9e798b0e3f 100644
--- a/libavutil/version.h
+++ b/libavutil/version.h
@@ -79,7 +79,7 @@
*/
#define LIBAVUTIL_VERSION_MAJOR 58
-#define LIBAVUTIL_VERSION_MINOR 14
+#define LIBAVUTIL_VERSION_MINOR 15
#define LIBAVUTIL_VERSION_MICRO 100
#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
diff --git a/libavutil/video_hint.c b/libavutil/video_hint.c new file mode 100644 index 0000000000..5730ed6cfb
--- /dev/null
+++ b/libavutil/video_hint.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2023 Elias Carotti <eliascrt at amazon dot it>
+ *
+ * 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 <string.h>
+
+#include "avstring.h"
+#include "frame.h"
+#include "macros.h"
+#include "mem.h"
+#include "video_hint.h"
+
+AVVideoHint *av_video_hint_alloc(size_t nb_rects,
+ size_t *out_size) {
+ struct TestStruct {
+ AVVideoHint hint;
+ AVVideoRect rect;
+ };
+ const size_t rect_offset = offsetof(struct TestStruct, rect);
+ size_t size = rect_offset;
+ AVVideoHint *hint;
+
+ *out_size = 0;
+ if (nb_rects > (SIZE_MAX - size) / sizeof(AVVideoRect))
+ return NULL;
+ size += sizeof(AVVideoRect) * nb_rects;
+
+ hint = av_mallocz(size);
+ if (!hint)
+ return NULL;
+
+ hint->nb_rects = nb_rects;
+ hint->rect_offset = rect_offset;
+ hint->rect_size = sizeof(AVVideoRect);
+
+ *out_size = size;
+
+ return hint;
+}
+
+AVVideoHint *av_video_hint_create_side_data(AVFrame *frame,
+ size_t nb_rects) {
+ AVVideoHint *hint;
+ AVBufferRef *buf;
+ size_t size = 0;
+
+ hint = av_video_hint_alloc(nb_rects, &size);
+ if (!hint)
+ return NULL;
+
+ buf = av_buffer_create((uint8_t *)hint, size, NULL, NULL, 0);
+ if (!buf) {
+ av_freep(&hint);
+ return NULL;
+ }
+
+ if (!av_frame_new_side_data_from_buf(frame, AV_FRAME_DATA_VIDEO_HINT, buf)) {
+ av_buffer_unref(&buf);
+ return NULL;
+ }
+
+ return hint;
+}
+
diff --git a/libavutil/video_hint.h b/libavutil/video_hint.h new file mode 100644 index 0000000000..86addf5ceb
--- /dev/null
+++ b/libavutil/video_hint.h
@@ -0,0 +1,108 @@
+/**
+ * Copyright 2023 Elias Carotti <eliascrt at amazon dot it>
+ *
+ * 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 */
+
+#ifndef AVUTIL_VIDEO_HINT_H
+#define AVUTIL_VIDEO_HINT_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include "libavutil/avassert.h"
+#include "libavutil/frame.h"
+
+typedef struct AVVideoRect {
+ uint32_t x, y;
+ uint32_t width, height;
+} AVVideoRect;
+
+typedef enum AVVideoHintType {
+ /* rectangled delimit the constant areas (unchanged), default is changed */
+ AV_VIDEO_HINT_CONSTANT,
+
+ /* rectangled delimit the constant areas (changed), default is not changed */
+ AV_VIDEO_HINT_CHANGED,
+} AVVideoHintType;
+
+typedef struct AVVideoHint {
+ /**
+ * Number of AVVideoRect present.
+ *
+ * May be 0, in which case no per-rectangle information is present. In this
+ * case the values of rect_offset / rect_size are unspecified and should
+ * not be accessed.
+ */
+ size_t nb_rects;
+
+ /**
+ * Offset in bytes from the beginning of this structure at which the array
+ * of AVVideoRect starts.
+ */
+ size_t rect_offset;
+
+ /**
+ * Size in bytes of AVVideoRect.
+ */
+ size_t rect_size;
+
+ AVVideoHintType type;
+} AVVideoHint;
+
+static av_always_inline AVVideoRect*
+av_video_hint_rects(const AVVideoHint *hints) {
+ return (AVVideoRect *)((uint8_t *)hints + hints->rect_offset); }
+
+static av_always_inline AVVideoRect*
+av_video_hint_get_rect(const AVVideoHint *hints, size_t idx) {
+ return (AVVideoRect *)((uint8_t *)hints + hints->rect_offset + idx
+* hints->rect_size); }
+
+/**
+ * Allocate memory for the AVVideoHint struct along with an
+nb_rects-sized
+ * arrays of AVVideoRect.
+ *
+ * The side data contains a list of rectangles for the portions of the
+frame
+ * which changed from the last encoded one (and the remainder are
+assumed to be
+ * changed), or, alternately (depending on the type parameter) the
+unchanged
+ * ones (and the remanining ones are those which changed).
+ * Macroblocks will thus be hinted either to be P_SKIP-ped or go
+through the
+ * regular encoding procedure.
+ *
+ * It's responsibility of the caller to fill the AVRects accordingly,
+and to set
+ * the proper AVVideoHintType field.
+ *
+ * @param out_size if non-NULL, the size in bytes of the resulting data array is
+ * written here
+ *
+ * @return newly allocated AVVideoHint struct (must be freed by the caller using
+ * av_free()) on success, NULL on memory allocation failure
+ */
+AVVideoHint *av_video_hint_alloc(size_t nb_rects,
+ size_t *out_size);
+/**
+ * Same as av_video_hint_alloc(), except newly-allocated AVVideoHint is
+attached
+ * as side data of type AV_FRAME_DATA_VIDEO_HINT_INFO to frame.
+ */
+AVVideoHint *av_video_hint_create_side_data(AVFrame *frame,
+ size_t nb_rects);
+
+
+#endif /* AVUTIL_VIDEO_HINT_H */
--
2.40.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
NICE SRL, viale Monte Grappa 3/5, 20124 Milano, Italia, Registro delle Imprese di Milano Monza Brianza Lodi REA n. 2096882, Capitale Sociale: 10.329,14 EUR i.v., Cod. Fisc. e P.IVA 01133050052, Societa con Socio Unico
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [FFmpeg-devel] [PATCH] lavu: add AVVideoHint API
2023-07-09 13:10 ` Lynne
@ 2023-07-10 8:13 ` Carotti, Elias
2023-07-10 12:51 ` Carotti, Elias
0 siblings, 1 reply; 33+ messages in thread
From: Carotti, Elias @ 2023-07-10 8:13 UTC (permalink / raw)
To: FFmpeg development discussions and patches
-----Original Message-----
From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of Lynne
Sent: Sunday, July 9, 2023 3:11 PM
To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org>
Subject: RE: [EXTERNAL][FFmpeg-devel] [PATCH] lavu: add AVVideoHint API
CAUTION: This email originated from outside of the organization. Do not click links or open attachments unless you can confirm the sender and know the content is safe.
Jul 9, 2023, 13:05 by anton@khirnov.net:
> From: Elias Carotti <eliascrt _at_ amazon _dot_ it>
>
> Add side data type to provide hint to the video encoders about
> unchanged portions of each frame.
>
> Signed-off-by: Anton Khirnov <anton@khirnov.net>
> ---
> I've made couple small changes:
> * rebased against current master
> * consistently refer to rectangles or AVVideoRect, not blocks
> * use size_t instead of int for AVVideoHint.nb_rects
> * build unconditionally -- this is public API, it must always be
> available regardless of what encoders are or are not available
> * tweaked documentation
>
> If you have no objections to the changes, I'll push this in a few days.
> ---
> doc/APIchanges | 3 ++
> libavutil/Makefile | 2 +
> libavutil/frame.h | 10 ++++
> libavutil/version.h | 2 +-
> libavutil/video_hint.c | 82 +++++++++++++++++++++++++++++++
> libavutil/video_hint.h | 108 +++++++++++++++++++++++++++++++++++++++++
> 6 files changed, 206 insertions(+), 1 deletion(-) create mode 100644
> libavutil/video_hint.c create mode 100644 libavutil/video_hint.h
>
AVVideoHint is a bad name for something like this.
Could you borrow some wording from graphics and call it AVVideoDamagedHint or maybe AVVideoChangedAreaHint or a combination of both?
I'd prefer the former, damage is standard language in graphics circles about what has changed since the last frame.
Hi,
I have no strong objections on this. Personally I also like the AVVideoDamagedHint name best, my only concern is that it is strictly related to the current use/implementation
(it's true right now that's the only kind of hint) while it may turn out to be a bad naming decision should other forms of hinting for the encoder be added in the future.
That said, I am fine with the change too.
Elias
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
NICE SRL, viale Monte Grappa 3/5, 20124 Milano, Italia, Registro delle Imprese di Milano Monza Brianza Lodi REA n. 2096882, Capitale Sociale: 10.329,14 EUR i.v., Cod. Fisc. e P.IVA 01133050052, Societa con Socio Unico
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [FFmpeg-devel] [PATCH] lavu: add AVVideoHint API
2023-07-10 8:13 ` Carotti, Elias
@ 2023-07-10 12:51 ` Carotti, Elias
2023-07-17 22:19 ` Stefano Sabatini
0 siblings, 1 reply; 33+ messages in thread
From: Carotti, Elias @ 2023-07-10 12:51 UTC (permalink / raw)
To: ffmpeg-devel
[-- Attachment #1: Type: text/plain, Size: 1273 bytes --]
On Mon, 2023-07-10 at 08:13 +0000, Carotti, Elias wrote:
>
> AVVideoHint is a bad name for something like this.
> Could you borrow some wording from graphics and call it
> AVVideoDamagedHint or maybe AVVideoChangedAreaHint or a combination
> of both?
> I'd prefer the former, damage is standard language in graphics
> circles about what has changed since the last frame.
>
> Hi,
> I have no strong objections on this. Personally I also like the
> AVVideoDamagedHint name best, my only concern is that it is strictly
> related to the current use/implementation
> (it's true right now that's the only kind of hint) while it may turn
> out to be a bad naming decision should other forms of hinting for the
> encoder be added in the future.
> That said, I am fine with the change too.
> Elias
>
I added a type to the AVVideoRect struct. This should solve the naming
issue above while preserving the possibility to extend this to
different hinting types.
These are the only changes to Anton's version.
Best
Elias
NICE SRL, viale Monte Grappa 3/5, 20124 Milano, Italia, Registro delle Imprese di Milano Monza Brianza Lodi REA n. 2096882, Capitale Sociale: 10.329,14 EUR i.v., Cod. Fisc. e P.IVA 01133050052, Societa con Socio Unico
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Add-side-data-type-to-provide-hint-to-the-video-enco.patch --]
[-- Type: text/x-patch; name="0001-Add-side-data-type-to-provide-hint-to-the-video-enco.patch", Size: 10027 bytes --]
From 8ef4f97410a6b78df048b71d9921a763da6255b3 Mon Sep 17 00:00:00 2001
From: Elias Carotti <eliascrt _at_ amazon _dot_ it>
Date: Mon, 10 Jul 2023 14:34:53 +0200
Subject: [PATCH] Add side data type to provide hint to the video encoders
about unchanged portions of each frame.
Signed-off-by: Anton Khirnov <anton@khirnov.net>
---
doc/APIchanges | 3 ++
libavutil/Makefile | 2 +
libavutil/frame.h | 10 ++++
libavutil/version.h | 2 +-
libavutil/video_hint.c | 82 +++++++++++++++++++++++++++++
libavutil/video_hint.h | 117 +++++++++++++++++++++++++++++++++++++++++
6 files changed, 215 insertions(+), 1 deletion(-)
create mode 100644 libavutil/video_hint.c
create mode 100644 libavutil/video_hint.h
diff --git a/doc/APIchanges b/doc/APIchanges
index 27f835cfce..0cda51fdee 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -2,6 +2,9 @@ The last version increases of all libraries were on 2023-02-09
API changes, most recent first:
+2023-07-xx - xxxxxxxxxx - lavu 58.15.100 - video_hint.h
+ Add AVVideoHint API.
+
2023-07-05 - xxxxxxxxxx - lavu 58.14.100 - random_seed.h
Add av_random_bytes()
diff --git a/libavutil/Makefile b/libavutil/Makefile
index bd9c6f9e32..7828c94dc5 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -91,6 +91,7 @@ HEADERS = adler32.h \
tea.h \
tx.h \
film_grain_params.h \
+ video_hint.h
ARCH_HEADERS = bswap.h \
intmath.h \
@@ -181,6 +182,7 @@ OBJS = adler32.o \
uuid.o \
version.o \
video_enc_params.o \
+ video_hint.o \
film_grain_params.o \
diff --git a/libavutil/frame.h b/libavutil/frame.h
index a491315f25..c0c1b23db7 100644
--- a/libavutil/frame.h
+++ b/libavutil/frame.h
@@ -214,6 +214,16 @@ enum AVFrameSideDataType {
* Ambient viewing environment metadata, as defined by H.274.
*/
AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT,
+
+ /**
+ * Provide encoder-specific hinting information about changed/unchanged
+ * portions of a frame. It can be used to pass information about which
+ * macroblocks can be skipped because they didn't change from the
+ * corresponding ones in the previous frame. This could be useful for
+ * applications which know this information in advance to speed up
+ * encoding.
+ */
+ AV_FRAME_DATA_VIDEO_HINT,
};
enum AVActiveFormatDescription {
diff --git a/libavutil/version.h b/libavutil/version.h
index 24af520e08..9e798b0e3f 100644
--- a/libavutil/version.h
+++ b/libavutil/version.h
@@ -79,7 +79,7 @@
*/
#define LIBAVUTIL_VERSION_MAJOR 58
-#define LIBAVUTIL_VERSION_MINOR 14
+#define LIBAVUTIL_VERSION_MINOR 15
#define LIBAVUTIL_VERSION_MICRO 100
#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
diff --git a/libavutil/video_hint.c b/libavutil/video_hint.c
new file mode 100644
index 0000000000..5730ed6cfb
--- /dev/null
+++ b/libavutil/video_hint.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2023 Elias Carotti <eliascrt at amazon dot it>
+ *
+ * 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 <string.h>
+
+#include "avstring.h"
+#include "frame.h"
+#include "macros.h"
+#include "mem.h"
+#include "video_hint.h"
+
+AVVideoHint *av_video_hint_alloc(size_t nb_rects,
+ size_t *out_size)
+{
+ struct TestStruct {
+ AVVideoHint hint;
+ AVVideoRect rect;
+ };
+ const size_t rect_offset = offsetof(struct TestStruct, rect);
+ size_t size = rect_offset;
+ AVVideoHint *hint;
+
+ *out_size = 0;
+ if (nb_rects > (SIZE_MAX - size) / sizeof(AVVideoRect))
+ return NULL;
+ size += sizeof(AVVideoRect) * nb_rects;
+
+ hint = av_mallocz(size);
+ if (!hint)
+ return NULL;
+
+ hint->nb_rects = nb_rects;
+ hint->rect_offset = rect_offset;
+ hint->rect_size = sizeof(AVVideoRect);
+
+ *out_size = size;
+
+ return hint;
+}
+
+AVVideoHint *av_video_hint_create_side_data(AVFrame *frame,
+ size_t nb_rects)
+{
+ AVVideoHint *hint;
+ AVBufferRef *buf;
+ size_t size = 0;
+
+ hint = av_video_hint_alloc(nb_rects, &size);
+ if (!hint)
+ return NULL;
+
+ buf = av_buffer_create((uint8_t *)hint, size, NULL, NULL, 0);
+ if (!buf) {
+ av_freep(&hint);
+ return NULL;
+ }
+
+ if (!av_frame_new_side_data_from_buf(frame, AV_FRAME_DATA_VIDEO_HINT, buf)) {
+ av_buffer_unref(&buf);
+ return NULL;
+ }
+
+ return hint;
+}
+
diff --git a/libavutil/video_hint.h b/libavutil/video_hint.h
new file mode 100644
index 0000000000..14bfe20aa6
--- /dev/null
+++ b/libavutil/video_hint.h
@@ -0,0 +1,117 @@
+/**
+ * Copyright 2023 Elias Carotti <eliascrt at amazon dot it>
+ *
+ * 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
+ */
+
+#ifndef AVUTIL_VIDEO_HINT_H
+#define AVUTIL_VIDEO_HINT_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include "libavutil/avassert.h"
+#include "libavutil/frame.h"
+
+/**
+ * The type of the hinting information provided by an AVVideoRect.
+ * Currently only damage information, i.e., changed/unchanged portions of the frame.
+ **/
+typedef enum AVVideoRectType {
+ AV_VIDEO_RECT_DAMAGE,
+} AVVideoRectType;
+
+typedef struct AVVideoRect {
+ uint32_t x, y;
+ uint32_t width, height;
+ AVVideoRectType type;
+} AVVideoRect;
+
+typedef enum AVVideoHintType {
+ /* rectangled delimit the constant areas (unchanged), default is changed */
+ AV_VIDEO_HINT_CONSTANT,
+
+ /* rectangled delimit the constant areas (changed), default is not changed */
+ AV_VIDEO_HINT_CHANGED,
+} AVVideoHintType;
+
+typedef struct AVVideoHint {
+ /**
+ * Number of AVVideoRect present.
+ *
+ * May be 0, in which case no per-rectangle information is present. In this
+ * case the values of rect_offset / rect_size are unspecified and should
+ * not be accessed.
+ */
+ size_t nb_rects;
+
+ /**
+ * Offset in bytes from the beginning of this structure at which the array
+ * of AVVideoRect starts.
+ */
+ size_t rect_offset;
+
+ /**
+ * Size in bytes of AVVideoRect.
+ */
+ size_t rect_size;
+
+ AVVideoHintType type;
+} AVVideoHint;
+
+static av_always_inline AVVideoRect*
+av_video_hint_rects(const AVVideoHint *hints)
+{
+ return (AVVideoRect *)((uint8_t *)hints + hints->rect_offset);
+}
+
+static av_always_inline AVVideoRect*
+av_video_hint_get_rect(const AVVideoHint *hints, size_t idx)
+{
+ return (AVVideoRect *)((uint8_t *)hints + hints->rect_offset + idx * hints->rect_size);
+}
+
+/**
+ * Allocate memory for the AVVideoHint struct along with an nb_rects-sized
+ * arrays of AVVideoRect.
+ *
+ * The side data contains a list of rectangles for the portions of the frame
+ * which changed from the last encoded one (and the remainder are assumed to be
+ * changed), or, alternately (depending on the type parameter) the unchanged
+ * ones (and the remanining ones are those which changed).
+ * Macroblocks will thus be hinted either to be P_SKIP-ped or go through the
+ * regular encoding procedure.
+ *
+ * It's responsibility of the caller to fill the AVRects accordingly, and to set
+ * the proper AVVideoHintType field.
+ *
+ * @param out_size if non-NULL, the size in bytes of the resulting data array is
+ * written here
+ *
+ * @return newly allocated AVVideoHint struct (must be freed by the caller using
+ * av_free()) on success, NULL on memory allocation failure
+ */
+AVVideoHint *av_video_hint_alloc(size_t nb_rects,
+ size_t *out_size);
+/**
+ * Same as av_video_hint_alloc(), except newly-allocated AVVideoHint is attached
+ * as side data of type AV_FRAME_DATA_VIDEO_HINT_INFO to frame.
+ */
+AVVideoHint *av_video_hint_create_side_data(AVFrame *frame,
+ size_t nb_rects);
+
+
+#endif /* AVUTIL_VIDEO_HINT_H */
--
2.34.1
[-- Attachment #3: Type: text/plain, Size: 251 bytes --]
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [FFmpeg-devel] [PATCH] lavu: add AVVideoHint API
2023-07-10 12:51 ` Carotti, Elias
@ 2023-07-17 22:19 ` Stefano Sabatini
2023-07-23 23:27 ` Stefano Sabatini
0 siblings, 1 reply; 33+ messages in thread
From: Stefano Sabatini @ 2023-07-17 22:19 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On date Monday 2023-07-10 12:51:25 +0000, Carotti, Elias wrote:
> On Mon, 2023-07-10 at 08:13 +0000, Carotti, Elias wrote:
> >
>
> > AVVideoHint is a bad name for something like this.
> > Could you borrow some wording from graphics and call it
> > AVVideoDamagedHint or maybe AVVideoChangedAreaHint or a combination
> > of both?
> > I'd prefer the former, damage is standard language in graphics
> > circles about what has changed since the last frame.
> >
> > Hi,
> > I have no strong objections on this. Personally I also like the
> > AVVideoDamagedHint name best, my only concern is that it is strictly
> > related to the current use/implementation
> > (it's true right now that's the only kind of hint) while it may turn
> > out to be a bad naming decision should other forms of hinting for the
> > encoder be added in the future.
> > That said, I am fine with the change too.
AVVideoDamagedHint would be too specific (what if we want to add
"hinting" for different things?).
> > Elias
> >
>
> I added a type to the AVVideoRect struct. This should solve the naming
> issue above while preserving the possibility to extend this to
> different hinting types.
> These are the only changes to Anton's version.
> Best
> Elias
>
>
>
>
>
>
>
> NICE SRL, viale Monte Grappa 3/5, 20124 Milano, Italia, Registro delle Imprese di Milano Monza Brianza Lodi REA n. 2096882, Capitale Sociale: 10.329,14 EUR i.v., Cod. Fisc. e P.IVA 01133050052, Societa con Socio Unico
>
>
> From 8ef4f97410a6b78df048b71d9921a763da6255b3 Mon Sep 17 00:00:00 2001
> From: Elias Carotti <eliascrt _at_ amazon _dot_ it>
> Date: Mon, 10 Jul 2023 14:34:53 +0200
> Subject: [PATCH] Add side data type to provide hint to the video encoders
> about unchanged portions of each frame.
>
> Signed-off-by: Anton Khirnov <anton@khirnov.net>
> ---
> doc/APIchanges | 3 ++
> libavutil/Makefile | 2 +
> libavutil/frame.h | 10 ++++
> libavutil/version.h | 2 +-
> libavutil/video_hint.c | 82 +++++++++++++++++++++++++++++
> libavutil/video_hint.h | 117 +++++++++++++++++++++++++++++++++++++++++
> 6 files changed, 215 insertions(+), 1 deletion(-)
> create mode 100644 libavutil/video_hint.c
> create mode 100644 libavutil/video_hint.h
>
> diff --git a/doc/APIchanges b/doc/APIchanges
> index 27f835cfce..0cda51fdee 100644
> --- a/doc/APIchanges
> +++ b/doc/APIchanges
> @@ -2,6 +2,9 @@ The last version increases of all libraries were on 2023-02-09
>
> API changes, most recent first:
>
> +2023-07-xx - xxxxxxxxxx - lavu 58.15.100 - video_hint.h
> + Add AVVideoHint API.
> +
> 2023-07-05 - xxxxxxxxxx - lavu 58.14.100 - random_seed.h
> Add av_random_bytes()
>
> diff --git a/libavutil/Makefile b/libavutil/Makefile
> index bd9c6f9e32..7828c94dc5 100644
> --- a/libavutil/Makefile
> +++ b/libavutil/Makefile
> @@ -91,6 +91,7 @@ HEADERS = adler32.h \
> tea.h \
> tx.h \
> film_grain_params.h \
> + video_hint.h
>
> ARCH_HEADERS = bswap.h \
> intmath.h \
> @@ -181,6 +182,7 @@ OBJS = adler32.o \
> uuid.o \
> version.o \
> video_enc_params.o \
> + video_hint.o \
> film_grain_params.o \
>
>
> diff --git a/libavutil/frame.h b/libavutil/frame.h
> index a491315f25..c0c1b23db7 100644
> --- a/libavutil/frame.h
> +++ b/libavutil/frame.h
> @@ -214,6 +214,16 @@ enum AVFrameSideDataType {
> * Ambient viewing environment metadata, as defined by H.274.
> */
> AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT,
> +
> + /**
> + * Provide encoder-specific hinting information about changed/unchanged
> + * portions of a frame. It can be used to pass information about which
> + * macroblocks can be skipped because they didn't change from the
> + * corresponding ones in the previous frame. This could be useful for
> + * applications which know this information in advance to speed up
> + * encoding.
> + */
> + AV_FRAME_DATA_VIDEO_HINT,
> };
>
> enum AVActiveFormatDescription {
> diff --git a/libavutil/version.h b/libavutil/version.h
> index 24af520e08..9e798b0e3f 100644
> --- a/libavutil/version.h
> +++ b/libavutil/version.h
> @@ -79,7 +79,7 @@
> */
>
> #define LIBAVUTIL_VERSION_MAJOR 58
> -#define LIBAVUTIL_VERSION_MINOR 14
> +#define LIBAVUTIL_VERSION_MINOR 15
> #define LIBAVUTIL_VERSION_MICRO 100
>
> #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
> diff --git a/libavutil/video_hint.c b/libavutil/video_hint.c
> new file mode 100644
> index 0000000000..5730ed6cfb
> --- /dev/null
> +++ b/libavutil/video_hint.c
> @@ -0,0 +1,82 @@
> +/*
> + * Copyright 2023 Elias Carotti <eliascrt at amazon dot it>
> + *
> + * 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 <string.h>
> +
> +#include "avstring.h"
> +#include "frame.h"
> +#include "macros.h"
> +#include "mem.h"
> +#include "video_hint.h"
> +
> +AVVideoHint *av_video_hint_alloc(size_t nb_rects,
> + size_t *out_size)
> +{
> + struct TestStruct {
> + AVVideoHint hint;
> + AVVideoRect rect;
> + };
> + const size_t rect_offset = offsetof(struct TestStruct, rect);
> + size_t size = rect_offset;
> + AVVideoHint *hint;
> +
> + *out_size = 0;
> + if (nb_rects > (SIZE_MAX - size) / sizeof(AVVideoRect))
> + return NULL;
> + size += sizeof(AVVideoRect) * nb_rects;
> +
> + hint = av_mallocz(size);
> + if (!hint)
> + return NULL;
> +
> + hint->nb_rects = nb_rects;
> + hint->rect_offset = rect_offset;
> + hint->rect_size = sizeof(AVVideoRect);
> +
> + *out_size = size;
> +
> + return hint;
> +}
> +
> +AVVideoHint *av_video_hint_create_side_data(AVFrame *frame,
> + size_t nb_rects)
> +{
> + AVVideoHint *hint;
> + AVBufferRef *buf;
> + size_t size = 0;
> +
> + hint = av_video_hint_alloc(nb_rects, &size);
> + if (!hint)
> + return NULL;
> +
> + buf = av_buffer_create((uint8_t *)hint, size, NULL, NULL, 0);
> + if (!buf) {
> + av_freep(&hint);
> + return NULL;
> + }
> +
> + if (!av_frame_new_side_data_from_buf(frame, AV_FRAME_DATA_VIDEO_HINT, buf)) {
> + av_buffer_unref(&buf);
> + return NULL;
> + }
> +
> + return hint;
> +}
> +
> diff --git a/libavutil/video_hint.h b/libavutil/video_hint.h
> new file mode 100644
> index 0000000000..14bfe20aa6
> --- /dev/null
> +++ b/libavutil/video_hint.h
> @@ -0,0 +1,117 @@
> +/**
> + * Copyright 2023 Elias Carotti <eliascrt at amazon dot it>
> + *
> + * 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
> + */
> +
> +#ifndef AVUTIL_VIDEO_HINT_H
> +#define AVUTIL_VIDEO_HINT_H
> +
> +#include <stddef.h>
> +#include <stdint.h>
> +#include "libavutil/avassert.h"
> +#include "libavutil/frame.h"
> +
> +/**
> + * The type of the hinting information provided by an AVVideoRect.
> + * Currently only damage information, i.e., changed/unchanged portions of the frame.
> + **/
> +typedef enum AVVideoRectType {
> + AV_VIDEO_RECT_DAMAGE,
AV_VIDEO_RECT_TYPE_DAMAGE for consistency
> +} AVVideoRectType;
> +
> +typedef struct AVVideoRect {
> + uint32_t x, y;
> + uint32_t width, height;
> + AVVideoRectType type;
> +} AVVideoRect;
> +
> +typedef enum AVVideoHintType {
> + /* rectangled delimit the constant areas (unchanged), default is changed */
rectangles?
> + AV_VIDEO_HINT_CONSTANT,
AV_VIDEO_HINT_TYPE_...
> +
> + /* rectangled delimit the constant areas (changed), default is not changed */
rectangles?
> + AV_VIDEO_HINT_CHANGED,
> +} AVVideoHintType;
>
> +typedef struct AVVideoHint {
> + /**
> + * Number of AVVideoRect present.
> + *
> + * May be 0, in which case no per-rectangle information is present. In this
> + * case the values of rect_offset / rect_size are unspecified and should
> + * not be accessed.
> + */
> + size_t nb_rects;
> +
> + /**
> + * Offset in bytes from the beginning of this structure at which the array
> + * of AVVideoRect starts.
> + */
> + size_t rect_offset;
> +
> + /**
> + * Size in bytes of AVVideoRect.
> + */
> + size_t rect_size;
> +
> + AVVideoHintType type;
sorry to nitpick, but if we have this information in the single rect
should not we use that instead?
Basically I see two options:
1. generic VideoHint, storing single hint type and rects
for example we might have type=changed, and the rects storing only the
changed rects
If we want to extend this then we need to add a new type. The problem
might be if we want to store more than one VideoHint in the side data
(it it possible to store more than one AVVideoHint, each one with a
different type, as side data?). Suppose for example we want to add a
new hint type, e.g. ROI, then we can add a new AVHideoHint with
type=roi - but I don't know if we can have several frame hint side
data (each one with different individual types).
2. generic VideoHint, storing rects each one containing the hint type
for example we might have a list of rects, each one with
type=changed|constant|roi. This would allow one to store different
kind of hints in the same AVVideoHint structure, but at the same time
would enable inconsistent data (for example we might have changed and
unchanged rects in the same list of rects)
In each case, storing the type in the generic AVVideHint and in each
rect might lead to inconsistent states (e.g. you might have generic
type=damage, and have type=roi and type=changed in the rects), in this
case having the type in both the general structure and in each rects
seems redundant and leads to possible data inconsistencies.
...
I would rather go to solution 1, but I'm not sure if having more than
one hint in the side data (with different subtypes) is possible and
wanted. If this is the case, probably the best solution would be to
store more than one AVVideoHint (each one with an individual type and
list of rects) in the single side data object.
> +} AVVideoHint;
> +
> +static av_always_inline AVVideoRect*
> +av_video_hint_rects(const AVVideoHint *hints)
> +{
> + return (AVVideoRect *)((uint8_t *)hints + hints->rect_offset);
> +}
> +
> +static av_always_inline AVVideoRect*
> +av_video_hint_get_rect(const AVVideoHint *hints, size_t idx)
> +{
> + return (AVVideoRect *)((uint8_t *)hints + hints->rect_offset + idx * hints->rect_size);
> +}
> +
> +/**
> + * Allocate memory for the AVVideoHint struct along with an nb_rects-sized
> + * arrays of AVVideoRect.
> + *
> + * The side data contains a list of rectangles for the portions of the frame
> + * which changed from the last encoded one (and the remainder are assumed to be
> + * changed), or, alternately (depending on the type parameter) the unchanged
> + * ones (and the remanining ones are those which changed).
> + * Macroblocks will thus be hinted either to be P_SKIP-ped or go through the
> + * regular encoding procedure.
> + *
> + * It's responsibility of the caller to fill the AVRects accordingly, and to set
> + * the proper AVVideoHintType field.
> + *
> + * @param out_size if non-NULL, the size in bytes of the resulting data array is
> + * written here
> + *
> + * @return newly allocated AVVideoHint struct (must be freed by the caller using
> + * av_free()) on success, NULL on memory allocation failure
> + */
> +AVVideoHint *av_video_hint_alloc(size_t nb_rects,
> + size_t *out_size);
> +/**
> + * Same as av_video_hint_alloc(), except newly-allocated AVVideoHint is attached
> + * as side data of type AV_FRAME_DATA_VIDEO_HINT_INFO to frame.
> + */
> +AVVideoHint *av_video_hint_create_side_data(AVFrame *frame,
> + size_t nb_rects);
> +
> +
> +#endif /* AVUTIL_VIDEO_HINT_H */
> --
> 2.34.1
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [FFmpeg-devel] [PATCH] lavu: add AVVideoHint API
2023-07-17 22:19 ` Stefano Sabatini
@ 2023-07-23 23:27 ` Stefano Sabatini
2023-07-26 10:52 ` Carotti, Elias
0 siblings, 1 reply; 33+ messages in thread
From: Stefano Sabatini @ 2023-07-23 23:27 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On date Tuesday 2023-07-18 00:19:40 +0200, Stefano Sabatini wrote:
> On date Monday 2023-07-10 12:51:25 +0000, Carotti, Elias wrote:
> > On Mon, 2023-07-10 at 08:13 +0000, Carotti, Elias wrote:
> > >
> >
> > > AVVideoHint is a bad name for something like this.
> > > Could you borrow some wording from graphics and call it
> > > AVVideoDamagedHint or maybe AVVideoChangedAreaHint or a combination
> > > of both?
> > > I'd prefer the former, damage is standard language in graphics
> > > circles about what has changed since the last frame.
> > >
> > > Hi,
> > > I have no strong objections on this. Personally I also like the
> > > AVVideoDamagedHint name best, my only concern is that it is strictly
> > > related to the current use/implementation
> > > (it's true right now that's the only kind of hint) while it may turn
> > > out to be a bad naming decision should other forms of hinting for the
> > > encoder be added in the future.
> > > That said, I am fine with the change too.
>
> AVVideoDamagedHint would be too specific (what if we want to add
> "hinting" for different things?).
>
> > > Elias
> > >
> >
> > I added a type to the AVVideoRect struct. This should solve the naming
> > issue above while preserving the possibility to extend this to
> > different hinting types.
> > These are the only changes to Anton's version.
> > Best
> > Elias
> >
> >
> >
> >
> >
> >
> >
> > NICE SRL, viale Monte Grappa 3/5, 20124 Milano, Italia, Registro delle Imprese di Milano Monza Brianza Lodi REA n. 2096882, Capitale Sociale: 10.329,14 EUR i.v., Cod. Fisc. e P.IVA 01133050052, Societa con Socio Unico
> >
> >
>
> > From 8ef4f97410a6b78df048b71d9921a763da6255b3 Mon Sep 17 00:00:00 2001
> > From: Elias Carotti <eliascrt _at_ amazon _dot_ it>
> > Date: Mon, 10 Jul 2023 14:34:53 +0200
> > Subject: [PATCH] Add side data type to provide hint to the video encoders
> > about unchanged portions of each frame.
> >
> > Signed-off-by: Anton Khirnov <anton@khirnov.net>
> > ---
> > doc/APIchanges | 3 ++
> > libavutil/Makefile | 2 +
> > libavutil/frame.h | 10 ++++
> > libavutil/version.h | 2 +-
> > libavutil/video_hint.c | 82 +++++++++++++++++++++++++++++
> > libavutil/video_hint.h | 117 +++++++++++++++++++++++++++++++++++++++++
> > 6 files changed, 215 insertions(+), 1 deletion(-)
> > create mode 100644 libavutil/video_hint.c
> > create mode 100644 libavutil/video_hint.h
> >
> > diff --git a/doc/APIchanges b/doc/APIchanges
> > index 27f835cfce..0cda51fdee 100644
> > --- a/doc/APIchanges
> > +++ b/doc/APIchanges
> > @@ -2,6 +2,9 @@ The last version increases of all libraries were on 2023-02-09
> >
> > API changes, most recent first:
> >
> > +2023-07-xx - xxxxxxxxxx - lavu 58.15.100 - video_hint.h
> > + Add AVVideoHint API.
> > +
> > 2023-07-05 - xxxxxxxxxx - lavu 58.14.100 - random_seed.h
> > Add av_random_bytes()
> >
> > diff --git a/libavutil/Makefile b/libavutil/Makefile
> > index bd9c6f9e32..7828c94dc5 100644
> > --- a/libavutil/Makefile
> > +++ b/libavutil/Makefile
> > @@ -91,6 +91,7 @@ HEADERS = adler32.h \
> > tea.h \
> > tx.h \
> > film_grain_params.h \
> > + video_hint.h
> >
> > ARCH_HEADERS = bswap.h \
> > intmath.h \
> > @@ -181,6 +182,7 @@ OBJS = adler32.o \
> > uuid.o \
> > version.o \
> > video_enc_params.o \
> > + video_hint.o \
> > film_grain_params.o \
> >
> >
> > diff --git a/libavutil/frame.h b/libavutil/frame.h
> > index a491315f25..c0c1b23db7 100644
> > --- a/libavutil/frame.h
> > +++ b/libavutil/frame.h
> > @@ -214,6 +214,16 @@ enum AVFrameSideDataType {
> > * Ambient viewing environment metadata, as defined by H.274.
> > */
> > AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT,
> > +
> > + /**
> > + * Provide encoder-specific hinting information about changed/unchanged
> > + * portions of a frame. It can be used to pass information about which
> > + * macroblocks can be skipped because they didn't change from the
> > + * corresponding ones in the previous frame. This could be useful for
> > + * applications which know this information in advance to speed up
> > + * encoding.
> > + */
> > + AV_FRAME_DATA_VIDEO_HINT,
> > };
> >
> > enum AVActiveFormatDescription {
> > diff --git a/libavutil/version.h b/libavutil/version.h
> > index 24af520e08..9e798b0e3f 100644
> > --- a/libavutil/version.h
> > +++ b/libavutil/version.h
> > @@ -79,7 +79,7 @@
> > */
> >
> > #define LIBAVUTIL_VERSION_MAJOR 58
> > -#define LIBAVUTIL_VERSION_MINOR 14
> > +#define LIBAVUTIL_VERSION_MINOR 15
> > #define LIBAVUTIL_VERSION_MICRO 100
> >
> > #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
> > diff --git a/libavutil/video_hint.c b/libavutil/video_hint.c
> > new file mode 100644
> > index 0000000000..5730ed6cfb
> > --- /dev/null
> > +++ b/libavutil/video_hint.c
> > @@ -0,0 +1,82 @@
> > +/*
> > + * Copyright 2023 Elias Carotti <eliascrt at amazon dot it>
> > + *
> > + * 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 <string.h>
> > +
> > +#include "avstring.h"
> > +#include "frame.h"
> > +#include "macros.h"
> > +#include "mem.h"
> > +#include "video_hint.h"
> > +
> > +AVVideoHint *av_video_hint_alloc(size_t nb_rects,
> > + size_t *out_size)
> > +{
> > + struct TestStruct {
> > + AVVideoHint hint;
> > + AVVideoRect rect;
> > + };
> > + const size_t rect_offset = offsetof(struct TestStruct, rect);
> > + size_t size = rect_offset;
> > + AVVideoHint *hint;
> > +
> > + *out_size = 0;
> > + if (nb_rects > (SIZE_MAX - size) / sizeof(AVVideoRect))
> > + return NULL;
> > + size += sizeof(AVVideoRect) * nb_rects;
> > +
> > + hint = av_mallocz(size);
> > + if (!hint)
> > + return NULL;
> > +
> > + hint->nb_rects = nb_rects;
> > + hint->rect_offset = rect_offset;
> > + hint->rect_size = sizeof(AVVideoRect);
> > +
> > + *out_size = size;
> > +
> > + return hint;
> > +}
> > +
> > +AVVideoHint *av_video_hint_create_side_data(AVFrame *frame,
> > + size_t nb_rects)
> > +{
> > + AVVideoHint *hint;
> > + AVBufferRef *buf;
> > + size_t size = 0;
> > +
> > + hint = av_video_hint_alloc(nb_rects, &size);
> > + if (!hint)
> > + return NULL;
> > +
> > + buf = av_buffer_create((uint8_t *)hint, size, NULL, NULL, 0);
> > + if (!buf) {
> > + av_freep(&hint);
> > + return NULL;
> > + }
> > +
> > + if (!av_frame_new_side_data_from_buf(frame, AV_FRAME_DATA_VIDEO_HINT, buf)) {
> > + av_buffer_unref(&buf);
> > + return NULL;
> > + }
> > +
> > + return hint;
> > +}
> > +
> > diff --git a/libavutil/video_hint.h b/libavutil/video_hint.h
> > new file mode 100644
> > index 0000000000..14bfe20aa6
> > --- /dev/null
> > +++ b/libavutil/video_hint.h
> > @@ -0,0 +1,117 @@
> > +/**
> > + * Copyright 2023 Elias Carotti <eliascrt at amazon dot it>
> > + *
> > + * 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
> > + */
> > +
> > +#ifndef AVUTIL_VIDEO_HINT_H
> > +#define AVUTIL_VIDEO_HINT_H
> > +
> > +#include <stddef.h>
> > +#include <stdint.h>
> > +#include "libavutil/avassert.h"
> > +#include "libavutil/frame.h"
> > +
>
> > +/**
> > + * The type of the hinting information provided by an AVVideoRect.
> > + * Currently only damage information, i.e., changed/unchanged portions of the frame.
> > + **/
>
> > +typedef enum AVVideoRectType {
> > + AV_VIDEO_RECT_DAMAGE,
>
> AV_VIDEO_RECT_TYPE_DAMAGE for consistency
>
> > +} AVVideoRectType;
>
> > +
> > +typedef struct AVVideoRect {
> > + uint32_t x, y;
> > + uint32_t width, height;
> > + AVVideoRectType type;
> > +} AVVideoRect;
> > +
> > +typedef enum AVVideoHintType {
> > + /* rectangled delimit the constant areas (unchanged), default is changed */
>
> rectangles?
>
> > + AV_VIDEO_HINT_CONSTANT,
>
> AV_VIDEO_HINT_TYPE_...
>
> > +
> > + /* rectangled delimit the constant areas (changed), default is not changed */
>
> rectangles?
>
> > + AV_VIDEO_HINT_CHANGED,
> > +} AVVideoHintType;
> >
> > +typedef struct AVVideoHint {
> > + /**
> > + * Number of AVVideoRect present.
> > + *
> > + * May be 0, in which case no per-rectangle information is present. In this
> > + * case the values of rect_offset / rect_size are unspecified and should
> > + * not be accessed.
> > + */
> > + size_t nb_rects;
> > +
> > + /**
> > + * Offset in bytes from the beginning of this structure at which the array
> > + * of AVVideoRect starts.
> > + */
> > + size_t rect_offset;
> > +
> > + /**
> > + * Size in bytes of AVVideoRect.
> > + */
> > + size_t rect_size;
> > +
>
> > + AVVideoHintType type;
>
> sorry to nitpick, but if we have this information in the single rect
> should not we use that instead?
>
> Basically I see two options:
> 1. generic VideoHint, storing single hint type and rects
>
> for example we might have type=changed, and the rects storing only the
> changed rects
>
> If we want to extend this then we need to add a new type. The problem
> might be if we want to store more than one VideoHint in the side data
> (it it possible to store more than one AVVideoHint, each one with a
> different type, as side data?). Suppose for example we want to add a
> new hint type, e.g. ROI, then we can add a new AVHideoHint with
> type=roi - but I don't know if we can have several frame hint side
> data (each one with different individual types).
>
> 2. generic VideoHint, storing rects each one containing the hint type
>
> for example we might have a list of rects, each one with
> type=changed|constant|roi. This would allow one to store different
> kind of hints in the same AVVideoHint structure, but at the same time
> would enable inconsistent data (for example we might have changed and
> unchanged rects in the same list of rects)
>
> In each case, storing the type in the generic AVVideHint and in each
> rect might lead to inconsistent states (e.g. you might have generic
> type=damage, and have type=roi and type=changed in the rects), in this
> case having the type in both the general structure and in each rects
> seems redundant and leads to possible data inconsistencies.
>
> ...
>
> I would rather go to solution 1, but I'm not sure if having more than
> one hint in the side data (with different subtypes) is possible and
> wanted. If this is the case, probably the best solution would be to
> store more than one AVVideoHint (each one with an individual type and
> list of rects) in the single side data object.
Elaborating on this.
1. Ideally we might want to extend the av_frame_get_side_data API to
be able to store more than one entry per side data, by adding a unique
label to the side data, but this requires probably more effort and
extends the scope even further.
2. Alternatively, we might extend the hint API like this:
AVVideoHint *av_video_hint_create_side_data(AVFrame *frame,
size_t nb_rects);
AVVideoHint *av_video_hint_extend_side_data(AVFrame *frame,
size_t nb_rects);
by marking the continuation on the previous hint (but this would
complicate deserialization as you need then to iterate to get all the
side data).
Or we could make a variadic function like this:
AVVideoHint *av_video_hint_create_side_data(AVFrame *frame, size_t nb_rects, ...);
Alternatively, we might store in AVVideoHint more than one hint, but
this somehow conflict with the general design.
...
As a low effort approach, I would keep the initial design of a single
hint type per side-data (dropping the possibility of having more than
one hint type in the same side data), which should be fixed
generically by implementing 1.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [FFmpeg-devel] [PATCH] lavu: add AVVideoHint API
2023-07-23 23:27 ` Stefano Sabatini
@ 2023-07-26 10:52 ` Carotti, Elias
2023-07-28 7:44 ` Stefano Sabatini
0 siblings, 1 reply; 33+ messages in thread
From: Carotti, Elias @ 2023-07-26 10:52 UTC (permalink / raw)
To: ffmpeg-devel
[-- Attachment #1: Type: text/plain, Size: 4318 bytes --]
On Mon, 2023-07-24 at 01:27 +0200, Stefano Sabatini wrote:
> CAUTION: This email originated from outside of the organization. Do
> not click links or open attachments unless you can confirm the sender
> and know the content is safe.
>
>
<snip>
> >
> > sorry to nitpick, but if we have this information in the single
> > rect
> > should not we use that instead?
> >
> > Basically I see two options:
> > 1. generic VideoHint, storing single hint type and rects
> >
> > for example we might have type=changed, and the rects storing only
> > the
> > changed rects
> >
> > If we want to extend this then we need to add a new type. The
> > problem
> > might be if we want to store more than one VideoHint in the side
> > data
> > (it it possible to store more than one AVVideoHint, each one with a
> > different type, as side data?). Suppose for example we want to add
> > a
> > new hint type, e.g. ROI, then we can add a new AVHideoHint with
> > type=roi - but I don't know if we can have several frame hint side
> > data (each one with different individual types).
> >
> > 2. generic VideoHint, storing rects each one containing the hint
> > type
> >
> > for example we might have a list of rects, each one with
> > type=changed|constant|roi. This would allow one to store different
> > kind of hints in the same AVVideoHint structure, but at the same
> > time
> > would enable inconsistent data (for example we might have changed
> > and
> > unchanged rects in the same list of rects)
> >
I don't think it allowed such inconsistency the way it was made.
Basically, the semantics was that the Hint type could be either
CONSTANT or CHANGED and that was the basis to interpret the rects with
type DAMAGE.
> > In each case, storing the type in the generic AVVideHint and in
> > each
> > rect might lead to inconsistent states (e.g. you might have generic
> > type=damage, and have type=roi and type=changed in the rects), in
> > this
> > case having the type in both the general structure and in each
> > rects
> > seems redundant and leads to possible data inconsistencies.
> >
> > ...
> >
>
> > I would rather go to solution 1, but I'm not sure if having more
> > than
> > one hint in the side data (with different subtypes) is possible and
> > wanted. If this is the case, probably the best solution would be to
> > store more than one AVVideoHint (each one with an individual type
> > and
> > list of rects) in the single side data object.
>
> Elaborating on this.
>
> 1. Ideally we might want to extend the av_frame_get_side_data API to
> be able to store more than one entry per side data, by adding a
> unique
> label to the side data, but this requires probably more effort and
> extends the scope even further.
>
> 2. Alternatively, we might extend the hint API like this:
>
> AVVideoHint *av_video_hint_create_side_data(AVFrame *frame,
> size_t nb_rects);
>
> AVVideoHint *av_video_hint_extend_side_data(AVFrame *frame,
> size_t nb_rects);
>
> by marking the continuation on the previous hint (but this would
> complicate deserialization as you need then to iterate to get all the
> side data).
>
> Or we could make a variadic function like this:
> AVVideoHint *av_video_hint_create_side_data(AVFrame *frame, size_t
> nb_rects, ...);
>
> Alternatively, we might store in AVVideoHint more than one hint, but
> this somehow conflict with the general design.
>
> ...
>
> As a low effort approach, I would keep the initial design of a single
> hint type per side-data (dropping the possibility of having more than
> one hint type in the same side data), which should be fixed
> generically by implementing 1.
Agreed.
For clarity I am attaching again the patch with Anton's changes just
rebased on the current master branch.
Anton, is this still ok to be merged?
Best,
Elias
NICE SRL, viale Monte Grappa 3/5, 20124 Milano, Italia, Registro delle Imprese di Milano Monza Brianza Lodi REA n. 2096882, Capitale Sociale: 10.329,14 EUR i.v., Cod. Fisc. e P.IVA 01133050052, Societa con Socio Unico
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Add-side-data-type-to-provide-hint-to-the-video-enco.patch --]
[-- Type: text/x-patch; name="0001-Add-side-data-type-to-provide-hint-to-the-video-enco.patch", Size: 9775 bytes --]
From fcd9051a9167f48083f0edc4bf44b3d09e568091 Mon Sep 17 00:00:00 2001
From: Elias Carotti <eliascrt _at_ amazon _dot_ it>
Date: Mon, 10 Jul 2023 14:34:53 +0200
Subject: [PATCH] Add side data type to provide hint to the video encoders
about unchanged portions of each frame.
Signed-off-by: Anton Khirnov <anton@khirnov.net>
---
doc/APIchanges | 3 ++
libavutil/Makefile | 2 +
libavutil/frame.h | 10 ++++
libavutil/version.h | 2 +-
libavutil/video_hint.c | 82 ++++++++++++++++++++++++++++++++
libavutil/video_hint.h | 105 +++++++++++++++++++++++++++++++++++++++++
6 files changed, 203 insertions(+), 1 deletion(-)
create mode 100644 libavutil/video_hint.c
create mode 100644 libavutil/video_hint.h
diff --git a/doc/APIchanges b/doc/APIchanges
index 5afe8bcb75..2adc7b5225 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -2,6 +2,9 @@ The last version increases of all libraries were on 2023-02-09
API changes, most recent first:
+2023-07-xx - xxxxxxxxxx - lavu 58.15.100 - video_hint.h
+ Add AVVideoHint API.
+
2023-07-xx - xxxxxxxxxx - lavc 60 - avcodec.h
Deprecate AV_CODEC_FLAG_DROPCHANGED without replacement.
diff --git a/libavutil/Makefile b/libavutil/Makefile
index bd9c6f9e32..7828c94dc5 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -91,6 +91,7 @@ HEADERS = adler32.h \
tea.h \
tx.h \
film_grain_params.h \
+ video_hint.h
ARCH_HEADERS = bswap.h \
intmath.h \
@@ -181,6 +182,7 @@ OBJS = adler32.o \
uuid.o \
version.o \
video_enc_params.o \
+ video_hint.o \
film_grain_params.o \
diff --git a/libavutil/frame.h b/libavutil/frame.h
index a491315f25..c0c1b23db7 100644
--- a/libavutil/frame.h
+++ b/libavutil/frame.h
@@ -214,6 +214,16 @@ enum AVFrameSideDataType {
* Ambient viewing environment metadata, as defined by H.274.
*/
AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT,
+
+ /**
+ * Provide encoder-specific hinting information about changed/unchanged
+ * portions of a frame. It can be used to pass information about which
+ * macroblocks can be skipped because they didn't change from the
+ * corresponding ones in the previous frame. This could be useful for
+ * applications which know this information in advance to speed up
+ * encoding.
+ */
+ AV_FRAME_DATA_VIDEO_HINT,
};
enum AVActiveFormatDescription {
diff --git a/libavutil/version.h b/libavutil/version.h
index 24af520e08..9e798b0e3f 100644
--- a/libavutil/version.h
+++ b/libavutil/version.h
@@ -79,7 +79,7 @@
*/
#define LIBAVUTIL_VERSION_MAJOR 58
-#define LIBAVUTIL_VERSION_MINOR 14
+#define LIBAVUTIL_VERSION_MINOR 15
#define LIBAVUTIL_VERSION_MICRO 100
#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
diff --git a/libavutil/video_hint.c b/libavutil/video_hint.c
new file mode 100644
index 0000000000..5730ed6cfb
--- /dev/null
+++ b/libavutil/video_hint.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2023 Elias Carotti <eliascrt at amazon dot it>
+ *
+ * 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 <string.h>
+
+#include "avstring.h"
+#include "frame.h"
+#include "macros.h"
+#include "mem.h"
+#include "video_hint.h"
+
+AVVideoHint *av_video_hint_alloc(size_t nb_rects,
+ size_t *out_size)
+{
+ struct TestStruct {
+ AVVideoHint hint;
+ AVVideoRect rect;
+ };
+ const size_t rect_offset = offsetof(struct TestStruct, rect);
+ size_t size = rect_offset;
+ AVVideoHint *hint;
+
+ *out_size = 0;
+ if (nb_rects > (SIZE_MAX - size) / sizeof(AVVideoRect))
+ return NULL;
+ size += sizeof(AVVideoRect) * nb_rects;
+
+ hint = av_mallocz(size);
+ if (!hint)
+ return NULL;
+
+ hint->nb_rects = nb_rects;
+ hint->rect_offset = rect_offset;
+ hint->rect_size = sizeof(AVVideoRect);
+
+ *out_size = size;
+
+ return hint;
+}
+
+AVVideoHint *av_video_hint_create_side_data(AVFrame *frame,
+ size_t nb_rects)
+{
+ AVVideoHint *hint;
+ AVBufferRef *buf;
+ size_t size = 0;
+
+ hint = av_video_hint_alloc(nb_rects, &size);
+ if (!hint)
+ return NULL;
+
+ buf = av_buffer_create((uint8_t *)hint, size, NULL, NULL, 0);
+ if (!buf) {
+ av_freep(&hint);
+ return NULL;
+ }
+
+ if (!av_frame_new_side_data_from_buf(frame, AV_FRAME_DATA_VIDEO_HINT, buf)) {
+ av_buffer_unref(&buf);
+ return NULL;
+ }
+
+ return hint;
+}
+
diff --git a/libavutil/video_hint.h b/libavutil/video_hint.h
new file mode 100644
index 0000000000..0442d635c9
--- /dev/null
+++ b/libavutil/video_hint.h
@@ -0,0 +1,105 @@
+/**
+ * Copyright 2023 Elias Carotti <eliascrt at amazon dot it>
+ *
+ * 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
+ */
+
+#ifndef AVUTIL_VIDEO_HINT_H
+#define AVUTIL_VIDEO_HINT_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include "libavutil/avassert.h"
+#include "libavutil/frame.h"
+
+typedef struct AVVideoRect {
+ uint32_t x, y;
+ uint32_t width, height;
+} AVVideoRect;
+
+typedef enum AVVideoHintType {
+ /* rectangled delimit the constant areas (unchanged), default is changed */
+ AV_VIDEO_HINT_CONSTANT,
+
+ /* rectangled delimit the constant areas (changed), default is not changed */
+ AV_VIDEO_HINT_CHANGED,
+} AVVideoHintType;
+
+typedef struct AVVideoHint {
+ /**
+ * Number of AVVideoRect present.
+ *
+ * May be 0, in which case no per-rectangle information is present. In this
+ * case the values of rect_offset / rect_size are unspecified and should
+ * not be accessed.
+ */
+ size_t nb_rects;
+
+ /**
+ * Offset in bytes from the beginning of this structure at which the array
+ * of AVVideoRect starts.
+ */
+ size_t rect_offset;
+
+ /**
+ * Size in bytes of AVVideoRect.
+ */
+ size_t rect_size;
+
+ AVVideoHintType type;
+} AVVideoHint;
+
+static av_always_inline AVVideoRect*
+av_video_hint_rects(const AVVideoHint *hints) {
+ return (AVVideoRect *)((uint8_t *)hints + hints->rect_offset); }
+
+static av_always_inline AVVideoRect*
+av_video_hint_get_rect(const AVVideoHint *hints, size_t idx) {
+ return (AVVideoRect *)((uint8_t *)hints + hints->rect_offset + idx
+* hints->rect_size); }
+
+/**
+ * Allocate memory for the AVVideoHint struct along with an nb_rects-sized
+ * arrays of AVVideoRect.
+ *
+ * The side data contains a list of rectangles for the portions of the frame
+ * which changed from the last encoded one (and the remainder are assumed to be
+ * changed), or, alternately (depending on the type parameter) the unchanged
+ * ones (and the remanining ones are those which changed).
+ * Macroblocks will thus be hinted either to be P_SKIP-ped or go through the
+ * regular encoding procedure.
+ *
+ * It's responsibility of the caller to fill the AVRects accordingly, and to set
+ * the proper AVVideoHintType field.
+ *
+ * @param out_size if non-NULL, the size in bytes of the resulting data array is
+ * written here
+ *
+ * @return newly allocated AVVideoHint struct (must be freed by the caller using
+ * av_free()) on success, NULL on memory allocation failure
+ */
+AVVideoHint *av_video_hint_alloc(size_t nb_rects,
+ size_t *out_size);
+/**
+ * Same as av_video_hint_alloc(), except newly-allocated AVVideoHint is attached
+ * as side data of type AV_FRAME_DATA_VIDEO_HINT_INFO to frame.
+ */
+AVVideoHint *av_video_hint_create_side_data(AVFrame *frame,
+ size_t nb_rects);
+
+
+#endif /* AVUTIL_VIDEO_HINT_H */
--
2.34.1
[-- Attachment #3: Type: text/plain, Size: 251 bytes --]
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [FFmpeg-devel] [PATCH] lavu: add AVVideoHint API
2023-07-26 10:52 ` Carotti, Elias
@ 2023-07-28 7:44 ` Stefano Sabatini
2023-08-02 5:36 ` Stefano Sabatini
0 siblings, 1 reply; 33+ messages in thread
From: Stefano Sabatini @ 2023-07-28 7:44 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On date Wednesday 2023-07-26 10:52:57 +0000, Carotti, Elias wrote:
> On Mon, 2023-07-24 at 01:27 +0200, Stefano Sabatini wrote:
> > CAUTION: This email originated from outside of the organization. Do
> > not click links or open attachments unless you can confirm the sender
> > and know the content is safe.
> >
> >
> <snip>
>
> > >
> > > sorry to nitpick, but if we have this information in the single
> > > rect
> > > should not we use that instead?
> > >
> > > Basically I see two options:
> > > 1. generic VideoHint, storing single hint type and rects
> > >
> > > for example we might have type=changed, and the rects storing only
> > > the
> > > changed rects
> > >
> > > If we want to extend this then we need to add a new type. The
> > > problem
> > > might be if we want to store more than one VideoHint in the side
> > > data
> > > (it it possible to store more than one AVVideoHint, each one with a
> > > different type, as side data?). Suppose for example we want to add
> > > a
> > > new hint type, e.g. ROI, then we can add a new AVHideoHint with
> > > type=roi - but I don't know if we can have several frame hint side
> > > data (each one with different individual types).
> > >
> > > 2. generic VideoHint, storing rects each one containing the hint
> > > type
> > >
> > > for example we might have a list of rects, each one with
> > > type=changed|constant|roi. This would allow one to store different
> > > kind of hints in the same AVVideoHint structure, but at the same
> > > time
> > > would enable inconsistent data (for example we might have changed
> > > and
> > > unchanged rects in the same list of rects)
> > >
>
> I don't think it allowed such inconsistency the way it was made.
> Basically, the semantics was that the Hint type could be either
> CONSTANT or CHANGED and that was the basis to interpret the rects with
> type DAMAGE.
Yes, but then there is no guarantee that you'll have all rects with
the same subtype, and you need to iterate and check each one to
check the subtype (so you might have mixed constant/changed and
unclear behavior to apply in this case).
> > > In each case, storing the type in the generic AVVideHint and in
> > > each
> > > rect might lead to inconsistent states (e.g. you might have generic
> > > type=damage, and have type=roi and type=changed in the rects), in
> > > this
> > > case having the type in both the general structure and in each
> > > rects
> > > seems redundant and leads to possible data inconsistencies.
> > >
> > > ...
> > >
> >
> > > I would rather go to solution 1, but I'm not sure if having more
> > > than
> > > one hint in the side data (with different subtypes) is possible and
> > > wanted. If this is the case, probably the best solution would be to
> > > store more than one AVVideoHint (each one with an individual type
> > > and
> > > list of rects) in the single side data object.
> >
> > Elaborating on this.
> >
> > 1. Ideally we might want to extend the av_frame_get_side_data API to
> > be able to store more than one entry per side data, by adding a
> > unique
> > label to the side data, but this requires probably more effort and
> > extends the scope even further.
> >
> > 2. Alternatively, we might extend the hint API like this:
> >
> > AVVideoHint *av_video_hint_create_side_data(AVFrame *frame,
> > size_t nb_rects);
> >
> > AVVideoHint *av_video_hint_extend_side_data(AVFrame *frame,
> > size_t nb_rects);
> >
> > by marking the continuation on the previous hint (but this would
> > complicate deserialization as you need then to iterate to get all the
> > side data).
> >
> > Or we could make a variadic function like this:
> > AVVideoHint *av_video_hint_create_side_data(AVFrame *frame, size_t
> > nb_rects, ...);
> >
> > Alternatively, we might store in AVVideoHint more than one hint, but
> > this somehow conflict with the general design.
> >
> > ...
> >
> > As a low effort approach, I would keep the initial design of a single
> > hint type per side-data (dropping the possibility of having more than
> > one hint type in the same side data), which should be fixed
> > generically by implementing 1.
>
> Agreed.
> For clarity I am attaching again the patch with Anton's changes just
> rebased on the current master branch.
> Anton, is this still ok to be merged?
I'm fine with the current patch, the behavior can then be extended
by extending side data with multiple-label for the same type.
Anton, if you are fine with it I would merge this one (and maybe get
included in the next release if we are not too late already).
Thanks.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [FFmpeg-devel] [PATCH] lavu: add AVVideoHint API
2023-07-28 7:44 ` Stefano Sabatini
@ 2023-08-02 5:36 ` Stefano Sabatini
2023-08-08 8:16 ` Stefano Sabatini
0 siblings, 1 reply; 33+ messages in thread
From: Stefano Sabatini @ 2023-08-02 5:36 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On date Friday 2023-07-28 09:44:37 +0200, Stefano Sabatini wrote:
> On date Wednesday 2023-07-26 10:52:57 +0000, Carotti, Elias wrote:
> > On Mon, 2023-07-24 at 01:27 +0200, Stefano Sabatini wrote:
> > > CAUTION: This email originated from outside of the organization. Do
> > > not click links or open attachments unless you can confirm the sender
> > > and know the content is safe.
> > >
> > >
> > <snip>
> >
> > > >
> > > > sorry to nitpick, but if we have this information in the single
> > > > rect
> > > > should not we use that instead?
> > > >
> > > > Basically I see two options:
> > > > 1. generic VideoHint, storing single hint type and rects
> > > >
> > > > for example we might have type=changed, and the rects storing only
> > > > the
> > > > changed rects
> > > >
> > > > If we want to extend this then we need to add a new type. The
> > > > problem
> > > > might be if we want to store more than one VideoHint in the side
> > > > data
> > > > (it it possible to store more than one AVVideoHint, each one with a
> > > > different type, as side data?). Suppose for example we want to add
> > > > a
> > > > new hint type, e.g. ROI, then we can add a new AVHideoHint with
> > > > type=roi - but I don't know if we can have several frame hint side
> > > > data (each one with different individual types).
> > > >
> > > > 2. generic VideoHint, storing rects each one containing the hint
> > > > type
> > > >
> > > > for example we might have a list of rects, each one with
> > > > type=changed|constant|roi. This would allow one to store different
> > > > kind of hints in the same AVVideoHint structure, but at the same
> > > > time
> > > > would enable inconsistent data (for example we might have changed
> > > > and
> > > > unchanged rects in the same list of rects)
> > > >
> >
>
> > I don't think it allowed such inconsistency the way it was made.
> > Basically, the semantics was that the Hint type could be either
> > CONSTANT or CHANGED and that was the basis to interpret the rects with
> > type DAMAGE.
>
> Yes, but then there is no guarantee that you'll have all rects with
> the same subtype, and you need to iterate and check each one to
> check the subtype (so you might have mixed constant/changed and
> unclear behavior to apply in this case).
>
> > > > In each case, storing the type in the generic AVVideHint and in
> > > > each
> > > > rect might lead to inconsistent states (e.g. you might have generic
> > > > type=damage, and have type=roi and type=changed in the rects), in
> > > > this
> > > > case having the type in both the general structure and in each
> > > > rects
> > > > seems redundant and leads to possible data inconsistencies.
> > > >
> > > > ...
> > > >
> > >
> > > > I would rather go to solution 1, but I'm not sure if having more
> > > > than
> > > > one hint in the side data (with different subtypes) is possible and
> > > > wanted. If this is the case, probably the best solution would be to
> > > > store more than one AVVideoHint (each one with an individual type
> > > > and
> > > > list of rects) in the single side data object.
> > >
> > > Elaborating on this.
> > >
> > > 1. Ideally we might want to extend the av_frame_get_side_data API to
> > > be able to store more than one entry per side data, by adding a
> > > unique
> > > label to the side data, but this requires probably more effort and
> > > extends the scope even further.
> > >
> > > 2. Alternatively, we might extend the hint API like this:
> > >
> > > AVVideoHint *av_video_hint_create_side_data(AVFrame *frame,
> > > size_t nb_rects);
> > >
> > > AVVideoHint *av_video_hint_extend_side_data(AVFrame *frame,
> > > size_t nb_rects);
> > >
> > > by marking the continuation on the previous hint (but this would
> > > complicate deserialization as you need then to iterate to get all the
> > > side data).
> > >
> > > Or we could make a variadic function like this:
> > > AVVideoHint *av_video_hint_create_side_data(AVFrame *frame, size_t
> > > nb_rects, ...);
> > >
> > > Alternatively, we might store in AVVideoHint more than one hint, but
> > > this somehow conflict with the general design.
> > >
> > > ...
> > >
> > > As a low effort approach, I would keep the initial design of a single
> > > hint type per side-data (dropping the possibility of having more than
> > > one hint type in the same side data), which should be fixed
> > > generically by implementing 1.
> >
> > Agreed.
> > For clarity I am attaching again the patch with Anton's changes just
> > rebased on the current master branch.
> > Anton, is this still ok to be merged?
>
> I'm fine with the current patch, the behavior can then be extended
> by extending side data with multiple-label for the same type.
>
> Anton, if you are fine with it I would merge this one (and maybe get
> included in the next release if we are not too late already).
I'll push this in a few days unless there are more comments.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [FFmpeg-devel] [PATCH] lavu: add AVVideoHint API
2023-08-02 5:36 ` Stefano Sabatini
@ 2023-08-08 8:16 ` Stefano Sabatini
0 siblings, 0 replies; 33+ messages in thread
From: Stefano Sabatini @ 2023-08-08 8:16 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On date Wednesday 2023-08-02 07:36:43 +0200, Stefano Sabatini wrote:
> On date Friday 2023-07-28 09:44:37 +0200, Stefano Sabatini wrote:
> > On date Wednesday 2023-07-26 10:52:57 +0000, Carotti, Elias wrote:
[...]
> > > Agreed.
> > > For clarity I am attaching again the patch with Anton's changes just
> > > rebased on the current master branch.
> > > Anton, is this still ok to be merged?
> >
> > I'm fine with the current patch, the behavior can then be extended
> > by extending side data with multiple-label for the same type.
> >
> > Anton, if you are fine with it I would merge this one (and maybe get
> > included in the next release if we are not too late already).
>
> I'll push this in a few days unless there are more comments.
Rebased and applied with a minor change (AV AV_VIDEO_HINT_* =>
AV_VIDEO_HINT_TYPE_*).
Thanks Elias for the contribution!
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 33+ messages in thread
end of thread, other threads:[~2023-08-08 8:16 UTC | newest]
Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-19 10:19 [FFmpeg-devel] [PATCH] Optimization: support for libx264's mb_info Carotti, Elias
2023-05-21 23:17 ` Stefano Sabatini
2023-05-22 9:19 ` Carotti, Elias
2023-05-29 17:56 ` Carotti, Elias
2023-06-04 15:29 ` Stefano Sabatini
2023-06-05 15:32 ` Carotti, Elias
2023-06-11 17:15 ` Stefano Sabatini
2023-06-12 8:23 ` Kieran Kunhya
2023-06-12 17:38 ` Carotti, Elias
2023-06-18 10:04 ` Stefano Sabatini
2023-06-12 17:28 ` Carotti, Elias
2023-06-18 10:18 ` Stefano Sabatini
2023-06-21 15:53 ` Carotti, Elias
2023-06-22 8:44 ` Anton Khirnov
2023-06-22 17:23 ` Carotti, Elias
2023-06-24 11:01 ` Anton Khirnov
2023-06-26 9:50 ` Carotti, Elias
2023-06-28 12:55 ` Anton Khirnov
2023-06-30 17:40 ` Carotti, Elias
2023-07-01 8:33 ` Anton Khirnov
2023-07-03 15:51 ` Carotti, Elias
2023-07-07 16:27 ` Carotti, Elias
2023-07-09 11:05 ` [FFmpeg-devel] [PATCH] lavu: add AVVideoHint API Anton Khirnov
2023-07-09 13:10 ` Lynne
2023-07-10 8:13 ` Carotti, Elias
2023-07-10 12:51 ` Carotti, Elias
2023-07-17 22:19 ` Stefano Sabatini
2023-07-23 23:27 ` Stefano Sabatini
2023-07-26 10:52 ` Carotti, Elias
2023-07-28 7:44 ` Stefano Sabatini
2023-08-02 5:36 ` Stefano Sabatini
2023-08-08 8:16 ` Stefano Sabatini
2023-07-10 8:09 ` Carotti, Elias
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
This inbox may be cloned and mirrored by anyone:
git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git
# If you have public-inbox 1.1+ installed, you may
# initialize and index your mirror using the following commands:
public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
ffmpegdev@gitmailbox.com
public-inbox-index ffmpegdev
Example config snippet for mirrors.
AGPL code for this site: git clone https://public-inbox.org/public-inbox.git