#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 level_hi; float level_low; float pos1; float pos2; float pos3; int direction; } const vf_priv_dflt = { NULL, 0, 0, 0, 0, 0 }; static 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->pos1; int pos2 = (int)priv->pos2; int pos3 = (int)priv->pos3; int dir = priv->direction; float level_hi = priv->level_hi; float level_low = priv->level_low; while (h--) { for (i = 0; i < w; i++) { if (!dir) { if (i >= pos1 && i < pos2) { *dest = level_hi * (*src); } else if (i >= pos2 && i < pos3) { float level = (float)(pos3 - i) / (pos3 -pos2) * (level_hi - level_low) + level_low; *dest = level * *src; } else { *dest = *src; } } else { if (i >= pos1 && i < pos2) { float level = (float)(i - pos1) / (pos2 -pos1) * (level_hi - level_low) + level_low; *dest = level * *src; } else if (i >= pos2 && i < pos3) { *dest = level_hi * *src; } else { *dest = *src; } } 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->pos1 = (int)(vf->priv->pos1 / 100 * width); vf->priv->pos2 = (int)(vf->priv->pos2 / 100 * width); vf->priv->pos3 = (int)(vf->priv->pos3 / 100 * width); mp_msg(MSGT_VFILTER, MSGL_INFO, "[Roll-off] hi: %f lo: %f p1: %d p2: %d p3: %d\n", vf->priv->level_hi, vf->priv->level_low, (int)vf->priv->pos1, (int)vf->priv->pos2, (int)vf->priv->pos3); 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; if(!vf->priv) { vf->priv = malloc(sizeof(struct vf_priv_s)); memset(vf->priv, 0, sizeof(struct vf_priv_s)); } return 1; } #define ST_OFF(f) M_ST_OFF(struct vf_priv_s,f) static m_option_t vf_opts_fields[] = { {"level_hi", ST_OFF(level_hi), CONF_TYPE_FLOAT, 0, 0 ,0, NULL}, {"level_low", ST_OFF(level_low), CONF_TYPE_FLOAT, 0, 0 ,0, NULL}, {"pos1", ST_OFF(pos1), CONF_TYPE_FLOAT, 0, 0 ,0, NULL}, {"pos2", ST_OFF(pos2), CONF_TYPE_FLOAT, 0, 0 ,0, NULL}, {"pos3", ST_OFF(pos3), CONF_TYPE_FLOAT, 0, 0 ,0, NULL}, {"direction", ST_OFF(direction), CONF_TYPE_INT, 0, 0 ,0, NULL}, { NULL, NULL, 0, 0, 0, 0, NULL } }; static m_struct_t vf_opts = { "eq", 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 };