[FFmpeg-devel] Setup for extracting quantization parameters from encoded streams

Submitted by =?UTF-8?q?Juan=20De=20Le=C3=B3n?= on July 17, 2019, 11:18 p.m.

Details

Message ID 20190717231811.48483-1-juandl@google.com
State New
Headers show

Commit Message

=?UTF-8?q?Juan=20De=20Le=C3=B3n?= July 17, 2019, 11:18 p.m.
---
 libavfilter/vf_extractqp.c      | 116 ++++++++++++++++++++++++++++++++
 libavutil/Makefile              |   2 +
 libavutil/quantization_params.c |  28 ++++++++
 libavutil/quantization_params.h |  98 +++++++++++++++++++++++++++
 4 files changed, 244 insertions(+)
 create mode 100644 libavfilter/vf_extractqp.c
 create mode 100644 libavutil/quantization_params.c
 create mode 100644 libavutil/quantization_params.h

Comments

=?UTF-8?q?Juan=20De=20Le=C3=B3n?= July 17, 2019, 11:25 p.m.
For context
https://docs.google.com/document/d/1WClt3EqhjwdGXhEw386O0wfn3IBQ1Ib-_5emVM1gbnA/edit?usp=sharing
Feel free to comment the doc.

On Wed, Jul 17, 2019 at 4:18 PM Juan De León <juandl@google.com> wrote:

