From patchwork Tue Mar 10 17:46:02 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 18114 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 91FCD44974D for ; Tue, 10 Mar 2020 19:48:56 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 7A03868A9AA; Tue, 10 Mar 2020 19:48:56 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail.red.khirnov.net (red.khirnov.net [176.97.15.12]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 7219F68A812 for ; Tue, 10 Mar 2020 19:48:50 +0200 (EET) Received: from localhost (localhost [IPv6:::1]) by mail.red.khirnov.net (Postfix) with ESMTP id 706E72956EE for ; Tue, 10 Mar 2020 18:48:47 +0100 (CET) Received: from mail.red.khirnov.net ([IPv6:::1]) by localhost (mail.red.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id vZkUT4vKxGY6 for ; Tue, 10 Mar 2020 18:48:46 +0100 (CET) Received: from quelana.khirnov.net (unknown [IPv6:2002:b061:f0a:201:5e:e696:5100:0]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256 client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "quelana.khirnov.net", Issuer "smtp.khirnov.net SMTP CA" (verified OK)) by mail.red.khirnov.net (Postfix) with ESMTPS id 465A12956E8 for ; Tue, 10 Mar 2020 18:48:46 +0100 (CET) Received: from localhost (quelana.khirnov.net [IPv6:::1]) by quelana.khirnov.net (Postfix) with ESMTP id D3B89251FA for ; Tue, 10 Mar 2020 18:48:45 +0100 (CET) Received: from quelana.khirnov.net ([IPv6:::1]) by localhost (quelana.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id 74mAh8JqCSjK for ; Tue, 10 Mar 2020 18:48:44 +0100 (CET) Received: from libav.daenerys.khirnov.net (libav.daenerys.khirnov.net [IPv6:2a00:c500:561:201::7]) by quelana.khirnov.net (Postfix) with ESMTP id 0E0E52532A for ; Tue, 10 Mar 2020 18:48:41 +0100 (CET) Received: by libav.daenerys.khirnov.net (Postfix, from userid 1000) id 7BF9320E0357; Tue, 10 Mar 2020 18:48:37 +0100 (CET) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Tue, 10 Mar 2020 18:46:02 +0100 Message-Id: <20200310174602.10217-7-anton@khirnov.net> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200310174602.10217-1-anton@khirnov.net> References: <20200310174602.10217-1-anton@khirnov.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 6/6] h264dec: support exporting QP tables through the AVVideoEncParams API X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" --- 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, }; /**