diff mbox

[FFmpeg-devel] Extract QP from h264 encoded videos

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

Commit Message

=?UTF-8?q?Juan=20De=20Le=C3=B3n?= July 29, 2019, 6:12 p.m. UTC
Here is the second patch, I sent the first one twice accidentaly. 
First patch is libavutil, this patch is libavcodec.

Signed-off-by: Juan De León <juandl@google.com>
---
 libavcodec/avcodec.h       |  1 +
 libavcodec/h264dec.c       | 44 ++++++++++++++++++++++++++++++++++++++
 libavcodec/options_table.h |  1 +
 3 files changed, 46 insertions(+)

Comments

Andreas Håkon July 29, 2019, 7:11 p.m. UTC | #1
Hi Juan,


‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
On Monday, 29 de July de 2019 20:12, Juan De León <juandl-at-google.com@ffmpeg.org> wrote:

> Here is the second patch, I sent the first one twice accidentaly.
> First patch is libavutil, this patch is libavcodec.
>

Interesting patch. But I have a question:
Could you implement the same thing when using the hardware decoders?

And also, could you make a similar patch for MPEG-2 as well?

Regards.
A.H.

---
=?UTF-8?q?Juan=20De=20Le=C3=B3n?= July 29, 2019, 7:21 p.m. UTC | #2
Thank you for the feedback Andrey, I will fix it ASAP.

On Mon, Jul 29, 2019 at 12:11 PM Andreas Håkon <andreas.hakon@protonmail.com>
wrote:

> Interesting patch. But I have a question:
> Could you implement the same thing when using the hardware decoders?

I believe this might be in the scope of my project.
I'm not too familiar with hardware decoders but when I complete the rest of
the implementation I will take a look at this.


> And also, could you make a similar patch for MPEG-2 as well?