> ---
>  libavfilter/vf_extractqp.c      | 116 ++++++++++++++++++++++++++++++++
>  libavutil/Makefile              |   2 +
>  libavutil/quantization_params.c |  28 ++++++++
>  libavutil/quantization_params.h |  98 +++++++++++++++++++++++++++
>  4 files changed, 244 insertions(+)
>  create mode 100644 libavfilter/vf_extractqp.c
>  create mode 100644 libavutil/quantization_params.c
>  create mode 100644 libavutil/quantization_params.h
>
> diff --git a/libavfilter/vf_extractqp.c b/libavfilter/vf_extractqp.c
> new file mode 100644
> index 0000000000..4332012cc4
> --- /dev/null
> +++ b/libavfilter/vf_extractqp.c
> @@ -0,0 +1,116 @@
> +/*
> + * 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 "libavutil/frame.h"
> +#include "libavutil/opt.h"
> +#include "libavutil/quantization_params.h"
> +#include "libavfilter/avfilter.h"
> +#include "libavfilter/internal.h"
> +
> +typedef struct QPExtractContext {
> +    const AVClass *class;
> +    FILE *stats_file;
> +    char *stats_file_str;
> +} QPExtractContext;
> +
> +#define OFFSET(x) offsetof(QPExtractContext, x)
> +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
> +
> +static const AVOption qpextract_options[] = {
> +    {"stats_file", "Set file to store QP information",
> OFFSET(stats_file_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
> +    {"f",          "Set file to store QP information",
> OFFSET(stats_file_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
> +    { NULL }
> +};
> +
> +AVFILTER_DEFINE_CLASS(qpextract);
> +
> +static av_cold int init(AVFilterContext *ctx)
> +{
> +    QPExtractContext *s = ctx->priv;
> +
> +    if (s->stats_file_str) {
> +        if (!strcmp(s->stats_file_str, "-")) {
> +            s->stats_file = stdout;
> +        } else {
> +            s->stats_file = fopen(s->stats_file_str, "w");
> +            if (!s->stats_file) {
> +                int err = AVERROR(errno);
> +                char buf[128];
> +                av_strerror(err, buf, sizeof(buf));
> +                av_log(ctx, AV_LOG_ERROR, "Could not open log file %s:
> %s\n",
> +                       s->stats_file_str, buf);
> +                return err;
> +            }
> +        }
> +    }
> +    return 0;
> +}
> +
> +static av_cold int uninit(AVFilterContext *ctx) {
> +    return 0;
> +}
> +
> +static int filter_frame(AVFilterLink *inlink, AVFrame *in) {
> +    AVFilterContext *ctx = inlink->dst;
> +    AVFilterLink *outlink = ctx->outputs[0];
> +    QPExtractContext *s = ctx->priv;
> +    AVFrame *out = NULL;
> +
> +    if (ctx->is_disabled) {
> +        return ff_filter_frame(outlink, in);
> +    }
> +
> +    AVFrameSideData *sd = av_frame_get_side_data(in,
> AV_FRAME_DATA_QUANTIZATION_PARAMS);
> +
> +    if (!sd) {
> +        fprintf(s->stats_file, "no side data");
> +    }
> +    else {
> +        fprintf(s->stats_file, "yes side data");
> +    }
> +
> +    return ff_filter_frame(outlink, in);
> +}
> +
> +static const AVFilterPad qpextract_inputs[] = {
> +    {
> +        .name         = "default",
> +        .type         = AVMEDIA_TYPE_VIDEO,
> +        .filter_frame = filter_frame,
> +    },
> +    { NULL }
> +};
> +
> +static const AVFilterPad qpextract_outputs[] = {
> +    {
> +        .name          = "default",
> +        .type          = AVMEDIA_TYPE_VIDEO,
> +    },
> +    { NULL }
> +};
> +
> +AVFilter ff_vf_qpextract = {
> +    .name          = "extractqp",
> +    .description   = NULL_IF_CONFIG_SMALL("Extract quantization
> parameters."),
> +    .init          = init,
> +    .uninit        = uninit,
> +    .priv_size     = sizeof(QPExtractContext),
> +    .priv_class    = &qpextract_class,
> +    .inputs        = qpextract_inputs,
> +    .outputs       = qpextract_outputs,
> +};
> diff --git a/libavutil/Makefile b/libavutil/Makefile
> index 8a7a44e4b5..be1a9c3a9c 100644
> --- a/libavutil/Makefile
> +++ b/libavutil/Makefile
> @@ -60,6 +60,7 @@ HEADERS = adler32.h
>                \
>            pixdesc.h                                                     \
>            pixelutils.h                                                  \
>            pixfmt.h                                                      \
> +          quantization_params.h                                         \
>            random_seed.h                                                 \
>            rc4.h                                                         \
>            rational.h                                                    \
> @@ -140,6 +141,7 @@ OBJS = adler32.o
>                   \
>         parseutils.o                                                     \
>         pixdesc.o                                                        \
>         pixelutils.o                                                     \
> +       quantization_params.o                                            \
>         random_seed.o                                                    \
>         rational.o                                                       \
>         reverse.o                                                        \
> diff --git a/libavutil/quantization_params.c
> b/libavutil/quantization_params.c
> new file mode 100644
> index 0000000000..96ffd78dbb
> --- /dev/null
> +++ b/libavutil/quantization_params.c
> @@ -0,0 +1,28 @@
> +/*
> + * 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 "libavutil/quantization_params.h"
> +
> +/**
> + * Strings for names of enums, used by Filter
> + */
> +const char* const QP_NAMES_H264[] = {"qp"};
> +const char* const QP_NAMES_VP9[] = {"qydc", "qyac", "quvdc", "quvac",
> "qiydc", "qiyac",
> +                              "qiuvdc", "qiuvac"};
> +const char* const QP_NAMES_AV1[] = {"qydc", "qyac", "qudc", "quac",
> "qvdc", "qvac",
> +                              "qiydc", "qiyac", "qiudc", "qiuac",
> "qivdc", "qivac"};
> \ No newline at end of file
> diff --git a/libavutil/quantization_params.h
> b/libavutil/quantization_params.h
> new file mode 100644
> index 0000000000..e986abe842
> --- /dev/null
> +++ b/libavutil/quantization_params.h
> @@ -0,0 +1,98 @@
> +/*
> + * 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_QUANTIZATION_PARAMS_H
> +#define AVUTIL_QUANTIZATION_PARAMS_H
> +
> +/**
> + * Data structure for extracting Quantization Parameters codec independent
> + */
> +typedef struct AVQuantizationParams {
> +    /**
> +     * x and y coordinates of the block in pixels
> +     */
> +    int x, y;
> +    /**
> +     * width and height of the block in pixels
> +     */
> +    int w, h;
> +    /**
> +     * qp array, indexed by type according to
> +     * the enum corresponding to the codec
> +     * size depends on codec
> +     */
> +    int *type;
> +} AVQuantizationParams;
> +
> +/**
> + * For storing an array of AVQuantization parameters and its size
> + * To be used as AVFrameSideData
> + */
> +typedef struct AVQuantizationParamsArray {
> +    /**
> +     * AVQuantizationParams block array
> +     */
> +    AVQuantizationParams *qp_arr;
> +    /**
> +     * size of the array
> +     */
> +    int nb_blocks;
> +} AVQuantizationParamsArray;
> +
> +/**
> + * Enums for different codecs to store qp in the type array
> + * Each enum must have an array of strings describing each field
> + * used for output
> + */
> +extern const char* const QP_ENUM_NAMES_H264[];
> +enum QP_ARR_INDEXES_FOR_H264 {
> +        QP_H264 = 0,            // qp value
> +        QP_TYPE_ARR_SIZE_H264   // used for allocating memory
> +};
> +
> +extern const char* const QP_NAMES_VP9[];
> +enum QP_ARR_INDEXES_FOR_VP9 {
> +        QP_YDC_VP9 = 0,
> +        QP_YAC_VP9,
> +        QP_UVDC_VP9,
> +        QP_UVAC_VP9,
> +        QP_INDEX_YDC_VP9,
> +        QP_INDEX_YAC_VP9,
> +        QP_INDEX_UVDC_VP9,
> +        QP_INDEX_UVAC_VP9,
> +        QP_ARR_SIZE_VP9
> +};
> +
> +extern const char* const QP_NAMES_AV1[];
> +enum QP_ARR_INDEXES_FOR_AV1 {
> +        QP_YDC_AV1 = 0,
> +        QP_YAC_AV1,
> +        QP_UDC_AV1,
> +        QP_UAC_AV1,
> +        QP_VDC_AV1,
> +        QP_VAC_AV1,
> +        QP_INDEX_YDC_AV1,
> +        QP_INDEX_YAC_AV1,
> +        QP_INDEX_UDC_AV1,
> +        QP_INDEX_UAC_AV1,
> +        QP_INDEX_VDC_AV1,
> +        QP_INDEX_VAC_AV1,
> +        QP_ARR_SIZE_AV1
> +};
> +
> +#endif /* AVUTIL_QUANTIZATION_PARAMS_H */
> --
> 2.22.0.510.g264f2c817a-goog
>
>
Moritz Barsnick July 18, 2019, 3:07 p.m.
On Wed, Jul 17, 2019 at 16:18:11 -0700, Juan De León wrote:
> ---
>  libavfilter/vf_extractqp.c      | 116 ++++++++++++++++++++++++++++++++
>  libavutil/Makefile              |   2 +
>  libavutil/quantization_params.c |  28 ++++++++
>  libavutil/quantization_params.h |  98 +++++++++++++++++++++++++++
>  4 files changed, 244 insertions(+)
>  create mode 100644 libavfilter/vf_extractqp.c
>  create mode 100644 libavutil/quantization_params.c
>  create mode 100644 libavutil/quantization_params.h

