[FFmpeg-devel] [PATCH v2 1/3] libavutil: introduce AVFilmGrainParams side data

James Almer jamrial at gmail.com
Thu Nov 12 20:46:50 EET 2020


On 11/12/2020 2:42 PM, Lynne wrote:
> This patch introduces a new frame side data type AVFilmGrainParams for use
> with video codecs which are able to use it.
> 
> It is generalized rather than being AV1 specific as AV2 is expected to carry
> the same data, as well as the fact there already exist rarely-used specifications
> for both H.264 and HEVC.
> 
> Patch attached.

> From 522e3a80f44129c98f0c564d44815dbe6a740568 Mon Sep 17 00:00:00 2001
> From: Lynne <dev at lynne.ee>
> Date: Thu, 12 Nov 2020 12:44:30 +0100
> Subject: [PATCH v2 1/3] libavutil: introduce AVFilmGrainParams side data
> 
> This patch introduces a new frame side data type AVFilmGrainParams for use
> with video codecs which are able to use it.
> 
> It is generalized rather than being AV1 specific as AV2 is expected to carry
> the same data, as well as the fact there already exist rarely-used specifications
> for both H.264 and HEVC.
> ---
>  doc/APIchanges                |   4 +
>  libavutil/Makefile            |   2 +
>  libavutil/film_grain_params.c |  42 +++++++++
>  libavutil/film_grain_params.h | 159 ++++++++++++++++++++++++++++++++++
>  libavutil/frame.c             |   1 +
>  libavutil/frame.h             |   6 ++
>  libavutil/version.h           |   2 +-
>  7 files changed, 215 insertions(+), 1 deletion(-)
>  create mode 100644 libavutil/film_grain_params.c
>  create mode 100644 libavutil/film_grain_params.h
> 
> diff --git a/doc/APIchanges b/doc/APIchanges
> index b70c78a483..41248724d9 100644
> --- a/doc/APIchanges
> +++ b/doc/APIchanges
> @@ -15,6 +15,10 @@ libavutil:     2017-10-21
>  
>  API changes, most recent first:
>  
> +2020-xx-xx - xxxxxxxxxx - lavu 56.61.100 - film_grain_params.h
> +  Adds a new API for extracting codec film grain parameters as side data.
> +  Adds a new AVFrameSideDataType entry AV_FRAME_DATA_FILM_GRAIN_PARAMS for it.
> +
>  2020-xx-xx - xxxxxxxxxx - lavf 58.64.100 - avformat.h
>    Add AVSTREAM_EVENT_FLAG_NEW_PACKETS.
>  
> diff --git a/libavutil/Makefile b/libavutil/Makefile
> index 9b08372eb2..27bafe9e12 100644
> --- a/libavutil/Makefile
> +++ b/libavutil/Makefile
> @@ -84,6 +84,7 @@ HEADERS = adler32.h                                                     \
>            xtea.h                                                        \
>            tea.h                                                         \
>            tx.h                                                          \
> +          film_grain_params.h                                           \
>  
>  HEADERS-$(CONFIG_LZO)                   += lzo.h
>  
> @@ -170,6 +171,7 @@ OBJS = adler32.o                                                        \
>         tx_double.o                                                      \
>         tx_int32.o                                                       \
>         video_enc_params.o                                               \
> +       film_grain_params.o                                              \
>  
>  
>  OBJS-$(CONFIG_CUDA)                     += hwcontext_cuda.o
> diff --git a/libavutil/film_grain_params.c b/libavutil/film_grain_params.c
> new file mode 100644
> index 0000000000..930d23c7fe
> --- /dev/null
> +++ b/libavutil/film_grain_params.c
> @@ -0,0 +1,42 @@
> +/**
> + * 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 "film_grain_params.h"
> +
> +AVFilmGrainParams *av_film_grain_params_alloc(size_t *size)
> +{
> +    AVFilmGrainParams *params = av_mallocz(sizeof(AVFilmGrainParams));
> +
> +    if (size)
> +        *size = sizeof(*params);
> +
> +    return params;
> +}
> +
> +AVFilmGrainParams *av_film_grain_params_create_side_data(AVFrame *frame)
> +{
> +    AVFrameSideData *side_data = av_frame_new_side_data(frame,
> +                                                        AV_FRAME_DATA_FILM_GRAIN_PARAMS,
> +                                                        sizeof(AVFilmGrainParams));
> +    if (!side_data)
> +        return NULL;
> +
> +    memset(side_data->data, 0, sizeof(AVFilmGrainParams));
> +
> +    return (AVFilmGrainParams *)side_data->data;
> +}
> diff --git a/libavutil/film_grain_params.h b/libavutil/film_grain_params.h
> new file mode 100644
> index 0000000000..ba20fe7fa6
> --- /dev/null
> +++ b/libavutil/film_grain_params.h
> @@ -0,0 +1,159 @@
> +/*
> + * Copyright (c) 2016 Neil Birkbeck <neil.birkbeck at gmail.com>

Copy paste mistake?

> + *
> + * 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_FILM_GRAIN_PARAMS_H
> +#define AVUTIL_FILM_GRAIN_PARAMS_H
> +
> +#include "frame.h"
> +
> +enum AVFilmGrainParamsType {
> +    AV_FILM_GRAM_PARAMS_NONE = 0,
> +
> +    /**
> +     * The union is valid when interpreted as AVFilmGrainAOMParams (codec.aom)
> +     */
> +    AV_FILM_GRAM_PARAMS_AV1,
> +};
> +
> +typedef struct AVFilmGrainAOMParams {

If you believe AV2 will have a compatible implementation, then this name 
is fine.

> +    /**
> +     * Number of points for the piecewise linear scaling function of the
> +     * luma plane.
> +     */
> +    int num_y_points;
> +
> +    /**
> +     * Piecewise scaling function values and scale for each point.
> +     */
> +    uint8_t y_points[14][2 /* value, scaling */];
> +
> +    /**
> +     * Signals whether to derive the chroma scaling function from the luma.
> +     * Not equivalent to copying the luma values and scales.
> +     */
> +    int chroma_scaling_from_luma;
> +
> +    /**
> +     * If chroma_scaling_from_luma is set to 0, signals the chroma scaling
> +     * function parameters.
> +     */
> +    int num_uv_points[2];
> +    uint8_t uv_points[2][10][2 /* value, scaling */];
> +
> +    /**
> +     * Specifies the shift applied to the chroma components. For AV1, its within
> +     * [8; 11] and determines the range and quantization of the film grain.
> +     */
> +    int scaling_shift;
> +
> +    /**
> +     * Specifies the auto-regression coefficients for both luma and chroma.
> +     */
> +    int ar_coeff_lag;
> +
> +    /**
> +     * Luma auto-regression coefficients.
> +     */
> +    int8_t ar_coeffs_y[24];
> +
> +    /**
> +     * Chroma auto-regression coefficients. Padded to help with SIMD, last
> +     * 3 values of each chroma coeff are not used.
> +     */
> +    int8_t ar_coeffs_uv[2][25 + 3 /* padding for alignment purposes */];

Shouldn't the compiler take care of alignment?

> +
> +    /**
> +     * Specifies the range of the auto-regressive coefficients. Values of 6,
> +     * 7, 8 and so on represent a range of [-2, 2), [-1, 1), [-0.5, 0.5) and
> +     * so on. For AV1 must be between 6 and 9.
> +     */
> +    uint64_t ar_coeff_shift;

Why uint64_t? Sounds like it may be excessive for this.

> +
> +    /**
> +     * Signals the down shift applied to the generated gaussian numbers during
> +     * synthesis.
> +     */
> +    int grain_scale_shift;
> +
> +    /**
> +     * Specifies the luma/chroma multipliers for the index to the component
> +     * scaling function.
> +     */
> +    int uv_mult[2];
> +    int uv_mult_luma[2];

int8_t, like ar_coeffs_y. Or could AV2 increase the range considerably?

> +
> +    /**
> +     * Offset used for component scaling function. For AV1 its a 9-bit value
> +     * with a range [-256, 255] */
> +    int uv_offset[2];

int16_t.

> +
> +    /**
> +     * Signals whether to overlap film grain blocks.
> +     */
> +    int overlap_flag;
> +} AVFilmGrainAOMParams;
> +
> +typedef struct AVFilmGrainParams {
> +    /**
> +     * Specifies the codec for which this structure is valid.
> +     */
> +    enum AVFilmGrainParamsType type;
> +
> +    /**
> +     * Seed to use for the synthesis process, if the codec allows for it.
> +     */
> +    uint32_t seed;

Maybe uint64_t, just in case. This is meant to apply to all implementations.

Looks good otherwise, but probably wait for comments from other devs.

> +
> +    /**
> +     * Signals to clip to limited color levels after film grain application
> +     * for AV1.
> +     */
> +    int limit_output_range;
> +
> +    /**
> +     * Additional fields may be added both here and in any structure included.
> +     * If a codec's film grain structure differs slightly over another
> +     * codec's, fields within may change meaning depending on the type.
> +     */
> +    union {
> +        AVFilmGrainAOMParams aom;
> +    } codec;
> +} AVFilmGrainParams;
> +
> +/**
> + * Allocate an AVFilmGrainParams structure and set its fields to
> + * default values. The resulting struct can be freed using av_freep().
> + * If size is not NULL it will be set to the number of bytes allocated.
> + *
> + * @return An AVFilmGrainParams filled with default values or NULL
> + *         on failure.
> + */
> +AVFilmGrainParams *av_film_grain_params_alloc(size_t *size);
> +
> +/**
> + * Allocate a complete AVFilmGrainParams and add it to the frame.
> + *
> + * @param frame The frame which side data is added to.
> + *
> + * @return The AVFilmGrainParams structure to be filled by caller.
> + */
> +AVFilmGrainParams *av_film_grain_params_create_side_data(AVFrame *frame);
> +
> +#endif /* AVUTIL_FILM_GRAIN_PARAMS_H */
> diff --git a/libavutil/frame.c b/libavutil/frame.c
> index 3ab1aa3242..668a0e9e3c 100644
> --- a/libavutil/frame.c
> +++ b/libavutil/frame.c
> @@ -864,6 +864,7 @@ const char *av_frame_side_data_name(enum AVFrameSideDataType type)
>      case AV_FRAME_DATA_REGIONS_OF_INTEREST: return "Regions Of Interest";
>      case AV_FRAME_DATA_VIDEO_ENC_PARAMS:            return "Video encoding parameters";
>      case AV_FRAME_DATA_SEI_UNREGISTERED:            return "H.26[45] User Data Unregistered SEI message";
> +    case AV_FRAME_DATA_FILM_GRAIN_PARAMS:           return "Film grain parameters";
>      }
>      return NULL;
>  }
> diff --git a/libavutil/frame.h b/libavutil/frame.h
> index 3bd240fc97..392315f40f 100644
> --- a/libavutil/frame.h
> +++ b/libavutil/frame.h
> @@ -192,6 +192,12 @@ enum AVFrameSideDataType {
>       * uuid_iso_iec_11578 followed by AVFrameSideData.size - 16 bytes of user_data_payload_byte.
>       */
>      AV_FRAME_DATA_SEI_UNREGISTERED,
> +
> +    /**
> +     * Film grain parameters for a frame, described by AVFilmGrainParameters.
> +     * Must be present for every frame which should have film grain applied.
> +     */
> +    AV_FRAME_DATA_FILM_GRAIN_PARAMS,
>  };
>  
>  enum AVActiveFormatDescription {
> diff --git a/libavutil/version.h b/libavutil/version.h
> index 1aca823650..55a59d6c58 100644
> --- a/libavutil/version.h
> +++ b/libavutil/version.h
> @@ -79,7 +79,7 @@
>   */
>  
>  #define LIBAVUTIL_VERSION_MAJOR  56
> -#define LIBAVUTIL_VERSION_MINOR  60
> +#define LIBAVUTIL_VERSION_MINOR  61
>  #define LIBAVUTIL_VERSION_MICRO 100
>  
>  #define LIBAVUTIL_VERSION_INT   AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
> -- 
> 2.29.2
> 


More information about the ffmpeg-devel mailing list