LCOV - code coverage report
Current view: top level - libavfilter - vf_qp.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 49 64 76.6 %
Date: 2017-12-18 20:14:19 Functions: 2 2 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2004 Michael Niedermayer <michaelni@gmx.at>
       3             :  *
       4             :  * This file is part of FFmpeg.
       5             :  *
       6             :  * FFmpeg is free software; you can redistribute it and/or
       7             :  * modify it under the terms of the GNU Lesser General Public
       8             :  * License as published by the Free Software Foundation; either
       9             :  * version 2.1 of the License, or (at your option) any later version.
      10             :  *
      11             :  * FFmpeg is distributed in the hope that it will be useful,
      12             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             :  * Lesser General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU Lesser General Public
      17             :  * License along with FFmpeg; if not, write to the Free Software
      18             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      19             :  */
      20             : 
      21             : #include <math.h>
      22             : #include "libavutil/eval.h"
      23             : #include "libavutil/imgutils.h"
      24             : #include "libavutil/pixdesc.h"
      25             : #include "libavutil/opt.h"
      26             : #include "avfilter.h"
      27             : #include "formats.h"
      28             : #include "internal.h"
      29             : #include "video.h"
      30             : 
      31             : typedef struct QPContext {
      32             :     const AVClass *class;
      33             :     char *qp_expr_str;
      34             :     int8_t lut[257];
      35             :     int h, qstride;
      36             :     int evaluate_per_mb;
      37             : } QPContext;
      38             : 
      39             : #define OFFSET(x) offsetof(QPContext, x)
      40             : #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
      41             : 
      42             : static const AVOption qp_options[] = {
      43             :     { "qp", "set qp expression", OFFSET(qp_expr_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
      44             :     { NULL }
      45             : };
      46             : 
      47             : AVFILTER_DEFINE_CLASS(qp);
      48             : 
      49           3 : static int config_input(AVFilterLink *inlink)
      50             : {
      51           3 :     AVFilterContext *ctx = inlink->dst;
      52           3 :     QPContext *s = ctx->priv;
      53             :     int i;
      54             :     int ret;
      55           3 :     AVExpr *e = NULL;
      56             :     static const char *var_names[] = { "known", "qp", "x", "y", "w", "h", NULL };
      57             : 
      58           3 :     if (!s->qp_expr_str)
      59           0 :         return 0;
      60             : 
      61           3 :     ret = av_expr_parse(&e, s->qp_expr_str, var_names, NULL, NULL, NULL, NULL, 0, ctx);
      62           3 :     if (ret < 0)
      63           0 :         return ret;
      64             : 
      65           3 :     s->h       = (inlink->h + 15) >> 4;
      66           3 :     s->qstride = (inlink->w + 15) >> 4;
      67         774 :     for (i = -129; i < 128; i++) {
      68         771 :         double var_values[] = { i != -129, i, NAN, NAN, s->qstride, s->h, 0};
      69         771 :         double temp_val = av_expr_eval(e, var_values, NULL);
      70             : 
      71         771 :         if (isnan(temp_val)) {
      72         514 :             if(strchr(s->qp_expr_str, 'x') || strchr(s->qp_expr_str, 'y'))
      73         514 :                 s->evaluate_per_mb = 1;
      74             :             else {
      75           0 :                 av_expr_free(e);
      76           0 :                 return AVERROR(EINVAL);
      77             :             }
      78             :         }
      79             : 
      80         771 :         s->lut[i + 129] = lrintf(temp_val);
      81             :     }
      82           3 :     av_expr_free(e);
      83             : 
      84           3 :     return 0;
      85             : }
      86             : 
      87          15 : static int filter_frame(AVFilterLink *inlink, AVFrame *in)
      88             : {
      89          15 :     AVFilterContext *ctx = inlink->dst;
      90          15 :     AVFilterLink *outlink = ctx->outputs[0];
      91          15 :     QPContext *s = ctx->priv;
      92             :     AVBufferRef *out_qp_table_buf;
      93          15 :     AVFrame *out = NULL;
      94             :     const int8_t *in_qp_table;
      95             :     int type, stride, ret;
      96             : 
      97          15 :     if (!s->qp_expr_str || ctx->is_disabled)
      98           0 :         return ff_filter_frame(outlink, in);
      99             : 
     100          15 :     out_qp_table_buf = av_buffer_alloc(s->h * s->qstride);
     101          15 :     if (!out_qp_table_buf) {
     102           0 :         ret = AVERROR(ENOMEM);
     103           0 :         goto fail;
     104             :     }
     105             : 
     106          15 :     out = av_frame_clone(in);
     107          15 :     if (!out) {
     108           0 :         av_buffer_unref(&out_qp_table_buf);
     109           0 :         ret = AVERROR(ENOMEM);
     110           0 :         goto fail;
     111             :     }
     112             : 
     113          15 :     in_qp_table = av_frame_get_qp_table(in, &stride, &type);
     114          15 :     av_frame_set_qp_table(out, out_qp_table_buf, s->qstride, type);
     115             : 
     116             : 
     117          15 :     if (s->evaluate_per_mb) {
     118             :         int y, x;
     119             : 
     120         190 :         for (y = 0; y < s->h; y++)
     121        4140 :             for (x = 0; x < s->qstride; x++) {
     122        3960 :                 int qp = in_qp_table ? in_qp_table[x + stride * y] : NAN;
     123        3960 :                 double var_values[] = { !!in_qp_table, qp, x, y, s->qstride, s->h, 0};
     124             :                 static const char *var_names[] = { "known", "qp", "x", "y", "w", "h", NULL };
     125             :                 double temp_val;
     126             : 
     127        3960 :                 ret = av_expr_parse_and_eval(&temp_val, s->qp_expr_str,
     128             :                                             var_names, var_values,
     129             :                                             NULL, NULL, NULL, NULL, 0, 0, ctx);
     130        3960 :                 if (ret < 0)
     131           0 :                     goto fail;
     132        3960 :                 out_qp_table_buf->data[x + s->qstride * y] = lrintf(temp_val);
     133             :             }
     134           5 :     } else if (in_qp_table) {
     135             :         int y, x;
     136             : 
     137           0 :         for (y = 0; y < s->h; y++)
     138           0 :             for (x = 0; x < s->qstride; x++)
     139           0 :                 out_qp_table_buf->data[x + s->qstride * y] = s->lut[129 +
     140           0 :                     ((int8_t)in_qp_table[x + stride * y])];
     141             :     } else {
     142           5 :         int y, x, qp = s->lut[0];
     143             : 
     144          95 :         for (y = 0; y < s->h; y++)
     145        2070 :             for (x = 0; x < s->qstride; x++)
     146        1980 :                 out_qp_table_buf->data[x + s->qstride * y] = qp;
     147             :     }
     148             : 
     149          15 :     ret = ff_filter_frame(outlink, out);
     150          15 :     out = NULL;
     151          15 : fail:
     152          15 :     av_frame_free(&in);
     153          15 :     av_frame_free(&out);
     154          15 :     return ret;
     155             : }
     156             : 
     157             : static const AVFilterPad qp_inputs[] = {
     158             :     {
     159             :         .name         = "default",
     160             :         .type         = AVMEDIA_TYPE_VIDEO,
     161             :         .filter_frame = filter_frame,
     162             :         .config_props = config_input,
     163             :     },
     164             :     { NULL }
     165             : };
     166             : 
     167             : static const AVFilterPad qp_outputs[] = {
     168             :     {
     169             :         .name = "default",
     170             :         .type = AVMEDIA_TYPE_VIDEO,
     171             :     },
     172             :     { NULL }
     173             : };
     174             : 
     175             : AVFilter ff_vf_qp = {
     176             :     .name          = "qp",
     177             :     .description   = NULL_IF_CONFIG_SMALL("Change video quantization parameters."),
     178             :     .priv_size     = sizeof(QPContext),
     179             :     .inputs        = qp_inputs,
     180             :     .outputs       = qp_outputs,
     181             :     .priv_class    = &qp_class,
     182             :     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL,
     183             : };

Generated by: LCOV version 1.13