summaryrefslogtreecommitdiffstats
path: root/libmpcodecs/vf.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2012-11-05 17:02:04 +0100
committerwm4 <wm4@nowhere>2012-11-12 20:06:14 +0100
commitd4bdd0473d6f43132257c9fb3848d829755167a3 (patch)
tree8021c2f7da1841393c8c832105e20cd527826d6c /libmpcodecs/vf.c
parentbd48deba77bd5582c5829d6fe73a7d2571088aba (diff)
downloadmpv-d4bdd0473d6f43132257c9fb3848d829755167a3.tar.bz2
mpv-d4bdd0473d6f43132257c9fb3848d829755167a3.tar.xz
Rename directories, move files (step 1 of 2) (does not compile)
Tis drops the silly lib prefixes, and attempts to organize the tree in a more logical way. Make the top-level directory less cluttered as well. Renames the following directories: libaf -> audio/filter libao2 -> audio/out libvo -> video/out libmpdemux -> demux Split libmpcodecs: vf* -> video/filter vd*, dec_video.* -> video/decode mp_image*, img_format*, ... -> video/ ad*, dec_audio.* -> audio/decode libaf/format.* is moved to audio/ - this is similar to how mp_image.* is located in video/. Move most top-level .c/.h files to core. (talloc.c/.h is left on top- level, because it's external.) Park some of the more annoying files in compat/. Some of these are relicts from the time mplayer used ffmpeg internals. sub/ is not split, because it's too much of a mess (subtitle code is mixed with OSD display and rendering). Maybe the organization of core is not ideal: it mixes playback core (like mplayer.c) and utility helpers (like bstr.c/h). Should the need arise, the playback core will be moved somewhere else, while core contains all helper and common code.
Diffstat (limited to 'libmpcodecs/vf.c')
-rw-r--r--libmpcodecs/vf.c830
1 files changed, 0 insertions, 830 deletions
diff --git a/libmpcodecs/vf.c b/libmpcodecs/vf.c
deleted file mode 100644
index 10b9fa546f..0000000000
--- a/libmpcodecs/vf.c
+++ /dev/null
@@ -1,830 +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 <assert.h>
-#include <sys/types.h>
-#include <libavutil/common.h>
-#include <libavutil/mem.h>
-
-#include "config.h"
-
-#include "mp_msg.h"
-#include "m_option.h"
-#include "m_struct.h"
-
-
-#include "img_format.h"
-#include "mp_image.h"
-#include "vf.h"
-
-#include "libvo/fastmemcpy.h"
-
-extern const vf_info_t vf_info_vo;
-extern const vf_info_t vf_info_crop;
-extern const vf_info_t vf_info_expand;
-extern const vf_info_t vf_info_pp;
-extern const vf_info_t vf_info_scale;
-extern const vf_info_t vf_info_format;
-extern const vf_info_t vf_info_noformat;
-extern const vf_info_t vf_info_flip;
-extern const vf_info_t vf_info_rotate;
-extern const vf_info_t vf_info_mirror;
-extern const vf_info_t vf_info_noise;
-extern const vf_info_t vf_info_eq2;
-extern const vf_info_t vf_info_gradfun;
-extern const vf_info_t vf_info_unsharp;
-extern const vf_info_t vf_info_swapuv;
-extern const vf_info_t vf_info_down3dright;
-extern const vf_info_t vf_info_hqdn3d;
-extern const vf_info_t vf_info_ilpack;
-extern const vf_info_t vf_info_dsize;
-extern const vf_info_t vf_info_softpulldown;
-extern const vf_info_t vf_info_pullup;
-extern const vf_info_t vf_info_delogo;
-extern const vf_info_t vf_info_phase;
-extern const vf_info_t vf_info_divtc;
-extern const vf_info_t vf_info_softskip;
-extern const vf_info_t vf_info_screenshot;
-extern const vf_info_t vf_info_screenshot_force;
-extern const vf_info_t vf_info_sub;
-extern const vf_info_t vf_info_yadif;
-extern const vf_info_t vf_info_stereo3d;
-extern const vf_info_t vf_info_dlopen;
-
-// list of available filters:
-static const vf_info_t *const filter_list[] = {
- &vf_info_crop,
- &vf_info_expand,
- &vf_info_scale,
- &vf_info_vo,
- &vf_info_format,
- &vf_info_noformat,
- &vf_info_flip,
- &vf_info_rotate,
- &vf_info_mirror,
-
-#ifdef CONFIG_LIBPOSTPROC
- &vf_info_pp,
-#endif
-
- &vf_info_screenshot,
- &vf_info_screenshot_force,
-
- &vf_info_noise,
- &vf_info_eq2,
- &vf_info_gradfun,
- &vf_info_unsharp,
- &vf_info_swapuv,
- &vf_info_down3dright,
- &vf_info_hqdn3d,
- &vf_info_ilpack,
- &vf_info_dsize,
- &vf_info_softpulldown,
- &vf_info_pullup,
- &vf_info_delogo,
- &vf_info_phase,
- &vf_info_divtc,
- &vf_info_sub,
- &vf_info_yadif,
- &vf_info_stereo3d,
- &vf_info_dlopen,
- NULL
-};
-
-// For the vf option
-const m_obj_list_t vf_obj_list = {
- (void **)filter_list,
- M_ST_OFF(vf_info_t, name),
- M_ST_OFF(vf_info_t, info),
- M_ST_OFF(vf_info_t, opts)
-};
-
-//============================================================================
-// mpi stuff:
-
-void vf_mpi_clear(mp_image_t *mpi, int x0, int y0, int w, int h)
-{
- int y;
- if (mpi->flags & MP_IMGFLAG_PLANAR) {
- y0 &= ~1;
- h += h & 1;
- if (x0 == 0 && w == mpi->width) {
- // full width clear:
- memset(mpi->planes[0] + mpi->stride[0] * y0, 0, mpi->stride[0] * h);
- memset(mpi->planes[1] + mpi->stride[1] *(y0 >> mpi->chroma_y_shift),
- 128, mpi->stride[1] * (h >> mpi->chroma_y_shift));
- memset(mpi->planes[2] + mpi->stride[2] *(y0 >> mpi->chroma_y_shift),
- 128, mpi->stride[2] * (h >> mpi->chroma_y_shift));
- } else
- for (y = y0; y < y0 + h; y += 2) {
- memset(mpi->planes[0] + x0 + mpi->stride[0] * y, 0, w);
- memset(mpi->planes[0] + x0 + mpi->stride[0] * (y + 1), 0, w);
- memset(mpi->planes[1] + (x0 >> mpi->chroma_x_shift) +
- mpi->stride[1] * (y >> mpi->chroma_y_shift),
- 128, (w >> mpi->chroma_x_shift));
- memset(mpi->planes[2] + (x0 >> mpi->chroma_x_shift) +
- mpi->stride[2] * (y >> mpi->chroma_y_shift),
- 128, (w >> mpi->chroma_x_shift));
- }
- return;
- }
- // packed:
- for (y = y0; y < y0 + h; y++) {
- unsigned char *dst = mpi->planes[0] + mpi->stride[0] * y +
- (mpi->bpp >> 3) * x0;
- if (mpi->flags & MP_IMGFLAG_YUV) {
- unsigned int *p = (unsigned int *) dst;
- int size = (mpi->bpp >> 3) * w / 4;
- int i;
-#ifdef BIG_ENDIAN
-#define CLEAR_PACKEDYUV_PATTERN 0x00800080
-#define CLEAR_PACKEDYUV_PATTERN_SWAPPED 0x80008000
-#else
-#define CLEAR_PACKEDYUV_PATTERN 0x80008000
-#define CLEAR_PACKEDYUV_PATTERN_SWAPPED 0x00800080
-#endif
- if (mpi->flags & MP_IMGFLAG_SWAPPED) {
- for (i = 0; i < size - 3; i += 4)
- p[i] = p[i + 1] = p[i + 2] = p[i + 3] = CLEAR_PACKEDYUV_PATTERN_SWAPPED;
- for (; i < size; i++)
- p[i] = CLEAR_PACKEDYUV_PATTERN_SWAPPED;
- } else {
- for (i = 0; i < size - 3; i += 4)
- p[i] = p[i + 1] = p[i + 2] = p[i + 3] = CLEAR_PACKEDYUV_PATTERN;
- for (; i < size; i++)
- p[i] = CLEAR_PACKEDYUV_PATTERN;
- }
- } else
- memset(dst, 0, (mpi->bpp >> 3) * w);
- }
-}
-
-mp_image_t *vf_get_image(vf_instance_t *vf, unsigned int outfmt,
- int mp_imgtype, int mp_imgflag, int w, int h)
-{
- mp_image_t *mpi = NULL;
- int w2;
- int number = mp_imgtype >> 16;
-
- assert(w == -1 || w >= vf->w);
- assert(h == -1 || h >= vf->h);
- assert(vf->w > 0);
- assert(vf->h > 0);
-
- if (w == -1)
- w = vf->w;
- if (h == -1)
- h = vf->h;
-
- w2 = (mp_imgflag & MP_IMGFLAG_ACCEPT_ALIGNED_STRIDE) ? FFALIGN(w, 32) : w;
-
- if (vf->put_image == vf_next_put_image) {
- // passthru mode, if the filter uses the fallback/default put_image()
- mpi = vf_get_image(vf->next,outfmt,mp_imgtype,mp_imgflag,w,h);
- mpi->usage_count++;
- return mpi;
- }
-
- // Note: we should call libvo first to check if it supports direct rendering
- // and if not, then fallback to software buffers:
- switch (mp_imgtype & 0xff) {
- case MP_IMGTYPE_EXPORT:
- if (!vf->imgctx.export_images[0])
- vf->imgctx.export_images[0] = new_mp_image(w2, h);
- mpi = vf->imgctx.export_images[0];
- break;
- case MP_IMGTYPE_STATIC:
- if (!vf->imgctx.static_images[0])
- vf->imgctx.static_images[0] = new_mp_image(w2, h);
- mpi = vf->imgctx.static_images[0];
- break;
- case MP_IMGTYPE_TEMP:
- if (!vf->imgctx.temp_images[0])
- vf->imgctx.temp_images[0] = new_mp_image(w2, h);
- mpi = vf->imgctx.temp_images[0];
- break;
- case MP_IMGTYPE_IPB:
- if (!(mp_imgflag & MP_IMGFLAG_READABLE)) { // B frame:
- if (!vf->imgctx.temp_images[0])
- vf->imgctx.temp_images[0] = new_mp_image(w2, h);
- mpi = vf->imgctx.temp_images[0];
- break;
- }
- case MP_IMGTYPE_IP:
- if (!vf->imgctx.static_images[vf->imgctx.static_idx])
- vf->imgctx.static_images[vf->imgctx.static_idx] = new_mp_image(w2, h);
- mpi = vf->imgctx.static_images[vf->imgctx.static_idx];
- vf->imgctx.static_idx ^= 1;
- break;
- case MP_IMGTYPE_NUMBERED:
- if (number == -1) {
- int i;
- for (i = 0; i < NUM_NUMBERED_MPI; i++)
- if (!vf->imgctx.numbered_images[i] ||
- !vf->imgctx.numbered_images[i]->usage_count)
- break;
- number = i;
- }
- if (number < 0 || number >= NUM_NUMBERED_MPI)
- return NULL;
- if (!vf->imgctx.numbered_images[number])
- vf->imgctx.numbered_images[number] = new_mp_image(w2, h);
- mpi = vf->imgctx.numbered_images[number];
- mpi->number = number;
- break;
- }
- if (mpi) {
- int missing_palette = !(mpi->flags & MP_IMGFLAG_RGB_PALETTE) &&
- (mp_imgflag & MP_IMGFLAG_RGB_PALETTE);
- mpi->type = mp_imgtype;
- mpi->w = vf->w;
- mpi->h = vf->h;
- // keep buffer allocation status & color flags only:
- mpi->flags &= MP_IMGFLAG_ALLOCATED | MP_IMGFLAG_TYPE_DISPLAYED |
- MP_IMGFLAGMASK_COLORS;
- // accept restrictions, draw_slice and palette flags only:
- mpi->flags |= mp_imgflag & (MP_IMGFLAGMASK_RESTRICTIONS |
- MP_IMGFLAG_DRAW_CALLBACK | MP_IMGFLAG_RGB_PALETTE);
- if (!vf->draw_slice)
- mpi->flags &= ~MP_IMGFLAG_DRAW_CALLBACK;
- if (mpi->width != w2 || mpi->height != h || missing_palette) {
- if (mpi->flags & MP_IMGFLAG_ALLOCATED) {
- if (mpi->width < w2 || mpi->height < h || missing_palette) {
- // need to re-allocate buffer memory:
- av_free(mpi->planes[0]);
- if (mpi->flags & MP_IMGFLAG_RGB_PALETTE)
- av_free(mpi->planes[1]);
- for (int n = 0; n < MP_MAX_PLANES; n++)
- mpi->planes[n] = NULL;
- mpi->flags &= ~MP_IMGFLAG_ALLOCATED;
- mp_msg(MSGT_VFILTER, MSGL_V,
- "vf.c: have to REALLOCATE buffer memory :(\n");
- }
- }
- mpi->width = w2;
- mpi->chroma_width = (w2 + (1 << mpi->chroma_x_shift) - 1) >>
- mpi->chroma_x_shift;
- mpi->height = h;
- mpi->chroma_height = (h + (1 << mpi->chroma_y_shift) - 1) >>
- mpi->chroma_y_shift;
- }
- if (!mpi->bpp)
- mp_image_setfmt(mpi, outfmt);
- if (!(mpi->flags & MP_IMGFLAG_ALLOCATED) &&
- mpi->type > MP_IMGTYPE_EXPORT) {
- // check libvo first!
- if (vf->get_image)
- vf->get_image(vf, mpi);
-
- if (!(mpi->flags & MP_IMGFLAG_DIRECT)) {
- // non-direct and not yet allocated image. allocate it!
- if (!mpi->bpp) { // no way we can allocate this
- mp_msg(MSGT_DECVIDEO, MSGL_FATAL,
- "vf_get_image: Tried to allocate a format that "
- "can not be allocated!\n");
- return NULL;
- }
-
- // check if codec prefer aligned stride:
- if (mp_imgflag & MP_IMGFLAG_PREFER_ALIGNED_STRIDE) {
- int align = (mpi->flags & MP_IMGFLAG_PLANAR &&
- mpi->flags & MP_IMGFLAG_YUV) ?
- (16 << mpi->chroma_x_shift) - 1 : 32; // OK?
- w2 = FFALIGN(w, align);
- if (mpi->width != w2) {
- // we have to change width... check if we CAN co it:
- int flags = vf->query_format(vf, outfmt);
- // should not fail
- if (!(flags & (VFCAP_CSP_SUPPORTED |
- VFCAP_CSP_SUPPORTED_BY_HW)))
- mp_msg(MSGT_DECVIDEO, MSGL_WARN,
- "??? vf_get_image{vf->query_format(outfmt)} "
- "failed!\n");
- if (flags & VFCAP_ACCEPT_STRIDE) {
- mpi->width = w2;
- mpi->chroma_width =
- (w2 + (1 << mpi->chroma_x_shift) - 1) >>
- mpi->chroma_x_shift;
- }
- }
- }
-
- mp_image_alloc_planes(mpi);
- vf_mpi_clear(mpi, 0, 0, mpi->width, mpi->height);
- }
- }
- if (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK)
- if (vf->start_slice)
- vf->start_slice(vf, mpi);
- if (!(mpi->flags & MP_IMGFLAG_TYPE_DISPLAYED)) {
- mp_msg(MSGT_DECVIDEO, MSGL_V,
- "*** [%s] %s%s mp_image_t, %dx%dx%dbpp %s %s, %d bytes\n",
- vf->info->name,
- (mpi->type == MP_IMGTYPE_EXPORT) ? "Exporting" :
- ((mpi->flags & MP_IMGFLAG_DIRECT) ?
- "Direct Rendering" : "Allocating"),
- (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK) ? " (slices)" : "",
- mpi->width, mpi->height, mpi->bpp,
- (mpi->flags & MP_IMGFLAG_YUV) ? "YUV" :
- ((mpi->flags & MP_IMGFLAG_SWAPPED) ? "BGR" : "RGB"),
- (mpi->flags & MP_IMGFLAG_PLANAR) ? "planar" : "packed",
- mpi->bpp * mpi->width * mpi->height / 8);
- mp_msg(MSGT_DECVIDEO, MSGL_DBG2, "(imgfmt: %x, planes: %p,%p,%p "
- "strides: %d,%d,%d, chroma: %dx%d, shift: h:%d,v:%d)\n",
- mpi->imgfmt, mpi->planes[0], mpi->planes[1], mpi->planes[2],
- mpi->stride[0], mpi->stride[1], mpi->stride[2],
- mpi->chroma_width, mpi->chroma_height,
- mpi->chroma_x_shift, mpi->chroma_y_shift);
- mpi->flags |= MP_IMGFLAG_TYPE_DISPLAYED;
- }
- mpi->qscale = NULL;
- mpi->usage_count++;
- }
- return mpi;
-}
-
-//============================================================================
-
-static int vf_default_query_format(struct vf_instance *vf, unsigned int fmt)
-{
- return vf_next_query_format(vf, fmt);
-}
-
-struct vf_instance *vf_open_plugin_noerr(struct MPOpts *opts,
- const vf_info_t *const *filter_list,
- vf_instance_t *next, const char *name,
- char **args, int *retcode)
-{
- vf_instance_t *vf;
- int i;
- for (i = 0;; i++) {
- if (!filter_list[i]) {
- mp_tmsg(MSGT_VFILTER, MSGL_ERR,
- "Couldn't find video filter '%s'.\n", name);
- return NULL; // no such filter!
- }
- if (!strcmp(filter_list[i]->name, name))
- break;
- }
- vf = calloc(1, sizeof *vf);
- vf->opts = opts;
- vf->info = filter_list[i];
- vf->next = next;
- vf->config = vf_next_config;
- vf->control = vf_next_control;
- vf->query_format = vf_default_query_format;
- vf->put_image = vf_next_put_image;
- vf->default_caps = VFCAP_ACCEPT_STRIDE;
- vf->default_reqs = 0;
- if (vf->info->opts) { // vf_vo get some special argument
- const m_struct_t *st = vf->info->opts;
- void *vf_priv = m_struct_alloc(st);
- int n;
- for (n = 0; args && args[2 * n]; n++)
- m_struct_set(st, vf_priv, args[2 * n], bstr0(args[2 * n + 1]));
- vf->priv = vf_priv;
- args = NULL;
- } else // Otherwise we should have the '_oldargs_'
- if (args && !strcmp(args[0], "_oldargs_"))
- args = (char **)args[1];
- else
- args = NULL;
- *retcode = vf->info->vf_open(vf, (char *)args);
- if (*retcode > 0)
- return vf;
- free(vf);
- return NULL;
-}
-
-struct vf_instance *vf_open_plugin(struct MPOpts *opts,
- const vf_info_t *const *filter_list,
- vf_instance_t *next, const char *name,
- char **args)
-{
- struct vf_instance *vf = vf_open_plugin_noerr(opts, filter_list, next,
- name, args, &(int){0});
- if (!vf)
- mp_tmsg(MSGT_VFILTER, MSGL_ERR, "Couldn't open video filter '%s'.\n",
- name);
- return vf;
-}
-
-vf_instance_t *vf_open_filter(struct MPOpts *opts, vf_instance_t *next,
- const char *name, char **args)
-{
- if (args && strcmp(args[0], "_oldargs_")) {
- int i, l = 0;
- for (i = 0; args && args[2 * i]; i++)
- l += 1 + strlen(args[2 * i]) + 1 + strlen(args[2 * i + 1]);
- l += strlen(name);
- {
- char str[l + 1];
- char *p = str;
- p += sprintf(str, "%s", name);
- for (i = 0; args && args[2 * i]; i++)
- p += sprintf(p, " %s=%s", args[2 * i], args[2 * i + 1]);
- mp_msg(MSGT_VFILTER, MSGL_INFO, "%s[%s]\n",
- mp_gtext("Opening video filter: "), str);
- }
- } else if (strcmp(name, "vo")) {
- if (args && strcmp(args[0], "_oldargs_") == 0)
- mp_msg(MSGT_VFILTER, MSGL_INFO, "%s[%s=%s]\n",
- mp_gtext("Opening video filter: "), name, args[1]);
- else
- mp_msg(MSGT_VFILTER, MSGL_INFO, "%s[%s]\n",
- mp_gtext("Opening video filter: "), name);
- }
- return vf_open_plugin(opts, filter_list, next, name, args);
-}
-
-/**
- * \brief adds a filter before the last one (which should be the vo filter).
- * \param vf start of the filter chain.
- * \param name name of the filter to add.
- * \param args argument list for the filter.
- * \return pointer to the filter instance that was created.
- */
-vf_instance_t *vf_add_before_vo(vf_instance_t **vf, char *name, char **args)
-{
- struct MPOpts *opts = (*vf)->opts;
- vf_instance_t *vo, *prev = NULL, *new;
- // Find the last filter (should be vf_vo)
- for (vo = *vf; vo->next; vo = vo->next)
- prev = vo;
- new = vf_open_filter(opts, vo, name, args);
- if (prev)
- prev->next = new;
- else
- *vf = new;
- return new;
-}
-
-//============================================================================
-
-unsigned int vf_match_csp(vf_instance_t **vfp, const unsigned int *list,
- unsigned int preferred)
-{
- vf_instance_t *vf = *vfp;
- struct MPOpts *opts = vf->opts;
- const unsigned int *p;
- unsigned int best = 0;
- int ret;
- if ((p = list))
- while (*p) {
- ret = vf->query_format(vf, *p);
- mp_msg(MSGT_VFILTER, MSGL_V, "[%s] query(%s) -> %x\n",
- vf->info->name, vo_format_name(*p), ret);
- if (ret & VFCAP_CSP_SUPPORTED_BY_HW) {
- best = *p;
- break;
- }
- if (ret & VFCAP_CSP_SUPPORTED && !best)
- best = *p;
- ++p;
- }
- if (best)
- return best; // bingo, they have common csp!
- // ok, then try with scale:
- if (vf->info == &vf_info_scale)
- return 0; // avoid infinite recursion!
- vf = vf_open_filter(opts, vf, "scale", NULL);
- if (!vf)
- return 0; // failed to init "scale"
- // try the preferred csp first:
- if (preferred && vf->query_format(vf, preferred))
- best = preferred;
- else
- // try the list again, now with "scaler" :
- if ((p = list))
- while (*p) {
- ret = vf->query_format(vf, *p);
- mp_msg(MSGT_VFILTER, MSGL_V, "[%s] query(%s) -> %x\n",
- vf->info->name, vo_format_name(*p), ret);
- if (ret & VFCAP_CSP_SUPPORTED_BY_HW) {
- best = *p;
- break;
- }
- if (ret & VFCAP_CSP_SUPPORTED && !best)
- best = *p;
- ++p;
- }
- if (best)
- *vfp = vf; // else uninit vf !FIXME!
- return best;
-}
-
-void vf_clone_mpi_attributes(mp_image_t *dst, mp_image_t *src)
-{
- dst->pict_type = src->pict_type;
- dst->fields = src->fields;
- dst->qscale_type = src->qscale_type;
- if (dst->width == src->width && dst->height == src->height) {
- dst->qstride = src->qstride;
- dst->qscale = src->qscale;
- dst->display_w = src->display_w;
- dst->display_h = src->display_h;
- }
- if ((dst->flags & MP_IMGFLAG_YUV) == (src->flags & MP_IMGFLAG_YUV)) {
- dst->colorspace = src->colorspace;
- dst->levels = src->levels;
- }
-}
-
-void vf_queue_frame(vf_instance_t *vf, int (*func)(vf_instance_t *))
-{
- vf->continue_buffered_image = func;
-}
-
-// Output the next buffered image (if any) from the filter chain.
-// The queue could be kept as a simple stack/list instead avoiding the
-// looping here, but there's currently no good context variable where
-// that could be stored so this was easier to implement.
-
-int vf_output_queued_frame(vf_instance_t *vf)
-{
- while (1) {
- int ret;
- vf_instance_t *current;
- vf_instance_t *last = NULL;
- int (*tmp)(vf_instance_t *);
- for (current = vf; current; current = current->next)
- if (current->continue_buffered_image)
- last = current;
- if (!last)
- return 0;
- tmp = last->continue_buffered_image;
- last->continue_buffered_image = NULL;
- ret = tmp(last);
- if (ret)
- return ret;
- }
-}
-
-
-/**
- * \brief Video config() function wrapper
- *
- * Blocks config() calls with different size or format for filters
- * with VFCAP_CONSTANT
- *
- * First call is redirected to vf->config.
- *
- * In following calls, it verifies that the configuration parameters
- * are unchanged, and returns either success or error.
- *
- */
-int vf_config_wrapper(struct vf_instance *vf,
- int width, int height, int d_width, int d_height,
- unsigned int flags, unsigned int outfmt)
-{
- vf->fmt.have_configured = 1;
- vf->fmt.orig_height = height;
- vf->fmt.orig_width = width;
- vf->fmt.orig_fmt = outfmt;
- int r = vf->config(vf, width, height, d_width, d_height, flags, outfmt);
- if (!r)
- vf->fmt.have_configured = 0;
- return r;
-}
-
-int vf_next_config(struct vf_instance *vf,
- int width, int height, int d_width, int d_height,
- unsigned int voflags, unsigned int outfmt)
-{
- struct MPOpts *opts = vf->opts;
- int miss;
- int flags = vf->next->query_format(vf->next, outfmt);
- if (!flags) {
- // hmm. colorspace mismatch!!!
- // let's insert the 'scale' filter, it does the job for us:
- vf_instance_t *vf2;
- if (vf->next->info == &vf_info_scale)
- return 0; // scale->scale
- vf2 = vf_open_filter(opts, vf->next, "scale", NULL);
- if (!vf2)
- return 0; // shouldn't happen!
- vf->next = vf2;
- flags = vf->next->query_format(vf->next, outfmt);
- if (!flags) {
- mp_tmsg(MSGT_VFILTER, MSGL_ERR, "Cannot find matching colorspace, "
- "even by inserting 'scale' :(\n");
- return 0; // FAIL
- }
- }
- mp_msg(MSGT_VFILTER, MSGL_V, "REQ: flags=0x%X req=0x%X \n",
- flags, vf->default_reqs);
- miss = vf->default_reqs - (flags & vf->default_reqs);
- if (miss & VFCAP_ACCEPT_STRIDE) {
- // vf requires stride support but vf->next doesn't support it!
- // let's insert the 'expand' filter, it does the job for us:
- vf_instance_t *vf2 = vf_open_filter(opts, vf->next, "expand", NULL);
- if (!vf2)
- return 0; // shouldn't happen!
- vf->next = vf2;
- }
- vf->next->w = width;
- vf->next->h = height;
- return vf_config_wrapper(vf->next, width, height, d_width, d_height,
- voflags, outfmt);
-}
-
-int vf_next_control(struct vf_instance *vf, int request, void *data)
-{
- return vf->next->control(vf->next, request, data);
-}
-
-int vf_next_query_format(struct vf_instance *vf, unsigned int fmt)
-{
- int flags = vf->next->query_format(vf->next, fmt);
- if (flags)
- flags |= vf->default_caps;
- return flags;
-}
-
-int vf_next_put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
-{
- return vf->next->put_image(vf->next, mpi, pts);
-}
-
-void vf_next_draw_slice(struct vf_instance *vf, unsigned char **src,
- int *stride, int w, int h, int x, int y)
-{
- if (vf->next->draw_slice) {
- vf->next->draw_slice(vf->next, src, stride, w, h, x, y);
- return;
- }
- if (!vf->dmpi) {
- mp_msg(MSGT_VFILTER, MSGL_ERR,
- "draw_slice: dmpi not stored by vf_%s\n", vf->info->name);
- return;
- }
- if (!(vf->dmpi->flags & MP_IMGFLAG_PLANAR)) {
- memcpy_pic(vf->dmpi->planes[0] + y * vf->dmpi->stride[0] +
- vf->dmpi->bpp / 8 * x,
- src[0], vf->dmpi->bpp / 8 * w, h, vf->dmpi->stride[0],
- stride[0]);
- return;
- }
- memcpy_pic(vf->dmpi->planes[0] + y * vf->dmpi->stride[0] + x, src[0],
- w, h, vf->dmpi->stride[0], stride[0]);
- memcpy_pic(vf->dmpi->planes[1]
- + (y >> vf->dmpi->chroma_y_shift) * vf->dmpi->stride[1]
- + (x >> vf->dmpi->chroma_x_shift),
- src[1], w >> vf->dmpi->chroma_x_shift,
- h >> vf->dmpi->chroma_y_shift, vf->dmpi->stride[1], stride[1]);
- memcpy_pic(vf->dmpi->planes[2]
- + (y >> vf->dmpi->chroma_y_shift) * vf->dmpi->stride[2]
- + (x >> vf->dmpi->chroma_x_shift),
- src[2], w >> vf->dmpi->chroma_x_shift,
- h >> vf->dmpi->chroma_y_shift, vf->dmpi->stride[2], stride[2]);
-}
-
-//============================================================================
-
-vf_instance_t *append_filters(vf_instance_t *last,
- struct m_obj_settings *vf_settings)
-{
- struct MPOpts *opts = last->opts;
- vf_instance_t *vf;
- int i;
-
- if (vf_settings) {
- // We want to add them in the 'right order'
- for (i = 0; vf_settings[i].name; i++)
- /* NOP */;
- for (i--; i >= 0; i--) {
- //printf("Open filter %s\n",vf_settings[i].name);
- vf = vf_open_filter(opts, last, vf_settings[i].name,
- vf_settings[i].attribs);
- if (vf)
- last = vf;
- }
- }
- return last;
-}
-
-//============================================================================
-
-void vf_uninit_filter(vf_instance_t *vf)
-{
- if (vf->uninit)
- vf->uninit(vf);
- free_mp_image(vf->imgctx.static_images[0]);
- free_mp_image(vf->imgctx.static_images[1]);
- free_mp_image(vf->imgctx.temp_images[0]);
- free_mp_image(vf->imgctx.export_images[0]);
- for (int i = 0; i < NUM_NUMBERED_MPI; i++)
- free_mp_image(vf->imgctx.numbered_images[i]);
- free(vf);
-}
-
-void vf_uninit_filter_chain(vf_instance_t *vf)
-{
- while (vf) {
- vf_instance_t *next = vf->next;
- vf_uninit_filter(vf);
- vf = next;
- }
-}
-
-void vf_detc_init_pts_buf(struct vf_detc_pts_buf *p)
-{
- p->inpts_prev = MP_NOPTS_VALUE;
- p->outpts_prev = MP_NOPTS_VALUE;
- p->lastdelta = 0;
-}
-
-static double vf_detc_adjust_pts_internal(struct vf_detc_pts_buf *p,
- double pts, bool reset_pattern,
- bool skip_frame, double delta,
- double boundfactor_minus,
- double increasefactor,
- double boundfactor_plus)
-{
- double newpts;
-
- if (pts == MP_NOPTS_VALUE)
- return pts;
-
- if (delta <= 0) {
- if (p->inpts_prev == MP_NOPTS_VALUE)
- delta = 0;
- else if (pts == p->inpts_prev)
- delta = p->lastdelta;
- else
- delta = pts - p->inpts_prev;
- }
- p->inpts_prev = pts;
- p->lastdelta = delta;
-
- if (skip_frame)
- return MP_NOPTS_VALUE;
-
- /* detect bogus deltas and then passthru pts (possibly caused by seeking,
- * or bad input) */
- if (p->outpts_prev == MP_NOPTS_VALUE || reset_pattern || delta <= 0.0 ||
- delta >= 0.5)
- newpts = pts;
- else {
- // turn 5 frames into 4
- newpts = p->outpts_prev + delta * increasefactor;
-
- // bound to input pts in a sensible way; these numbers come because we
- // map frames the following way when ivtc'ing:
- // 0/30 -> 0/24 diff=0
- // 1/30 -> 1/24 diff=1/120
- // 2/30 -> -
- // 3/30 -> 2/24 diff=-1/60
- // 4/30 -> 3/24 diff=-1/120
- if (newpts < pts - delta * boundfactor_minus)
- newpts = pts - delta * boundfactor_minus;
- if (newpts > pts + delta * boundfactor_plus)
- newpts = pts + delta * boundfactor_plus;
- if (newpts < p->outpts_prev)
- newpts = p->outpts_prev; // damage control
- }
- p->outpts_prev = newpts;
-
- return newpts;
-}
-
-double vf_detc_adjust_pts(struct vf_detc_pts_buf *p, double pts,
- bool reset_pattern, bool skip_frame)
-{
- // standard telecine (see above)
- return vf_detc_adjust_pts_internal(p, pts, reset_pattern, skip_frame,
- 0, 0.5, 1.25, 0.25);
-}
-
-double vf_softpulldown_adjust_pts(struct vf_detc_pts_buf *p, double pts,
- bool reset_pattern, bool skip_frame,
- int last_frame_duration)
-{
- // for the softpulldown filter we get:
- // 0/60 -> 0/30
- // 2/60 -> 1/30
- // 5/60 -> 2/30
- // 7/60 -> 3/30, 4/30
- return vf_detc_adjust_pts_internal(p, pts, reset_pattern, skip_frame,
- 0, 1.0 / last_frame_duration,
- 2.0 / last_frame_duration,
- 1.0 / last_frame_duration);
-}