[FFmpeg-devel] [PATCH 6/6] h264dec: support exporting QP tables through the AVVideoEncParams API
Anton Khirnov
anton at khirnov.net
Tue Mar 10 19:46:02 EET 2020
---
libavcodec/h264_picture.c | 8 +++++-
libavcodec/h264_slice.c | 9 +++++++
libavcodec/h264dec.c | 47 ++++++++++++++++++++++++++++++++++++
libavcodec/h264dec.h | 6 +++++
libavutil/video_enc_params.h | 1 +
5 files changed, 70 insertions(+), 1 deletion(-)
diff --git a/libavcodec/h264_picture.c b/libavcodec/h264_picture.c
index e833835a77..0fcb45ffed 100644
--- a/libavcodec/h264_picture.c
+++ b/libavcodec/h264_picture.c
@@ -55,6 +55,7 @@ void ff_h264_unref_picture(H264Context *h, H264Picture *pic)
av_buffer_unref(&pic->qscale_table_buf);
av_buffer_unref(&pic->mb_type_buf);
+ av_buffer_unref(&pic->pps_buf);
for (i = 0; i < 2; i++) {
av_buffer_unref(&pic->motion_val_buf[i]);
av_buffer_unref(&pic->ref_index_buf[i]);
@@ -78,12 +79,14 @@ int ff_h264_ref_picture(H264Context *h, H264Picture *dst, H264Picture *src)
dst->qscale_table_buf = av_buffer_ref(src->qscale_table_buf);
dst->mb_type_buf = av_buffer_ref(src->mb_type_buf);
- if (!dst->qscale_table_buf || !dst->mb_type_buf) {
+ dst->pps_buf = av_buffer_ref(src->pps_buf);
+ if (!dst->qscale_table_buf || !dst->mb_type_buf || !dst->pps_buf) {
ret = AVERROR(ENOMEM);
goto fail;
}
dst->qscale_table = src->qscale_table;
dst->mb_type = src->mb_type;
+ dst->pps = src->pps;
for (i = 0; i < 2; i++) {
dst->motion_val_buf[i] = av_buffer_ref(src->motion_val_buf[i]);
@@ -121,6 +124,9 @@ int ff_h264_ref_picture(H264Context *h, H264Picture *dst, H264Picture *src)
dst->recovered = src->recovered;
dst->invalid_gap = src->invalid_gap;
dst->sei_recovery_frame_cnt = src->sei_recovery_frame_cnt;
+ dst->mb_width = src->mb_width;
+ dst->mb_height = src->mb_height;
+ dst->mb_stride = src->mb_stride;
return 0;
fail:
diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c
index e24d41ca50..d064234b64 100644
--- a/libavcodec/h264_slice.c
+++ b/libavcodec/h264_slice.c
@@ -244,6 +244,15 @@ static int alloc_picture(H264Context *h, H264Picture *pic)
pic->ref_index[i] = pic->ref_index_buf[i]->data;
}
+ pic->pps_buf = av_buffer_ref(h->ps.pps_ref);
+ if (!pic->pps_buf)
+ goto fail;
+ pic->pps = (const PPS*)pic->pps_buf->data;
+
+ pic->mb_width = h->mb_width;
+ pic->mb_height = h->mb_height;
+ pic->mb_stride = h->mb_stride;
+
return 0;
fail:
ff_h264_unref_picture(h, pic);
diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c
index f12651fa3d..0975d1cb2e 100644
--- a/libavcodec/h264dec.c
+++ b/libavcodec/h264dec.c
@@ -33,6 +33,8 @@
#include "libavutil/opt.h"
#include "libavutil/stereo3d.h"
#include "libavutil/timer.h"
+#include "libavutil/video_enc_params.h"
+
#include "internal.h"
#include "bytestream.h"
#include "cabac.h"
@@ -834,6 +836,42 @@ static int get_consumed_bytes(int pos, int buf_size)
return pos;
}
+static int export_enc_params(H264Context *h, AVFrame *f, H264Picture *p)
+{
+ AVVideoEncParams *par;
+ unsigned int nb_mb = p->mb_height * p->mb_width;
+ unsigned int x, y;
+
+ par = av_video_enc_params_create_side_data(f, nb_mb);
+ if (!par)
+ return AVERROR(ENOMEM);
+
+ par->type = AV_VIDEO_ENC_PARAMS_H264;
+
+ par->qp[0] = p->pps->init_qp;
+ par->qp[1] = par->qp[0];
+ par->qp[2] = par->qp[0];
+
+ for (y = 0; y < p->mb_height; y++)
+ for (x = 0; x < p->mb_width; x++) {
+ const unsigned int block_idx = y * p->mb_width + x;
+ const unsigned int mb_xy = y * p->mb_stride + x;
+ AVVideoBlockParams *b = av_video_enc_params_block(par, block_idx);
+
+ b->src_x = x * 16;
+ b->src_y = y * 16;
+ b->w = 16;
+ b->h = 16;
+
+ b->delta_qp[0] = p->qscale_table[mb_xy] - par->qp[0];
+ b->delta_qp[1] = get_chroma_qp(p->pps, 0, b->delta_qp[0]) - par->qp[1];
+ b->delta_qp[2] = get_chroma_qp(p->pps, 1, b->delta_qp[0]) - par->qp[2];
+ }
+
+
+ return 0;
+}
+
static int output_frame(H264Context *h, AVFrame *dst, H264Picture *srcp)
{
AVFrame *src = srcp->f;
@@ -848,7 +886,16 @@ static int output_frame(H264Context *h, AVFrame *dst, H264Picture *srcp)
if (srcp->sei_recovery_frame_cnt == 0)
dst->key_frame = 1;
+ if (h->avctx->export_side_data & AV_CODEC_EXPORT_DATA_VIDEO_ENC_PARAMS) {
+ ret = export_enc_params(h, dst, srcp);
+ if (ret < 0)
+ goto fail;
+ }
+
return 0;
+fail:
+ av_frame_unref(dst);
+ return ret;
}
static int is_extra(const uint8_t *buf, int buf_size)
diff --git a/libavcodec/h264dec.h b/libavcodec/h264dec.h
index 530e2d4071..29c4d4e42c 100644
--- a/libavcodec/h264dec.h
+++ b/libavcodec/h264dec.h
@@ -161,6 +161,12 @@ typedef struct H264Picture {
int recovered; ///< picture at IDR or recovery point + recovery count
int invalid_gap;
int sei_recovery_frame_cnt;
+
+ AVBufferRef *pps_buf;
+ const PPS *pps;
+
+ int mb_width, mb_height;
+ int mb_stride;
} H264Picture;
typedef struct H264Ref {
diff --git a/libavutil/video_enc_params.h b/libavutil/video_enc_params.h
index 166a49bd6d..da3e831b54 100644
--- a/libavutil/video_enc_params.h
+++ b/libavutil/video_enc_params.h
@@ -29,6 +29,7 @@ enum AVVideoEncParamsType {
AV_VIDEO_ENC_PARAMS_NONE = -1,
AV_VIDEO_ENC_PARAMS_MPEG2,
AV_VIDEO_ENC_PARAMS_H263,
+ AV_VIDEO_ENC_PARAMS_H264,
};
/**
--
2.24.1
More information about the ffmpeg-devel
mailing list