The scope was limited to H264, VP9 and AV1 but I will talk about it with my
team.
Again, thanks for the feedback.
Michael Niedermayer Aug. 3, 2019, 7:36 p.m. UTC | #3
On Mon, Jul 29, 2019 at 11:12:34AM -0700, Juan De León wrote:
> Here is the second patch, I sent the first one twice accidentaly. 
> First patch is libavutil, this patch is libavcodec.
> 
> Signed-off-by: Juan De León <juandl@google.com>
> ---
>  libavcodec/avcodec.h       |  1 +
>  libavcodec/h264dec.c       | 44 ++++++++++++++++++++++++++++++++++++++
>  libavcodec/options_table.h |  1 +
>  3 files changed, 46 insertions(+)
> 
> diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
> index d234271c5b..9e3185720a 100644
> --- a/libavcodec/avcodec.h
> +++ b/libavcodec/avcodec.h
> @@ -2671,6 +2671,7 @@ typedef struct AVCodecContext {
>  #endif
>  #define FF_DEBUG_BUFFERS     0x00008000
>  #define FF_DEBUG_THREADS     0x00010000
> +#define FF_DEBUG_EXTRACTQP   0x00020000
>  #define FF_DEBUG_GREEN_MD    0x00800000
>  #define FF_DEBUG_NOMC        0x01000000
>  
> diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c
> index 8d1bd16a8e..52ad12e55d 100644
> --- a/libavcodec/h264dec.c
> +++ b/libavcodec/h264dec.c
> @@ -33,6 +33,7 @@
>  #include "libavutil/opt.h"
>  #include "libavutil/stereo3d.h"
>  #include "libavutil/timer.h"
> +#include "libavutil/quantization_params.h"
>  #include "internal.h"
>  #include "bytestream.h"
>  #include "cabac.h"
> @@ -922,6 +923,49 @@ static int finalize_frame(H264Context *h, AVFrame *dst, H264Picture *out, int *g
>          }
>      }
>  
> +    if (h->avctx->debug & FF_DEBUG_EXTRACTQP) {
> +        int mb_height = h->height / 16;
> +        int mb_width = h->width / 16;

has this been tested with files which have dimensions not a multiple of 16 ?


> +        int mb_xy = mb_width * mb_height;
> +
> +        int buf_size = sizeof(AVQuantizationParamsArray) +
> +                       mb_xy * sizeof(AVQuantizationParams);
> +        AVBufferRef *buffer = av_buffer_alloc(buf_size);
> +        if (!buffer) {
> +            return AVERROR(ENOMEM);
> +        }
> +
> +        AVQuantizationParamsArray *params = (AVQuantizationParamsArray *)buffer->data;
> +        params->nb_blocks = mb_xy;
> +        params->codec_id = h->avctx->codec_id;
> +        // offset memory for qp_arr in same buffer
> +        params->qp_arr = (AVQuantizationParams*) (params + 1);
> +
> +        // loop allocate qp
> +        int qp_index = 0;
> +        for (int mb_y = 0; mb_y < mb_height; mb_y++) {
> +            for (int mb_x = 0; mb_x < mb_width; mb_x++) {
> +                int qs_index = mb_x + mb_y * h->mb_stride;
> +                AVQuantizationParams *qp_block = &(params->qp_arr[qp_index]);
> +
> +                qp_block->x = mb_x * 16;
> +                qp_block->y = mb_y * 16;
> +                qp_block->w = qp_block->h = 16;
> +                qp_block->type[QP_H264] = out->qscale_table[qs_index];
> +
> +                qp_index++;
> +            }
> +        }
> +

> +        AVFrameSideData *sd;
> +        sd = av_frame_new_side_data_from_buf(dst,
> +                                             AV_FRAME_DATA_QUANTIZATION_PARAMS,
> +                                             buffer);
> +        if (!sd) {
> +            return AVERROR(ENOMEM);

buffer leaks here


[...]

thx
diff mbox

Patch

diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index d234271c5b..9e3185720a 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -2671,6 +2671,7 @@  typedef struct AVCodecContext {
 #endif
 #define FF_DEBUG_BUFFERS     0x00008000
 #define FF_DEBUG_THREADS     0x00010000
+#define FF_DEBUG_EXTRACTQP   0x00020000
 #define FF_DEBUG_GREEN_MD    0x00800000
 #define FF_DEBUG_NOMC        0x01000000
 
diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c
index 8d1bd16a8e..52ad12e55d 100644
--- a/libavcodec/h264dec.c
+++ b/libavcodec/h264dec.c
@@ -33,6 +33,7 @@ 
 #include "libavutil/opt.h"
 #include "libavutil/stereo3d.h"
 #include "libavutil/timer.h"
+#include "libavutil/quantization_params.h"
 #include "internal.h"
 #include "bytestream.h"
 #include "cabac.h"
@@ -922,6 +923,49 @@  static int finalize_frame(H264Context *h, AVFrame *dst, H264Picture *out, int *g
         }
     }
 
+    if (h->avctx->debug & FF_DEBUG_EXTRACTQP) {
+        int mb_height = h->height / 16;
+        int mb_width = h->width / 16;
+        int mb_xy = mb_width * mb_height;
+
+        int buf_size = sizeof(AVQuantizationParamsArray) +
+                       mb_xy * sizeof(AVQuantizationParams);
+        AVBufferRef *buffer = av_buffer_alloc(buf_size);
+        if (!buffer) {
+            return AVERROR(ENOMEM);
+        }
+
+        AVQuantizationParamsArray *params = (AVQuantizationParamsArray *)buffer->data;
+        params->nb_blocks = mb_xy;
+        params->codec_id = h->avctx->codec_id;
+        // offset memory for qp_arr in same buffer
+        params->qp_arr = (AVQuantizationParams*) (params + 1);
+
+        // loop allocate qp
+        int qp_index = 0;
+        for (int mb_y = 0; mb_y < mb_height; mb_y++) {
+            for (int mb_x = 0; mb_x < mb_width; mb_x++) {
+                int qs_index = mb_x + mb_y * h->mb_stride;
+                AVQuantizationParams *qp_block = &(params->qp_arr[qp_index]);
+
+                qp_block->x = mb_x * 16;
+                qp_block->y = mb_y * 16;
+                qp_block->w = qp_block->h = 16;
+                qp_block->type[QP_H264] = out->qscale_table[qs_index];
+
+                qp_index++;
+            }
+        }
+
+        AVFrameSideData *sd;
+        sd = av_frame_new_side_data_from_buf(dst,
+                                             AV_FRAME_DATA_QUANTIZATION_PARAMS,
+                                             buffer);
+        if (!sd) {
+            return AVERROR(ENOMEM);
+        }
+    }
+    
     return 0;
 }
 
diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h
index 4a266eca16..e0e78a69c5 100644
--- a/libavcodec/options_table.h
+++ b/libavcodec/options_table.h
@@ -219,6 +219,7 @@  static const AVOption avcodec_options[] = {
 {"buffers", "picture buffer allocations", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_BUFFERS }, INT_MIN, INT_MAX, V|D, "debug"},
 {"thread_ops", "threading operations", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_THREADS }, INT_MIN, INT_MAX, V|A|D, "debug"},
 {"nomc", "skip motion compensation", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_NOMC }, INT_MIN, INT_MAX, V|A|D, "debug"},
+{"extractqp", "enable QP extraction per frame", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_EXTRACTQP }, INT_MIN, INT_MAX, V|D, "debug"},
 {"dia_size", "diamond type & size for motion estimation", OFFSET(dia_size), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E},
 {"last_pred", "amount of motion predictors from the previous frame", OFFSET(last_predictor_count), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E},
 #if FF_API_PRIVATE_OPT