Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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. static int config_input(AVFilterLink *inlink)
  50. {
  51.     AVFilterContext *ctx = inlink->dst;
  52.     QPContext *s = ctx->priv;
  53.     int i;
  54.     int ret;
  55.     AVExpr *e = NULL;
  56.     static const char *var_names[] = { "known", "qp", "x", "y", "w", "h", NULL };
  57.  
  58.     if (!s->qp_expr_str)
  59.         return 0;
  60.  
  61.     ret = av_expr_parse(&e, s->qp_expr_str, var_names, NULL, NULL, NULL, NULL, 0, ctx);
  62.     if (ret < 0)
  63.         return ret;
  64.  
  65.     s->h       = (inlink->h + 15) >> 4;
  66.     s->qstride = (inlink->w + 15) >> 4;
  67.     for (i = -129; i < 128; i++) {
  68.         double var_values[] = { i != -129, i, NAN, NAN, s->qstride, s->h, 0};
  69.         double temp_val = av_expr_eval(e, var_values, NULL);
  70.  
  71.         if (isnan(temp_val)) {
  72.             if(strchr(s->qp_expr_str, 'x') || strchr(s->qp_expr_str, 'y'))
  73.                 s->evaluate_per_mb = 1;
  74.             else {
  75.                 av_expr_free(e);
  76.                 return AVERROR(EINVAL);
  77.             }
  78.         }
  79.  
  80.         s->lut[i + 129] = lrintf(temp_val);
  81.     }
  82.     av_expr_free(e);
  83.  
  84.     return 0;
  85. }
  86.  
  87. static int filter_frame(AVFilterLink *inlink, AVFrame *in)
  88. {
  89.     AVFilterContext *ctx = inlink->dst;
  90.     AVFilterLink *outlink = ctx->outputs[0];
  91.     QPContext *s = ctx->priv;
  92.     AVBufferRef *out_qp_table_buf;
  93.     AVFrame *out = NULL;
  94.     const int8_t *in_qp_table;
  95.     int type, stride, ret;
  96.  
  97.     if (!s->qp_expr_str || ctx->is_disabled)
  98.         return ff_filter_frame(outlink, in);
  99.  
  100.     out_qp_table_buf = av_buffer_alloc(s->h * s->qstride);
  101.     if (!out_qp_table_buf) {
  102.         ret = AVERROR(ENOMEM);
  103.         goto fail;
  104.     }
  105.  
  106.     out = av_frame_clone(in);
  107.     if (!out) {
  108.         av_buffer_unref(&out_qp_table_buf);
  109.         ret = AVERROR(ENOMEM);
  110.         goto fail;
  111.     }
  112.  
  113.     in_qp_table = av_frame_get_qp_table(in, &stride, &type);
  114.     av_frame_set_qp_table(out, out_qp_table_buf, s->qstride, type);
  115.  
  116.  
  117.     if (s->evaluate_per_mb) {
  118.         int y, x;
  119.  
  120.         for (y = 0; y < s->h; y++)
  121.             for (x = 0; x < s->qstride; x++) {
  122.                 int qp = in_qp_table ? in_qp_table[x + stride * y] : NAN;
  123.                 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.                 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.                 if (ret < 0)
  131.                     goto fail;
  132.                 out_qp_table_buf->data[x + s->qstride * y] = lrintf(temp_val);
  133.             }
  134.     } else if (in_qp_table) {
  135.         int y, x;
  136.  
  137.         for (y = 0; y < s->h; y++)
  138.             for (x = 0; x < s->qstride; x++)
  139.                 out_qp_table_buf->data[x + s->qstride * y] = s->lut[129 +
  140.                     ((int8_t)in_qp_table[x + stride * y])];
  141.     } else {
  142.         int y, x, qp = s->lut[0];
  143.  
  144.         for (y = 0; y < s->h; y++)
  145.             for (x = 0; x < s->qstride; x++)
  146.                 out_qp_table_buf->data[x + s->qstride * y] = qp;
  147.     }
  148.  
  149.     ret = ff_filter_frame(outlink, out);
  150.     out = NULL;
  151. fail:
  152.     av_frame_free(&in);
  153.     av_frame_free(&out);
  154.     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. };
  184.