diff mbox

[FFmpeg-devel] libavutil: AVEncodeInfo data structures and AV_FRAME_DATA_ENCODE_INFO AVFrameSideDataType

Message ID 20190809173803.82156-1-juandl@google.com
State Superseded
Headers show

Commit Message

=?UTF-8?q?Juan=20De=20Le=C3=B3n?= Aug. 9, 2019, 5:38 p.m. UTC
AVEncodeInfoFrame data structure to store as AVFrameSideData of type AV_FRAME_DATA_ENCODE_INFO.
The structure stores quantization index for each plane, DC/AC deltas for luma and chroma planes, and an array of AVEncodeInfoBlock struct denoting position, size, and delta quantizer for each block in the frame.
Can be extended to support extraction of other block information.

Signed-off-by: Juan De León <juandl@google.com>
---
fixed a typo in frame.h comment
 libavutil/Makefile      |  2 +
 libavutil/encode_info.c | 67 +++++++++++++++++++++++++++++++
 libavutil/encode_info.h | 87 +++++++++++++++++++++++++++++++++++++++++
 libavutil/frame.c       |  1 +
 libavutil/frame.h       |  7 ++++
 5 files changed, 164 insertions(+)
 create mode 100644 libavutil/encode_info.c
 create mode 100644 libavutil/encode_info.h

Comments

