[FFmpeg-devel] [PATCH] Extract QP from h264 encoded videos

Andrey Semashev andrey.semashev at gmail.com
Tue Jul 30 12:19:50 EEST 2019


On 7/30/19 12:11 PM, Andrey Semashev wrote:
> On 7/30/19 5:39 AM, Juan De León wrote:
>> I tried to fix all you suggested, please have a look and let me know 
>> what you think.
>>
>> design doc: 
>> https://docs.google.com/document/d/1WClt3EqhjwdGXhEw386O0wfn3IBQ1Ib-_5emVM1gbnA/edit?usp=sharing 
>>
>>
>> Signed-off-by: Juan De León <juandl at google.com>
>> ---
>>   libavutil/Makefile              |   2 +
>>   libavutil/frame.h               |   6 ++
>>   libavutil/quantization_params.c |  42 ++++++++++++
>>   libavutil/quantization_params.h | 114 ++++++++++++++++++++++++++++++++
>>   4 files changed, 164 insertions(+)
>>   create mode 100644 libavutil/quantization_params.c
>>   create mode 100644 libavutil/quantization_params.h
>>
>> 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/frame.h b/libavutil/frame.h
>> index 5d3231e7bb..b64fd9c02c 100644
>> --- a/libavutil/frame.h
>> +++ b/libavutil/frame.h
>> @@ -179,6 +179,12 @@ enum AVFrameSideDataType {
>>        * array element is implied by AVFrameSideData.size / 
>> AVRegionOfInterest.self_size.
>>        */
>>       AV_FRAME_DATA_REGIONS_OF_INTEREST,
>> +    /**
>> +     * To extract quantization parameters from supported decoders.
>> +     * The data is stored as AVQuantizationParamsArray type, 
>> described in
>> +     * libavuitl/quantization_params.h
>> +     */
>> +    AV_FRAME_DATA_QUANTIZATION_PARAMS,
>>   };
>>   enum AVActiveFormatDescription {
>> diff --git a/libavutil/quantization_params.c 
>> b/libavutil/quantization_params.c
>> new file mode 100644
>> index 0000000000..fc51b55eee
>> --- /dev/null
>> +++ b/libavutil/quantization_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 "libavutil/quantization_params.h"
>> +#include "libavutil/mem.h"
>> +
>> +static const char* const QP_NAMES_H264[] = {"qpy", "qpuv"};
>> +
>> +static const char* const QP_NAMES_VP9[] = {"qyac", "qydc", "quvdc", 
>> "quvac",
>> +                                           "qiyac", "qiydc", 
>> "qiuvdc", "qiuvac"};
>> +
>> +static const char* const QP_NAMES_AV1[] = {"qydc", "qyac", "qudc", 
>> "quac", "qvdc", "qvac",
>> +                                      "qiydc", "qiyac", "qiudc", 
>> "qiuac", "qivdc", "qivac"};
>> +
>> +char* av_get_qp_type_string(enum AVExtractQPSupportedCodecs codec_id, 
>> int index)
>> +{
>> +    switch (codec_id) {
>> +        case AV_EXTRACT_QP_CODEC_ID_H264:
>> +            return index < AV_QP_ARR_SIZE_H264 ? 
>> av_strdup(QP_NAMES_H264[index]) :NULL;
>> +        case AV_EXTRACT_QP_CODEC_ID_VP9:
>> +            return index < AV_QP_ARR_SIZE_VP9  ? 
>> av_strdup(QP_NAMES_VP9[index])  :NULL;
>> +        case AV_EXTRACT_QP_CODEC_ID_AV1:
>> +            return index < AV_QP_ARR_SIZE_AV1  ? 
>> av_strdup(QP_NAMES_AV1[index])  :NULL;
>> +        default:
>> +            return NULL;
>> +    }
>> +}

Why strdup here? Why not return the pointer from the static array?

If you really do intend to strdup, the function documentation should 
state clearly that the caller is supposed to av_free the returned pointer.

>> diff --git a/libavutil/quantization_params.h 
>> b/libavutil/quantization_params.h
>> new file mode 100644
>> index 0000000000..d123aade3b
>> --- /dev/null
>> +++ b/libavutil/quantization_params.h
>> @@ -0,0 +1,114 @@
>> +/*
>> + * 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
>> +
>> +/*
>> + * Supported decoders
>> + */
>> +enum AVExtractQPSupportedCodecs {
>> +    AV_EXTRACT_QP_CODEC_ID_H264 = 0,
>> +    AV_EXTRACT_QP_CODEC_ID_VP9,
>> +    AV_EXTRACT_QP_CODEC_ID_AV1,
>> +};
> 
> Just a thought. If you need codec ids and implement codec-specific 
> functionality, then this whole thing probably belongs to libavcodec, not 
> libavutil.
> 
>> +
>> +/**
>> + * Enums for different codecs to store qp in the type array
>> + * Each enum must have an array of strings describing each field
>> + * declared in quantization_params.c
>> + */
>> +
>> +enum AVQPArrIndexesH264 {
>> +    AV_QP_Y_H264 = 0,       // qp value index in qp_type array
>> +    AV_QP_UV_H264,
>> +    AV_QP_ARR_SIZE_H264     // number of QP stored for this codec
>> +};
>> +
>> +enum AVQPArrIndexesVP9 {
>> +    AV_QP_YAC_VP9 = 0,    // get_dc_quant[][AV_QP_INDEX_YAC_VP9]
>> +    AV_QP_YDC_VP9,        // get_dc_quant[][AV_QP_INDEX_YDC_VP9]
>> +    AV_QP_UVDC_VP9,       // get_dc_quant[][AV_QP_INDEX_UVDC_VP9]
>> +    AV_QP_UVAC_VP9,       // get_ac_quant[][AV_QP_INDEX_UVAC_VP9]
>> +    AV_QP_INDEX_YAC_VP9,  // base_q_idx
>> +    AV_QP_INDEX_YDC_VP9,  // base_q_idx+delta_q_y_dc
>> +    AV_QP_INDEX_UVDC_VP9, // base_q_idx+delta_q_uv_dc
>> +    AV_QP_INDEX_UVAC_VP9, // base_q_idx+delta_q_uv_ac
>> +    AV_QP_ARR_SIZE_VP9
>> +};
>> +
>> +enum AVQPArrIndexesAV1 {
>> +    AV_QP_YDC_AV1 = 0,
>> +    AV_QP_YAC_AV1,
>> +    AV_QP_UDC_AV1,
>> +    AV_QP_UAC_AV1,
>> +    AV_QP_VDC_AV1,
>> +    AV_QP_VAC_AV1,
>> +    AV_QP_INDEX_YDC_AV1,
>> +    AV_QP_INDEX_YAC_AV1,
>> +    AV_QP_INDEX_UDC_AV1,
>> +    AV_QP_INDEX_UAC_AV1,
>> +    AV_QP_INDEX_VDC_AV1,
>> +    AV_QP_INDEX_VAC_AV1,
>> +    AV_QP_ARR_SIZE_AV1
>> +};
>> +
>> +/**
>> + * 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
>> +     */
>> +    int qp_type[AV_QP_ARR_SIZE_AV1];
>> +} AVQuantizationParams;
>> +
>> +/**
>> + * For storing an array of AVQuantization parameters and its size
>> + * Used as AVFrameSideData
>> + */
>> +typedef struct AVQuantizationParamsArray {
>> +    /**
>> +     * Array of AVQuantizationParams type blocks
>> +     */
>> +    AVQuantizationParams *qp_block_array;
>> +    /**
>> +     * size of the array
>> +     */
>> +    int nb_blocks;
>> +    /**
>> +     * Stores an id corresponding to one of the suppported codecs
>> +     */
>> +    enum AVExtractQPSupportedCodecs codec_id;
>> +} AVQuantizationParamsArray;
>> +
>> +/**
>> + * Get the string describing the qp type for the given codec
>> + */
>> +char* av_get_qp_type_string(enum AVExtractQPSupportedCodecs codec_id, 
>> int index);

Also, as it was mentioned, this function should return a const pointer.

>> +
>> +#endif /* AVUTIL_QUANTIZATION_PARAMS_H */
>>
> 



More information about the ffmpeg-devel mailing list