Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright (c) 2003 Rich Felker
  3.  * Copyright (c) 2012 Stefano Sabatini
  4.  *
  5.  * This file is part of FFmpeg.
  6.  *
  7.  * FFmpeg is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU Lesser General Public
  9.  * License as published by the Free Software Foundation; either
  10.  * version 2.1 of the License, or (at your option) any later version.
  11.  *
  12.  * FFmpeg is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  * Lesser General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU Lesser General Public
  18.  * License along with FFmpeg; if not, write to the Free Software
  19.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20.  */
  21.  
  22. /**
  23.  * @file
  24.  * field filter, based on libmpcodecs/vf_field.c by Rich Felker
  25.  */
  26.  
  27. #include "libavutil/opt.h"
  28. #include "libavutil/pixdesc.h"
  29. #include "avfilter.h"
  30. #include "internal.h"
  31.  
  32. enum FieldType { FIELD_TYPE_TOP = 0, FIELD_TYPE_BOTTOM };
  33.  
  34. typedef struct {
  35.     const AVClass *class;
  36.     enum FieldType type;
  37.     int nb_planes;              ///< number of planes of the current format
  38. } FieldContext;
  39.  
  40. #define OFFSET(x) offsetof(FieldContext, x)
  41. #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
  42.  
  43. static const AVOption field_options[] = {
  44.     {"type", "set field type (top or bottom)", OFFSET(type), AV_OPT_TYPE_INT, {.i64=FIELD_TYPE_TOP}, 0, 1, FLAGS, "field_type" },
  45.     {"top",    "select top field",    0, AV_OPT_TYPE_CONST, {.i64=FIELD_TYPE_TOP},    INT_MIN, INT_MAX, FLAGS, "field_type"},
  46.     {"bottom", "select bottom field", 0, AV_OPT_TYPE_CONST, {.i64=FIELD_TYPE_BOTTOM}, INT_MIN, INT_MAX, FLAGS, "field_type"},
  47.     {NULL}
  48. };
  49.  
  50. AVFILTER_DEFINE_CLASS(field);
  51.  
  52. static int config_props_output(AVFilterLink *outlink)
  53. {
  54.     AVFilterContext *ctx = outlink->src;
  55.     FieldContext *field = ctx->priv;
  56.     AVFilterLink *inlink = ctx->inputs[0];
  57.  
  58.     field->nb_planes = av_pix_fmt_count_planes(outlink->format);
  59.  
  60.     outlink->w = inlink->w;
  61.     outlink->h = (inlink->h + (field->type == FIELD_TYPE_TOP)) / 2;
  62.  
  63.     av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d type:%s -> w:%d h:%d\n",
  64.            inlink->w, inlink->h, field->type == FIELD_TYPE_BOTTOM ? "bottom" : "top",
  65.            outlink->w, outlink->h);
  66.     return 0;
  67. }
  68.  
  69. static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref)
  70. {
  71.     FieldContext *field = inlink->dst->priv;
  72.     AVFilterLink *outlink = inlink->dst->outputs[0];
  73.     int i;
  74.  
  75.     inpicref->height = outlink->h;
  76.     inpicref->interlaced_frame = 0;
  77.  
  78.     for (i = 0; i < field->nb_planes; i++) {
  79.         if (field->type == FIELD_TYPE_BOTTOM)
  80.             inpicref->data[i] = inpicref->data[i] + inpicref->linesize[i];
  81.         inpicref->linesize[i] = 2 * inpicref->linesize[i];
  82.     }
  83.     return ff_filter_frame(outlink, inpicref);
  84. }
  85.  
  86. static const AVFilterPad field_inputs[] = {
  87.     {
  88.         .name         = "default",
  89.         .type         = AVMEDIA_TYPE_VIDEO,
  90.         .filter_frame = filter_frame,
  91.     },
  92.     { NULL }
  93. };
  94.  
  95. static const AVFilterPad field_outputs[] = {
  96.     {
  97.         .name         = "default",
  98.         .type         = AVMEDIA_TYPE_VIDEO,
  99.         .config_props = config_props_output,
  100.     },
  101.     { NULL }
  102. };
  103.  
  104. AVFilter avfilter_vf_field = {
  105.     .name        = "field",
  106.     .description = NULL_IF_CONFIG_SMALL("Extract a field from the input video."),
  107.     .priv_size   = sizeof(FieldContext),
  108.     .inputs      = field_inputs,
  109.     .outputs     = field_outputs,
  110.     .priv_class  = &field_class,
  111. };
  112.