James Almer Aug. 9, 2019, 5:52 p.m. UTC | #1
On 8/9/2019 2:38 PM, Juan De León wrote:
> AVEncodeInfoFrame data structure to store as AVFrameSideData of type AV_FRAME_DATA_ENCODE_INFO.
> The structure stores quantization index for each plane, DC/AC deltas for luma and chroma planes, and an array of AVEncodeInfoBlock struct denoting position, size, and delta quantizer for each block in the frame.
> Can be extended to support extraction of other block information.
> 
> Signed-off-by: Juan De León <juandl@google.com>
> ---
> fixed a typo in frame.h comment
>  libavutil/Makefile      |  2 +
>  libavutil/encode_info.c | 67 +++++++++++++++++++++++++++++++
>  libavutil/encode_info.h | 87 +++++++++++++++++++++++++++++++++++++++++
>  libavutil/frame.c       |  1 +
>  libavutil/frame.h       |  7 ++++
>  5 files changed, 164 insertions(+)
>  create mode 100644 libavutil/encode_info.c
>  create mode 100644 libavutil/encode_info.h
> 
> diff --git a/libavutil/Makefile b/libavutil/Makefile
> index 57e6e3d7e8..37cfb099e9 100644
> --- a/libavutil/Makefile
> +++ b/libavutil/Makefile
> @@ -24,6 +24,7 @@ HEADERS = adler32.h                                                     \
>            dict.h                                                        \
>            display.h                                                     \
>            downmix_info.h                                                \
> +          encode_info.h                                                 \
>            encryption_info.h                                             \
>            error.h                                                       \
>            eval.h                                                        \
> @@ -111,6 +112,7 @@ OBJS = adler32.o                                                        \
>         dict.o                                                           \
>         display.o                                                        \
>         downmix_info.o                                                   \
> +       encode_info.o                                                    \
>         encryption_info.o                                                \
>         error.o                                                          \
>         eval.o                                                           \
> diff --git a/libavutil/encode_info.c b/libavutil/encode_info.c
> new file mode 100644
> index 0000000000..68c30af4d7
> --- /dev/null
> +++ b/libavutil/encode_info.c
> @@ -0,0 +1,67 @@
> +/*
> + * 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/encode_info.h"
> +#include "libavutil/mem.h"
> +
> +static int init_encode_info_data(AVEncodeInfoFrame *ptr, int nb_blocks) {
> +    ptr->nb_blocks = nb_blocks;
> +    ptr->dc_q = ptr->ac_q = -1;
> +    ptr->dc_chroma_q = ptr->ac_chroma_q = -1;
> +
> +    for(int i=0;i<AV_NUM_DATA_POINTERS;i++)
> +        ptr->plane_q[i] = -1;
> +
> +    return 0;
> +}
> +
> +AVEncodeInfoFrame *av_encode_info_alloc(int nb_blocks)
> +{
> +    AVEncodeInfoFrame *ptr;
> +    size_t size = sizeof(AVEncodeInfoFrame) + sizeof(AVEncodeInfoBlock)*nb_blocks;
> +
> +    if (nb_blocks < 0 || size >= INT_MAX)
> +        return NULL;
> +
> +    ptr = av_mallocz(size);
> +    if (!ptr)
> +        return NULL;
> +
> +    init_encode_info_data(ptr, nb_blocks);
> +
> +    return ptr;
> +}
> +
> +AVEncodeInfoFrame *av_encode_info_create_side_data(AVFrame *frame, int nb_blocks)
> +{
> +    size_t size = sizeof(AVEncodeInfoFrame) + sizeof(AVEncodeInfoBlock)*nb_blocks;
> +
> +    if (nb_blocks < 0 || size >= INT_MAX)
> +        return NULL;
> +
> +    AVFrameSideData *sd = av_frame_new_side_data(frame,
> +                                                 AV_FRAME_DATA_ENCODE_INFO,
> +                                                 size);
> +    if (!sd)
> +        return NULL;
> +
> +    memset(sd->data, 0, size);
> +    init_encode_info_data((AVEncodeInfoFrame*)sd->data, nb_blocks);
> +
> +    return (AVEncodeInfoFrame*)sd->data;
> +}
> diff --git a/libavutil/encode_info.h b/libavutil/encode_info.h
> new file mode 100644
> index 0000000000..cbe8be2891
> --- /dev/null
> +++ b/libavutil/encode_info.h
> @@ -0,0 +1,87 @@
> +/*
> + * 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_ENCODE_INFO_H
> +#define AVUTIL_ENCODE_INFO_H
> +
> +#include "libavutil/frame.h"
> +
> +/**
> + * Data structure for extracting block data stored in an array in AVEncodeInfoFrame
> + */
> +typedef struct AVEncodeInfoBlock{
> +    /**
> +     * Distance in luma pixels from the top-left corner of the visible frame
> +     * to the top-left corner of the block.
> +     * Can be negative if top/right padding is present on the coded frame.
> +     */
> +    int src_x, src_y;
> +    /**
> +     * Width and height of the block in luma pixels
> +     */
> +    int w, h;
> +    /**
> +     * Delta quantization index for the block
> +     */
> +    int delta_q;
> +
> +    uint8_t reserved[128];
> +} AVEncodeInfoBlock;
> +
> +/**
> + * Frame encoding info, used as AVFrameSideData
> + */
> +typedef struct AVEncodeInfoFrame {
> +    /**
> +     * Number of blocks in the array
> +     */
> +    int nb_blocks;
> +    /**
> +     * Base plane quantizer for the frame, set to -1 when value is unsupported
> +     */
> +    int plane_q[AV_NUM_DATA_POINTERS];
> +    /**
> +     * DC/AC quantizer index delta, set to -1 when value is value unsupported.
> +     */
> +    int ac_q, dc_q;
> +    /**
> +     * DC/AC chroma quantizer index delta, set to -1 when value is value unsupported.
> +     */
> +    int ac_chroma_q, dc_chroma_q;
> +
> +    uint8_t reserved[256];
> +
> +    AVEncodeInfoBlock blocks[];

Flexible array members will break compatibility with C++ projects.

> +} AVEncodeInfoFrame;
> +
> +/**
> + * Allocates memory for AVEncodeInfoFrame plus an array of
> + * {@code nb_blocks} AVEncodeInfoBlock and initializes the variables.
> + * Can be freed with a normal av_free() call.
> + */
> +AVEncodeInfoFrame *av_encode_info_alloc(int nb_blocks);
> +
> +/**
> + * Allocates memory for AVEncodeInfoFrame plus an array of
> + * {@code nb_blocks} AVEncodeInfoBlock in the given AVFrame {@code frame}
> + * as AVFrameSideData of type AV_FRAME_DATA_ENCODE_INFO
> + * and initializes the variables
> + */
> +AVEncodeInfoFrame *av_encode_info_create_side_data(AVFrame *frame, int nb_blocks);
> +
> +#endif /* AVUTIL_ENCODE_INFO_H */
> diff --git a/libavutil/frame.c b/libavutil/frame.c
> index dcf1fc3d17..c5ec6d13ca 100644
> --- a/libavutil/frame.c
> +++ b/libavutil/frame.c
> @@ -842,6 +842,7 @@ const char *av_frame_side_data_name(enum AVFrameSideDataType type)
>  #endif
>      case AV_FRAME_DATA_DYNAMIC_HDR_PLUS: return "HDR Dynamic Metadata SMPTE2094-40 (HDR10+)";
>      case AV_FRAME_DATA_REGIONS_OF_INTEREST: return "Regions Of Interest";
> +    case AV_FRAME_DATA_ENCODE_INFO:                  return "AVEncodeInfo";
>      }
>      return NULL;
>  }
> diff --git a/libavutil/frame.h b/libavutil/frame.h
> index 5d3231e7bb..f2865b6146 100644
> --- a/libavutil/frame.h
> +++ b/libavutil/frame.h
> @@ -179,6 +179,13 @@ enum AVFrameSideDataType {
>       * array element is implied by AVFrameSideData.size / AVRegionOfInterest.self_size.
>       */
>      AV_FRAME_DATA_REGIONS_OF_INTEREST,
> +    /**
> +     * Extract block data from supported decoders. The data is stored in
> +     * AVEncodeInfoFrame type, which contains an array of AVEncodeInfoBLock
> +     * described in libavuitl/encode_info.h
> +     * Can be allocated in the frame directly with av_encode_info_create_side_data().
> +     */
> +    AV_FRAME_DATA_ENCODE_INFO,
>  };
>  
>  enum AVActiveFormatDescription {

No comments about the actual feature. Will leave that to other developers.
Hendrik Leppkes Aug. 9, 2019, 5:58 p.m. UTC | #2
On Fri, Aug 9, 2019 at 7:52 PM James Almer <jamrial@gmail.com> wrote:
>
> On 8/9/2019 2:38 PM, Juan De León wrote:
> > AVEncodeInfoFrame data structure to store as AVFrameSideData of type AV_FRAME_DATA_ENCODE_INFO.
> > The structure stores quantization index for each plane, DC/AC deltas for luma and chroma planes, and an array of AVEncodeInfoBlock struct denoting position, size, and delta quantizer for each block in the frame.
> > Can be extended to support extraction of other block information.
> >
> > Signed-off-by: Juan De León <juandl@google.com>
> > ---
> > fixed a typo in frame.h comment
> >  libavutil/Makefile      |  2 +
> >  libavutil/encode_info.c | 67 +++++++++++++++++++++++++++++++
> >  libavutil/encode_info.h | 87 +++++++++++++++++++++++++++++++++++++++++
> >  libavutil/frame.c       |  1 +
> >  libavutil/frame.h       |  7 ++++
> >  5 files changed, 164 insertions(+)
> >  create mode 100644 libavutil/encode_info.c
> >  create mode 100644 libavutil/encode_info.h
> >
> > diff --git a/libavutil/Makefile b/libavutil/Makefile
> > index 57e6e3d7e8..37cfb099e9 100644
> > --- a/libavutil/Makefile
> > +++ b/libavutil/Makefile
> > @@ -24,6 +24,7 @@ HEADERS = adler32.h                                                     \
> >            dict.h                                                        \
> >            display.h                                                     \
> >            downmix_info.h                                                \
> > +          encode_info.h                                                 \
> >            encryption_info.h                                             \
> >            error.h                                                       \
> >            eval.h                                                        \
> > @@ -111,6 +112,7 @@ OBJS = adler32.o                                                        \
> >         dict.o                                                           \
> >         display.o                                                        \
> >         downmix_info.o                                                   \
> > +       encode_info.o                                                    \
> >         encryption_info.o                                                \
> >         error.o                                                          \
> >         eval.o                                                           \
> > diff --git a/libavutil/encode_info.c b/libavutil/encode_info.c
> > new file mode 100644
> > index 0000000000..68c30af4d7
> > --- /dev/null
> > +++ b/libavutil/encode_info.c
> > @@ -0,0 +1,67 @@
> > +/*
> > + * 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/encode_info.h"
> > +#include "libavutil/mem.h"
> > +
> > +static int init_encode_info_data(AVEncodeInfoFrame *ptr, int nb_blocks) {
> > +    ptr->nb_blocks = nb_blocks;
> > +    ptr->dc_q = ptr->ac_q = -1;
> > +    ptr->dc_chroma_q = ptr->ac_chroma_q = -1;
> > +
> > +    for(int i=0;i<AV_NUM_DATA_POINTERS;i++)
> > +        ptr->plane_q[i] = -1;
> > +
> > +    return 0;
> > +}
> > +
> > +AVEncodeInfoFrame *av_encode_info_alloc(int nb_blocks)
> > +{
> > +    AVEncodeInfoFrame *ptr;
> > +    size_t size = sizeof(AVEncodeInfoFrame) + sizeof(AVEncodeInfoBlock)*nb_blocks;
> > +
> > +    if (nb_blocks < 0 || size >= INT_MAX)
> > +        return NULL;
> > +
> > +    ptr = av_mallocz(size);
> > +    if (!ptr)
> > +        return NULL;
> > +
> > +    init_encode_info_data(ptr, nb_blocks);
> > +
> > +    return ptr;
> > +}
> > +
> > +AVEncodeInfoFrame *av_encode_info_create_side_data(AVFrame *frame, int nb_blocks)
> > +{
> > +    size_t size = sizeof(AVEncodeInfoFrame) + sizeof(AVEncodeInfoBlock)*nb_blocks;
> > +
> > +    if (nb_blocks < 0 || size >= INT_MAX)
> > +        return NULL;
> > +
> > +    AVFrameSideData *sd = av_frame_new_side_data(frame,
> > +                                                 AV_FRAME_DATA_ENCODE_INFO,
> > +                                                 size);
> > +    if (!sd)
> > +        return NULL;
> > +
> > +    memset(sd->data, 0, size);
> > +    init_encode_info_data((AVEncodeInfoFrame*)sd->data, nb_blocks);
> > +
> > +    return (AVEncodeInfoFrame*)sd->data;
> > +}
> > diff --git a/libavutil/encode_info.h b/libavutil/encode_info.h
> > new file mode 100644
> > index 0000000000..cbe8be2891
> > --- /dev/null
> > +++ b/libavutil/encode_info.h
> > @@ -0,0 +1,87 @@
> > +/*
> > + * 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_ENCODE_INFO_H
> > +#define AVUTIL_ENCODE_INFO_H
> > +
> > +#include "libavutil/frame.h"
> > +
> > +/**
> > + * Data structure for extracting block data stored in an array in AVEncodeInfoFrame
> > + */
> > +typedef struct AVEncodeInfoBlock{
> > +    /**
> > +     * Distance in luma pixels from the top-left corner of the visible frame
> > +     * to the top-left corner of the block.
> > +     * Can be negative if top/right padding is present on the coded frame.
> > +     */
> > +    int src_x, src_y;
> > +    /**
> > +     * Width and height of the block in luma pixels
> > +     */
> > +    int w, h;
> > +    /**
> > +     * Delta quantization index for the block
> > +     */
> > +    int delta_q;
> > +
> > +    uint8_t reserved[128];
> > +} AVEncodeInfoBlock;
> > +
> > +/**
> > + * Frame encoding info, used as AVFrameSideData
> > + */
> > +typedef struct AVEncodeInfoFrame {
> > +    /**
> > +     * Number of blocks in the array
> > +     */
> > +    int nb_blocks;
> > +    /**
> > +     * Base plane quantizer for the frame, set to -1 when value is unsupported
> > +     */
> > +    int plane_q[AV_NUM_DATA_POINTERS];
> > +    /**
> > +     * DC/AC quantizer index delta, set to -1 when value is value unsupported.
> > +     */
> > +    int ac_q, dc_q;
> > +    /**
> > +     * DC/AC chroma quantizer index delta, set to -1 when value is value unsupported.
> > +     */
> > +    int ac_chroma_q, dc_chroma_q;
> > +
> > +    uint8_t reserved[256];
> > +
> > +    AVEncodeInfoBlock blocks[];
>
> Flexible array members will break compatibility with C++ projects.
>

If its the last element in the struct, just make it blocks[1] or
something and document that dynamically allocated data follows in its
place. This is common-place even in C++ compatible structs.
I believe we even use it in some structs ourself.

- Hendrik
James Almer Aug. 9, 2019, 6:02 p.m. UTC | #3
On 8/9/2019 2:58 PM, Hendrik Leppkes wrote:
> On Fri, Aug 9, 2019 at 7:52 PM James Almer <jamrial@gmail.com> wrote:
>>
>> On 8/9/2019 2:38 PM, Juan De León wrote:
>>> AVEncodeInfoFrame data structure to store as AVFrameSideData of type AV_FRAME_DATA_ENCODE_INFO.
>>> The structure stores quantization index for each plane, DC/AC deltas for luma and chroma planes, and an array of AVEncodeInfoBlock struct denoting position, size, and delta quantizer for each block in the frame.
>>> Can be extended to support extraction of other block information.
>>>
>>> Signed-off-by: Juan De León <juandl@google.com>
>>> ---
>>> fixed a typo in frame.h comment
>>>  libavutil/Makefile      |  2 +
>>>  libavutil/encode_info.c | 67 +++++++++++++++++++++++++++++++
>>>  libavutil/encode_info.h | 87 +++++++++++++++++++++++++++++++++++++++++
>>>  libavutil/frame.c       |  1 +
>>>  libavutil/frame.h       |  7 ++++
>>>  5 files changed, 164 insertions(+)
>>>  create mode 100644 libavutil/encode_info.c
>>>  create mode 100644 libavutil/encode_info.h
>>>
>>> diff --git a/libavutil/Makefile b/libavutil/Makefile
>>> index 57e6e3d7e8..37cfb099e9 100644
>>> --- a/libavutil/Makefile
>>> +++ b/libavutil/Makefile
>>> @@ -24,6 +24,7 @@ HEADERS = adler32.h                                                     \
>>>            dict.h                                                        \
>>>            display.h                                                     \
>>>            downmix_info.h                                                \
>>> +          encode_info.h                                                 \
>>>            encryption_info.h                                             \
>>>            error.h                                                       \
>>>            eval.h                                                        \
>>> @@ -111,6 +112,7 @@ OBJS = adler32.o                                                        \
>>>         dict.o                                                           \
>>>         display.o                                                        \
>>>         downmix_info.o                                                   \
>>> +       encode_info.o                                                    \
>>>         encryption_info.o                                                \
>>>         error.o                                                          \
>>>         eval.o                                                           \
>>> diff --git a/libavutil/encode_info.c b/libavutil/encode_info.c
>>> new file mode 100644
>>> index 0000000000..68c30af4d7
>>> --- /dev/null
>>> +++ b/libavutil/encode_info.c
>>> @@ -0,0 +1,67 @@
>>> +/*
>>> + * 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/encode_info.h"
>>> +#include "libavutil/mem.h"
>>> +
>>> +static int init_encode_info_data(AVEncodeInfoFrame *ptr, int nb_blocks) {
>>> +    ptr->nb_blocks = nb_blocks;
>>> +    ptr->dc_q = ptr->ac_q = -1;
>>> +    ptr->dc_chroma_q = ptr->ac_chroma_q = -1;
>>> +
>>> +    for(int i=0;i<AV_NUM_DATA_POINTERS;i++)
>>> +        ptr->plane_q[i] = -1;
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +AVEncodeInfoFrame *av_encode_info_alloc(int nb_blocks)
>>> +{
>>> +    AVEncodeInfoFrame *ptr;
>>> +    size_t size = sizeof(AVEncodeInfoFrame) + sizeof(AVEncodeInfoBlock)*nb_blocks;
>>> +
>>> +    if (nb_blocks < 0 || size >= INT_MAX)
>>> +        return NULL;
>>> +
>>> +    ptr = av_mallocz(size);
>>> +    if (!ptr)
>>> +        return NULL;
>>> +
>>> +    init_encode_info_data(ptr, nb_blocks);
>>> +
>>> +    return ptr;
>>> +}
>>> +
>>> +AVEncodeInfoFrame *av_encode_info_create_side_data(AVFrame *frame, int nb_blocks)
>>> +{
>>> +    size_t size = sizeof(AVEncodeInfoFrame) + sizeof(AVEncodeInfoBlock)*nb_blocks;
>>> +
>>> +    if (nb_blocks < 0 || size >= INT_MAX)
>>> +        return NULL;
>>> +
>>> +    AVFrameSideData *sd = av_frame_new_side_data(frame,
>>> +                                                 AV_FRAME_DATA_ENCODE_INFO,
>>> +                                                 size);
>>> +    if (!sd)
>>> +        return NULL;
>>> +
>>> +    memset(sd->data, 0, size);
>>> +    init_encode_info_data((AVEncodeInfoFrame*)sd->data, nb_blocks);
>>> +
>>> +    return (AVEncodeInfoFrame*)sd->data;
>>> +}
>>> diff --git a/libavutil/encode_info.h b/libavutil/encode_info.h
>>> new file mode 100644
>>> index 0000000000..cbe8be2891
>>> --- /dev/null
>>> +++ b/libavutil/encode_info.h
>>> @@ -0,0 +1,87 @@
>>> +/*
>>> + * 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_ENCODE_INFO_H
>>> +#define AVUTIL_ENCODE_INFO_H
>>> +
>>> +#include "libavutil/frame.h"
>>> +
>>> +/**
>>> + * Data structure for extracting block data stored in an array in AVEncodeInfoFrame
>>> + */
>>> +typedef struct AVEncodeInfoBlock{
>>> +    /**
>>> +     * Distance in luma pixels from the top-left corner of the visible frame
>>> +     * to the top-left corner of the block.
>>> +     * Can be negative if top/right padding is present on the coded frame.
>>> +     */
>>> +    int src_x, src_y;
>>> +    /**
>>> +     * Width and height of the block in luma pixels
>>> +     */
>>> +    int w, h;
>>> +    /**
>>> +     * Delta quantization index for the block
>>> +     */
>>> +    int delta_q;
>>> +
>>> +    uint8_t reserved[128];
>>> +} AVEncodeInfoBlock;
>>> +
>>> +/**
>>> + * Frame encoding info, used as AVFrameSideData
>>> + */
>>> +typedef struct AVEncodeInfoFrame {
>>> +    /**
>>> +     * Number of blocks in the array
>>> +     */
>>> +    int nb_blocks;
>>> +    /**
>>> +     * Base plane quantizer for the frame, set to -1 when value is unsupported
>>> +     */
>>> +    int plane_q[AV_NUM_DATA_POINTERS];
>>> +    /**
>>> +     * DC/AC quantizer index delta, set to -1 when value is value unsupported.
>>> +     */
>>> +    int ac_q, dc_q;
>>> +    /**
>>> +     * DC/AC chroma quantizer index delta, set to -1 when value is value unsupported.
>>> +     */
>>> +    int ac_chroma_q, dc_chroma_q;
>>> +
>>> +    uint8_t reserved[256];
>>> +
>>> +    AVEncodeInfoBlock blocks[];
>>
>> Flexible array members will break compatibility with C++ projects.
>>
> 
> If its the last element in the struct, just make it blocks[1] or
> something and document that dynamically allocated data follows in its
> place. This is common-place even in C++ compatible structs.
> I believe we even use it in some structs ourself.

Or just a pointer that points to the first byte after itself.
Nicolas George Aug. 9, 2019, 6:28 p.m. UTC | #4
James Almer (12019-08-09):
> Or just a pointer that points to the first byte after itself.

The pointer takes places by itself. And it prevents the structure from
being copied flatly, which IIRC is forbidden with side data.

By the way, the lines of the commit message are too long.

Regards,
James Almer Aug. 9, 2019, 6:31 p.m. UTC | #5
On 8/9/2019 3:28 PM, Nicolas George wrote:
> James Almer (12019-08-09):
>> Or just a pointer that points to the first byte after itself.
> 
> The pointer takes places by itself. And it prevents the structure from
> being copied flatly, which IIRC is forbidden with side data.

Yeah, you're right, make_writable() and similar functions would break it.

> 
> By the way, the lines of the commit message are too long.
> 
> Regards,
> 
> 
> _______________________________________________
> 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".
>
diff mbox

Patch

diff --git a/libavutil/Makefile b/libavutil/Makefile
index 57e6e3d7e8..37cfb099e9 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -24,6 +24,7 @@  HEADERS = adler32.h                                                     \
           dict.h                                                        \
           display.h                                                     \
           downmix_info.h                                                \
+          encode_info.h                                                 \
           encryption_info.h                                             \
           error.h                                                       \
           eval.h                                                        \
@@ -111,6 +112,7 @@  OBJS = adler32.o                                                        \
        dict.o                                                           \
        display.o                                                        \
        downmix_info.o                                                   \
+       encode_info.o                                                    \
        encryption_info.o                                                \
        error.o                                                          \
        eval.o                                                           \
diff --git a/libavutil/encode_info.c b/libavutil/encode_info.c
new file mode 100644
index 0000000000..68c30af4d7
--- /dev/null
+++ b/libavutil/encode_info.c
@@ -0,0 +1,67 @@ 
+/*
+ * 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/encode_info.h"
+#include "libavutil/mem.h"
+
+static int init_encode_info_data(AVEncodeInfoFrame *ptr, int nb_blocks) {
+    ptr->nb_blocks = nb_blocks;
+    ptr->dc_q = ptr->ac_q = -1;
+    ptr->dc_chroma_q = ptr->ac_chroma_q = -1;
+
+    for(int i=0;i<AV_NUM_DATA_POINTERS;i++)
+        ptr->plane_q[i] = -1;
+
+    return 0;
+}
+
+AVEncodeInfoFrame *av_encode_info_alloc(int nb_blocks)
+{
+    AVEncodeInfoFrame *ptr;
+    size_t size = sizeof(AVEncodeInfoFrame) + sizeof(AVEncodeInfoBlock)*nb_blocks;
+
+    if (nb_blocks < 0 || size >= INT_MAX)
+        return NULL;
+
+    ptr = av_mallocz(size);
+    if (!ptr)
+        return NULL;
+
+    init_encode_info_data(ptr, nb_blocks);
+
+    return ptr;
+}
+
+AVEncodeInfoFrame *av_encode_info_create_side_data(AVFrame *frame, int nb_blocks)
+{
+    size_t size = sizeof(AVEncodeInfoFrame) + sizeof(AVEncodeInfoBlock)*nb_blocks;
+
+    if (nb_blocks < 0 || size >= INT_MAX)
+        return NULL;
+
+    AVFrameSideData *sd = av_frame_new_side_data(frame,
+                                                 AV_FRAME_DATA_ENCODE_INFO,
+                                                 size);
+    if (!sd)
+        return NULL;
+
+    memset(sd->data, 0, size);
+    init_encode_info_data((AVEncodeInfoFrame*)sd->data, nb_blocks);
+
+    return (AVEncodeInfoFrame*)sd->data;
+}
diff --git a/libavutil/encode_info.h b/libavutil/encode_info.h
new file mode 100644
index 0000000000..cbe8be2891
--- /dev/null
+++ b/libavutil/encode_info.h
@@ -0,0 +1,87 @@ 
+/*
+ * 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_ENCODE_INFO_H
+#define AVUTIL_ENCODE_INFO_H
+
+#include "libavutil/frame.h"
+
+/**
+ * Data structure for extracting block data stored in an array in AVEncodeInfoFrame
+ */
+typedef struct AVEncodeInfoBlock{
+    /**
+     * Distance in luma pixels from the top-left corner of the visible frame
+     * to the top-left corner of the block.
+     * Can be negative if top/right padding is present on the coded frame.
+     */
+    int src_x, src_y;
+    /**
+     * Width and height of the block in luma pixels
+     */
+    int w, h;
+    /**
+     * Delta quantization index for the block
+     */
+    int delta_q;
+
+    uint8_t reserved[128];
+} AVEncodeInfoBlock;
+
+/**
+ * Frame encoding info, used as AVFrameSideData
+ */
+typedef struct AVEncodeInfoFrame {
+    /**
+     * Number of blocks in the array
+     */
+    int nb_blocks;
+    /**
+     * Base plane quantizer for the frame, set to -1 when value is unsupported
+     */
+    int plane_q[AV_NUM_DATA_POINTERS];
+    /**
+     * DC/AC quantizer index delta, set to -1 when value is value unsupported.
+     */
+    int ac_q, dc_q;
+    /**
+     * DC/AC chroma quantizer index delta, set to -1 when value is value unsupported.
+     */
+    int ac_chroma_q, dc_chroma_q;
+
+    uint8_t reserved[256];
+
+    AVEncodeInfoBlock blocks[];
+} AVEncodeInfoFrame;
+
+/**
+ * Allocates memory for AVEncodeInfoFrame plus an array of
+ * {@code nb_blocks} AVEncodeInfoBlock and initializes the variables.
+ * Can be freed with a normal av_free() call.
+ */
+AVEncodeInfoFrame *av_encode_info_alloc(int nb_blocks);
+
+/**
+ * Allocates memory for AVEncodeInfoFrame plus an array of
+ * {@code nb_blocks} AVEncodeInfoBlock in the given AVFrame {@code frame}
+ * as AVFrameSideData of type AV_FRAME_DATA_ENCODE_INFO
+ * and initializes the variables
+ */
+AVEncodeInfoFrame *av_encode_info_create_side_data(AVFrame *frame, int nb_blocks);
+
+#endif /* AVUTIL_ENCODE_INFO_H */
diff --git a/libavutil/frame.c b/libavutil/frame.c
index dcf1fc3d17..c5ec6d13ca 100644
--- a/libavutil/frame.c
+++ b/libavutil/frame.c
@@ -842,6 +842,7 @@  const char *av_frame_side_data_name(enum AVFrameSideDataType type)
 #endif
     case AV_FRAME_DATA_DYNAMIC_HDR_PLUS: return "HDR Dynamic Metadata SMPTE2094-40 (HDR10+)";
     case AV_FRAME_DATA_REGIONS_OF_INTEREST: return "Regions Of Interest";
+    case AV_FRAME_DATA_ENCODE_INFO:                  return "AVEncodeInfo";
     }
     return NULL;
 }
diff --git a/libavutil/frame.h b/libavutil/frame.h
index 5d3231e7bb..f2865b6146 100644
--- a/libavutil/frame.h
+++ b/libavutil/frame.h
@@ -179,6 +179,13 @@  enum AVFrameSideDataType {
      * array element is implied by AVFrameSideData.size / AVRegionOfInterest.self_size.
      */
     AV_FRAME_DATA_REGIONS_OF_INTEREST,
+    /**
+     * Extract block data from supported decoders. The data is stored in
+     * AVEncodeInfoFrame type, which contains an array of AVEncodeInfoBLock
+     * described in libavuitl/encode_info.h
+     * Can be allocated in the frame directly with av_encode_info_create_side_data().
+     */
+    AV_FRAME_DATA_ENCODE_INFO,
 };
 
 enum AVActiveFormatDescription {