diff options
author | wm4 <wm4@nowhere> | 2012-11-05 17:02:04 +0100 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2012-11-12 20:06:14 +0100 |
commit | d4bdd0473d6f43132257c9fb3848d829755167a3 (patch) | |
tree | 8021c2f7da1841393c8c832105e20cd527826d6c /libmpcodecs/vf.c | |
parent | bd48deba77bd5582c5829d6fe73a7d2571088aba (diff) | |
download | mpv-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.c | 830 |
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); -} |