Subversion Repositories Kolibri OS

Rev

Go to most recent revision | 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.     enum FilterMode luma_mode, chroma_mode, alpha_mode;
  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; fmt < AV_PIX_FMT_NB; 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.     ff_set_common_formats(ctx, formats);
  96.     return 0;
  97. }
  98.  
  99. static int config_input(AVFilterLink *inlink)
  100. {
  101.     IlContext *il = inlink->dst->priv;
  102.     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
  103.     int ret;
  104.  
  105.     il->nb_planes = av_pix_fmt_count_planes(inlink->format);
  106.  
  107.     il->has_alpha = !!(desc->flags & AV_PIX_FMT_FLAG_ALPHA);
  108.     if ((ret = av_image_fill_linesizes(il->linesize, inlink->format, inlink->w)) < 0)
  109.         return ret;
  110.  
  111.     il->chroma_height = FF_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
  112.  
  113.     return 0;
  114. }
  115.  
  116. static void interleave(uint8_t *dst, uint8_t *src, int w, int h,
  117.                        int dst_linesize, int src_linesize,
  118.                        enum FilterMode mode, int swap)
  119. {
  120.     const int a = swap;
  121.     const int b = 1 - a;
  122.     const int m = h >> 1;
  123.     int y;
  124.  
  125.     switch (mode) {
  126.     case MODE_DEINTERLEAVE:
  127.         for (y = 0; y < m; y++) {
  128.             memcpy(dst + dst_linesize *  y     , src + src_linesize * (y * 2 + a), w);
  129.             memcpy(dst + dst_linesize * (y + m), src + src_linesize * (y * 2 + b), w);
  130.         }
  131.         break;
  132.     case MODE_NONE:
  133.         for (y = 0; y < m; y++) {
  134.             memcpy(dst + dst_linesize *  y * 2     , src + src_linesize * (y * 2 + a), w);
  135.             memcpy(dst + dst_linesize * (y * 2 + 1), src + src_linesize * (y * 2 + b), w);
  136.         }
  137.         break;
  138.     case MODE_INTERLEAVE:
  139.         for (y = 0; y < m; y++) {
  140.             memcpy(dst + dst_linesize * (y * 2 + a), src + src_linesize *  y     , w);
  141.             memcpy(dst + dst_linesize * (y * 2 + b), src + src_linesize * (y + m), w);
  142.         }
  143.         break;
  144.     }
  145. }
  146.  
  147. static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref)
  148. {
  149.     IlContext *il = inlink->dst->priv;
  150.     AVFilterLink *outlink = inlink->dst->outputs[0];
  151.     AVFrame *out;
  152.     int comp;
  153.  
  154.     out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
  155.     if (!out) {
  156.         av_frame_free(&inpicref);
  157.         return AVERROR(ENOMEM);
  158.     }
  159.     av_frame_copy_props(out, inpicref);
  160.  
  161.     interleave(out->data[0], inpicref->data[0],
  162.                il->linesize[0], inlink->h,
  163.                out->linesize[0], inpicref->linesize[0],
  164.                il->luma_mode, il->luma_swap);
  165.  
  166.     for (comp = 1; comp < (il->nb_planes - il->has_alpha); comp++) {
  167.         interleave(out->data[comp], inpicref->data[comp],
  168.                    il->linesize[comp], il->chroma_height,
  169.                    out->linesize[comp], inpicref->linesize[comp],
  170.                    il->chroma_mode, il->chroma_swap);
  171.     }
  172.  
  173.     if (il->has_alpha) {
  174.         comp = il->nb_planes - 1;
  175.         interleave(out->data[comp], inpicref->data[comp],
  176.                    il->linesize[comp], inlink->h,
  177.                    out->linesize[comp], inpicref->linesize[comp],
  178.                    il->alpha_mode, il->alpha_swap);
  179.     }
  180.  
  181.     av_frame_free(&inpicref);
  182.     return ff_filter_frame(outlink, out);
  183. }
  184.  
  185. static const AVFilterPad inputs[] = {
  186.     {
  187.         .name         = "default",
  188.         .type         = AVMEDIA_TYPE_VIDEO,
  189.         .filter_frame = filter_frame,
  190.         .config_props = config_input,
  191.     },
  192.     { NULL }
  193. };
  194.  
  195. static const AVFilterPad outputs[] = {
  196.     {
  197.         .name = "default",
  198.         .type = AVMEDIA_TYPE_VIDEO,
  199.     },
  200.     { NULL }
  201. };
  202.  
  203. AVFilter avfilter_vf_il = {
  204.     .name          = "il",
  205.     .description   = NULL_IF_CONFIG_SMALL("Deinterleave or interleave fields."),
  206.     .priv_size     = sizeof(IlContext),
  207.     .query_formats = query_formats,
  208.     .inputs        = inputs,
  209.     .outputs       = outputs,
  210.     .priv_class    = &il_class,
  211.     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
  212. };
  213.