Is this just an initial proposal and a proof of concept?

The side data which is supposed to come from the codecs isn't available
yet. I don't see AV_FRAME_DATA_QUANTIZATION_PARAMS defined anywhere. I
see no example of how to let the decoders detect the quantization and
insert that side data.

The "extractqp" filter apparently demonstrates how to detect
availability of this side data, i.e. shows how to call
av_frame_get_side_data(). It doesn't do anything useful at all though,
and it isn't included in the build (or documented).

Moritz
Lynne July 18, 2019, 4:53 p.m.
Jul 18, 2019, 12:25 AM by juandl-at-google.com@ffmpeg.org <mailto:juandl-at-google.com@ffmpeg.org>:

> For context
> https://docs.google.com/document/d/1WClt3EqhjwdGXhEw386O0wfn3IBQ1Ib-_5emVM1gbnA/edit?usp=sharing <https://docs.google.com/document/d/1WClt3EqhjwdGXhEw386O0wfn3IBQ1Ib-_5emVM1gbnA/edit?usp=sharing>
> Feel free to comment the doc.
>

This is meant for analyzers and debugging, so I don't think we should implement such tools.
Nicolas George July 19, 2019, 8 a.m.
Juan De León (12019-07-17):
> +    FILE *stats_file;

I do not judge whether this filter would be useful and should be
included, but if so, then I would appreciate that the output be done
using AVIO, so that it can go to any supported protocol.

