Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright (c) 2002 Michael Niedermayer <michaelni@gmx.at>
  3.  * Copyright (c) 2013 Paul B Mahol
  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.  * (de)interleave fields filter
  25.  */
  26.  
  27. #include "libavutil/opt.h"
  28. #include "libavutil/imgutils.h"
  29. #include "libavutil/pixdesc.h"
  30. #include "avfilter.h"
  31. #include "internal.h"
  32.  
  33. enum FilterMode {
  34.     MODE_NONE,
  35.     MODE_INTERLEAVE,
  36.     MODE_DEINTERLEAVE
  37. };
  38.  
  39. typedef struct {
  40.     const AVClass *class;
  41.     int luma_mode, chroma_mode, alpha_mode; ///<FilterMode
  42.     int luma_swap, chroma_swap, alpha_swap;
  43.     int nb_planes;
  44.     int linesize[4], chroma_height;
  45.     int has_alpha;
  46. } IlContext;
  47.  
  48. #define OFFSET(x) offsetof(IlContext, x)
  49. #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
  50.  
  51. static const AVOption il_options[] = {
  52.     {"luma_mode",   "select luma mode", OFFSET(luma_mode), AV_OPT_TYPE_INT, {.i64=MODE_NONE}, MODE_NONE, MODE_DEINTERLEAVE, FLAGS, "luma_mode"},
  53.     {"l",           "select luma mode", OFFSET(luma_mode), AV_OPT_TYPE_INT, {.i64=MODE_NONE}, MODE_NONE, MODE_DEINTERLEAVE, FLAGS, "luma_mode"},
  54.     {"none",         NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_NONE},         0, 0, FLAGS, "luma_mode"},
  55.     {"interleave",   NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_INTERLEAVE},   0, 0, FLAGS, "luma_mode"},
  56.     {"i",            NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_INTERLEAVE},   0, 0, FLAGS, "luma_mode"},
  57.     {"deinterleave", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_DEINTERLEAVE}, 0, 0, FLAGS, "luma_mode"},
  58.     {"d",            NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_DEINTERLEAVE}, 0, 0, FLAGS, "luma_mode"},
  59.     {"chroma_mode", "select chroma mode", OFFSET(chroma_mode), AV_OPT_TYPE_INT, {.i64=MODE_NONE}, MODE_NONE, MODE_DEINTERLEAVE, FLAGS, "chroma_mode"},
  60.     {"c",           "select chroma mode", OFFSET(chroma_mode), AV_OPT_TYPE_INT, {.i64=MODE_NONE}, MODE_NONE, MODE_DEINTERLEAVE, FLAGS, "chroma_mode"},
  61.     {"none",         NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_NONE},         0, 0, FLAGS, "chroma_mode"},
  62.     {"interleave",   NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_INTERLEAVE},   0, 0, FLAGS, "chroma_mode"},
  63.     {"i",            NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_INTERLEAVE},   0, 0, FLAGS, "chroma_mode"},
  64.     {"deinterleave", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_DEINTERLEAVE}, 0, 0, FLAGS, "chroma_mode"},
  65.     {"d",            NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_DEINTERLEAVE}, 0, 0, FLAGS, "chroma_mode"},
  66.     {"alpha_mode", "select alpha mode", OFFSET(alpha_mode), AV_OPT_TYPE_INT, {.i64=MODE_NONE}, MODE_NONE, MODE_DEINTERLEAVE, FLAGS, "alpha_mode"},
  67.     {"a",          "select alpha mode", OFFSET(alpha_mode), AV_OPT_TYPE_INT, {.i64=MODE_NONE}, MODE_NONE, MODE_DEINTERLEAVE, FLAGS, "alpha_mode"},
  68.     {"none",         NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_NONE},         0, 0, FLAGS, "alpha_mode"},
  69.     {"interleave",   NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_INTERLEAVE},   0, 0, FLAGS, "alpha_mode"},
  70.     {"i",            NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_INTERLEAVE},   0, 0, FLAGS, "alpha_mode"},
  71.     {"deinterleave", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_DEINTERLEAVE}, 0, 0, FLAGS, "alpha_mode"},
  72.     {"d",            NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_DEINTERLEAVE}, 0, 0, FLAGS, "alpha_mode"},
  73.     {"luma_swap",   "swap luma fields",   OFFSET(luma_swap),   AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS},
  74.     {"ls",          "swap luma fields",   OFFSET(luma_swap),   AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS},
  75.     {"chroma_swap", "swap chroma fields", OFFSET(chroma_swap), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS},
  76.     {"cs",          "swap chroma fields", OFFSET(chroma_swap), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS},
  77.     {"alpha_swap",  "swap alpha fields",  OFFSET(alpha_swap),  AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS},
  78.     {"as",          "swap alpha fields",  OFFSET(alpha_swap),  AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS},
  79.     {NULL}
  80. };
  81.  
  82. AVFILTER_DEFINE_CLASS(il);
  83.  
  84. static int query_formats(AVFilterContext *ctx)
  85. {
  86.     AVFilterFormats *formats = NULL;
  87.     int fmt;
  88.  
  89.     for (fmt = 0; av_pix_fmt_desc_get(fmt); fmt++) {
  90.         const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt);
  91.         if (!(desc->flags & AV_PIX_FMT_FLAG_PAL) && !(desc->flags & AV_PIX_FMT_FLAG_HWACCEL))
  92.             ff_add_format(&formats, fmt);
  93.     }
  94.  
  95.     return ff_set_common_formats(ctx, formats);
  96. }
  97.  
  98. static int config_input(AVFilterLink *inlink)
  99. {
  100.     IlContext *s = inlink->dst->priv;
  101.     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
  102.     int ret;
  103.  
  104.     s->nb_planes = av_pix_fmt_count_planes(inlink->format);
  105.  
  106.     s->has_alpha = !!(desc->flags & AV_PIX_FMT_FLAG_ALPHA);
  107.     if ((ret = av_image_fill_linesizes(s->linesize, inlink->format, inlink->w)) < 0)
  108.         return ret;
  109.  
  110.     s->chroma_height = FF_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
  111.  
  112.     return 0;
  113. }
  114.  
  115. static void interleave(uint8_t *dst, uint8_t *src, int w, int h,
  116.                        int dst_linesize, int src_linesize,
  117.                        enum FilterMode mode, int swap)
  118. {
  119.     const int a = swap;
  120.     const int b = 1 - a;
  121.     const int m = h >> 1;
  122.     int y;
  123.  
  124.     switch (mode) {
  125.     case MODE_DEINTERLEAVE:
  126.         for (y = 0; y < m; y++) {
  127.             memcpy(dst + dst_linesize *  y     , src + src_linesize * (y * 2 + a), w);
  128.             memcpy(dst + dst_linesize * (y + m), src + src_linesize * (y * 2 + b), w);
  129.         }
  130.         break;
  131.     case MODE_NONE:
  132.         for (y = 0; y < m; y++) {
  133.             memcpy(dst + dst_linesize *  y * 2     , src + src_linesize * (y * 2 + a), w);
  134.             memcpy(dst + dst_linesize * (y * 2 + 1), src + src_linesize * (y * 2 + b), w);
  135.         }
  136.         break;
  137.     case MODE_INTERLEAVE:
  138.         for (y = 0; y < m; y++) {
  139.             memcpy(dst + dst_linesize * (y * 2 + a), src + src_linesize *  y     , w);
  140.             memcpy(dst + dst_linesize * (y * 2 + b), src + src_linesize * (y + m), w);
  141.         }
  142.         break;
  143.     }
  144. }
  145.  
  146. static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref)
  147. {
  148.     IlContext *s = inlink->dst->priv;
  149.     AVFilterLink *outlink = inlink->dst->outputs[0];
  150.     AVFrame *out;
  151.     int comp;
  152.  
  153.     out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
  154.     if (!out) {
  155.         av_frame_free(&inpicref);
  156.         return AVERROR(ENOMEM);
  157.     }
  158.     av_frame_copy_props(out, inpicref);
  159.  
  160.     interleave(out->data[0], inpicref->data[0],
  161.                s->linesize[0], inlink->h,
  162.                out->linesize[0], inpicref->linesize[0],
  163.                s->luma_mode, s->luma_swap);
  164.  
  165.     for (comp = 1; comp < (s->nb_planes - s->has_alpha); comp++) {
  166.         interleave(out->data[comp], inpicref->data[comp],
  167.                    s->linesize[comp], s->chroma_height,
  168.                    out->linesize[comp], inpicref->linesize[comp],
  169.                    s->chroma_mode, s->chroma_swap);
  170.     }
  171.  
  172.     if (s->has_alpha) {
  173.         comp = s->nb_planes - 1;
  174.         interleave(out->data[comp], inpicref->data[comp],
  175.                    s->linesize[comp], inlink->h,
  176.                    out->linesize[comp], inpicref->linesize[comp],
  177.                    s->alpha_mode, s->alpha_swap);
  178.     }
  179.  
  180.     av_frame_free(&inpicref);
  181.     return ff_filter_frame(outlink, out);
  182. }
  183.  
  184. static const AVFilterPad inputs[] = {
  185.     {
  186.         .name         = "default",
  187.         .type         = AVMEDIA_TYPE_VIDEO,
  188.         .filter_frame = filter_frame,
  189.         .config_props = config_input,
  190.     },
  191.     { NULL }
  192. };
  193.  
  194. static const AVFilterPad outputs[] = {
  195.     {
  196.         .name = "default",
  197.         .type = AVMEDIA_TYPE_VIDEO,
  198.     },
  199.     { NULL }
  200. };
  201.  
  202. AVFilter ff_vf_il = {
  203.     .name          = "il",
  204.     .description   = NULL_IF_CONFIG_SMALL("Deinterleave or interleave fields."),
  205.     .priv_size     = sizeof(IlContext),
  206.     .query_formats = query_formats,
  207.     .inputs        = inputs,
  208.     .outputs       = outputs,
  209.     .priv_class    = &il_class,
  210.     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
  211. };
  212.