Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright (c) 2003 Rich Felker
  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 General Public
  8.  * License as published by the Free Software Foundation; either
  9.  * version 2 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
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License along
  17.  * 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/avassert.h"
  22. #include "libavutil/imgutils.h"
  23. #include "libavutil/opt.h"
  24. #include "libavutil/pixdesc.h"
  25. #include "avfilter.h"
  26. #include "formats.h"
  27. #include "internal.h"
  28. #include "video.h"
  29. #include "vf_pullup.h"
  30.  
  31. #define F_HAVE_BREAKS   1
  32. #define F_HAVE_AFFINITY 2
  33.  
  34. #define BREAK_LEFT  1
  35. #define BREAK_RIGHT 2
  36.  
  37. #define OFFSET(x) offsetof(PullupContext, x)
  38. #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
  39.  
  40. static const AVOption pullup_options[] = {
  41.     { "jl", "set left junk size",  OFFSET(junk_left),  AV_OPT_TYPE_INT, {.i64=1}, 0, INT_MAX, FLAGS },
  42.     { "jr", "set right junk size", OFFSET(junk_right), AV_OPT_TYPE_INT, {.i64=1}, 0, INT_MAX, FLAGS },
  43.     { "jt", "set top junk size",   OFFSET(junk_top),   AV_OPT_TYPE_INT, {.i64=4}, 1, INT_MAX, FLAGS },
  44.     { "jb", "set bottom junk size", OFFSET(junk_bottom), AV_OPT_TYPE_INT, {.i64=4}, 1, INT_MAX, FLAGS },
  45.     { "sb", "set strict breaks", OFFSET(strict_breaks), AV_OPT_TYPE_INT, {.i64=0},-1, 1, FLAGS },
  46.     { "mp", "set metric plane",  OFFSET(metric_plane),  AV_OPT_TYPE_INT, {.i64=0}, 0, 2, FLAGS, "mp" },
  47.     { "y", "luma",        0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "mp" },
  48.     { "u", "chroma blue", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "mp" },
  49.     { "v", "chroma red",  0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "mp" },
  50.     { NULL }
  51. };
  52.  
  53. AVFILTER_DEFINE_CLASS(pullup);
  54.  
  55. static int query_formats(AVFilterContext *ctx)
  56. {
  57.     static const enum AVPixelFormat pix_fmts[] = {
  58.         AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ440P,
  59.         AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ420P,
  60.         AV_PIX_FMT_YUV444P,  AV_PIX_FMT_YUV440P,
  61.         AV_PIX_FMT_YUV422P,  AV_PIX_FMT_YUV420P,
  62.         AV_PIX_FMT_YUV411P,  AV_PIX_FMT_YUV410P,
  63.         AV_PIX_FMT_YUVJ411P, AV_PIX_FMT_GRAY8,
  64.         AV_PIX_FMT_NONE
  65.     };
  66.  
  67.     AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts);
  68.     if (!fmts_list)
  69.         return AVERROR(ENOMEM);
  70.     return ff_set_common_formats(ctx, fmts_list);
  71. }
  72.  
  73. #define ABS(a) (((a) ^ ((a) >> 31)) - ((a) >> 31))
  74.  
  75. static int diff_c(const uint8_t *a, const uint8_t *b, ptrdiff_t s)
  76. {
  77.     int i, j, diff = 0;
  78.  
  79.     for (i = 0; i < 4; i++) {
  80.         for (j = 0; j < 8; j++)
  81.             diff += ABS(a[j] - b[j]);
  82.         a += s;
  83.         b += s;
  84.     }
  85.  
  86.     return diff;
  87. }
  88.  
  89. static int comb_c(const uint8_t *a, const uint8_t *b, ptrdiff_t s)
  90. {
  91.     int i, j, comb = 0;
  92.  
  93.     for (i = 0; i < 4; i++) {
  94.         for (j = 0; j < 8; j++)
  95.             comb += ABS((a[j] << 1) - b[j - s] - b[j    ]) +
  96.                     ABS((b[j] << 1) - a[j    ] - a[j + s]);
  97.         a += s;
  98.         b += s;
  99.     }
  100.  
  101.     return comb;
  102. }
  103.  
  104. static int var_c(const uint8_t *a, const uint8_t *b, ptrdiff_t s)
  105. {
  106.     int i, j, var = 0;
  107.  
  108.     for (i = 0; i < 3; i++) {
  109.         for (j = 0; j < 8; j++)
  110.             var += ABS(a[j] - a[j + s]);
  111.         a += s;
  112.     }
  113.  
  114.     return 4 * var; /* match comb scaling */
  115. }
  116.  
  117. static int alloc_metrics(PullupContext *s, PullupField *f)
  118. {
  119.     f->diffs = av_calloc(FFALIGN(s->metric_length, 16), sizeof(*f->diffs));
  120.     f->combs = av_calloc(FFALIGN(s->metric_length, 16), sizeof(*f->combs));
  121.     f->vars  = av_calloc(FFALIGN(s->metric_length, 16), sizeof(*f->vars));
  122.  
  123.     if (!f->diffs || !f->combs || !f->vars) {
  124.         av_freep(&f->diffs);
  125.         av_freep(&f->combs);
  126.         av_freep(&f->vars);
  127.         return AVERROR(ENOMEM);
  128.     }
  129.     return 0;
  130. }
  131.  
  132. static void free_field_queue(PullupField *head)
  133. {
  134.     PullupField *f = head;
  135.     do {
  136.         PullupField *next;
  137.         if (!f)
  138.             break;
  139.         av_free(f->diffs);
  140.         av_free(f->combs);
  141.         av_free(f->vars);
  142.         next = f->next;
  143.         memset(f, 0, sizeof(*f)); // clear all pointers to avoid stale ones
  144.         av_free(f);
  145.         f = next;
  146.     } while (f != head);
  147. }
  148.  
  149. static PullupField *make_field_queue(PullupContext *s, int len)
  150. {
  151.     PullupField *head, *f;
  152.  
  153.     f = head = av_mallocz(sizeof(*head));
  154.     if (!f)
  155.         return NULL;
  156.  
  157.     if (alloc_metrics(s, f) < 0) {
  158.         av_free(f);
  159.         return NULL;
  160.     }
  161.  
  162.     for (; len > 0; len--) {
  163.         f->next = av_mallocz(sizeof(*f->next));
  164.         if (!f->next) {
  165.             free_field_queue(head);
  166.             return NULL;
  167.         }
  168.  
  169.         f->next->prev = f;
  170.         f = f->next;
  171.         if (alloc_metrics(s, f) < 0) {
  172.             free_field_queue(head);
  173.             return NULL;
  174.         }
  175.     }
  176.  
  177.     f->next = head;
  178.     head->prev = f;
  179.  
  180.     return head;
  181. }
  182.  
  183. static int config_input(AVFilterLink *inlink)
  184. {
  185.     AVFilterContext *ctx = inlink->dst;
  186.     PullupContext *s = ctx->priv;
  187.     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
  188.     int mp = s->metric_plane;
  189.  
  190.     s->nb_planes = av_pix_fmt_count_planes(inlink->format);
  191.  
  192.     if (mp + 1 > s->nb_planes) {
  193.         av_log(ctx, AV_LOG_ERROR, "input format does not have such plane\n");
  194.         return AVERROR(EINVAL);
  195.     }
  196.  
  197.     s->planeheight[1] = s->planeheight[2] = FF_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
  198.     s->planeheight[0] = s->planeheight[3] = inlink->h;
  199.     s->planewidth[1]  = s->planewidth[2]  = FF_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w);
  200.     s->planewidth[0]  = s->planewidth[3]  = inlink->w;
  201.  
  202.     s->metric_w      = (s->planewidth[mp]  - ((s->junk_left + s->junk_right)  << 3)) >> 3;
  203.     s->metric_h      = (s->planeheight[mp] - ((s->junk_top  + s->junk_bottom) << 1)) >> 3;
  204.     s->metric_offset = (s->junk_left << 3) + (s->junk_top << 1) * s->planewidth[mp];
  205.     s->metric_length = s->metric_w * s->metric_h;
  206.  
  207.     av_log(ctx, AV_LOG_DEBUG, "w: %d h: %d\n", s->metric_w, s->metric_h);
  208.     av_log(ctx, AV_LOG_DEBUG, "offset: %d length: %d\n", s->metric_offset, s->metric_length);
  209.  
  210.     s->head = make_field_queue(s, 8);
  211.     if (!s->head)
  212.         return AVERROR(ENOMEM);
  213.  
  214.     s->diff = diff_c;
  215.     s->comb = comb_c;
  216.     s->var  = var_c;
  217.  
  218.     if (ARCH_X86)
  219.         ff_pullup_init_x86(s);
  220.     return 0;
  221. }
  222.  
  223. static int config_output(AVFilterLink *outlink)
  224. {
  225.     outlink->flags |= FF_LINK_FLAG_REQUEST_LOOP;
  226.     return 0;
  227. }
  228.  
  229. static PullupBuffer *pullup_lock_buffer(PullupBuffer *b, int parity)
  230. {
  231.     if (!b)
  232.         return NULL;
  233.  
  234.     if ((parity + 1) & 1)
  235.         b->lock[0]++;
  236.     if ((parity + 1) & 2)
  237.         b->lock[1]++;
  238.  
  239.     return b;
  240. }
  241.  
  242. static void pullup_release_buffer(PullupBuffer *b, int parity)
  243. {
  244.     if (!b)
  245.         return;
  246.  
  247.     if ((parity + 1) & 1)
  248.         b->lock[0]--;
  249.     if ((parity + 1) & 2)
  250.         b->lock[1]--;
  251. }
  252.  
  253. static int alloc_buffer(PullupContext *s, PullupBuffer *b)
  254. {
  255.     int i;
  256.  
  257.     if (b->planes[0])
  258.         return 0;
  259.     for (i = 0; i < s->nb_planes; i++) {
  260.         b->planes[i] = av_malloc(s->planeheight[i] * s->planewidth[i]);
  261.     }
  262.     if (s->nb_planes == 1)
  263.         b->planes[1] = av_malloc(4*256);
  264.  
  265.     return 0;
  266. }
  267.  
  268. static PullupBuffer *pullup_get_buffer(PullupContext *s, int parity)
  269. {
  270.     int i;
  271.  
  272.     /* Try first to get the sister buffer for the previous field */
  273.     if (parity < 2 && s->last && parity != s->last->parity
  274.         && !s->last->buffer->lock[parity]) {
  275.         alloc_buffer(s, s->last->buffer);
  276.         return pullup_lock_buffer(s->last->buffer, parity);
  277.     }
  278.  
  279.     /* Prefer a buffer with both fields open */
  280.     for (i = 0; i < FF_ARRAY_ELEMS(s->buffers); i++) {
  281.         if (s->buffers[i].lock[0])
  282.             continue;
  283.         if (s->buffers[i].lock[1])
  284.             continue;
  285.         alloc_buffer(s, &s->buffers[i]);
  286.         return pullup_lock_buffer(&s->buffers[i], parity);
  287.     }
  288.  
  289.     if (parity == 2)
  290.         return 0;
  291.  
  292.     /* Search for any half-free buffer */
  293.     for (i = 0; i < FF_ARRAY_ELEMS(s->buffers); i++) {
  294.         if (((parity + 1) & 1) && s->buffers[i].lock[0])
  295.             continue;
  296.         if (((parity + 1) & 2) && s->buffers[i].lock[1])
  297.             continue;
  298.         alloc_buffer(s, &s->buffers[i]);
  299.         return pullup_lock_buffer(&s->buffers[i], parity);
  300.     }
  301.  
  302.     return NULL;
  303. }
  304.  
  305. static int queue_length(PullupField *begin, PullupField *end)
  306. {
  307.     PullupField *f;
  308.     int count = 1;
  309.  
  310.     if (!begin || !end)
  311.         return 0;
  312.  
  313.     for (f = begin; f != end; f = f->next)
  314.         count++;
  315.  
  316.     return count;
  317. }
  318.  
  319. static int find_first_break(PullupField *f, int max)
  320. {
  321.     int i;
  322.  
  323.     for (i = 0; i < max; i++) {
  324.         if (f->breaks & BREAK_RIGHT || f->next->breaks & BREAK_LEFT)
  325.             return i + 1;
  326.         f = f->next;
  327.     }
  328.  
  329.     return 0;
  330. }
  331.  
  332. static void compute_breaks(PullupContext *s, PullupField *f0)
  333. {
  334.     PullupField *f1 = f0->next;
  335.     PullupField *f2 = f1->next;
  336.     PullupField *f3 = f2->next;
  337.     int i, l, max_l = 0, max_r = 0;
  338.  
  339.     if (f0->flags & F_HAVE_BREAKS)
  340.         return;
  341.  
  342.     f0->flags |= F_HAVE_BREAKS;
  343.  
  344.     /* Special case when fields are 100% identical */
  345.     if (f0->buffer == f2->buffer && f1->buffer != f3->buffer) {
  346.         f2->breaks |= BREAK_RIGHT;
  347.         return;
  348.     }
  349.  
  350.     if (f0->buffer != f2->buffer && f1->buffer == f3->buffer) {
  351.         f1->breaks |= BREAK_LEFT;
  352.         return;
  353.     }
  354.  
  355.     for (i = 0; i < s->metric_length; i++) {
  356.         l = f2->diffs[i] - f3->diffs[i];
  357.  
  358.         if ( l > max_l)
  359.             max_l =  l;
  360.         if (-l > max_r)
  361.             max_r = -l;
  362.     }
  363.  
  364.     /* Don't get tripped up when differences are mostly quant error */
  365.     if (max_l + max_r < 128)
  366.         return;
  367.     if (max_l > 4 * max_r)
  368.         f1->breaks |= BREAK_LEFT;
  369.     if (max_r > 4 * max_l)
  370.         f2->breaks |= BREAK_RIGHT;
  371. }
  372.  
  373. static void compute_affinity(PullupContext *s, PullupField *f)
  374. {
  375.     int i, max_l = 0, max_r = 0, l;
  376.  
  377.     if (f->flags & F_HAVE_AFFINITY)
  378.         return;
  379.  
  380.     f->flags |= F_HAVE_AFFINITY;
  381.  
  382.     if (f->buffer == f->next->next->buffer) {
  383.         f->affinity             =  1;
  384.         f->next->affinity       =  0;
  385.         f->next->next->affinity = -1;
  386.         f->next->flags         |= F_HAVE_AFFINITY;
  387.         f->next->next->flags   |= F_HAVE_AFFINITY;
  388.         return;
  389.     }
  390.  
  391.     for (i = 0; i < s->metric_length; i++) {
  392.         int v  = f->vars[i];
  393.         int lv = f->prev->vars[i];
  394.         int rv = f->next->vars[i];
  395.         int lc = f->      combs[i] - 2*(v < lv ? v : lv);
  396.         int rc = f->next->combs[i] - 2*(v < rv ? v : rv);
  397.  
  398.         lc = FFMAX(lc, 0);
  399.         rc = FFMAX(rc, 0);
  400.         l  = lc - rc;
  401.  
  402.         if ( l > max_l)
  403.             max_l =  l;
  404.         if (-l > max_r)
  405.             max_r = -l;
  406.     }
  407.  
  408.     if (max_l + max_r < 64)
  409.         return;
  410.  
  411.     if (max_r > 6 * max_l)
  412.         f->affinity = -1;
  413.     else if (max_l > 6 * max_r)
  414.         f->affinity =  1;
  415. }
  416.  
  417. static int decide_frame_length(PullupContext *s)
  418. {
  419.     PullupField *f0 = s->first;
  420.     PullupField *f1 = f0->next;
  421.     PullupField *f2 = f1->next;
  422.     PullupField *f;
  423.     int i, l, n;
  424.  
  425.     if (queue_length(s->first, s->last) < 4)
  426.         return 0;
  427.  
  428.     f = s->first;
  429.     n = queue_length(f, s->last);
  430.     for (i = 0; i < n - 1; i++) {
  431.         if (i < n - 3)
  432.             compute_breaks(s, f);
  433.  
  434.         compute_affinity(s, f);
  435.  
  436.         f = f->next;
  437.     }
  438.  
  439.     if (f0->affinity == -1)
  440.         return 1;
  441.  
  442.     l = find_first_break(f0, 3);
  443.  
  444.     if (l == 1 && s->strict_breaks < 0)
  445.         l = 0;
  446.  
  447.     switch (l) {
  448.     case 1:
  449.         return 1 + (s->strict_breaks < 1 && f0->affinity == 1 && f1->affinity == -1);
  450.     case 2:
  451.         /* FIXME: strictly speaking, f0->prev is no longer valid... :) */
  452.         if (s->strict_pairs
  453.             && (f0->prev->breaks & BREAK_RIGHT) && (f2->breaks & BREAK_LEFT)
  454.             && (f0->affinity != 1 || f1->affinity != -1) )
  455.             return 1;
  456.         return 1 + (f1->affinity != 1);
  457.     case 3:
  458.         return 2 + (f2->affinity != 1);
  459.     default:
  460.         /* 9 possibilities covered before switch */
  461.         if (f1->affinity == 1)
  462.             return 1; /* covers 6 */
  463.         else if (f1->affinity == -1)
  464.             return 2; /* covers 6 */
  465.         else if (f2->affinity == -1) { /* covers 2 */
  466.             return (f0->affinity == 1) ? 3 : 1;
  467.         } else {
  468.             return 2; /* the remaining 6 */
  469.         }
  470.     }
  471. }
  472.  
  473. static PullupFrame *pullup_get_frame(PullupContext *s)
  474. {
  475.     PullupFrame *fr = &s->frame;
  476.     int i, n = decide_frame_length(s);
  477.     int aff = s->first->next->affinity;
  478.  
  479.     av_assert1(n < FF_ARRAY_ELEMS(fr->ifields));
  480.     if (!n || fr->lock)
  481.         return NULL;
  482.  
  483.     fr->lock++;
  484.     fr->length = n;
  485.     fr->parity = s->first->parity;
  486.     fr->buffer = 0;
  487.  
  488.     for (i = 0; i < n; i++) {
  489.         /* We cheat and steal the buffer without release+relock */
  490.         fr->ifields[i]   = s->first->buffer;
  491.         s->first->buffer = 0;
  492.         s->first         = s->first->next;
  493.     }
  494.  
  495.     if (n == 1) {
  496.         fr->ofields[fr->parity    ] = fr->ifields[0];
  497.         fr->ofields[fr->parity ^ 1] = 0;
  498.     } else if (n == 2) {
  499.         fr->ofields[fr->parity    ] = fr->ifields[0];
  500.         fr->ofields[fr->parity ^ 1] = fr->ifields[1];
  501.     } else if (n == 3) {
  502.         if (!aff)
  503.             aff = (fr->ifields[0] == fr->ifields[1]) ? -1 : 1;
  504.         fr->ofields[fr->parity    ] = fr->ifields[1 + aff];
  505.         fr->ofields[fr->parity ^ 1] = fr->ifields[1      ];
  506.     }
  507.  
  508.     pullup_lock_buffer(fr->ofields[0], 0);
  509.     pullup_lock_buffer(fr->ofields[1], 1);
  510.  
  511.     if (fr->ofields[0] == fr->ofields[1]) {
  512.         fr->buffer = fr->ofields[0];
  513.         pullup_lock_buffer(fr->buffer, 2);
  514.         return fr;
  515.     }
  516.  
  517.     return fr;
  518. }
  519.  
  520. static void pullup_release_frame(PullupFrame *f)
  521. {
  522.     int i;
  523.  
  524.     for (i = 0; i < f->length; i++)
  525.         pullup_release_buffer(f->ifields[i], f->parity ^ (i & 1));
  526.  
  527.     pullup_release_buffer(f->ofields[0], 0);
  528.     pullup_release_buffer(f->ofields[1], 1);
  529.  
  530.     if (f->buffer)
  531.         pullup_release_buffer(f->buffer, 2);
  532.     f->lock--;
  533. }
  534.  
  535. static void compute_metric(PullupContext *s, int *dest,
  536.                            PullupField *fa, int pa, PullupField *fb, int pb,
  537.                            int (*func)(const uint8_t *, const uint8_t *, ptrdiff_t))
  538. {
  539.     int mp = s->metric_plane;
  540.     int xstep = 8;
  541.     int ystep = s->planewidth[mp] << 3;
  542.     int stride = s->planewidth[mp] << 1; /* field stride */
  543.     int w = s->metric_w * xstep;
  544.     uint8_t *a, *b;
  545.     int x, y;
  546.  
  547.     if (!fa->buffer || !fb->buffer)
  548.         return;
  549.  
  550.     /* Shortcut for duplicate fields (e.g. from RFF flag) */
  551.     if (fa->buffer == fb->buffer && pa == pb) {
  552.         memset(dest, 0, s->metric_length * sizeof(*dest));
  553.         return;
  554.     }
  555.  
  556.     a = fa->buffer->planes[mp] + pa * s->planewidth[mp] + s->metric_offset;
  557.     b = fb->buffer->planes[mp] + pb * s->planewidth[mp] + s->metric_offset;
  558.  
  559.     for (y = 0; y < s->metric_h; y++) {
  560.         for (x = 0; x < w; x += xstep)
  561.             *dest++ = func(a + x, b + x, stride);
  562.         a += ystep; b += ystep;
  563.     }
  564. }
  565.  
  566. static int check_field_queue(PullupContext *s)
  567. {
  568.     int ret;
  569.  
  570.     if (s->head->next == s->first) {
  571.         PullupField *f = av_mallocz(sizeof(*f));
  572.  
  573.         if (!f)
  574.             return AVERROR(ENOMEM);
  575.  
  576.         if ((ret = alloc_metrics(s, f)) < 0) {
  577.             av_free(f);
  578.             return ret;
  579.         }
  580.  
  581.         f->prev        = s->head;
  582.         f->next        = s->first;
  583.         s->head->next  = f;
  584.         s->first->prev = f;
  585.     }
  586.  
  587.     return 0;
  588. }
  589.  
  590. static void pullup_submit_field(PullupContext *s, PullupBuffer *b, int parity)
  591. {
  592.     PullupField *f;
  593.  
  594.     /* Grow the circular list if needed */
  595.     if (check_field_queue(s) < 0)
  596.         return;
  597.  
  598.     /* Cannot have two fields of same parity in a row; drop the new one */
  599.     if (s->last && s->last->parity == parity)
  600.         return;
  601.  
  602.     f = s->head;
  603.     f->parity   = parity;
  604.     f->buffer   = pullup_lock_buffer(b, parity);
  605.     f->flags    = 0;
  606.     f->breaks   = 0;
  607.     f->affinity = 0;
  608.  
  609.     compute_metric(s, f->diffs, f, parity, f->prev->prev, parity, s->diff);
  610.     compute_metric(s, f->combs, parity ? f->prev : f, 0, parity ? f : f->prev, 1, s->comb);
  611.     compute_metric(s, f->vars, f, parity, f, -1, s->var);
  612.     emms_c();
  613.  
  614.     /* Advance the circular list */
  615.     if (!s->first)
  616.         s->first = s->head;
  617.  
  618.     s->last = s->head;
  619.     s->head = s->head->next;
  620. }
  621.  
  622. static void copy_field(PullupContext *s,
  623.                        PullupBuffer *dst, PullupBuffer *src, int parity)
  624. {
  625.     uint8_t *dd, *ss;
  626.     int i;
  627.  
  628.     for (i = 0; i < s->nb_planes; i++) {
  629.         ss = src->planes[i] + parity * s->planewidth[i];
  630.         dd = dst->planes[i] + parity * s->planewidth[i];
  631.  
  632.         av_image_copy_plane(dd, s->planewidth[i] << 1,
  633.                             ss, s->planewidth[i] << 1,
  634.                             s->planewidth[i], s->planeheight[i] >> 1);
  635.     }
  636. }
  637.  
  638. static void pullup_pack_frame(PullupContext *s, PullupFrame *fr)
  639. {
  640.     int i;
  641.  
  642.     if (fr->buffer)
  643.         return;
  644.  
  645.     if (fr->length < 2)
  646.         return; /* FIXME: deal with this */
  647.  
  648.     for (i = 0; i < 2; i++) {
  649.         if (fr->ofields[i]->lock[i^1])
  650.             continue;
  651.  
  652.         fr->buffer = fr->ofields[i];
  653.         pullup_lock_buffer(fr->buffer, 2);
  654.         copy_field(s, fr->buffer, fr->ofields[i^1], i^1);
  655.         return;
  656.     }
  657.  
  658.     fr->buffer = pullup_get_buffer(s, 2);
  659.  
  660.     copy_field(s, fr->buffer, fr->ofields[0], 0);
  661.     copy_field(s, fr->buffer, fr->ofields[1], 1);
  662. }
  663.  
  664. static int filter_frame(AVFilterLink *inlink, AVFrame *in)
  665. {
  666.     AVFilterContext *ctx = inlink->dst;
  667.     AVFilterLink *outlink = ctx->outputs[0];
  668.     PullupContext *s = ctx->priv;
  669.     PullupBuffer *b;
  670.     PullupFrame *f;
  671.     AVFrame *out;
  672.     int p, ret = 0;
  673.  
  674.     b = pullup_get_buffer(s, 2);
  675.     if (!b) {
  676.         av_log(ctx, AV_LOG_WARNING, "Could not get buffer!\n");
  677.         f = pullup_get_frame(s);
  678.         pullup_release_frame(f);
  679.         goto end;
  680.     }
  681.  
  682.     av_image_copy(b->planes, s->planewidth,
  683.                   (const uint8_t**)in->data, in->linesize,
  684.                   inlink->format, inlink->w, inlink->h);
  685.  
  686.     p = in->interlaced_frame ? !in->top_field_first : 0;
  687.     pullup_submit_field(s, b, p  );
  688.     pullup_submit_field(s, b, p^1);
  689.  
  690.     if (in->repeat_pict)
  691.         pullup_submit_field(s, b, p);
  692.  
  693.     pullup_release_buffer(b, 2);
  694.  
  695.     f = pullup_get_frame(s);
  696.     if (!f)
  697.         goto end;
  698.  
  699.     if (f->length < 2) {
  700.         pullup_release_frame(f);
  701.         f = pullup_get_frame(s);
  702.         if (!f)
  703.             goto end;
  704.         if (f->length < 2) {
  705.             pullup_release_frame(f);
  706.             if (!in->repeat_pict)
  707.                 goto end;
  708.             f = pullup_get_frame(s);
  709.             if (!f)
  710.                 goto end;
  711.             if (f->length < 2) {
  712.                 pullup_release_frame(f);
  713.                 goto end;
  714.             }
  715.         }
  716.     }
  717.  
  718.     /* If the frame isn't already exportable... */
  719.     if (!f->buffer)
  720.         pullup_pack_frame(s, f);
  721.  
  722.     out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
  723.     if (!out) {
  724.         ret = AVERROR(ENOMEM);
  725.         goto end;
  726.     }
  727.     av_frame_copy_props(out, in);
  728.  
  729.     av_image_copy(out->data, out->linesize,
  730.                   (const uint8_t**)f->buffer->planes, s->planewidth,
  731.                   inlink->format, inlink->w, inlink->h);
  732.  
  733.     ret = ff_filter_frame(outlink, out);
  734.     pullup_release_frame(f);
  735. end:
  736.     av_frame_free(&in);
  737.     return ret;
  738. }
  739.  
  740. static av_cold void uninit(AVFilterContext *ctx)
  741. {
  742.     PullupContext *s = ctx->priv;
  743.     int i;
  744.  
  745.     free_field_queue(s->head);
  746.     s->last = NULL;
  747.  
  748.     for (i = 0; i < FF_ARRAY_ELEMS(s->buffers); i++) {
  749.         av_freep(&s->buffers[i].planes[0]);
  750.         av_freep(&s->buffers[i].planes[1]);
  751.         av_freep(&s->buffers[i].planes[2]);
  752.     }
  753. }
  754.  
  755. static const AVFilterPad pullup_inputs[] = {
  756.     {
  757.         .name         = "default",
  758.         .type         = AVMEDIA_TYPE_VIDEO,
  759.         .filter_frame = filter_frame,
  760.         .config_props = config_input,
  761.     },
  762.     { NULL }
  763. };
  764.  
  765. static const AVFilterPad pullup_outputs[] = {
  766.     {
  767.         .name         = "default",
  768.         .type         = AVMEDIA_TYPE_VIDEO,
  769.         .config_props = config_output,
  770.     },
  771.     { NULL }
  772. };
  773.  
  774. AVFilter ff_vf_pullup = {
  775.     .name          = "pullup",
  776.     .description   = NULL_IF_CONFIG_SMALL("Pullup from field sequence to frames."),
  777.     .priv_size     = sizeof(PullupContext),
  778.     .priv_class    = &pullup_class,
  779.     .uninit        = uninit,
  780.     .query_formats = query_formats,
  781.     .inputs        = pullup_inputs,
  782.     .outputs       = pullup_outputs,
  783. };
  784.