Regards,
Moritz Barsnick July 19, 2019, 7:47 p.m.
On Fri, Jul 19, 2019 at 10:00:52 +0200, Nicolas George wrote:
> I do not judge whether this filter would be useful and should be
> included, but if so, then I would appreciate that the output be done
> using AVIO, so that it can go to any supported protocol.

The metadata filter has a nice example of how to use avio, incl.
mapping to stdout:

https://github.com/FFmpeg/FFmpeg/blob/f102a4efcef33014d414f9bf4492a04feab20c82/libavfilter/f_metadata.c#L250

I suppose this can been used as a reference.

Moritz
=?UTF-8?q?Juan=20De=20Le=C3=B3n?= July 22, 2019, 7:03 p.m.
On Fri, Jul 19, 2019 at 12:47 PM Moritz Barsnick <barsnick@gmx.net> wrote:

> On Fri, Jul 19, 2019 at 10:00:52 +0200, Nicolas George wrote:
> > I do not judge whether this filter would be useful and should be
> > included, but if so, then I would appreciate that the output be done
> > using AVIO, so that it can go to any supported protocol.
>
> The metadata filter has a nice example of how to use avio, incl.
> mapping to stdout:
>
>
> https://github.com/FFmpeg/FFmpeg/blob/f102a4efcef33014d414f9bf4492a04feab20c82/libavfilter/f_metadata.c#L250
>
> I suppose this can been used as a reference.
>
> Moritz
> _______________________________________________
> 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".


Thanks, I will update the filter to use avio.
Pinging the thread.
Lynne July 22, 2019, 7:17 p.m.
Jul 22, 2019, 8:03 PM by juandl-at-google.com@ffmpeg.org:

> On Fri, Jul 19, 2019 at 12:47 PM Moritz Barsnick <barsnick@gmx.net> wrote:
>
>> On Fri, Jul 19, 2019 at 10:00:52 +0200, Nicolas George wrote:
>> > I do not judge whether this filter would be useful and should be
>> > included, but if so, then I would appreciate that the output be done
>> > using AVIO, so that it can go to any supported protocol.
>>
>> The metadata filter has a nice example of how to use avio, incl.
>> mapping to stdout:
>>
>>
>> https://github.com/FFmpeg/FFmpeg/blob/f102a4efcef33014d414f9bf4492a04feab20c82/libavfilter/f_metadata.c#L250
>>
>> I suppose this can been used as a reference.
>>
>> Moritz
>> _______________________________________________
>> 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".
>>
>
>
> Thanks, I will update the filter to use avio.
> Pinging the thread.
>

I've explained why this is a bad idea and why you should maintain it internally.
You can't hack a decoder in any nice and performant way for it to output data to an analyzer.
=?UTF-8?q?Juan=20De=20Le=C3=B3n?= July 22, 2019, 11:23 p.m.
> On Mon, Jul 22, 2019 at 12:17 PM Lynne <dev@lynne.ee> wrote:
> You can't hack a decoder in any nice and performant way for it to output
data to an analyzer.
Hi, Lynne
I hear your concern about the decoder performance.
I believe that the way we would like to modify the decoder should not
affect its performance, since
AV_FRAME_QUANTIZATION_PARAMS will be disabled by default; the extraction is
done optionally with a flag.
I would be glad to verify that by running tests and measuring performance
with and without my changes.
If you have in mind any tests I should run, please let me know.

> I've explained why this is a bad idea and why you should maintain
it internally.
FFmpeg already has a lot of analyzing tools, I disagree that this change
does not belong to ffmpeg.
Lynne July 23, 2019, 2:52 a.m.
Jul 23, 2019, 12:23 AM by juandl-at-google.com@ffmpeg.org:

>> On Mon, Jul 22, 2019 at 12:17 PM Lynne <dev@lynne.ee> wrote:
>> You can't hack a decoder in any nice and performant way for it to output
>>
> data to an analyzer.
> Hi, Lynne
> I hear your concern about the decoder performance.
> I believe that the way we would like to modify the decoder should not
> affect its performance, since
> AV_FRAME_QUANTIZATION_PARAMS will be disabled by default; the extraction is
> done optionally with a flag.
> I would be glad to verify that by running tests and measuring performance
> with and without my changes.
> If you have in mind any tests I should run, please let me know.
>
>> I've explained why this is a bad idea and why you should maintain
>>
> it internally.
> FFmpeg already has a lot of analyzing tools, I disagree that this change
> does not belong to ffmpeg.
>

