#include #include #include #include #include "config.h" #include "mp_msg.h" #include "cpudetect.h" #include "img_format.h" #include "mp_image.h" #include "vf.h" #include "libvo/video_out.h" #include "m_option.h" #include "m_struct.h" static struct vf_priv_s { unsigned char *buf; float level1; float level2; float pos1; // position to start changing chroma level to level1 float pos2; // position to start rolling off from level1 to level2 float pos3; // position to roll off to level2 float pos4; // position to changing chroma level to original int pixel_pos1; int pixel_pos2; int pixel_pos3; int pixel_pos4; float delta; } const vf_priv_dflt = { NULL, 0, 0, 0, 0, 0 }; static inline void process(unsigned char *dest, int dstride, unsigned char *src, int sstride, int w, int h, struct vf_priv_s* priv) { int i; int dstep = dstride-w; int sstep = sstride-w; int pos1 = (int)priv->pixel_pos1; int pos2 = (int)priv->pixel_pos2; int pos3 = (int)priv->pixel_pos3; int pos4 = (int)priv->pixel_pos4; float delta = priv->delta; while (h--) { float level = priv->level1; for (i = 0; i < w; i++) { if (i >= pos1 && i < pos4) { if (i >= pos2 && i < pos3) level += delta; *dest++ = level * (*src++); } else { *dest++ = *src++; } } src += sstep; dest += dstep; } } static int put_image(struct vf_instance_s* vf, mp_image_t *mpi, double pts) { mp_image_t *dmpi; dmpi=vf_get_image(vf->next, mpi->imgfmt, MP_IMGTYPE_EXPORT, 0, mpi->w, mpi->h); dmpi->stride[0] = mpi->stride[0]; dmpi->planes[1] = mpi->planes[1]; dmpi->planes[2] = mpi->planes[2]; dmpi->stride[1] = mpi->stride[1]; dmpi->stride[2] = mpi->stride[2]; if (!vf->priv->buf) vf->priv->buf = malloc(mpi->stride[0]*mpi->h); dmpi->planes[0] = vf->priv->buf; process(dmpi->planes[0], dmpi->stride[0], mpi->planes[0], mpi->stride[0], mpi->w, mpi->h, vf->priv); return vf_next_put_image(vf,dmpi, pts); } static int query_format(struct vf_instance_s* vf, unsigned int fmt) { switch (fmt) { case IMGFMT_YVU9: case IMGFMT_IF09: case IMGFMT_YV12: case IMGFMT_I420: case IMGFMT_IYUV: case IMGFMT_CLPL: case IMGFMT_Y800: case IMGFMT_Y8: case IMGFMT_NV12: case IMGFMT_NV21: case IMGFMT_444P: case IMGFMT_422P: case IMGFMT_411P: return vf_next_query_format(vf, fmt); } return 0; } static void uninit(struct vf_instance_s* vf) { if (vf->priv->buf) free(vf->priv->buf); free(vf->priv); } static int config(struct vf_instance_s* vf, int width, int height, int d_width, int d_height, unsigned int flags, unsigned int outfmt){ // convert percentage to pixel vf->priv->pixel_pos1 = (int)(vf->priv->pos1 / 100 * width); vf->priv->pixel_pos2 = (int)(vf->priv->pos2 / 100 * width); vf->priv->pixel_pos3 = (int)(vf->priv->pos3 / 100 * width); vf->priv->pixel_pos4 = (int)(vf->priv->pos4 / 100 * width); vf->priv->delta = (vf->priv->level2 - vf->priv->level1) / (vf->priv->pixel_pos3 -vf->priv->pixel_pos2); mp_msg(MSGT_VFILTER, MSGL_INFO, "[Roll-off] l1: %f l2: %f p1: %d p2: %d p3: %d p4: %d\n", vf->priv->level1, vf->priv->level2, vf->priv->pixel_pos1, vf->priv->pixel_pos2, vf->priv->pixel_pos3, vf->priv->pixel_pos4); return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt); } static int open(vf_instance_t *vf, char* args) { vf->config=config; vf->query_format=query_format; vf->put_image=put_image; vf->uninit=uninit; return 1; } #define ST_OFF(f) M_ST_OFF(struct vf_priv_s,f) static m_option_t vf_opts_fields[] = { {"level1", ST_OFF(level1), CONF_TYPE_FLOAT, M_OPT_RANGE, 0, 1, NULL}, {"level2", ST_OFF(level2), CONF_TYPE_FLOAT, M_OPT_RANGE, 0, 1, NULL}, {"pos1", ST_OFF(pos1), CONF_TYPE_FLOAT, M_OPT_RANGE, 0, 100, NULL}, {"pos2", ST_OFF(pos2), CONF_TYPE_FLOAT, M_OPT_RANGE, 0 ,100, NULL}, {"pos3", ST_OFF(pos3), CONF_TYPE_FLOAT, M_OPT_RANGE, 0 ,100, NULL}, {"pos4", ST_OFF(pos4), CONF_TYPE_FLOAT, M_OPT_RANGE, 0 ,100, NULL}, { NULL, NULL, 0, 0, 0, 0, NULL } }; static m_struct_t vf_opts = { "rolloff", sizeof(struct vf_priv_s), &vf_priv_dflt, vf_opts_fields }; vf_info_t vf_info_rolloff = { "chroma roll-off filter", "rolloff", "Stanley Huang", "", open, &vf_opts };