--- 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 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".