Switches like these only make code slower, not faster. And they don't erase code either.
I'll not accept this API without a decoder patch either.
=?UTF-8?q?Juan=20De=20Le=C3=B3n?= July 25, 2019, 5:58 p.m.
I submitted another patch in a new email thread addressing your concerns,
apologies for the confusion.
The subject is "[PATCH] Extract QP from h264 encoded videos".
Here is the link to the archive
http://ffmpeg.org/pipermail/ffmpeg-devel/2019-July/247037.html

Patch hide | download patch | download mbox

diff --git a/libavfilter/vf_extractqp.c b/libavfilter/vf_extractqp.c
new file mode 100644
index 0000000000..4332012cc4
--- /dev/null
+++ b/libavfilter/vf_extractqp.c
@@ -0,0 +1,116 @@ 
+/*
+ * 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 "libavutil/frame.h"
+#include "libavutil/opt.h"
+#include "libavutil/quantization_params.h"
+#include "libavfilter/avfilter.h"
+#include "libavfilter/internal.h"
+
+typedef struct QPExtractContext {
+    const AVClass *class;
+    FILE *stats_file;
+    char *stats_file_str;
+} QPExtractContext;
+
+#define OFFSET(x) offsetof(QPExtractContext, x)
+#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
+
+static const AVOption qpextract_options[] = {
+    {"stats_file", "Set file to store QP information", OFFSET(stats_file_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
+    {"f",          "Set file to store QP information", OFFSET(stats_file_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
+    { NULL }
+};
+
+AVFILTER_DEFINE_CLASS(qpextract);
+
+static av_cold int init(AVFilterContext *ctx)
+{
+    QPExtractContext *s = ctx->priv;
+
+    if (s->stats_file_str) {
+        if (!strcmp(s->stats_file_str, "-")) {
+            s->stats_file = stdout;
+        } else {
+            s->stats_file = fopen(s->stats_file_str, "w");
+            if (!s->stats_file) {
+                int err = AVERROR(errno);
+                char buf[128];
+                av_strerror(err, buf, sizeof(buf));
+                av_log(ctx, AV_LOG_ERROR, "Could not open log file %s: %s\n",
+                       s->stats_file_str, buf);
+                return err;
+            }
+        }
+    }
+    return 0;
+}
+
+static av_cold int uninit(AVFilterContext *ctx) {
+    return 0;
+}
+
+static int filter_frame(AVFilterLink *inlink, AVFrame *in) {
+    AVFilterContext *ctx = inlink->dst;
+    AVFilterLink *outlink = ctx->outputs[0];
+    QPExtractContext *s = ctx->priv;
+    AVFrame *out = NULL;
+
+    if (ctx->is_disabled) {
+        return ff_filter_frame(outlink, in);
+    }
+
+    AVFrameSideData *sd = av_frame_get_side_data(in, AV_FRAME_DATA_QUANTIZATION_PARAMS);
+
+    if (!sd) {
+        fprintf(s->stats_file, "no side data");
+    }
+    else {
+        fprintf(s->stats_file, "yes side data");
+    }
+
+    return ff_filter_frame(outlink, in);
+}
+
+static const AVFilterPad qpextract_inputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .filter_frame = filter_frame,
+    },
+    { NULL }
+};
+
+static const AVFilterPad qpextract_outputs[] = {
+    {
+        .name          = "default",
+        .type          = AVMEDIA_TYPE_VIDEO,
+    },
+    { NULL }
+};
+
+AVFilter ff_vf_qpextract = {
+    .name          = "extractqp",
+    .description   = NULL_IF_CONFIG_SMALL("Extract quantization parameters."),
+    .init          = init,
+    .uninit        = uninit,
+    .priv_size     = sizeof(QPExtractContext),
+    .priv_class    = &qpextract_class,
+    .inputs        = qpextract_inputs,
+    .outputs       = qpextract_outputs,
+};
diff --git a/libavutil/Makefile b/libavutil/Makefile
index 8a7a44e4b5..be1a9c3a9c 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -60,6 +60,7 @@  HEADERS = adler32.h                                                     \
           pixdesc.h                                                     \
           pixelutils.h                                                  \
           pixfmt.h                                                      \
+          quantization_params.h                                         \
           random_seed.h                                                 \
           rc4.h                                                         \
           rational.h                                                    \
@@ -140,6 +141,7 @@  OBJS = adler32.o                                                        \
        parseutils.o                                                     \
        pixdesc.o                                                        \
        pixelutils.o                                                     \
+       quantization_params.o                                            \
        random_seed.o                                                    \
        rational.o                                                       \
        reverse.o                                                        \
diff --git a/libavutil/quantization_params.c b/libavutil/quantization_params.c
new file mode 100644
index 0000000000..96ffd78dbb
--- /dev/null
+++ b/libavutil/quantization_params.c
@@ -0,0 +1,28 @@ 
+/*
+ * 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 "libavutil/quantization_params.h"
+
+/**
+ * Strings for names of enums, used by Filter
+ */
+const char* const QP_NAMES_H264[] = {"qp"};
+const char* const QP_NAMES_VP9[] = {"qydc", "qyac", "quvdc", "quvac", "qiydc", "qiyac",
+                              "qiuvdc", "qiuvac"};
+const char* const QP_NAMES_AV1[] = {"qydc", "qyac", "qudc", "quac", "qvdc", "qvac",
+                              "qiydc", "qiyac", "qiudc", "qiuac", "qivdc", "qivac"};
\ No newline at end of file
diff --git a/libavutil/quantization_params.h b/libavutil/quantization_params.h
new file mode 100644
index 0000000000..e986abe842
--- /dev/null
+++ b/libavutil/quantization_params.h
@@ -0,0 +1,98 @@ 
+/*
+ * 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_QUANTIZATION_PARAMS_H
+#define AVUTIL_QUANTIZATION_PARAMS_H
+
+/**
+ * Data structure for extracting Quantization Parameters codec independent
+ */
+typedef struct AVQuantizationParams {
+    /**
+     * x and y coordinates of the block in pixels
+     */
+    int x, y;
+    /**
+     * width and height of the block in pixels
+     */
+    int w, h;
+    /**
+     * qp array, indexed by type according to
+     * the enum corresponding to the codec
+     * size depends on codec
+     */
+    int *type;
+} AVQuantizationParams;
+
+/**
+ * For storing an array of AVQuantization parameters and its size
+ * To be used as AVFrameSideData
+ */
+typedef struct AVQuantizationParamsArray {
+    /**
+     * AVQuantizationParams block array
+     */
+    AVQuantizationParams *qp_arr;
+    /**
+     * size of the array
+     */
+    int nb_blocks;
+} AVQuantizationParamsArray;
+
+/**
+ * Enums for different codecs to store qp in the type array
+ * Each enum must have an array of strings describing each field
+ * used for output
+ */
+extern const char* const QP_ENUM_NAMES_H264[];
+enum QP_ARR_INDEXES_FOR_H264 {
+        QP_H264 = 0,            // qp value
+        QP_TYPE_ARR_SIZE_H264   // used for allocating memory
+};
+
+extern const char* const QP_NAMES_VP9[];
+enum QP_ARR_INDEXES_FOR_VP9 {
+        QP_YDC_VP9 = 0,
+        QP_YAC_VP9,
+        QP_UVDC_VP9,
+        QP_UVAC_VP9,
+        QP_INDEX_YDC_VP9,
+        QP_INDEX_YAC_VP9,
+        QP_INDEX_UVDC_VP9,
+        QP_INDEX_UVAC_VP9,
+        QP_ARR_SIZE_VP9
+};
+
+extern const char* const QP_NAMES_AV1[];
+enum QP_ARR_INDEXES_FOR_AV1 {
+        QP_YDC_AV1 = 0,
+        QP_YAC_AV1,
+        QP_UDC_AV1,
+        QP_UAC_AV1,
+        QP_VDC_AV1,
+        QP_VAC_AV1,
+        QP_INDEX_YDC_AV1,
+        QP_INDEX_YAC_AV1,
+        QP_INDEX_UDC_AV1,
+        QP_INDEX_UAC_AV1,
+        QP_INDEX_VDC_AV1,
+        QP_INDEX_VAC_AV1,
+        QP_ARR_SIZE_AV1
+};
+
+#endif /* AVUTIL_QUANTIZATION_PARAMS_H */