X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavfilter%2Fvf_uspp.c;h=b70d48e515eca2b23d77cb63a1133049dac8f9b6;hb=3a3e8c35b63a40c4d59161097dc8652c15d13779;hp=da4029f4b2c554addc8bfec1388e993ee25d9d7f;hpb=6fc762b4fd2c28ef7a0689a1df5ce200e5f5948f;p=ffmpeg diff --git a/libavfilter/vf_uspp.c b/libavfilter/vf_uspp.c index da4029f4b2c..b70d48e515e 100644 --- a/libavfilter/vf_uspp.c +++ b/libavfilter/vf_uspp.c @@ -29,9 +29,11 @@ #include "libavutil/avassert.h" #include "libavutil/imgutils.h" +#include "libavutil/mem_internal.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "internal.h" +#include "qp_table.h" #include "avfilter.h" #define MAX_LEVEL 8 /* quality levels */ @@ -49,10 +51,11 @@ typedef struct USPPContext { int outbuf_size; uint8_t *outbuf; AVCodecContext *avctx_enc[BLOCK*BLOCK]; + AVPacket *pkt; AVFrame *frame; AVFrame *frame_dec; - uint8_t *non_b_qp_table; - int non_b_qp_alloc_size; + int8_t *non_b_qp_table; + int non_b_qp_stride; int use_bframe_qp; } USPPContext; @@ -238,23 +241,24 @@ static void filter(USPPContext *p, uint8_t *dst[3], uint8_t *src[3], const int y1c = y1 >> p->vsub; const int BLOCKc = BLOCK >> p->hsub; int offset; - AVPacket pkt = {0}; + AVPacket *pkt = p->pkt; int got_pkt_ptr; - av_init_packet(&pkt); - pkt.data = p->outbuf; - pkt.size = p->outbuf_size; + av_packet_unref(pkt); + pkt->data = p->outbuf; + pkt->size = p->outbuf_size; p->frame->data[0] = p->src[0] + x1 + y1 * p->frame->linesize[0]; p->frame->data[1] = p->src[1] + x1c + y1c * p->frame->linesize[1]; p->frame->data[2] = p->src[2] + x1c + y1c * p->frame->linesize[2]; p->frame->format = p->avctx_enc[i]->pix_fmt; - ret = avcodec_encode_video2(p->avctx_enc[i], &pkt, p->frame, &got_pkt_ptr); + ret = avcodec_encode_video2(p->avctx_enc[i], pkt, p->frame, &got_pkt_ptr); if (ret < 0) { av_log(p->avctx_enc[i], AV_LOG_ERROR, "Encoding failed\n"); continue; } + av_packet_unref(pkt); p->frame_dec = p->avctx_enc[i]->coded_frame; @@ -316,7 +320,7 @@ static int config_input(AVFilterLink *inlink) const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); int i; - AVCodec *enc = avcodec_find_encoder(AV_CODEC_ID_SNOW); + const AVCodec *enc = avcodec_find_encoder(AV_CODEC_ID_SNOW); if (!enc) { av_log(ctx, AV_LOG_ERROR, "SNOW encoder not found.\n"); return AVERROR(EINVAL); @@ -362,15 +366,17 @@ static int config_input(AVFilterLink *inlink) avctx_enc->global_quality = 123; av_dict_set(&opts, "no_bitstream", "1", 0); ret = avcodec_open2(avctx_enc, enc, &opts); + av_dict_free(&opts); if (ret < 0) return ret; - av_dict_free(&opts); av_assert0(avctx_enc->codec); } uspp->outbuf_size = (width + BLOCK) * (height + BLOCK) * 10; if (!(uspp->frame = av_frame_alloc())) return AVERROR(ENOMEM); + if (!(uspp->pkt = av_packet_alloc())) + return AVERROR(ENOMEM); if (!(uspp->outbuf = av_malloc(uspp->outbuf_size))) return AVERROR(ENOMEM); @@ -385,45 +391,32 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) AVFrame *out = in; int qp_stride = 0; - uint8_t *qp_table = NULL; + int8_t *qp_table = NULL; + int ret = 0; /* if we are not in a constant user quantizer mode and we don't want to use * the quantizers from the B-frames (B-frames often have a higher QP), we * need to save the qp table from the last non B-frame; this is what the * following code block does */ - if (!uspp->qp) { - qp_table = av_frame_get_qp_table(in, &qp_stride, &uspp->qscale_type); - - if (qp_table && !uspp->use_bframe_qp && in->pict_type != AV_PICTURE_TYPE_B) { - int w, h; - - /* if the qp stride is not set, it means the QP are only defined on - * a line basis */ - if (!qp_stride) { - w = AV_CEIL_RSHIFT(inlink->w, 4); - h = 1; - } else { - w = qp_stride; - h = AV_CEIL_RSHIFT(inlink->h, 4); - } - - if (w * h > uspp->non_b_qp_alloc_size) { - int ret = av_reallocp_array(&uspp->non_b_qp_table, w, h); - if (ret < 0) { - uspp->non_b_qp_alloc_size = 0; - return ret; - } - uspp->non_b_qp_alloc_size = w * h; - } + if (!uspp->qp && (uspp->use_bframe_qp || in->pict_type != AV_PICTURE_TYPE_B)) { + ret = ff_qp_table_extract(in, &qp_table, &qp_stride, NULL, &uspp->qscale_type); + if (ret < 0) { + av_frame_free(&in); + return ret; + } - av_assert0(w * h <= uspp->non_b_qp_alloc_size); - memcpy(uspp->non_b_qp_table, qp_table, w * h); + if (!uspp->use_bframe_qp && in->pict_type != AV_PICTURE_TYPE_B) { + av_freep(&uspp->non_b_qp_table); + uspp->non_b_qp_table = qp_table; + uspp->non_b_qp_stride = qp_stride; } } if (uspp->log2_count && !ctx->is_disabled) { - if (!uspp->use_bframe_qp && uspp->non_b_qp_table) + if (!uspp->use_bframe_qp && uspp->non_b_qp_table) { qp_table = uspp->non_b_qp_table; + qp_stride = uspp->non_b_qp_stride; + } if (qp_table || uspp->qp) { @@ -436,6 +429,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) out = ff_get_video_buffer(outlink, aligned_w, aligned_h); if (!out) { av_frame_free(&in); + if (qp_table != uspp->non_b_qp_table) + av_free(qp_table); return AVERROR(ENOMEM); } av_frame_copy_props(out, in); @@ -455,7 +450,10 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) inlink->w, inlink->h); av_frame_free(&in); } - return ff_filter_frame(outlink, out); + ret = ff_filter_frame(outlink, out); + if (qp_table != uspp->non_b_qp_table) + av_freep(&qp_table); + return ret; } static av_cold void uninit(AVFilterContext *ctx) @@ -468,13 +466,12 @@ static av_cold void uninit(AVFilterContext *ctx) av_freep(&uspp->src[i]); } - for (i = 0; i < (1 << uspp->log2_count); i++) { - avcodec_close(uspp->avctx_enc[i]); - av_freep(&uspp->avctx_enc[i]); - } + for (i = 0; i < (1 << uspp->log2_count); i++) + avcodec_free_context(&uspp->avctx_enc[i]); av_freep(&uspp->non_b_qp_table); av_freep(&uspp->outbuf); + av_packet_free(&uspp->pkt); av_frame_free(&uspp->frame); } @@ -496,7 +493,7 @@ static const AVFilterPad uspp_outputs[] = { { NULL } }; -AVFilter ff_vf_uspp = { +const AVFilter ff_vf_uspp = { .name = "uspp", .description = NULL_IF_CONFIG_SMALL("Apply Ultra Simple / Slow Post-processing filter."), .priv_size = sizeof(USPPContext),