summaryrefslogtreecommitdiffstats
path: root/video/filter
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2015-01-27 18:53:28 +0100
committerwm4 <wm4@nowhere>2015-01-27 18:53:28 +0100
commit69e5dd9bceea5a691038f4c1c8300fba28cc4e8a (patch)
treef6df75397db4472ff8b362b027283688f4109a37 /video/filter
parent2bbad06bfcb189784e7cc5938cfb3a1c7cd9b0cf (diff)
downloadmpv-69e5dd9bceea5a691038f4c1c8300fba28cc4e8a.tar.bz2
mpv-69e5dd9bceea5a691038f4c1c8300fba28cc4e8a.tar.xz
vf_pullup: remove builtin implementation
Now it requires libavfilter. The wrapper is left in place, so FFmpeg users will not notice any change. On Libav, the filter stops working.
Diffstat (limited to 'video/filter')
-rw-r--r--video/filter/pullup.c611
-rw-r--r--video/filter/pullup.h96
-rw-r--r--video/filter/vf_pullup.c223
3 files changed, 10 insertions, 920 deletions
diff --git a/video/filter/pullup.c b/video/filter/pullup.c
deleted file mode 100644
index 864cc90ba4..0000000000
--- a/video/filter/pullup.c
+++ /dev/null
@@ -1,611 +0,0 @@
-/*
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "config.h"
-#include "pullup.h"
-#include "common/common.h"
-
-
-#define ABS(a) (((a)^((a)>>31))-((a)>>31))
-
-static int diff_y(unsigned char *a, unsigned char *b, int s)
-{
- int i, j, diff=0;
- for (i=4; i; i--) {
- for (j=0; j<8; j++) diff += ABS(a[j]-b[j]);
- a+=s; b+=s;
- }
- return diff;
-}
-
-static int licomb_y(unsigned char *a, unsigned char *b, int s)
-{
- int i, j, diff=0;
- for (i=4; i; i--) {
- for (j=0; j<8; j++)
- diff += ABS((a[j]<<1) - b[j-s] - b[j])
- + ABS((b[j]<<1) - a[j] - a[j+s]);
- a+=s; b+=s;
- }
- return diff;
-}
-
-#if 0
-static int qpcomb_y(unsigned char *a, unsigned char *b, int s)
-{
- int i, j, diff=0;
- for (i=4; i; i--) {
- for (j=0; j<8; j++)
- diff += ABS(a[j] - 3*b[j-s] + 3*a[j+s] - b[j]);
- a+=s; b+=s;
- }
- return diff;
-}
-
-static int licomb_y_test(unsigned char *a, unsigned char *b, int s)
-{
- int c = licomb_y(a,b,s);
- int m = licomb_y_mmx(a,b,s);
- if (c != m) printf("%d != %d\n", c, m);
- return m;
-}
-#endif
-
-static int var_y(unsigned char *a, unsigned char *b, int s)
-{
- int i, j, var=0;
- for (i=3; i; i--) {
- for (j=0; j<8; j++) {
- var += ABS(a[j]-a[j+s]);
- }
- a+=s; b+=s;
- }
- return 4*var; /* match comb scaling */
-}
-
-
-
-
-
-
-
-
-
-static void alloc_buffer(struct pullup_context *c, struct pullup_buffer *b)
-{
- int i;
- if (b->planes) return;
- b->planes = calloc(c->nplanes, sizeof(unsigned char *));
- for (i = 0; i < c->nplanes; i++) {
- b->planes[i] = malloc(c->h[i]*c->stride[i]);
- /* Deal with idiotic 128=0 for chroma: */
- memset(b->planes[i], c->background[i], c->h[i]*c->stride[i]);
- }
-}
-
-struct pullup_buffer *pullup_lock_buffer(struct pullup_buffer *b, int parity)
-{
- if (!b) return 0;
- if ((parity+1) & 1) b->lock[0]++;
- if ((parity+1) & 2) b->lock[1]++;
- return b;
-}
-
-void pullup_release_buffer(struct pullup_buffer *b, int parity)
-{
- if (!b) return;
- if ((parity+1) & 1) b->lock[0]--;
- if ((parity+1) & 2) b->lock[1]--;
-}
-
-struct pullup_buffer *pullup_get_buffer(struct pullup_context *c, int parity)
-{
- int i;
-
- /* Try first to get the sister buffer for the previous field */
- if (parity < 2 && c->last && parity != c->last->parity
- && !c->last->buffer->lock[parity]) {
- alloc_buffer(c, c->last->buffer);
- return pullup_lock_buffer(c->last->buffer, parity);
- }
-
- /* Prefer a buffer with both fields open */
- for (i = 0; i < c->nbuffers; i++) {
- if (c->buffers[i].lock[0]) continue;
- if (c->buffers[i].lock[1]) continue;
- alloc_buffer(c, &c->buffers[i]);
- return pullup_lock_buffer(&c->buffers[i], parity);
- }
-
- if (parity == 2) return 0;
-
- /* Search for any half-free buffer */
- for (i = 0; i < c->nbuffers; i++) {
- if (((parity+1) & 1) && c->buffers[i].lock[0]) continue;
- if (((parity+1) & 2) && c->buffers[i].lock[1]) continue;
- alloc_buffer(c, &c->buffers[i]);
- return pullup_lock_buffer(&c->buffers[i], parity);
- }
-
- return 0;
-}
-
-
-
-
-
-
-static void compute_metric(struct pullup_context *c,
- struct pullup_field *fa, int pa,
- struct pullup_field *fb, int pb,
- int (*func)(unsigned char *, unsigned char *, int), int *dest)
-{
- unsigned char *a, *b;
- int x, y;
- int mp = c->metric_plane;
- int xstep = c->bpp[mp];
- int ystep = c->stride[mp]<<3;
- int s = c->stride[mp]<<1; /* field stride */
- int w = c->metric_w*xstep;
-
- if (!fa->buffer || !fb->buffer) return;
-
- /* Shortcut for duplicate fields (e.g. from RFF flag) */
- if (fa->buffer == fb->buffer && pa == pb) {
- memset(dest, 0, c->metric_len * sizeof(int));
- return;
- }
-
- a = fa->buffer->planes[mp] + pa * c->stride[mp] + c->metric_offset;
- b = fb->buffer->planes[mp] + pb * c->stride[mp] + c->metric_offset;
-
- for (y = c->metric_h; y; y--) {
- for (x = 0; x < w; x += xstep) {
- *dest++ = func(a + x, b + x, s);
- }
- a += ystep; b += ystep;
- }
-}
-
-
-
-
-
-static void alloc_metrics(struct pullup_context *c, struct pullup_field *f)
-{
- f->diffs = calloc(c->metric_len, sizeof(int));
- f->comb = calloc(c->metric_len, sizeof(int));
- f->var = calloc(c->metric_len, sizeof(int));
- /* add more metrics here as needed */
-}
-
-static struct pullup_field *make_field_queue(struct pullup_context *c, int len)
-{
- struct pullup_field *head, *f;
- f = head = calloc(1, sizeof(struct pullup_field));
- alloc_metrics(c, f);
- for (; len > 0; len--) {
- f->next = calloc(1, sizeof(struct pullup_field));
- f->next->prev = f;
- f = f->next;
- alloc_metrics(c, f);
- }
- f->next = head;
- head->prev = f;
- return head;
-}
-
-static void check_field_queue(struct pullup_context *c)
-{
- if (c->head->next == c->first) {
- struct pullup_field *f = calloc(1, sizeof(struct pullup_field));
- alloc_metrics(c, f);
- f->prev = c->head;
- f->next = c->first;
- c->head->next = f;
- c->first->prev = f;
- }
-}
-
-void pullup_submit_field(struct pullup_context *c, struct pullup_buffer *b,
- int parity, double pts)
-{
- struct pullup_field *f;
-
- /* Grow the circular list if needed */
- check_field_queue(c);
-
- /* Cannot have two fields of same parity in a row; drop the new one */
- if (c->last && c->last->parity == parity) return;
-
- f = c->head;
- f->parity = parity;
- f->buffer = pullup_lock_buffer(b, parity);
- f->flags = 0;
- f->breaks = 0;
- f->affinity = 0;
- f->pts = pts;
-
- compute_metric(c, f, parity, f->prev->prev, parity, c->diff, f->diffs);
- compute_metric(c, parity?f->prev:f, 0, parity?f:f->prev, 1, c->comb, f->comb);
- compute_metric(c, f, parity, f, -1, c->var, f->var);
-
- /* Advance the circular list */
- if (!c->first) c->first = c->head;
- c->last = c->head;
- c->head = c->head->next;
-}
-
-
-
-
-#define F_HAVE_BREAKS 1
-#define F_HAVE_AFFINITY 2
-
-
-#define BREAK_LEFT 1
-#define BREAK_RIGHT 2
-
-
-
-
-static int queue_length(struct pullup_field *begin, struct pullup_field *end)
-{
- int count = 1;
- struct pullup_field *f;
-
- if (!begin || !end) return 0;
- for (f = begin; f != end; f = f->next) count++;
- return count;
-}
-
-static int find_first_break(struct pullup_field *f, int max)
-{
- int i;
- for (i = 0; i < max; i++) {
- if (f->breaks & BREAK_RIGHT || f->next->breaks & BREAK_LEFT)
- return i+1;
- f = f->next;
- }
- return 0;
-}
-
-static void compute_breaks(struct pullup_context *c, struct pullup_field *f0)
-{
- int i;
- struct pullup_field *f1 = f0->next;
- struct pullup_field *f2 = f1->next;
- struct pullup_field *f3 = f2->next;
- int l, max_l=0, max_r=0;
- //struct pullup_field *ff;
- //for (i=0, ff=c->first; ff != f0; i++, ff=ff->next);
-
- if (f0->flags & F_HAVE_BREAKS) return;
- //printf("\n%d: ", i);
- f0->flags |= F_HAVE_BREAKS;
-
- /* Special case when fields are 100% identical */
- if (f0->buffer == f2->buffer && f1->buffer != f3->buffer) {
- f2->breaks |= BREAK_RIGHT;
- return;
- }
- if (f0->buffer != f2->buffer && f1->buffer == f3->buffer) {
- f1->breaks |= BREAK_LEFT;
- return;
- }
-
- for (i = 0; i < c->metric_len; i++) {
- l = f2->diffs[i] - f3->diffs[i];
- if (l > max_l) max_l = l;
- if (-l > max_r) max_r = -l;
- }
- /* Don't get tripped up when differences are mostly quant error */
- //printf("%d %d\n", max_l, max_r);
- if (max_l + max_r < 128) return;
- if (max_l > 4*max_r) f1->breaks |= BREAK_LEFT;
- if (max_r > 4*max_l) f2->breaks |= BREAK_RIGHT;
-}
-
-static void compute_affinity(struct pullup_context *c, struct pullup_field *f)
-{
- int i;
- int max_l=0, max_r=0, l;
- if (f->flags & F_HAVE_AFFINITY) return;
- f->flags |= F_HAVE_AFFINITY;
- if (f->buffer == f->next->next->buffer) {
- f->affinity = 1;
- f->next->affinity = 0;
- f->next->next->affinity = -1;
- f->next->flags |= F_HAVE_AFFINITY;
- f->next->next->flags |= F_HAVE_AFFINITY;
- return;
- }
- if (1) {
- for (i = 0; i < c->metric_len; i++) {
- int lv = f->prev->var[i];
- int rv = f->next->var[i];
- int v = f->var[i];
- int lc = f->comb[i] - (v+lv) + ABS(v-lv);
- int rc = f->next->comb[i] - (v+rv) + ABS(v-rv);
- lc = lc>0 ? lc : 0;
- rc = rc>0 ? rc : 0;
- l = lc - rc;
- if (l > max_l) max_l = l;
- if (-l > max_r) max_r = -l;
- }
- if (max_l + max_r < 64) return;
- if (max_r > 6*max_l) f->affinity = -1;
- else if (max_l > 6*max_r) f->affinity = 1;
- } else {
- for (i = 0; i < c->metric_len; i++) {
- l = f->comb[i] - f->next->comb[i];
- if (l > max_l) max_l = l;
- if (-l > max_r) max_r = -l;
- }
- if (max_l + max_r < 64) return;
- if (max_r > 2*max_l) f->affinity = -1;
- else if (max_l > 2*max_r) f->affinity = 1;
- }
-}
-
-static void foo(struct pullup_context *c)
-{
- struct pullup_field *f = c->first;
- int i, n = queue_length(f, c->last);
- for (i = 0; i < n-1; i++) {
- if (i < n-3) compute_breaks(c, f);
- compute_affinity(c, f);
- f = f->next;
- }
-}
-
-static int decide_frame_length(struct pullup_context *c)
-{
- struct pullup_field *f0 = c->first;
- struct pullup_field *f1 = f0->next;
- struct pullup_field *f2 = f1->next;
- int l;
-
- if (queue_length(c->first, c->last) < 4) return 0;
- foo(c);
-
- if (f0->affinity == -1) return 1;
-
- l = find_first_break(f0, 3);
- if (l == 1 && c->strict_breaks < 0) l = 0;
-
- switch (l) {
- case 1:
- if (c->strict_breaks < 1 && f0->affinity == 1 && f1->affinity == -1)
- return 2;
- else return 1;
- case 2:
- /* FIXME: strictly speaking, f0->prev is no longer valid... :) */
- if (c->strict_pairs
- && (f0->prev->breaks & BREAK_RIGHT) && (f2->breaks & BREAK_LEFT)
- && (f0->affinity != 1 || f1->affinity != -1) )
- return 1;
- if (f1->affinity == 1) return 1;
- else return 2;
- case 3:
- if (f2->affinity == 1) return 2;
- else return 3;
- default:
- /* 9 possibilities covered before switch */
- if (f1->affinity == 1) return 1; /* covers 6 */
- else if (f1->affinity == -1) return 2; /* covers 6 */
- else if (f2->affinity == -1) { /* covers 2 */
- if (f0->affinity == 1) return 3;
- else return 1;
- }
- else return 2; /* the remaining 6 */
- }
-}
-
-
-static void print_aff_and_breaks(struct pullup_context *c, struct pullup_field *f)
-{
- int i;
- struct pullup_field *f0 = f;
- const char aff_l[] = "+..", aff_r[] = "..+";
- printf("\naffinity: ");
- for (i = 0; i < 4; i++) {
- printf("%c%d%c", aff_l[1+f->affinity], i, aff_r[1+f->affinity]);
- f = f->next;
- }
- f = f0;
- printf("\nbreaks: ");
- for (i=0; i<4; i++) {
- printf("%c%d%c", f->breaks & BREAK_LEFT ? '|' : '.', i, f->breaks & BREAK_RIGHT ? '|' : '.');
- f = f->next;
- }
- printf("\n");
-}
-
-
-
-
-
-struct pullup_frame *pullup_get_frame(struct pullup_context *c)
-{
- int i;
- struct pullup_frame *fr = c->frame;
- int n = decide_frame_length(c);
- int aff = c->first->next->affinity;
-
- if (!n) return 0;
- if (fr->lock) return 0;
-
- if (c->verbose) {
- print_aff_and_breaks(c, c->first);
- printf("duration: %d \n", n);
- }
-
- fr->lock++;
- fr->length = n;
- fr->parity = c->first->parity;
- fr->buffer = 0;
- fr->pts = 0;
- for (i = 0; i < n; i++) {
- /* We cheat and steal the buffer without release+relock */
- fr->ifields[i] = c->first->buffer;
- c->first->buffer = 0;
- if (c->first->pts == MP_NOPTS_VALUE || fr->pts == MP_NOPTS_VALUE)
- fr->pts = MP_NOPTS_VALUE;
- else
- fr->pts += c->first->pts;
- c->first = c->first->next;
- }
- if (fr->pts != MP_NOPTS_VALUE)
- fr->pts /= n;
-
- if (n == 1) {
- fr->ofields[fr->parity] = fr->ifields[0];
- fr->ofields[fr->parity^1] = 0;
- } else if (n == 2) {
- fr->ofields[fr->parity] = fr->ifields[0];
- fr->ofields[fr->parity^1] = fr->ifields[1];
- } else if (n == 3) {
- if (aff == 0)
- aff = (fr->ifields[0] == fr->ifields[1]) ? -1 : 1;
- /* else if (c->verbose) printf("forced aff: %d \n", aff); */
- fr->ofields[fr->parity] = fr->ifields[1+aff];
- fr->ofields[fr->parity^1] = fr->ifields[1];
- }
- pullup_lock_buffer(fr->ofields[0], 0);
- pullup_lock_buffer(fr->ofields[1], 1);
-
- if (fr->ofields[0] == fr->ofields[1]) {
- fr->buffer = fr->ofields[0];
- pullup_lock_buffer(fr->buffer, 2);
- return fr;
- }
- return fr;
-}
-
-static void copy_field(struct pullup_context *c, struct pullup_buffer *dest,
- struct pullup_buffer *src, int parity)
-{
- int i, j;
- unsigned char *d, *s;
- for (i = 0; i < c->nplanes; i++) {
- s = src->planes[i] + parity*c->stride[i];
- d = dest->planes[i] + parity*c->stride[i];
- for (j = c->h[i]>>1; j; j--) {
- memcpy(d, s, c->stride[i]);
- s += c->stride[i]<<1;
- d += c->stride[i]<<1;
- }
- }
-}
-
-void pullup_pack_frame(struct pullup_context *c, struct pullup_frame *fr)
-{
- int i;
- if (fr->buffer) return;
- if (fr->length < 2) return; /* FIXME: deal with this */
- for (i = 0; i < 2; i++)
- {
- if (fr->ofields[i]->lock[i^1]) continue;
- fr->buffer = fr->ofields[i];
- pullup_lock_buffer(fr->buffer, 2);
- copy_field(c, fr->buffer, fr->ofields[i^1], i^1);
- return;
- }
- fr->buffer = pullup_get_buffer(c, 2);
- copy_field(c, fr->buffer, fr->ofields[0], 0);
- copy_field(c, fr->buffer, fr->ofields[1], 1);
-}
-
-void pullup_release_frame(struct pullup_frame *fr)
-{
- int i;
- for (i = 0; i < fr->length; i++)
- pullup_release_buffer(fr->ifields[i], fr->parity ^ (i&1));
- pullup_release_buffer(fr->ofields[0], 0);
- pullup_release_buffer(fr->ofields[1], 1);
- if (fr->buffer) pullup_release_buffer(fr->buffer, 2);
- fr->lock--;
-}
-
-
-
-
-
-
-struct pullup_context *pullup_alloc_context(void)
-{
- struct pullup_context *c;
-
- c = calloc(1, sizeof(struct pullup_context));
-
- return c;
-}
-
-void pullup_preinit_context(struct pullup_context *c)
-{
- c->bpp = calloc(c->nplanes, sizeof(int));
- c->w = calloc(c->nplanes, sizeof(int));
- c->h = calloc(c->nplanes, sizeof(int));
- c->stride = calloc(c->nplanes, sizeof(int));
- c->background = calloc(c->nplanes, sizeof(int));
-}
-
-void pullup_init_context(struct pullup_context *c)
-{
- int mp = c->metric_plane;
- if (c->nbuffers < 10) c->nbuffers = 10;
- c->buffers = calloc(c->nbuffers, sizeof (struct pullup_buffer));
-
- c->metric_w = (c->w[mp] - ((c->junk_left + c->junk_right) << 3)) >> 3;
- c->metric_h = (c->h[mp] - ((c->junk_top + c->junk_bottom) << 1)) >> 3;
- c->metric_offset = c->junk_left*c->bpp[mp] + (c->junk_top<<1)*c->stride[mp];
- c->metric_len = c->metric_w * c->metric_h;
-
- c->head = make_field_queue(c, 8);
-
- c->frame = calloc(1, sizeof (struct pullup_frame));
- c->frame->ifields = calloc(3, sizeof (struct pullup_buffer *));
-
- switch(c->format) {
- case PULLUP_FMT_Y:
- c->diff = diff_y;
- c->comb = licomb_y;
- c->var = var_y;
- break;
- }
-}
-
-void pullup_free_context(struct pullup_context *c)
-{
- struct pullup_field *f;
- free(c->buffers);
- f = c->head;
- do {
- if (!f) break;
- free(f->diffs);
- free(f->comb);
- f = f->next;
- free(f->prev);
- } while (f != c->head);
- free(c->frame);
- free(c);
-}
diff --git a/video/filter/pullup.h b/video/filter/pullup.h
deleted file mode 100644
index 8bf060f88d..0000000000
--- a/video/filter/pullup.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef MPLAYER_PULLUP_H
-#define MPLAYER_PULLUP_H
-
-#define PULLUP_FMT_Y 1
-#define PULLUP_FMT_YUY2 2
-#define PULLUP_FMT_UYVY 3
-#define PULLUP_FMT_RGB32 4
-
-struct pullup_buffer
-{
- int lock[2];
- unsigned char **planes;
-};
-
-struct pullup_field
-{
- int parity;
- double pts;
- struct pullup_buffer *buffer;
- unsigned int flags;
- int breaks;
- int affinity;
- int *diffs;
- int *comb;
- int *var;
- struct pullup_field *prev, *next;
-};
-
-struct pullup_frame
-{
- int lock;
- int length;
- int parity;
- double pts;
- struct pullup_buffer **ifields, *ofields[2];
- struct pullup_buffer *buffer;
-};
-
-struct pullup_context
-{
- /* Public interface */
- int format;
- int nplanes;
- int *bpp, *w, *h, *stride, *background;
- int junk_left, junk_right, junk_top, junk_bottom;
- int verbose;
- int metric_plane;
- int strict_breaks;
- int strict_pairs;
- /* Internal data */
- struct pullup_field *first, *last, *head;
- struct pullup_buffer *buffers;
- int nbuffers;
- int (*diff)(unsigned char *, unsigned char *, int);
- int (*comb)(unsigned char *, unsigned char *, int);
- int (*var)(unsigned char *, unsigned char *, int);
- int metric_w, metric_h, metric_len, metric_offset;
- struct pullup_frame *frame;
-};
-
-
-struct pullup_buffer *pullup_lock_buffer(struct pullup_buffer *b, int parity);
-void pullup_release_buffer(struct pullup_buffer *b, int parity);
-struct pullup_buffer *pullup_get_buffer(struct pullup_context *c, int parity);
-
-void pullup_submit_field(struct pullup_context *c, struct pullup_buffer *b,
- int parity, double pts);
-
-struct pullup_frame *pullup_get_frame(struct pullup_context *c);
-void pullup_pack_frame(struct pullup_context *c, struct pullup_frame *fr);
-void pullup_release_frame(struct pullup_frame *fr);
-
-struct pullup_context *pullup_alloc_context(void);
-void pullup_preinit_context(struct pullup_context *c);
-void pullup_init_context(struct pullup_context *c);
-void pullup_free_context(struct pullup_context *c);
-
-#endif /* MPLAYER_PULLUP_H */
diff --git a/video/filter/vf_pullup.c b/video/filter/vf_pullup.c
index 763783dc9e..fbf500d8cd 100644
--- a/video/filter/vf_pullup.c
+++ b/video/filter/vf_pullup.c
@@ -20,22 +20,13 @@
#include <stdlib.h>
#include <string.h>
-#include "config.h"
#include "common/msg.h"
#include "options/m_option.h"
-#include "video/img_format.h"
-#include "video/mp_image.h"
#include "vf.h"
-#include "video/memcpy_pic.h"
-
-#include "pullup.h"
#include "vf_lavfi.h"
-#undef MAX
-#define MAX(a,b) ((a)>(b)?(a):(b))
-
struct vf_priv_s {
struct pullup_context *ctx;
int init;
@@ -46,213 +37,19 @@ struct vf_priv_s {
struct vf_lw_opts *lw_opts;
};
-static void reset(struct vf_instance *vf)
-{
- if (vf->priv->ctx)
- pullup_free_context(vf->priv->ctx);
- vf->priv->init = 0;
- struct pullup_context *c;
- vf->priv->ctx = c = pullup_alloc_context();
- vf->priv->fakecount = 1;
- c->junk_left = vf->priv->junk_left;
- c->junk_right = vf->priv->junk_right;
- c->junk_top = vf->priv->junk_top;
- c->junk_bottom = vf->priv->junk_bottom;
- c->strict_breaks = vf->priv->strict_breaks;
- c->metric_plane = vf->priv->metric_plane;
-}
-
-static void init_pullup(struct vf_instance *vf, mp_image_t *mpi)
-{
- struct pullup_context *c = vf->priv->ctx;
-
- c->format = PULLUP_FMT_Y;
- c->nplanes = 4;
- pullup_preinit_context(c);
- c->bpp[0] = c->bpp[1] = c->bpp[2] = 8;
- c->w[0] = mpi->w;
- c->h[0] = mpi->h;
- c->w[1] = c->w[2] = mpi->chroma_width;
- c->h[1] = c->h[2] = mpi->chroma_height;
- c->w[3] = ((mpi->w+15)/16) * ((mpi->h+15)/16);
- c->h[3] = 2;
- c->stride[0] = mpi->w;
- c->stride[1] = c->stride[2] = mpi->chroma_width;
- c->stride[3] = c->w[3];
- c->background[1] = c->background[2] = 128;
-
- pullup_init_context(c);
-
- vf->priv->init = 1;
-}
-
-static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi)
-{
- struct pullup_context *c = vf->priv->ctx;
- struct pullup_buffer *b;
- struct pullup_frame *f;
- int p;
- double pts = mpi->pts;
- struct mp_image *dmpi = NULL;
-
- if (!vf->priv->init) init_pullup(vf, mpi);
-
- if (1) {
- b = pullup_get_buffer(c, 2);
- if (!b) {
- MP_ERR(vf, "Could not get buffer from pullup!\n");
- f = pullup_get_frame(c);
- pullup_release_frame(f);
- goto skip;
- }
- memcpy_pic(b->planes[0], mpi->planes[0], mpi->w, mpi->h,
- c->stride[0], mpi->stride[0]);
- memcpy_pic(b->planes[1], mpi->planes[1],
- mpi->chroma_width, mpi->chroma_height,
- c->stride[1], mpi->stride[1]);
- memcpy_pic(b->planes[2], mpi->planes[2],
- mpi->chroma_width, mpi->chroma_height,
- c->stride[2], mpi->stride[2]);
- }
- p = mpi->fields & MP_IMGFIELD_TOP_FIRST ? 0 :
- (mpi->fields & MP_IMGFIELD_ORDERED ? 1 : 0);
-
- if (pts == MP_NOPTS_VALUE) {
- pullup_submit_field(c, b, p, MP_NOPTS_VALUE);
- pullup_submit_field(c, b, p^1, MP_NOPTS_VALUE);
- if (mpi->fields & MP_IMGFIELD_REPEAT_FIRST)
- pullup_submit_field(c, b, p, MP_NOPTS_VALUE);
- } else {
- double delta;
- if (vf->priv->lastpts == MP_NOPTS_VALUE)
- delta = 1001.0/60000.0; // delta = field time distance
- else
- delta = (pts - vf->priv->lastpts) / 2;
- if (delta <= 0.0 || delta >= 0.5)
- delta = 0.0;
- vf->priv->lastpts = pts;
- if (mpi->fields & MP_IMGFIELD_REPEAT_FIRST) {
- pullup_submit_field(c, b, p, pts - delta);
- pullup_submit_field(c, b, p^1, pts);
- pullup_submit_field(c, b, p, pts + delta);
- } else {
- pullup_submit_field(c, b, p, pts - delta * 0.5);
- pullup_submit_field(c, b, p^1, pts + delta * 0.5);
- }
- }
-
- pullup_release_buffer(b, 2);
-
- f = pullup_get_frame(c);
-
- /* Fake yes for first few frames (buffer depth) to keep from
- * breaking A/V sync with G1's bad architecture... */
- //if (!f) return vf->priv->fakecount ? (--vf->priv->fakecount,1) : 0;
- if (!f)
- goto skip;
-
- if (f->length < 2) {
- pullup_release_frame(f);
- f = pullup_get_frame(c);
- if (!f) goto skip;
- if (f->length < 2) {
- pullup_release_frame(f);
- if (!(mpi->fields & MP_IMGFIELD_REPEAT_FIRST))
- goto skip;
- f = pullup_get_frame(c);
- if (!f) goto skip;
- if (f->length < 2) {
- pullup_release_frame(f);
- goto skip;
- }
- }
- }
-
- /* If the frame isn't already exportable... */
- if (!f->buffer)
- pullup_pack_frame(c, f);
-
- // NOTE: the copy could probably be avoided by changing or using the
- // pullup internal buffer management. But right now just do the
- // safe thing and always copy. Code outside the filter might
- // hold a buffer reference even if the filter chain is destroyed.
- dmpi = vf_alloc_out_image(vf);
- if (!dmpi)
- return NULL;
- mp_image_copy_attributes(dmpi, mpi);
-
- struct mp_image data = *dmpi;
-
- data.planes[0] = f->buffer->planes[0];
- data.planes[1] = f->buffer->planes[1];
- data.planes[2] = f->buffer->planes[2];
-
- data.stride[0] = c->stride[0];
- data.stride[1] = c->stride[1];
- data.stride[2] = c->stride[2];
-
- mp_image_copy(dmpi, &data);
-
- dmpi->pts = f->pts;
-
- pullup_release_frame(f);
-
-skip:
- talloc_free(mpi);
- return dmpi;
-}
-
-static int query_format(struct vf_instance *vf, unsigned int fmt)
-{
- /* FIXME - support more formats */
- switch (fmt) {
- case IMGFMT_420P:
- return vf_next_query_format(vf, fmt);
- }
- return 0;
-}
-
-static int config(struct vf_instance *vf,
- int width, int height, int d_width, int d_height,
- unsigned int flags, unsigned int outfmt)
-{
- reset(vf);
- if (height&3) return 0;
- return vf_next_config(vf, width, height, d_width, d_height, flags, outfmt);
-}
-
-static void uninit(struct vf_instance *vf)
-{
- pullup_free_context(vf->priv->ctx);
-}
-
-static int control(vf_instance_t *vf, int request, void *data)
+static int vf_open(vf_instance_t *vf)
{
- switch (request) {
- case VFCTRL_SEEK_RESET:
- reset(vf);
- return CONTROL_OK;
+ struct vf_priv_s *p = vf->priv;
+ const char *pname[3] = {"y", "u", "v"};
+ if (vf_lw_set_graph(vf, p->lw_opts, "pullup", "%d:%d:%d:%d:%d:%s",
+ p->junk_left, p->junk_right, p->junk_top, p->junk_bottom,
+ p->strict_breaks, pname[p->metric_plane]) >= 0)
+ {
+ return 1;
}
- return CONTROL_UNKNOWN;
-}
-static int vf_open(vf_instance_t *vf)
-{;
- vf->filter = filter;
- vf->config = config;
- vf->query_format = query_format;
- vf->control = control;
- vf->uninit = uninit;
- struct vf_priv_s *p = vf->priv;
- const char *pname[3] = {"y", "u", "v"};
- if (vf_lw_set_graph(vf, p->lw_opts, "pullup", "%d:%d:%d:%d:%d:%s",
- p->junk_left, p->junk_right, p->junk_top, p->junk_bottom,
- p->strict_breaks, pname[p->metric_plane]) >= 0)
- {
- return 1;
- }
- reset(vf);
- return 1;
+ MP_FATAL(vf, "Requires libavfilter.\n");
+ return 0;
}
#define OPT_BASE_STRUCT struct vf_priv_s