Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright (c) 2012 Rudolf Polzer
  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 telecine filter, heavily based from mpv-player:TOOLS/vf_dlopen/telecine.c by
  24.  * Rudolf Polzer.
  25.  */
  26.  
  27. #include "libavutil/avstring.h"
  28. #include "libavutil/imgutils.h"
  29. #include "libavutil/opt.h"
  30. #include "libavutil/pixdesc.h"
  31. #include "avfilter.h"
  32. #include "formats.h"
  33. #include "internal.h"
  34. #include "video.h"
  35.  
  36. typedef struct {
  37.     const AVClass *class;
  38.     int first_field;
  39.     char *pattern;
  40.     unsigned int pattern_pos;
  41.  
  42.     AVRational pts;
  43.     double ts_unit;
  44.     int out_cnt;
  45.     int occupied;
  46.  
  47.     int nb_planes;
  48.     int planeheight[4];
  49.     int stride[4];
  50.  
  51.     AVFrame *frame[5];
  52.     AVFrame *temp;
  53. } TelecineContext;
  54.  
  55. #define OFFSET(x) offsetof(TelecineContext, x)
  56. #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
  57.  
  58. static const AVOption telecine_options[] = {
  59.     {"first_field", "select first field", OFFSET(first_field), AV_OPT_TYPE_INT,   {.i64=0}, 0, 1, FLAGS, "field"},
  60.         {"top",    "select top field first",                0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "field"},
  61.         {"t",      "select top field first",                0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "field"},
  62.         {"bottom", "select bottom field first",             0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "field"},
  63.         {"b",      "select bottom field first",             0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "field"},
  64.     {"pattern", "pattern that describe for how many fields a frame is to be displayed", OFFSET(pattern), AV_OPT_TYPE_STRING, {.str="23"}, 0, 0, FLAGS},
  65.     {NULL}
  66. };
  67.  
  68. AVFILTER_DEFINE_CLASS(telecine);
  69.  
  70. static av_cold int init(AVFilterContext *ctx)
  71. {
  72.     TelecineContext *tc = ctx->priv;
  73.     const char *p;
  74.     int max = 0;
  75.  
  76.     if (!strlen(tc->pattern)) {
  77.         av_log(ctx, AV_LOG_ERROR, "No pattern provided.\n");
  78.         return AVERROR_INVALIDDATA;
  79.     }
  80.  
  81.     for (p = tc->pattern; *p; p++) {
  82.         if (!av_isdigit(*p)) {
  83.             av_log(ctx, AV_LOG_ERROR, "Provided pattern includes non-numeric characters.\n");
  84.             return AVERROR_INVALIDDATA;
  85.         }
  86.  
  87.         max = FFMAX(*p - '0', max);
  88.         tc->pts.num += 2;
  89.         tc->pts.den += *p - '0';
  90.     }
  91.  
  92.     tc->out_cnt = (max + 1) / 2;
  93.     av_log(ctx, AV_LOG_INFO, "Telecine pattern %s yields up to %d frames per frame, pts advance factor: %d/%d\n",
  94.            tc->pattern, tc->out_cnt, tc->pts.num, tc->pts.den);
  95.  
  96.     return 0;
  97. }
  98.  
  99. static int query_formats(AVFilterContext *ctx)
  100. {
  101.     AVFilterFormats *pix_fmts = NULL;
  102.     int fmt;
  103.  
  104.     for (fmt = 0; fmt < AV_PIX_FMT_NB; fmt++) {
  105.         const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt);
  106.         if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL ||
  107.               desc->flags & AV_PIX_FMT_FLAG_PAL     ||
  108.               desc->flags & AV_PIX_FMT_FLAG_BITSTREAM))
  109.             ff_add_format(&pix_fmts, fmt);
  110.     }
  111.  
  112.     ff_set_common_formats(ctx, pix_fmts);
  113.     return 0;
  114. }
  115.  
  116. static int config_input(AVFilterLink *inlink)
  117. {
  118.     TelecineContext *tc = inlink->dst->priv;
  119.     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
  120.     int i, ret;
  121.  
  122.     tc->temp = ff_get_video_buffer(inlink, inlink->w, inlink->h);
  123.     if (!tc->temp)
  124.         return AVERROR(ENOMEM);
  125.     for (i = 0; i < tc->out_cnt; i++) {
  126.         tc->frame[i] = ff_get_video_buffer(inlink, inlink->w, inlink->h);
  127.         if (!tc->frame[i])
  128.             return AVERROR(ENOMEM);
  129.     }
  130.  
  131.     if ((ret = av_image_fill_linesizes(tc->stride, inlink->format, inlink->w)) < 0)
  132.         return ret;
  133.  
  134.     tc->planeheight[1] = tc->planeheight[2] = FF_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
  135.     tc->planeheight[0] = tc->planeheight[3] = inlink->h;
  136.  
  137.     tc->nb_planes = av_pix_fmt_count_planes(inlink->format);
  138.  
  139.     return 0;
  140. }
  141.  
  142. static int config_output(AVFilterLink *outlink)
  143. {
  144.     AVFilterContext *ctx = outlink->src;
  145.     TelecineContext *tc = ctx->priv;
  146.     const AVFilterLink *inlink = ctx->inputs[0];
  147.     AVRational fps = inlink->frame_rate;
  148.  
  149.     if (!fps.num || !fps.den) {
  150.         av_log(ctx, AV_LOG_ERROR, "The input needs a constant frame rate; "
  151.                "current rate of %d/%d is invalid\n", fps.num, fps.den);
  152.         return AVERROR(EINVAL);
  153.     }
  154.     fps = av_mul_q(fps, av_inv_q(tc->pts));
  155.     av_log(ctx, AV_LOG_VERBOSE, "FPS: %d/%d -> %d/%d\n",
  156.            inlink->frame_rate.num, inlink->frame_rate.den, fps.num, fps.den);
  157.  
  158.     outlink->flags |= FF_LINK_FLAG_REQUEST_LOOP;
  159.     outlink->frame_rate = fps;
  160.     outlink->time_base = av_mul_q(inlink->time_base, tc->pts);
  161.     av_log(ctx, AV_LOG_VERBOSE, "TB: %d/%d -> %d/%d\n",
  162.            inlink->time_base.num, inlink->time_base.den, outlink->time_base.num, outlink->time_base.den);
  163.  
  164.     tc->ts_unit = av_q2d(av_inv_q(av_mul_q(fps, outlink->time_base)));
  165.  
  166.     return 0;
  167. }
  168.  
  169. static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref)
  170. {
  171.     AVFilterContext *ctx = inlink->dst;
  172.     AVFilterLink *outlink = ctx->outputs[0];
  173.     TelecineContext *tc = ctx->priv;
  174.     int i, len, ret = 0, nout = 0;
  175.  
  176.     len = tc->pattern[tc->pattern_pos] - '0';
  177.  
  178.     tc->pattern_pos++;
  179.     if (!tc->pattern[tc->pattern_pos])
  180.         tc->pattern_pos = 0;
  181.  
  182.     if (!len) { // do not output any field from this frame
  183.         av_frame_free(&inpicref);
  184.         return 0;
  185.     }
  186.  
  187.     if (tc->occupied) {
  188.         for (i = 0; i < tc->nb_planes; i++) {
  189.             // fill in the EARLIER field from the buffered pic
  190.             av_image_copy_plane(tc->frame[nout]->data[i] + tc->frame[nout]->linesize[i] * tc->first_field,
  191.                                 tc->frame[nout]->linesize[i] * 2,
  192.                                 tc->temp->data[i] + tc->temp->linesize[i] * tc->first_field,
  193.                                 tc->temp->linesize[i] * 2,
  194.                                 tc->stride[i],
  195.                                 (tc->planeheight[i] - tc->first_field + 1) / 2);
  196.             // fill in the LATER field from the new pic
  197.             av_image_copy_plane(tc->frame[nout]->data[i] + tc->frame[nout]->linesize[i] * !tc->first_field,
  198.                                 tc->frame[nout]->linesize[i] * 2,
  199.                                 inpicref->data[i] + inpicref->linesize[i] * !tc->first_field,
  200.                                 inpicref->linesize[i] * 2,
  201.                                 tc->stride[i],
  202.                                 (tc->planeheight[i] - !tc->first_field + 1) / 2);
  203.         }
  204.         nout++;
  205.         len--;
  206.         tc->occupied = 0;
  207.     }
  208.  
  209.     while (len >= 2) {
  210.         // output THIS image as-is
  211.         for (i = 0; i < tc->nb_planes; i++)
  212.             av_image_copy_plane(tc->frame[nout]->data[i], tc->frame[nout]->linesize[i],
  213.                                 inpicref->data[i], inpicref->linesize[i],
  214.                                 tc->stride[i],
  215.                                 tc->planeheight[i]);
  216.         nout++;
  217.         len -= 2;
  218.     }
  219.  
  220.     if (len >= 1) {
  221.         // copy THIS image to the buffer, we need it later
  222.         for (i = 0; i < tc->nb_planes; i++)
  223.             av_image_copy_plane(tc->temp->data[i], tc->temp->linesize[i],
  224.                                 inpicref->data[i], inpicref->linesize[i],
  225.                                 tc->stride[i],
  226.                                 tc->planeheight[i]);
  227.         tc->occupied = 1;
  228.     }
  229.  
  230.     for (i = 0; i < nout; i++) {
  231.         AVFrame *frame = av_frame_clone(tc->frame[i]);
  232.  
  233.         if (!frame) {
  234.             av_frame_free(&inpicref);
  235.             return AVERROR(ENOMEM);
  236.         }
  237.  
  238.         frame->pts = outlink->frame_count * tc->ts_unit;
  239.         ret = ff_filter_frame(outlink, frame);
  240.     }
  241.     av_frame_free(&inpicref);
  242.  
  243.     return ret;
  244. }
  245.  
  246. static av_cold void uninit(AVFilterContext *ctx)
  247. {
  248.     TelecineContext *tc = ctx->priv;
  249.     int i;
  250.  
  251.     av_frame_free(&tc->temp);
  252.     for (i = 0; i < tc->out_cnt; i++)
  253.         av_frame_free(&tc->frame[i]);
  254. }
  255.  
  256. static const AVFilterPad telecine_inputs[] = {
  257.     {
  258.         .name          = "default",
  259.         .type          = AVMEDIA_TYPE_VIDEO,
  260.         .filter_frame  = filter_frame,
  261.         .config_props  = config_input,
  262.     },
  263.     { NULL }
  264. };
  265.  
  266. static const AVFilterPad telecine_outputs[] = {
  267.     {
  268.         .name          = "default",
  269.         .type          = AVMEDIA_TYPE_VIDEO,
  270.         .config_props  = config_output,
  271.     },
  272.     { NULL }
  273. };
  274.  
  275. AVFilter avfilter_vf_telecine = {
  276.     .name          = "telecine",
  277.     .description   = NULL_IF_CONFIG_SMALL("Apply a telecine pattern."),
  278.     .priv_size     = sizeof(TelecineContext),
  279.     .priv_class    = &telecine_class,
  280.     .init          = init,
  281.     .uninit        = uninit,
  282.     .query_formats = query_formats,
  283.     .inputs        = telecine_inputs,
  284.     .outputs       = telecine_outputs,
  285. };
  286.