Subversion Repositories Kolibri OS

Rev

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

  1. /*
  2.  * Copyright (c) 2013 Paul B Mahol
  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 "libavutil/pixdesc.h"
  22. #include "avfilter.h"
  23. #include "internal.h"
  24.  
  25. typedef struct {
  26.     int nb_planes;
  27.     AVFrame *second;
  28. } SeparateFieldsContext;
  29.  
  30. static int config_props_output(AVFilterLink *outlink)
  31. {
  32.     AVFilterContext *ctx = outlink->src;
  33.     SeparateFieldsContext *sf = ctx->priv;
  34.     AVFilterLink *inlink = ctx->inputs[0];
  35.  
  36.     sf->nb_planes = av_pix_fmt_count_planes(inlink->format);
  37.  
  38.     if (inlink->h & 1) {
  39.         av_log(ctx, AV_LOG_ERROR, "height must be even\n");
  40.         return AVERROR_INVALIDDATA;
  41.     }
  42.  
  43.     outlink->time_base.num = inlink->time_base.num;
  44.     outlink->time_base.den = inlink->time_base.den * 2;
  45.     outlink->frame_rate.num = inlink->frame_rate.num * 2;
  46.     outlink->frame_rate.den = inlink->frame_rate.den;
  47.     outlink->w = inlink->w;
  48.     outlink->h = inlink->h / 2;
  49.  
  50.     return 0;
  51. }
  52.  
  53. static void extract_field(AVFrame *frame, int nb_planes, int type)
  54. {
  55.     int i;
  56.  
  57.     for (i = 0; i < nb_planes; i++) {
  58.         if (type)
  59.             frame->data[i] = frame->data[i] + frame->linesize[i];
  60.         frame->linesize[i] *= 2;
  61.     }
  62. }
  63.  
  64. static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref)
  65. {
  66.     AVFilterContext *ctx = inlink->dst;
  67.     SeparateFieldsContext *sf = ctx->priv;
  68.     AVFilterLink *outlink = ctx->outputs[0];
  69.     int ret;
  70.  
  71.     inpicref->height = outlink->h;
  72.     inpicref->interlaced_frame = 0;
  73.  
  74.     if (!sf->second) {
  75.         goto clone;
  76.     } else {
  77.         AVFrame *second = sf->second;
  78.  
  79.         extract_field(second, sf->nb_planes, second->top_field_first);
  80.  
  81.         if (second->pts != AV_NOPTS_VALUE &&
  82.             inpicref->pts != AV_NOPTS_VALUE)
  83.             second->pts += inpicref->pts;
  84.         else
  85.             second->pts = AV_NOPTS_VALUE;
  86.  
  87.         ret = ff_filter_frame(outlink, second);
  88.         if (ret < 0)
  89.             return ret;
  90. clone:
  91.         sf->second = av_frame_clone(inpicref);
  92.         if (!sf->second)
  93.             return AVERROR(ENOMEM);
  94.     }
  95.  
  96.     extract_field(inpicref, sf->nb_planes, !inpicref->top_field_first);
  97.  
  98.     if (inpicref->pts != AV_NOPTS_VALUE)
  99.         inpicref->pts *= 2;
  100.  
  101.     return ff_filter_frame(outlink, inpicref);
  102. }
  103.  
  104. static int request_frame(AVFilterLink *outlink)
  105. {
  106.     AVFilterContext *ctx = outlink->src;
  107.     SeparateFieldsContext *sf = ctx->priv;
  108.     int ret;
  109.  
  110.     ret = ff_request_frame(ctx->inputs[0]);
  111.     if (ret == AVERROR_EOF && sf->second) {
  112.         sf->second->pts *= 2;
  113.         extract_field(sf->second, sf->nb_planes, sf->second->top_field_first);
  114.         ret = ff_filter_frame(outlink, sf->second);
  115.         sf->second = 0;
  116.     }
  117.  
  118.     return ret;
  119. }
  120.  
  121. static const AVFilterPad separatefields_inputs[] = {
  122.     {
  123.         .name         = "default",
  124.         .type         = AVMEDIA_TYPE_VIDEO,
  125.         .filter_frame = filter_frame,
  126.     },
  127.     { NULL }
  128. };
  129.  
  130. static const AVFilterPad separatefields_outputs[] = {
  131.     {
  132.         .name          = "default",
  133.         .type          = AVMEDIA_TYPE_VIDEO,
  134.         .config_props  = config_props_output,
  135.         .request_frame = request_frame,
  136.     },
  137.     { NULL }
  138. };
  139.  
  140. AVFilter avfilter_vf_separatefields = {
  141.     .name        = "separatefields",
  142.     .description = NULL_IF_CONFIG_SMALL("Split input video frames into fields."),
  143.     .priv_size   = sizeof(SeparateFieldsContext),
  144.     .inputs      = separatefields_inputs,
  145.     .outputs     = separatefields_outputs,
  146. };
  147.