]> git.sesse.net Git - ffmpeg/blobdiff - libavfilter/vf_uspp.c
hwcontext_vulkan: dynamically load functions
[ffmpeg] / libavfilter / vf_uspp.c
index da4029f4b2c554addc8bfec1388e993ee25d9d7f..b70d48e515eca2b23d77cb63a1133049dac8f9b6 100644 (file)
 
 #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),