static int vag_inspect(TCModuleInstance *self,
                       const char *param, const char **value)
{
    PrivateData *pd = NULL;
    static char buf[TC_BUF_MAX];

    TC_MODULE_SELF_CHECK(self, "inspect");
    TC_MODULE_SELF_CHECK(param, "inspect");
    TC_MODULE_SELF_CHECK(value, "inspect");

    pd = self->userdata;

    if (optstr_lookup(param, "help")) {
        tc_snprintf(buf, sizeof(buf),
                "Overview:\n"
                "    Decodes PlayStation VAG format (ADPCM-style) audio.\n"
                "Options available:\n"
                "    blocksize=N   Set stereo blocking size (16-%d, default %d)\n",
                MAX_STEREO_BLOCK, DEF_STEREO_BLOCK);
        *value = buf;
        return TC_IMPORT_OK;
    }
    if (optstr_lookup(param, "blocksize")) {
        tc_snprintf(buf, sizeof(buf), "%d", pd->blocksize);
        *value = buf;
        return TC_IMPORT_OK;
    }
    return TC_IMPORT_OK;
}
static int astat_inspect(TCModuleInstance *self,
                             const char *param, const char **value)
{
    AStatPrivateData *pd = NULL;

    TC_MODULE_SELF_CHECK(self, "inspect");
    TC_MODULE_SELF_CHECK(param, "inspect");
    TC_MODULE_SELF_CHECK(value, "inspect");

    pd = self->userdata;

    if (optstr_lookup(param, "help")) {
        *value = help_string; 
    }
    if (optstr_lookup(param, "file")) {
        if (pd->filepath == NULL) {
            *value = "None";
        } else {
            tc_snprintf(pd->optstr_buf, sizeof(pd->optstr_buf),
                        "%s", pd->filepath);
            *value = pd->optstr_buf;
        }
    }
    if (optstr_lookup(param, "silence_limit")) {
        tc_snprintf(pd->optstr_buf, sizeof(pd->optstr_buf),
                    "%i", pd->silence_limit);
        *value = pd->optstr_buf;
    }

    return TC_OK;
}
static int fields_inspect(TCModuleInstance *self,
                          const char *param, const char **value)
{
    FieldsPrivateData *pd = NULL;

    TC_MODULE_SELF_CHECK(self, "inspect");
    TC_MODULE_SELF_CHECK(param, "inspect");
    
    pd = self->userdata;

    if (optstr_lookup(param, "help")) {
        *value = fields_help;
    }

    if (optstr_lookup(param, "flip")) {
        tc_snprintf(pd->conf_str, sizeof(pd->conf_str),
                    "%s", (pd->field_ops & FIELD_OP_FLIP) ?"yes" :"no");
        *value = pd->conf_str;
    }
    if (optstr_lookup(param, "shift")) {
        tc_snprintf(pd->conf_str, sizeof(pd->conf_str),
                    "%s", (pd->field_ops & FIELD_OP_SHIFT) ?"yes" :"no");
        *value = pd->conf_str;
    }
    if (optstr_lookup(param, "flip_first")) {
        tc_snprintf(pd->conf_str, sizeof(pd->conf_str),
                    "%s", (pd->field_ops & FIELD_OP_REVERSE) ?"yes" :"no");
        *value = pd->conf_str;
    }

    return TC_OK;
}
static int doublefps_inspect(TCModuleInstance *self,
                             const char *param, const char **value)
{
    DfpsPrivateData *pd = NULL;
    static char buf[TC_BUF_MAX];

    TC_MODULE_SELF_CHECK(self, "inspect");
    TC_MODULE_SELF_CHECK(param, "inspect");
    TC_MODULE_SELF_CHECK(value, "inspect");

    pd = self->userdata;

    if (optstr_lookup(param, "help")) {
        *value = 
"Overview:\n"
"\n"
"    Doubles the frame rate of interlaced video by separating each field\n"
"    into a separate frame.  The fields can either be left as is (giving a\n"
"    progessive video with half the height of the original) or re-interlaced\n"
"    into their original height (at the doubled frame rate) for the\n"
"    application of a separate deinterlacing filter.\n"
"\n"
"    Note that due to transcode limitations, it is currently necessary to\n"
"    use the -Z option to specify the output frame size when using\n"
"    half-height mode (this does not slow the program down if no actual\n"
"    zooming is done).\n"
"\n"
"    When using this filter in half-height mode, make sure you specify\n"
"    \"--encode_fields p\" on the transcode command line, and do not use the\n"
"    \"-I\" option.\n"
"\n"
"Options available:\n"
"\n"
"    topfirst=0|1     Selects whether the top field is the first displayed.\n"
"                     Defaults to 0 (bottom-first) for 480-line video, 1\n"
"                     (top-first) otherwise.\n"
"\n"
"    fullheight=0|1   Selects whether or not to retain full height when\n"
"                     doubling the frame rate.  If this is set to 1, the\n"
"                     resulting video will have the same frame size as the\n"
"                     original at double the frame rate, and the frames will\n"
"                     consist of fields 0 and 1, 1 and 2, 2 and 3, and so\n"
"                     forth.  This can be used to let a separate filter\n"
"                     perform deinterlacing on the double-rate frames; note\n"
"                     that the filter must be able to deal with the top and\n"
"                     bottom fields switching with each frame.\n"
"                     Note that this option cannot be changed after startup.\n"
;
    }
    if (optstr_lookup(param, "topfirst")) {
        tc_snprintf(buf, sizeof(buf), "%d", pd->topfirst);
        *value = buf;
    }
    if (optstr_lookup(param, "fullheight")) {
        tc_snprintf(buf, sizeof(buf), "%d", pd->fullheight);
        *value = buf;
    }
    return TC_OK;
}
static int fields_configure(TCModuleInstance *self,
            			    const char *options,
                            TCJob *vob,
                            TCModuleExtraData *xdata[])
{
    FieldsPrivateData *pd = NULL;

    TC_MODULE_SELF_CHECK(self, "configure");

    pd = self->userdata;

    // Some of the data in buffer may get used for half of the first frame (when
    // shifting) so make sure it's blank to start with.
    pd->buffer = tc_zalloc(SIZE_RGB_FRAME);
    if (!pd->buffer) {
        tc_log_error(MOD_NAME, "Unable to allocate memory.  Aborting.");
        return TC_ERROR;
    }

    if (options != NULL) {
        if (optstr_lookup(options, "flip"))
            pd->field_ops |= FIELD_OP_FLIP;
        if (optstr_lookup(options, "shift"))
            pd->field_ops |= FIELD_OP_SHIFT;
        if (optstr_lookup(options, "flip_first"))
            pd->field_ops |= FIELD_OP_REVERSE;
    }

    // FIELD_OP_REVERSE (aka flip_first) only makes sense if we're doing
    // both operations.  If we're not, unset it.
    if (pd->field_ops != FIELD_OP_FLIPSHIFT)
        pd->field_ops &= ~FIELD_OP_REVERSE;

    if (verbose) {
        if (pd->field_ops & FIELD_OP_SHIFT)
            tc_log_info(MOD_NAME, "Adjusting frame positions (shift)");
        if (pd->field_ops & FIELD_OP_FLIP)
            tc_log_info(MOD_NAME, "Transposing input fields  (flip)");
        if (pd->field_ops & FIELD_OP_REVERSE)
            tc_log_info(MOD_NAME, "Flipping will occur before shifting (flip_first)");
    }

    if (!pd->field_ops) {
        tc_log_warn(MOD_NAME, "No operations specified to perform.");
        return TC_ERROR;
    }

    if (vob->im_v_codec == TC_CODEC_RGB24);
        pd->rgb_mode = TC_TRUE;

    if (verbose)
        tc_log_info(MOD_NAME, "%s %s", MOD_VERSION, MOD_CAP);

    return TC_OK;
}
Beispiel #6
0
static int deshake_inspect(TCModuleInstance *self,
			   const char *param, const char **value)
{
  DeshakeData *sd = NULL;

  TC_MODULE_SELF_CHECK(self, "inspect");
  TC_MODULE_SELF_CHECK(param, "inspect");
  TC_MODULE_SELF_CHECK(value, "inspect");
  sd = self->userdata;
  MotionDetect* md = &(sd->md);
  if (optstr_lookup(param, "help")) {
    *value = deshake_help;
  }
  CHECKPARAM("shakiness","shakiness=%d", md->shakiness);
  CHECKPARAM("accuracy", "accuracy=%d",  md->accuracy);
  CHECKPARAM("stepsize", "stepsize=%d",  md->stepSize);
  CHECKPARAM("allowmax", "allowmax=%d",  md->allowMax);
  CHECKPARAM("algo",     "algo=%d",      md->algo);
  CHECKPARAM("result",   "result=%s",    sd->result);
  CHECKPARAM("maxshift", "maxshift=%d",  sd->td.maxShift);
  CHECKPARAM("maxangle", "maxangle=%f",  sd->td.maxAngle);
  CHECKPARAM("smoothing","smoothing=%d", sd->td.smoothing);
  CHECKPARAM("crop",     "crop=%d",      sd->td.crop);
  CHECKPARAM("optzoom",  "optzoom=%i",   sd->td.optZoom);
  CHECKPARAM("zoom",     "zoom=%f",      sd->td.zoom);
  CHECKPARAM("sharpen",  "sharpen=%f",   sd->td.sharpen);

  return TC_OK;
}
Beispiel #7
0
/**
 * stabilize_inspect:  Return the value of an option in this instance of
 * the module.  See tcmodule-data.h for function details.
 */
static int transform_inspect(TCModuleInstance *self,
                       const char *param, const char **value)
{
    FilterData *fd = NULL;
    TC_MODULE_SELF_CHECK(self,  "inspect");
    TC_MODULE_SELF_CHECK(param, "inspect");
    TC_MODULE_SELF_CHECK(value, "inspect");

    fd = self->userdata;

    if (optstr_lookup(param, "help")) {
        *value = vs_transform_help;
    }
    VSTransformConfig conf;
    vsTransformGetConfig(&conf,&fd->td);
    CHECKPARAM("maxshift", "maxshift=%d",  conf.maxShift);
    CHECKPARAM("maxangle", "maxangle=%f",  conf.maxAngle);
    CHECKPARAM("smoothing","smoothing=%d", conf.smoothing);
    CHECKPARAM("crop",     "crop=%d",      conf.crop);
    CHECKPARAM("relative", "relative=%d",  conf.relative);
    CHECKPARAM("invert",   "invert=%i",    conf.invert);
    CHECKPARAM("input",    "input=%s",     fd->input);
    CHECKPARAM("optzoom",  "optzoom=%i",   conf.optZoom);
    CHECKPARAM("zoom",     "zoom=%f",      conf.zoom);
    CHECKPARAM("sharpen",  "sharpen=%f",   fd->sharpen);

    return TC_OK;
};
static int raw_inspect(TCModuleInstance *self,
                       const char *options, const char **value)
{
    TC_MODULE_SELF_CHECK(self, "inspect");
    
    if (optstr_lookup(options, "help")) {
        *value = raw_help;
    }

    return TC_OK;
}
static int tc_x11_inspect(TCModuleInstance *self,
                          const char *param, const char **value)
{
    TC_MODULE_SELF_CHECK(self, "inspect");

    if (optstr_lookup(param, "help")) {
        *value = tc_x11_help;
    }

    return TC_OK;
}
Beispiel #10
0
static int flogo_parse_options(LogoPrivateData *pd,
                               const char *options, char *logo_file)
{
    /* default */
    strlcpy(logo_file, DEFAULT_LOGO_FILE, PATH_MAX);

    optstr_get(options, "file",     "%[^:]", logo_file);
    optstr_get(options, "posdef",   "%d",    (int *)&pd->pos);
    optstr_get(options, "pos",      "%dx%d", &pd->posx,  &pd->posy);
    optstr_get(options, "range",    "%u-%u", &pd->start, &pd->end);
    optstr_get(options, "fade",     "%u-%u", &pd->fadein, &pd->fadeout);

    if (optstr_lookup(options, "ignoredelay") != NULL)
        pd->ignoredelay = !pd->ignoredelay;
    if (optstr_lookup(options, "flip") != NULL)
        pd->flip    = !pd->flip;
    if (optstr_lookup(options, "rgbswap") != NULL)
        pd->rgbswap = !pd->rgbswap;
    if (optstr_lookup(options, "grayout") != NULL)
        pd->grayout = !pd->grayout;
    if (optstr_lookup(options, "hqconv") != NULL)
        pd->hqconv  = !pd->hqconv;

    if (verbose) {
        tc_log_info(MOD_NAME, " Logo renderer Settings:");
        tc_log_info(MOD_NAME, "         file = %s",    logo_file);
        tc_log_info(MOD_NAME, "       posdef = %d",    pd->pos);
        tc_log_info(MOD_NAME, "          pos = %dx%d", pd->posx,
                                                       pd->posy);
        tc_log_info(MOD_NAME, "        range = %u-%u", pd->start,
                                                       pd->end);
        tc_log_info(MOD_NAME, "         fade = %u-%u", pd->fadein,
                                                       pd->fadeout);
        tc_log_info(MOD_NAME, "         flip = %d",    pd->flip);
        tc_log_info(MOD_NAME, "  ignoredelay = %d",    pd->ignoredelay);
        tc_log_info(MOD_NAME, "      rgbswap = %d",    pd->rgbswap);
        tc_log_info(MOD_NAME, "      grayout = %d",    pd->grayout);
        tc_log_info(MOD_NAME, "       hqconv = %d",    pd->hqconv);
    }
    return TC_OK;
}
Beispiel #11
0
static int tc_im_inspect(TCModuleInstance *self,
                         const char *param, const char **value)
{
    TCIMPrivateData *pd = NULL;
    
    TC_MODULE_SELF_CHECK(self, "inspect");

    pd = self->userdata;

    if (optstr_lookup(param, "help")) {
        *value = tc_im_help;
    }
    if (optstr_lookup(param, "format")) {
        *value = pd->img_fmt;
    }
    if (optstr_lookup(param, "quality")) {
        tc_snprintf(pd->opt_buf, sizeof(pd->opt_buf), "%lu", pd->quality);
        *value = pd->opt_buf;
    }
    return TC_OK;
}
static int lowpass_inspect(TCModuleInstance *self,
                          const char *param, const char **value)
{
    LowPassPrivateData *pd = NULL;

    TC_MODULE_SELF_CHECK(self, "inspect");
    TC_MODULE_SELF_CHECK(param, "inspect");
    
    pd = self->userdata;

    if (optstr_lookup(param, "help")) {
        *value = lowpass_help;
    }

    if (optstr_lookup(param, "taps")) {
        tc_snprintf(pd->conf_str, sizeof(pd->conf_str),
                    "taps=%i", pd->taps);
        *value = pd->conf_str;
    }

    return TC_OK;
}
static int invert_inspect(TCModuleInstance *self,
                        const char *param, const char **value)
{
    InvertPrivateData *mfd = NULL;

    TC_MODULE_SELF_CHECK(self, "inspect");
    TC_MODULE_SELF_CHECK(param, "inspect");
    TC_MODULE_SELF_CHECK(value, "inspect");

    mfd = self->userdata;

    if (optstr_lookup(param, "help")) {
        *value = invert_help; 
    }
    if (optstr_lookup(param, "range")) {
	    tc_snprintf(mfd->opt_buf, sizeof(mfd->opt_buf), "%u-%u/%d",
                    mfd->start, mfd->end, mfd->step);
        *value = mfd->opt_buf; 
    }

    return TC_OK;
}
static int tc_vorbis_inspect(TCModuleInstance *self,
                             const char *param, const char **value)
{
    VorbisPrivateData *pd = NULL;

    TC_MODULE_SELF_CHECK(self, "inspect");

    pd = self->userdata;

    if (optstr_lookup(param, "help")) {
        *value = tc_vorbis_help;
    }

    return TC_OK;
}
Beispiel #15
0
static int faac_inspect(TCModuleInstance *self,
                       const char *param, const char **value)
{
    static char buf[TC_BUF_MAX];

    TC_MODULE_SELF_CHECK(self, "inspect");
    TC_MODULE_SELF_CHECK(param, "inspect");

    if (optstr_lookup(param, "help")) {
        tc_snprintf(buf, sizeof(buf),
                "Overview:\n"
                "    Encodes audio to AAC using the FAAC library.\n"
                "Options:\n"
                "    quality: set encoder quality [0-100]\n");
        *value = buf;
    }
    return TC_OK;
}
static int template_inspect(TCModuleInstance *self,
                             const char *param, const char **value)
{
    PrivateData *pd = NULL;

    TC_MODULE_SELF_CHECK(self, "inspect");
    TC_MODULE_SELF_CHECK(param, "inspect");
    TC_MODULE_SELF_CHECK(value, "inspect");

    pd = self->userdata;

    if (optstr_lookup(param, "help")) {
        *value = help_string; 
    }
    /* put back configurable options */

    return TC_OK;
}
static int pvn_inspect(TCModuleInstance *self,
                       const char *param, const char **value)
{
    static char buf[TC_BUF_MAX];

    TC_MODULE_SELF_CHECK(self, "inspect");
    TC_MODULE_SELF_CHECK(param, "inspect");

    if (optstr_lookup(param, "help")) {
        tc_snprintf(buf, sizeof(buf),
                    "Overview:\n"
                    "    Writes a PVN video stream (format PV6a, 8-bit data).\n"
                    "    A grayscale file (PV5a) is written instead if the -K\n"
                    "    switch is given to transcode.\n"
                    "    The RGB colorspace must be used (-V rgb24).\n"
                    "No options available.\n");
        *value = buf;
    }
    return TC_OK;
}
static int nuv_inspect(TCModuleInstance *self,
                       const char *param, const char **value)
{
    PrivateData *pd;
    static char buf[TC_BUF_MAX];

    TC_MODULE_SELF_CHECK(self, "inspect");
    TC_MODULE_SELF_CHECK(param, "inspect");
    TC_MODULE_SELF_CHECK(value, "inspect");

    pd = self->userdata;

    if (optstr_lookup(param, "help")) {
        tc_snprintf(buf, sizeof(buf),
                    "Overview:\n"
                    "    Decodes NuppelVideo streams.\n"
                    "Options available: None.\n");
       *value = buf;
    }
    return TC_IMPORT_OK;
}
int tc_filter(frame_list_t *vframe_, char * options)
{
	vframe_list_t *vframe = (vframe_list_t *)vframe_;
	int instance;
	int tag = vframe->tag;
	dn3d_private_data_t * pd;

	if(tag & TC_AUDIO)
		return(0);

	instance	= vframe->filter_id;
	pd			= &dn3d_private_data[instance];

	if(tag & TC_FILTER_GET_CONFIG)
	{
		char buf[128];
		optstr_filter_desc(options, MOD_NAME, MOD_CAP, MOD_VERSION, MOD_AUTHOR, "VYMOE", "2");

		tc_snprintf(buf, 128, "%f", DEFAULT_LUMA_SPATIAL);
		optstr_param(options, "luma", "spatial luma strength", "%f", buf, "0.0", "100.0" );

		tc_snprintf(buf, 128, "%f", DEFAULT_CHROMA_SPATIAL);
		optstr_param(options, "chroma", "spatial chroma strength", "%f", buf, "0.0", "100.0" );

		tc_snprintf(buf, 128, "%f", DEFAULT_LUMA_TEMPORAL);
		optstr_param(options, "luma_strength", "temporal luma strength", "%f", buf, "0.0", "100.0" );

		tc_snprintf(buf, 128, "%f", DEFAULT_CHROMA_TEMPORAL);
		optstr_param(options, "chroma_strength", "temporal chroma strength", "%f", buf, "0.0", "100.0" );

		tc_snprintf(buf, 128, "%d", dn3d_private_data[instance].prefilter);
		optstr_param(options, "pre", "run as a pre filter", "%d", buf, "0", "1" );
	}

	if(tag & TC_FILTER_INIT)
	{
		int format_index, plane_index, found;
		const dn3d_layout_t * lp;
		size_t size;

		if(!(pd->vob = tc_get_vob()))
			return(TC_IMPORT_ERROR);

		pd->parameter.luma_spatial		= 0;
		pd->parameter.luma_temporal		= 0;
		pd->parameter.chroma_spatial	= 0;
		pd->parameter.chroma_temporal	= 0;

		if(!options)
		{
			tc_log_error(MOD_NAME, "options not set!");
			return(TC_IMPORT_ERROR);
		}

		if(optstr_lookup(options, "help"))
		{
			help_optstr();
			return(TC_IMPORT_ERROR);
	  	}

		optstr_get(options, "luma",				"%lf",	&pd->parameter.luma_spatial);
		optstr_get(options, "luma_strength",	"%lf",	&pd->parameter.luma_temporal);
		optstr_get(options, "chroma",			"%lf",	&pd->parameter.chroma_spatial);
		optstr_get(options, "chroma_strength",	"%lf",	&pd->parameter.chroma_temporal);
		optstr_get(options, "pre",				"%d",	&dn3d_private_data[instance].prefilter);

		if((pd->parameter.luma_spatial < 0) || (pd->parameter.luma_temporal < 0))
			pd->enable_luma = 0;
		else
		{
			pd->enable_luma = 1;

			if(pd->parameter.luma_spatial == 0)
			{
				if(pd->parameter.luma_temporal == 0)
				{
					pd->parameter.luma_spatial	= DEFAULT_LUMA_SPATIAL;
					pd->parameter.luma_temporal	= DEFAULT_LUMA_TEMPORAL;
				}
				else
				{
					pd->parameter.luma_spatial = pd->parameter.luma_temporal * 3 / 2;
				}
			}
			else
			{
				if(pd->parameter.luma_temporal == 0)
				{
					pd->parameter.luma_temporal = pd->parameter.luma_spatial * 2 / 3;
				}
			}
		}

		if((pd->parameter.chroma_spatial < 0) || (pd->parameter.chroma_temporal < 0))
			pd->enable_chroma = 0;
		else
		{
			pd->enable_chroma = 1;

			if(pd->parameter.chroma_spatial == 0)
			{
				if(pd->parameter.chroma_temporal == 0)
				{
					pd->parameter.chroma_spatial	= DEFAULT_CHROMA_SPATIAL;
					pd->parameter.chroma_temporal	= DEFAULT_CHROMA_TEMPORAL;
				}
				else
				{
					pd->parameter.chroma_spatial = pd->parameter.chroma_temporal * 3 / 2;
				}
			}
			else
			{
				if(pd->parameter.chroma_temporal == 0)
				{
					pd->parameter.chroma_temporal = pd->parameter.chroma_spatial * 2 / 3;
				}
			}
		}

		for(format_index = 0, found = 0; format_index < (sizeof(dn3d_layout) / sizeof(*dn3d_layout)); format_index++)
		{
			if(pd->vob->im_v_codec == dn3d_layout[format_index].tc_fmt)
			{
				found = 1;
				break;
			}
		}

		if(!found)
		{
			tc_log_error(MOD_NAME, "This filter is only capable of YUV, YUV422 and RGB mode");
	  		return(TC_IMPORT_ERROR);
		}

		lp = &dn3d_layout[format_index];
		pd->layout_data = *lp;

		for(plane_index = 0; plane_index < MAX_PLANES; plane_index++)
		{
			if((pd->layout_data.layout[plane_index].plane_type == dn3d_luma) && !pd->enable_luma)
				pd->layout_data.layout[plane_index].plane_type = dn3d_disabled;

			if((pd->layout_data.layout[plane_index].plane_type == dn3d_chroma) && !pd->enable_chroma)
				pd->layout_data.layout[plane_index].plane_type = dn3d_disabled;
		}

		size = pd->vob->im_v_width * MAX_PLANES * sizeof(char) * 2;

		pd->lineant = tc_zalloc(size);
		if(pd->lineant == NULL)
			tc_log_error(MOD_NAME, "Malloc failed");

		size *= pd->vob->im_v_height * 2;

		pd->previous = tc_zalloc(size);
		if(pd->previous == NULL)
			tc_log_error(MOD_NAME, "Malloc failed");

		PrecalcCoefs(pd->coefficients[0], pd->parameter.luma_spatial);
		PrecalcCoefs(pd->coefficients[1], pd->parameter.luma_temporal);
		PrecalcCoefs(pd->coefficients[2], pd->parameter.chroma_spatial);
		PrecalcCoefs(pd->coefficients[3], pd->parameter.chroma_temporal);

		if(verbose)
		{
			tc_log_info(MOD_NAME, "%s %s #%d", MOD_VERSION, MOD_CAP, instance);
			tc_log_info(MOD_NAME, "Settings luma (spatial): %.2f "
                                  "luma_strength (temporal): %.2f "
                                  "chroma (spatial): %.2f "
                                  "chroma_strength (temporal): %.2f",
				        pd->parameter.luma_spatial,
        				pd->parameter.luma_temporal,
		        		pd->parameter.chroma_spatial,
				        pd->parameter.chroma_temporal);
			tc_log_info(MOD_NAME, "luma enabled: %s, chroma enabled: %s",
		                pd->enable_luma ? "yes" : "no",
                        pd->enable_chroma ? "yes" : "no");
		}
	}

	if(((tag & TC_PRE_M_PROCESS  && pd->prefilter) || (tag & TC_POST_M_PROCESS && !pd->prefilter)) &&
		!(vframe->attributes & TC_FRAME_IS_SKIPPED))
	{
		int plane_index, coef[2];
		int offset = 0;
		const dn3d_single_layout_t * lp;

		for(plane_index = 0; plane_index < MAX_PLANES; plane_index++)
		{
			lp = &pd->layout_data.layout[plane_index];

			if(lp->plane_type != dn3d_disabled)
			{
				// if(plane_index != 2) // debug
				//	continue;

				coef[0] = (lp->plane_type == dn3d_luma) ? 0 : 2;
				coef[1] = coef[0] + 1;

				switch(lp->offset)
				{
					case(dn3d_off_r):		offset = 0; break;
					case(dn3d_off_g):		offset = 1; break;
					case(dn3d_off_b):		offset = 2; break;

					case(dn3d_off_y420):	offset = vframe->v_width * vframe->v_height * 0 / 4; break;
					case(dn3d_off_u420):	offset = vframe->v_width * vframe->v_height * 4 / 4; break;
					case(dn3d_off_v420):	offset = vframe->v_width * vframe->v_height * 5 / 4; break;

					case(dn3d_off_y422):	offset = vframe->v_width * vframe->v_height * 0 / 2; break;
					case(dn3d_off_u422):	offset = vframe->v_width * vframe->v_height * 2 / 2; break;
					case(dn3d_off_v422):	offset = vframe->v_width * vframe->v_height * 3 / 2; break;

				}

				deNoise(vframe->video_buf,			// frame
					pd->previous,					// previous (saved) frame
					pd->lineant,					// line buffer
					vframe->v_width / lp->scale_x,	// width (pixels)
					vframe->v_height / lp->scale_y,	// height (pixels) // debug
					pd->coefficients[coef[0]],		// horizontal (spatial) strength
					pd->coefficients[coef[0]],		// vertical (spatial) strength
					pd->coefficients[coef[1]],		// temporal strength
					offset,							// offset in bytes of first relevant pixel in frame
					lp->skip						// skip this amount of bytes between two pixels
				);
			}
		}
	}

	if(tag & TC_FILTER_CLOSE)
	{
		if(pd->previous)
		{
			free(pd->previous);
			pd->previous = 0;
		}

		if(pd->lineant)
		{
			free(pd->lineant);
			pd->lineant = 0;
		}
	}

	return(0);
}
Beispiel #20
0
int optstr_get(const char *options, const char *name, const char *fmt, ...)
{
    va_list ap;     /* points to each unnamed arg in turn */
    int num_args = 0, n = 0;
    size_t pos, fmt_len = strlen(fmt);
    const char *ch = NULL;

#ifndef HAVE_VSSCANF
    void *temp[ARG_MAXIMUM];
#endif

    ch = optstr_lookup(options, name);
    if (!ch) {
        return -1;
    }

    /* name IS in options */

    /* Find how many arguments we expect */
    for (pos = 0; pos < fmt_len; pos++) {
        if (fmt[pos] == '%') {
            ++num_args;
            /* is this one quoted  with '%%' */
            if (pos + 1 < fmt_len && fmt[pos + 1] == '%') {
                --num_args;
                ++pos;
            }
        }
    }

#ifndef HAVE_VSSCANF
    if (num_args > ARG_MAXIMUM) {
        fprintf (stderr,
                 "(%s:%d) Internal Overflow; redefine ARG_MAXIMUM (%d) to something higher\n",
                 __FILE__, __LINE__, ARG_MAXIMUM);
        return -2;
    }
#endif

    n = num_args;
    /* Bool argument */
    if (num_args <= 0) {
        return 0;
    }

    /* skip the `=' (if it is one) */
    ch += strlen( name );
    if( *ch == '=' )
        ch++;

    if( !*ch )
        return 0;

    va_start(ap, fmt);

#ifndef HAVE_VSSCANF
    while (--n >= 0) {
        temp[num_args - n - 1] = va_arg(ap, void *);
    }

    n = sscanf(ch, fmt,
               temp[0],  temp[1],  temp[2],  temp[3]);

#else
    /* this would be very nice instead of the above,
     * but it does not seem portable
     */
    n = vsscanf(ch, fmt, ap);
#endif

    va_end(ap);

    return n;
}
int tc_filter(frame_list_t *ptr_, char *options)
{
  vframe_list_t *ptr = (vframe_list_t *)ptr_;
  static vob_t *vob=NULL;

  int is_interlaced = 0;
  int instance = ptr->filter_id;

  //----------------------------------
  //
  // filter init
  //
  //----------------------------------


  if(ptr->tag & TC_FILTER_GET_CONFIG) {
      char buf[255];
      optstr_filter_desc (options, MOD_NAME, MOD_CAP, MOD_VERSION, "Thomas", "VRYMEO", "1");

      tc_snprintf(buf, sizeof(buf), "%d", THRESHOLD);
      optstr_param (options, "threshold", "Interlace detection threshold", "%d", buf, "0", "255");

      tc_snprintf(buf, sizeof(buf), "%d", THRESHOLD/2);
      optstr_param (options, "chromathres", "Interlace detection chroma threshold", "%d", buf, "0", "255");

      tc_snprintf(buf, sizeof(buf), "%d", COLOR_EQUAL);
      optstr_param (options, "equal", "threshold for equal colors", "%d", buf, "0", "255");

      tc_snprintf(buf, sizeof(buf), "%d", COLOR_EQUAL/2);
      optstr_param (options, "chromaeq", "threshold for equal chroma", "%d", buf, "0", "255");

      tc_snprintf(buf, sizeof(buf), "%d", COLOR_DIFF);
      optstr_param (options, "diff", "threshold for different colors", "%d", buf, "0", "255");

      tc_snprintf(buf, sizeof(buf), "%d", COLOR_DIFF/2);
      optstr_param (options, "chromadi", "threshold for different chroma", "%d", buf, "0", "255");

      optstr_param (options, "force_mode", "set internal force de-interlace flag with mode -I N",
	      "%d", "0", "0", "5");

      optstr_param (options, "pre", "run as pre filter", "%d", "1", "0", "1");
      optstr_param (options, "verbose", "show results", "", "0");
      return (0);
  }

  if(ptr->tag & TC_FILTER_INIT) {

      if((vob = tc_get_vob())==NULL) return(-1);

      color_diff_threshold1[instance]  = COLOR_EQUAL;
      chroma_diff_threshold1[instance] = COLOR_EQUAL/2;
      color_diff_threshold2[instance]  = COLOR_DIFF;
      chroma_diff_threshold2[instance] = COLOR_DIFF/2;
      threshold[instance]              = THRESHOLD;
      chroma_threshold[instance]       = THRESHOLD/2;
      show_results[instance]           = 0;
      pre[instance]                    = 1;

      // filter init ok.

      if(verbose) tc_log_info(MOD_NAME, "%s %s", MOD_VERSION, MOD_CAP);

      // process filter options:

      if (options != NULL) {

	  if(verbose) tc_log_info(MOD_NAME, "options=%s", options);

	  optstr_get (options, "threshold", "%d",  &threshold[instance]);
	  optstr_get (options, "chromathres", "%d",  &chroma_threshold[instance]);
	  optstr_get (options, "force_mode", "%d",  &force_mode);
	  optstr_get (options, "equal", "%d",  &color_diff_threshold1[instance]);
	  optstr_get (options, "chromaeq", "%d",  &chroma_diff_threshold1[instance]);
	  optstr_get (options, "diff", "%d",  &color_diff_threshold2[instance]);
	  optstr_get (options, "chromadi", "%d",  &chroma_diff_threshold2[instance]);
	  optstr_get (options, "pre", "%d",  &pre[instance]);

	  if (optstr_lookup (options, "verbose") != NULL) {
	      show_results[instance]=1;
	  }

	  if (optstr_lookup (options, "help") != NULL) {
	      help_optstr();
	  }
      }

      return(0);
  }

  //----------------------------------
  //
  // filter close
  //
  //----------------------------------


  if(ptr->tag & TC_FILTER_CLOSE) {
    return(0);
  }

  //----------------------------------
  //
  // filter frame routine
  //
  //----------------------------------


  // tag variable indicates, if we are called before
  // transcodes internal video/audo frame processing routines
  // or after and determines video/audio context

  if (!(ptr->tag & TC_VIDEO))
	  return (0);

  //if((ptr->tag & TC_PRE_M_PROCESS) && (ptr->tag & TC_VIDEO))  {
  if(((ptr->tag & TC_PRE_M_PROCESS  && pre[instance]) ||
	  (ptr->tag & TC_POST_M_PROCESS && !pre[instance])) && !(ptr->attributes & TC_FRAME_IS_SKIPPED)) {

    //if (ptr->tag & TC_PRE_M_PROCESS) tc_log_msg(MOD_NAME, "32#%d pre (%d)", instance, ptr->id);
    //if (ptr->tag & TC_POST_M_PROCESS) tc_log_msg(MOD_NAME, "32#%d post (%d)", instance, ptr->id);

    if(vob->im_v_codec==CODEC_RGB) {
	is_interlaced = interlace_test(ptr->video_buf, 3*ptr->v_width, ptr->v_height, ptr->id, instance,
		threshold[instance], color_diff_threshold1[instance], color_diff_threshold2[instance]);
    } else {
	is_interlaced += interlace_test(ptr->video_buf, ptr->v_width, ptr->v_height, ptr->id, instance,
		threshold[instance], color_diff_threshold1[instance], color_diff_threshold2[instance]);
	is_interlaced += interlace_test(ptr->video_buf+ptr->v_width*ptr->v_height, ptr->v_width/2, ptr->v_height/2, ptr->id, instance,
		chroma_threshold[instance], chroma_diff_threshold1[instance], chroma_diff_threshold2[instance]);
	is_interlaced += interlace_test(ptr->video_buf+ptr->v_width*ptr->v_height*5/4, ptr->v_width/2, ptr->v_height/2, ptr->id, instance,
		chroma_threshold[instance], chroma_diff_threshold1[instance], chroma_diff_threshold2[instance]);
    }

    //force de-interlacing?
    if(force_mode && is_interlaced) {
	ptr->attributes  |= TC_FRAME_IS_INTERLACED;
	ptr->deinter_flag = force_mode;
    }

    //reset
    is_interlaced=0;

  }

  return(0);
}
int bktr_parse_options(char *options)
{
    char format[128];
    char vsource[128];
    char asource[128];
    char tuner[128];
    int i;

    if (optstr_lookup(options, "help") != NULL) {
        bktr_usage();
        return(1);
    }

    if (optstr_lookup(options, "hwfps") != NULL)
        bktr_hwfps = 1;

    if (optstr_lookup(options, "mute") != NULL)
        bktr_mute = 1;

    if (optstr_get(options, "format", "%[^:]", &format) >= 0) {
        for (i = 0; formats[i].name; i++)
            if (strncmp(formats[i].name, format, 128) == 0)
                break;
        if (formats[i].name)
            bktr_format = formats[i].format;
        else {
            tc_log_warn(MOD_NAME,
                        "invalid format: %s",
                        format);
            return(1);
        }
    }

    if (optstr_get(options, "vsource", "%[^:]", &vsource) >= 0) {
        for (i = 0; vsources[i].name; i++)
            if (strncmp(vsources[i].name, vsource, 128) == 0)
                break;
        if (vsources[i].name)
            bktr_vsource = vsources[i].vsource;
        else {
            tc_log_warn(MOD_NAME,
                        "invalid vsource: %s",
                        vsource);
            return(1);
        }
    }

    if (optstr_get(options, "asource", "%[^:]", &asource) >= 0) {
        for (i = 0; asources[i].name; i++)
            if (strncmp(asources[i].name, asource, 128) == 0)
                break;
        if (asources[i].name)
            bktr_asource = asources[i].asource;
        else {
            tc_log_warn(MOD_NAME,
                        "invalid asource: %s",
                        asource);
            return(1);
        }
    }

    if (optstr_get(options, "tunerdev", "%[^:]", &tuner) >= 0)
        strlcpy(bktr_tuner, tuner, sizeof(bktr_tuner));

    return(0);
}
int tc_filter(frame_list_t *ptr_, char *options)
{
	vframe_list_t *ptr = (vframe_list_t *)ptr_;
	int instance = ptr->filter_id;
	Image *pattern, *resized, *orig = 0;
	ImageInfo *image_info;

	PixelPacket *pixel_packet;
	pixelsMask *pixel_last;
	ExceptionInfo exception_info;

	if(ptr->tag & TC_FILTER_GET_CONFIG) {
		char buf[128];
		optstr_filter_desc(options, MOD_NAME, MOD_CAP, MOD_VERSION,
				   MOD_AUTHOR, "VRYMO", "1");

		tc_snprintf(buf, 128, "/dev/null");
		optstr_param(options, "pattern", "Pattern image file path", "%s", buf);
		tc_snprintf(buf, 128, "results.dat");
		optstr_param(options, "results", "Results file path" , "%s", buf);
		tc_snprintf(buf, 128, "%f", compare[instance]->delta);
		optstr_param(options, "delta", "Delta error", "%f",buf,"0.0", "100.0");
		return 0;
	}

	//----------------------------------
	//
	// filter init
	//
	//----------------------------------


	if(ptr->tag & TC_FILTER_INIT)
	{

		unsigned int t,r,index;
		pixelsMask *temp;

		compare[instance] = tc_malloc(sizeof(compareData));
		if(compare[instance] == NULL)
			return (-1);

		compare[instance]->vob = tc_get_vob();
		if(compare[instance]->vob ==NULL)
            return(-1);

		compare[instance]->delta=DELTA_COLOR;
		compare[instance]->step=1;
		compare[instance]->width=0;
		compare[instance]->height=0;
		compare[instance]->frames = 0;
		compare[instance]->pixel_mask = NULL;
		pixel_last = NULL;

		compare[instance]->width = compare[instance]->vob->ex_v_width;
		compare[instance]->height = compare[instance]->vob->ex_v_height;

		if (options != NULL) {
			char pattern_name[PATH_MAX];
			char results_name[PATH_MAX];
			memset(pattern_name,0,PATH_MAX);
			memset(results_name,0,PATH_MAX);

			if(verbose) tc_log_info(MOD_NAME, "options=%s", options);

			optstr_get(options, "pattern", "%[^:]", pattern_name);
			optstr_get(options, "results", "%[^:]", results_name);
			optstr_get(options, "delta", "%f", &compare[instance]->delta);

			if (verbose > 1) {
				tc_log_info(MOD_NAME, "Compare Image Settings:");
				tc_log_info(MOD_NAME, "      pattern = %s\n", pattern_name);
				tc_log_info(MOD_NAME, "      results = %s\n", results_name);
				tc_log_info(MOD_NAME, "        delta = %f\n", compare[instance]->delta);
			}

			if (strlen(results_name) == 0) {
				// Ponemos el nombre del fichero al original con extension dat
				strlcpy(results_name, "/tmp/compare.dat", sizeof(results_name));

			}
			if (!(compare[instance]->results = fopen(results_name, "w")))
			{
				tc_log_perror(MOD_NAME, "could not open file for writing");
			}

			InitializeMagick("");
			if (verbose > 1)
                tc_log_info(MOD_NAME, "Magick Initialized successfully");

			GetExceptionInfo(&exception_info);
			image_info = CloneImageInfo ((ImageInfo *) NULL);
			strlcpy(image_info->filename, pattern_name, MaxTextExtent);
			if (verbose > 1)
			     tc_log_info(MOD_NAME, "Trying to open image");
			orig = ReadImage(image_info,
					 &exception_info);

			if (orig == (Image *) NULL) {
				MagickWarning(exception_info.severity,
					      exception_info.reason,
					      exception_info.description);
				strlcpy(pattern_name, "/dev/null", sizeof(pattern_name));
			}else{
			       if (verbose > 1)
			       		tc_log_info(MOD_NAME, "Image loaded successfully");
			     }
		}

		else{
			tc_log_perror(MOD_NAME, "Not image provided");
		}

		if (options != NULL)
			if (optstr_lookup (options, "help")) {
				help_optstr();
			}


		fprintf(compare[instance]->results,"#fps:%f\n",compare[instance]->vob->fps);

		if (orig != NULL){
                        // Flip and resize
			if (compare[instance]->vob->im_v_codec == CODEC_YUV)
				TransformRGBImage(orig,YCbCrColorspace);
			if (verbose > 1) tc_log_info(MOD_NAME, "Resizing the Image");
			resized = ResizeImage(orig,
					      compare[instance]->width,
					      compare[instance]->height,
					      GaussianFilter,
					      1,
					      &exception_info);
			if (verbose > 1)
				tc_log_info(MOD_NAME, "Flipping the Image");
			pattern = FlipImage(resized, &exception_info);
			if (pattern == (Image *) NULL) {
				MagickError (exception_info.severity,
					     exception_info.reason,
					     exception_info.description);
			}

			// Filling the matrix with the pixels values not
			// alpha

			if (verbose > 1) tc_log_info(MOD_NAME, "GetImagePixels");
			pixel_packet = GetImagePixels(pattern,0,0,
						      pattern->columns,
						      pattern->rows);

			if (verbose > 1) tc_log_info(MOD_NAME, "Filling the Image matrix");
			for (t = 0; t < pattern->rows; t++)
				for (r = 0; r < pattern->columns; r++){
					index = t*pattern->columns + r;
					if (pixel_packet[index].opacity == 0){
						temp=tc_malloc(sizeof(struct pixelsMask));
						temp->row=t;
						temp->col=r;
						temp->r = (uint8_t)ScaleQuantumToChar(pixel_packet[index].red);
						temp->g = (uint8_t)ScaleQuantumToChar(pixel_packet[index].green);
						temp->b = (uint8_t)ScaleQuantumToChar(pixel_packet[index].blue);
						temp->next=NULL;

						if (pixel_last == NULL){
							pixel_last = temp;
							compare[instance]->pixel_mask = temp;
						}else{
							pixel_last->next = temp;
							pixel_last = temp;
						}
					}
				}

			if (verbose)
                tc_log_info(MOD_NAME, "%s %s",
					    MOD_VERSION, MOD_CAP);
		}
		return(0);
	}


	//----------------------------------
	//
	// filter close
	//
	//----------------------------------


	if(ptr->tag & TC_FILTER_CLOSE) {

		if (compare[instance] != NULL) {
			fclose(compare[instance]->results);
			free(compare[instance]);
		}
		DestroyMagick();
		compare[instance]=NULL;

		return(0);

	} /* filter close */

	//----------------------------------
	//
	// filter frame routine
	//
	//----------------------------------


	// tag variable indicates, if we are called before
	// transcodes internal video/audio frame processing routines
	// or after and determines video/audio context

	if((ptr->tag & TC_POST_M_PROCESS) && (ptr->tag & TC_VIDEO))  {
		// For now I only support RGB color space
		pixelsMask *item = NULL;
		double sr,sg,sb;
		double avg_dr,avg_dg,avg_db;

		if (compare[instance]->vob->im_v_codec == CODEC_RGB){

			int r,g,b,c;
			double width_long;

			if (compare[instance]->pixel_mask != NULL)
			{
				item = compare[instance]->pixel_mask;
				c = 0;

				sr = 0.0;
				sg = 0.0;
				sb = 0.0;

				width_long = compare[instance]->width*3;
				while(item){
					r = item->row*width_long + item->col*3;
					g = item->row*width_long
						+ item->col*3 + 1;
					b = item->row*width_long
						+ item->col*3 + 2;

				// diff between points
				// Interchange RGB values if necesary
					sr = sr + (double)abs((unsigned char)ptr->video_buf[r] - item->r);
					sg = sg + (double)abs((unsigned char)ptr->video_buf[g] - item->g);
					sb = sb + (double)abs((unsigned char)ptr->video_buf[b] - item->b);
					item = item->next;
					c++;
				}

				avg_dr = sr/(double)c;
				avg_dg = sg/(double)c;
				avg_db = sb/(double)c;

				if ((avg_dr < compare[instance]->delta) && (avg_dg < compare[instance]->delta) && (avg_db < compare[instance]->delta))
					fprintf(compare[instance]->results,"1");
				else
					fprintf(compare[instance]->results,"n");
				fflush(compare[instance]->results);
			}
			compare[instance]->frames++;
			return(0);
		}else{

                        // The colospace is YUV

                        // FIXME: Doesn't works, I need to code all this part
			// again

			int Y,Cr,Cb,c;

			if (compare[instance]->pixel_mask != NULL)
			{
				item = compare[instance]->pixel_mask;
				c = 0;

				sr = 0.0;
				sg = 0.0;
				sb = 0.0;

				while(item){
					Y  = item->row*compare[instance]->width + item->col;
					Cb = compare[instance]->height*compare[instance]->width
						+ (int)((item->row*compare[instance]->width + item->col)/4);
					Cr = compare[instance]->height*compare[instance]->width
						+ (int)((compare[instance]->height*compare[instance]->width)/4)
						+ (int)((item->row*compare[instance]->width + item->col)/4);

				        // diff between points
				        // Interchange RGB values if necesary

					sr = sr + (double)abs((unsigned char)ptr->video_buf[Y] - item->r);
					sg = sg + (double)abs((unsigned char)ptr->video_buf[Cb] - item->g);
					sb = sb + (double)abs((unsigned char)ptr->video_buf[Cr] - item->b);
					item = item->next;
					c++;
				}

				avg_dr = sr/(double)c;
				avg_dg = sg/(double)c;
				avg_db = sb/(double)c;

				if ((avg_dr < compare[instance]->delta) && (avg_dg < compare[instance]->delta) && (avg_db < compare[instance]->delta))
					fprintf(compare[instance]->results,"1");
				else
					fprintf(compare[instance]->results,"n");
			}
			compare[instance]->frames++;
			return(0);

		}
	}

	return(0);
}
Beispiel #24
0
/**
 * transform_configure:  Configure this instance of the module.  See
 * tcmodule-data.h for function details.
 */
static int transform_configure(TCModuleInstance *self,
             const char *options, vob_t *vob)
{
    FilterData *fd = NULL;
    char* filenamecopy, *filebasename;
    FILE* f;
    TC_MODULE_SELF_CHECK(self, "configure");

    fd = self->userdata;
    VSTransformData* td = &(fd->td);

    fd->vob = vob;
    if (!fd->vob)
        return TC_ERROR; /* cannot happen */

    /**** Initialise private data structure */

    VSFrameInfo fi_src;
    VSFrameInfo fi_dest;
    vsFrameInfoInit(&fi_src, fd->vob->ex_v_width, fd->vob->ex_v_height,
                  transcode2ourPF(fd->vob->im_v_codec));
    vsFrameInfoInit(&fi_dest, fd->vob->ex_v_width, fd->vob->ex_v_height,
                  transcode2ourPF(fd->vob->im_v_codec));

    VSTransformConfig conf = vsTransformGetDefaultConfig(MOD_NAME);
    conf.verbose = verbose;
    fd->sharpen  = 0.8;


    vsTransformationsInit(&fd->trans);

    filenamecopy = tc_strdup(fd->vob->video_in_file);
    filebasename = basename(filenamecopy);
    if (strlen(filebasename) < TC_BUF_LINE - 4) {
        tc_snprintf(fd->input, TC_BUF_LINE, "%s.trf", filebasename);
    } else {
        tc_log_warn(MOD_NAME, "input name too long, using default `%s'",
                    DEFAULT_TRANS_FILE_NAME);
        tc_snprintf(fd->input, TC_BUF_LINE, DEFAULT_TRANS_FILE_NAME);
    }



    /* process remaining options */
    if (options != NULL) {
        // We support also the help option.
        if(optstr_lookup(options, "help")) {
            tc_log_info(MOD_NAME,vs_transform_help);
            return(TC_IMPORT_ERROR);
        }
        optstr_get(options, "input",  "%[^:]", (char*)&fd->input);
        optstr_get(options, "maxshift",  "%d", &conf.maxShift);
        optstr_get(options, "maxangle", "%lf", &conf.maxAngle);
        optstr_get(options, "smoothing", "%d", &conf.smoothing);
        optstr_get(options, "invert"   , "%d", &conf.invert);
        optstr_get(options, "relative" , "%d", &conf.relative);
        optstr_get(options, "zoom"     ,"%lf", &conf.zoom);
        optstr_get(options, "optzoom"  , "%d", &conf.optZoom);
        optstr_get(options, "zoomspeed", "%lf",&conf.zoomSpeed);
        optstr_get(options, "interpol" , "%d", (int*)(&conf.interpolType));
        optstr_get(options, "sharpen"  ,"%lf", &fd->sharpen);
        if(optstr_lookup(options, "tripod")){
            tc_log_info(MOD_NAME,"Virtual tripod mode: relative=False, smoothing=0");
            conf.relative=0;
            conf.smoothing=0;
        }
    }

    if(vsTransformDataInit(td, &conf, &fi_src, &fi_dest) != VS_OK){
        tc_log_error(MOD_NAME, "initialization of VSTransformData failed");
        return TC_ERROR;
    }
    vsTransformGetConfig(&conf,td);

    if (verbose) {
        tc_log_info(MOD_NAME, "Image Transformation/Stabilization Settings:");
        tc_log_info(MOD_NAME, "    input     = %s", fd->input);
        tc_log_info(MOD_NAME, "    smoothing = %d", conf.smoothing);
        tc_log_info(MOD_NAME, "    maxshift  = %d", conf.maxShift);
        tc_log_info(MOD_NAME, "    maxangle  = %f", conf.maxAngle);
        tc_log_info(MOD_NAME, "    crop      = %s",
                        conf.crop ? "Black" : "Keep");
        tc_log_info(MOD_NAME, "    relative  = %s",
                    conf.relative ? "True": "False");
        tc_log_info(MOD_NAME, "    invert    = %s",
                    conf.invert ? "True" : "False");
        tc_log_info(MOD_NAME, "    zoom      = %f", conf.zoom);
        tc_log_info(MOD_NAME, "    optzoom   = %d", conf.optZoom);
        if(conf.optZoom==2){
            tc_log_info(MOD_NAME, "    zoomspeed = %f", conf.zoomSpeed);
        }
        tc_log_info(MOD_NAME, "    interpol  = %s",
                    getInterpolationTypeName(conf.interpolType));
        tc_log_info(MOD_NAME, "    sharpen   = %f", fd->sharpen);
    }

    f = fopen(fd->input, "r");
    if (f == NULL) {
        tc_log_error(MOD_NAME, "cannot open input file %s!\n", fd->input);
        /* return (-1); when called using tcmodinfo this will fail */
    } else {
        VSManyLocalMotions mlms;
        if(vsReadLocalMotionsFile(f,&mlms)==VS_OK){
            // calculate the actual transforms from the localmotions
            if(vsLocalmotions2Transforms(td, &mlms,&fd->trans)!=VS_OK)
                tc_log_error(MOD_NAME, "calculating transformations failed!\n");
        }else{ // try to read old format
            if (!vsReadOldTransforms(td, f, &fd->trans)) { /* read input file */
                tc_log_error(MOD_NAME, "error parsing input file %s!\n", fd->input);
            }
        }
    }
    fclose(f);

    if (vsPreprocessTransforms(td, &fd->trans)!= VS_OK ) {
        tc_log_error(MOD_NAME, "error while preprocessing transforms!");
        return TC_ERROR;
    }

    // sharpen is still in transcode...
    /* Is this the right point to add the filter? Seems to be the case.*/
    if(fd->sharpen>0){
        /* load unsharp filter */
        char unsharp_param[256];
        sprintf(unsharp_param,"luma=%f:%s:chroma=%f:%s",
                fd->sharpen, "luma_matrix=5x5",
                fd->sharpen/2, "chroma_matrix=5x5");
        if (!tc_filter_add("unsharp", unsharp_param)) {
            tc_log_warn(MOD_NAME, "cannot load unsharp filter!");
        }
    }

    return TC_OK;
}
int tc_filter(frame_list_t *ptr_, char *options)
{
  vframe_list_t *ptr = (vframe_list_t *)ptr_;
  int instance=ptr->filter_id;


  //----------------------------------
  //
  // filter get config
  //
  //----------------------------------


  if(ptr->tag & TC_FILTER_GET_CONFIG && options) {

    char buf[255];
    optstr_filter_desc (options, MOD_NAME, MOD_CAP, MOD_VERSION, MOD_AUTHOR, "VRYOM", "1");

    tc_snprintf (buf, sizeof(buf), "%u-%u", data[instance]->start, data[instance]->end);
    optstr_param (options, "range",  "Frame Range",                         "%d-%d",     buf, "0", "oo",    "0", "oo");

    tc_snprintf (buf, sizeof(buf), "%dx%d", data[instance]->xpos, data[instance]->ypos);
    optstr_param (options, "pos",    "Position of logo",                    "%dx%d",     buf, "0", "width", "0", "height");

    tc_snprintf (buf, sizeof(buf), "%dx%d", data[instance]->width, data[instance]->height);
    optstr_param (options, "size",   "Size of logo",                        "%dx%d",     buf, "0", "width", "0", "height");

    tc_snprintf (buf, sizeof(buf), "%d", data[instance]->mode);
    optstr_param (options, "mode",   "Filter Mode (0=none,1=solid,2=xy,3=shape)", "%d",  buf, "0", "3");

    tc_snprintf (buf, sizeof(buf), "%d",  data[instance]->border);
    optstr_param (options, "border", "Visible Border",                      "",          buf);

    tc_snprintf (buf, sizeof(buf), "%d",  data[instance]->dump);
    optstr_param (options, "dump", "Dump filterarea to file",               "",          buf);

    tc_snprintf (buf, sizeof(buf), "%d", data[instance]->xweight);
    optstr_param (options, "xweight","X-Y Weight(0%-100%)",                 "%d",        buf, "0", "100");

    tc_snprintf (buf, sizeof(buf), "%x%x%x", data[instance]->rcolor, data[instance]->gcolor, data[instance]->bcolor);
    optstr_param (options, "fill",   "Solid Fill Color(RGB)",               "%2x%2x%2x", buf, "00", "FF",   "00", "FF", "00", "FF");

    tc_snprintf (buf, sizeof(buf), "%s",  data[instance]->file);
    optstr_param (options, "file",   "Image with alpha/shape information",  "%s",        buf);

    return 0;
  }


  //----------------------------------
  //
  // filter init
  //
  //----------------------------------


  if(ptr->tag & TC_FILTER_INIT) {

    if((vob = tc_get_vob())==NULL) return(-1);

    if((data[instance] = tc_malloc (sizeof(logoaway_data))) == NULL) {
      tc_log_error(MOD_NAME, "can't allocate filter data");
      return (-1);
    }

    data[instance]->start    = 0;
    data[instance]->end      = (unsigned int)-1;
    data[instance]->xpos     = -1;
    data[instance]->ypos     = -1;
    data[instance]->width    = -1;
    data[instance]->height   = -1;
    data[instance]->mode     = 0;
    data[instance]->border   = 0;
    data[instance]->xweight  = 50;
    data[instance]->yweight  = 50;
    data[instance]->rcolor   = 0;
    data[instance]->gcolor   = 0;
    data[instance]->bcolor   = 0;
    data[instance]->ycolor   = 16;
    data[instance]->ucolor   = 128;
    data[instance]->vcolor   = 128;
    data[instance]->alpha    = 0;
    data[instance]->dump     = 0;

    // filter init ok.

    if(verbose) tc_log_info(MOD_NAME, "%s %s", MOD_VERSION, MOD_CAP);

    if(options!=NULL) {
      optstr_get     (options,  "range",   "%d-%d",     &data[instance]->start,  &data[instance]->end);
      optstr_get     (options,  "pos",     "%dx%d",     &data[instance]->xpos,   &data[instance]->ypos);
      optstr_get     (options,  "size",    "%dx%d",     &data[instance]->width,  &data[instance]->height);
        data[instance]->width += data[instance]->xpos; data[instance]->height += data[instance]->ypos;
      optstr_get     (options,  "mode",    "%d",        &data[instance]->mode);
      if (optstr_lookup (options,  "border") != NULL)
        data[instance]->border = 1;
      if (optstr_lookup (options,  "help") != NULL)
        help_optstr();
      optstr_get     (options,  "xweight", "%d",        &data[instance]->xweight);
        data[instance]->yweight = 100 - data[instance]->xweight;
      optstr_get     (options,  "fill",    "%2x%2x%2x", &data[instance]->rcolor, &data[instance]->gcolor, &data[instance]->bcolor);
        data[instance]->ycolor =  (0.257 * data[instance]->rcolor) + (0.504 * data[instance]->gcolor) + (0.098 * data[instance]->bcolor) + 16;
        data[instance]->ucolor =  (0.439 * data[instance]->rcolor) - (0.368 * data[instance]->gcolor) - (0.071 * data[instance]->bcolor) + 128;
        data[instance]->vcolor = -(0.148 * data[instance]->rcolor) - (0.291 * data[instance]->gcolor) + (0.439 * data[instance]->bcolor) + 128;
      if (optstr_get (options,  "file",    "%[^:]",     data[instance]->file) >= 0)
        data[instance]->alpha = 1;
      if (optstr_lookup (options,  "dump") != NULL)
        data[instance]->dump = 1;
    }

    if(verbose) tc_log_info(MOD_NAME, "instance(%d) options=%s", instance, options);
    if(verbose > 1) {
      tc_log_info (MOD_NAME, " LogoAway Filter Settings:");
      tc_log_info (MOD_NAME, "            pos = %dx%d", data[instance]->xpos, data[instance]->ypos);
      tc_log_info (MOD_NAME, "           size = %dx%d", data[instance]->width-data[instance]->xpos, data[instance]->height-data[instance]->ypos);
      tc_log_info (MOD_NAME, "           mode = %d(%s)", data[instance]->mode, modes[data[instance]->mode]);
      tc_log_info (MOD_NAME, "         border = %d", data[instance]->border);
      tc_log_info (MOD_NAME, "     x-y weight = %d:%d", data[instance]->xweight, data[instance]->yweight);
      tc_log_info (MOD_NAME, "     fill color = %2X%2X%2X", data[instance]->rcolor, data[instance]->gcolor, data[instance]->bcolor);
      if(data[instance]->alpha)
        tc_log_info (MOD_NAME, "           file = %s", data[instance]->file);
      if(data[instance]->dump)
        tc_log_info (MOD_NAME, "           dump = %d", data[instance]->dump);
    }

    if( (data[instance]->xpos > vob->im_v_width) || (data[instance]->ypos > vob->im_v_height) || (data[instance]->xpos < 0) || (data[instance]->ypos < 0) )  {
      tc_log_error(MOD_NAME, "invalid position");
      return(-1);
    }
    if( (data[instance]->width > vob->im_v_width) || (data[instance]->height > vob->im_v_height) || (data[instance]->width-data[instance]->xpos < 0) || (data[instance]->height-data[instance]->ypos < 0) ) {
      tc_log_error(MOD_NAME, "invalid size");
      return(-1);
    }
    if( (data[instance]->xweight > 100) || (data[instance]->xweight < 0) ) {
      tc_log_error(MOD_NAME, "invalid x weight");
      return(-1);
    }
    if( (data[instance]->mode < 0) || (data[instance]->mode > 3) ) {
      tc_log_error(MOD_NAME, "invalid mode");
      return(-1);
    }
    if( (data[instance]->mode == 3) && (data[instance]->alpha == 0) ) {
      tc_log_error(MOD_NAME, "alpha/shape file needed for SHAPE-mode");
      return(-1);
    }

    if((data[instance]->alpha) || (data[instance]->dump)) {
      InitializeMagick("");
      GetExceptionInfo(&data[instance]->exception_info);

      if(data[instance]->alpha) {
        data[instance]->image_info = CloneImageInfo((ImageInfo *) NULL);

        strlcpy(data[instance]->image_info->filename, data[instance]->file, MaxTextExtent);
        data[instance]->image = ReadImage(data[instance]->image_info, &data[instance]->exception_info);
        if (data[instance]->image == (Image *) NULL) {
          tc_log_error(MOD_NAME, "\n");
          MagickWarning (data[instance]->exception_info.severity, data[instance]->exception_info.reason, data[instance]->exception_info.description);
          return(-1);
        }

        if ((data[instance]->image->columns != (data[instance]->width-data[instance]->xpos)) || (data[instance]->image->rows != (data[instance]->height-data[instance]->ypos))) {
          tc_log_error(MOD_NAME, "\"%s\" has incorrect size", data[instance]->file);

          return(-1);
        }

        data[instance]->pixel_packet = GetImagePixels(data[instance]->image, 0, 0, data[instance]->image->columns, data[instance]->image->rows);
      }
      if(data[instance]->dump) {
        if((data[instance]->dump_buf = tc_malloc ((data[instance]->width-data[instance]->xpos)*(data[instance]->height-data[instance]->ypos)*3)) == NULL)
          tc_log_error(MOD_NAME, "out of memory");

        data[instance]->dumpimage_info = CloneImageInfo((ImageInfo *) NULL);
      }
    }

    return(0);
  }


  //----------------------------------
  //
  // filter close
  //
  //----------------------------------


  if(ptr->tag & TC_FILTER_CLOSE) {

    if (data[instance]->image != (Image *)NULL) {
      DestroyImage(data[instance]->image);
      DestroyImageInfo(data[instance]->image_info);
    }
    if (data[instance]->dumpimage != (Image *)NULL) {
      DestroyImage(data[instance]->dumpimage);
      DestroyImageInfo(data[instance]->dumpimage_info);
      DestroyConstitute();
    }
    DestroyExceptionInfo(&data[instance]->exception_info);
    DestroyMagick();

    if(data[instance]->dump_buf) free(data[instance]->dump_buf);
    if(data[instance]) free(data[instance]);
    data[instance] = NULL;

    return(0);
  }


  //----------------------------------
  //
  // filter frame routine
  //
  //----------------------------------


  if(ptr->tag & TC_PRE_M_PROCESS && ptr->tag & TC_VIDEO && !(ptr->attributes & TC_FRAME_IS_SKIPPED)) {

    if (ptr->id < data[instance]->start || ptr->id > data[instance]->end) return (0);

    if(vob->im_v_codec==TC_CODEC_RGB24) {
      work_with_rgb_frame(ptr->video_buf, vob->im_v_width, vob->im_v_height, instance);
    } else {
      work_with_yuv_frame(ptr->video_buf, vob->im_v_width, vob->im_v_height, instance);
    }
  }
  return(0);
}
int tc_filter(frame_list_t *ptr_, char *options)
{
    vframe_list_t *ptr = (vframe_list_t *)ptr_;
    vob_t         *vob = NULL;

    int instance = ptr->filter_id;
    MyFilterData  *mfd = mfd_all[instance];

    if (mfd != NULL) {
        vob = mfd->vob;
    }

    //----------------------------------
    //
    // filter init
    //
    //----------------------------------


    if (ptr->tag & TC_FILTER_GET_CONFIG) {
        optstr_filter_desc(options, MOD_NAME, MOD_CAP, MOD_VERSION, MOD_AUTHOR, "VRYO", "1");
        // buf, name, comment, format, val, from, to
        optstr_param(options, "file",   "Image filename",    "%s",    "logo.png");
        optstr_param(options, "posdef", "Position (0=None, 1=TopL, 2=TopR, 3=BotL, 4=BotR, 5=Center)",  "%d", "0", "0", "5");
        optstr_param(options, "pos",    "Position (0-width x 0-height)",  "%dx%d", "0x0", "0", "width", "0", "height");
        optstr_param(options, "range",  "Restrict rendering to framerange",  "%u-%u", "0-0", "0", "oo", "0", "oo");
        optstr_param(options, "fade",   "Fade image in/out (# of frames)",  "%u-%u", "0-0", "0", "oo", "0", "oo");
        // bools
        optstr_param(options, "ignoredelay", "Ignore delay specified in animations", "", "0");
        optstr_param(options, "rgbswap", "Swap red/blue colors", "", "0");
        optstr_param(options, "grayout", "YUV only: don't write Cb and Cr, makes a nice effect", "",  "0");
        optstr_param(options, "hqconv",  "YUV only: do high quality rgb->yuv img conversion", "",  "0");
        optstr_param(options, "flip",    "Mirror image",  "", "0");

        return 0;
    }

    if (ptr->tag & TC_FILTER_INIT) {
        Image         *timg;
        Image         *nimg;
        ImageInfo     *image_info;
        ExceptionInfo  exception_info;

        int rgb_off = 0;

        vob_t *tmpvob;

        tmpvob = tc_get_vob();
        if (tmpvob == NULL)
            return -1;
        mfd_all[instance] = tc_zalloc(sizeof(MyFilterData));
        if (mfd_all[instance] == NULL)
            return -1;

        mfd = mfd_all[instance];

        strlcpy(mfd->file, "logo.png", PATH_MAX);
        mfd->end = (unsigned int)-1;
        mfd->vob = tmpvob;
        vob      = mfd->vob;

        if (options != NULL) {
            if (verbose)
                tc_log_info(MOD_NAME, "options=%s", options);

            optstr_get(options, "file",     "%[^:]", mfd->file);
            optstr_get(options, "posdef",   "%d",    (int *)&mfd->pos);
            optstr_get(options, "pos",      "%dx%d", &mfd->posx,  &mfd->posy);
            optstr_get(options, "range",    "%u-%u", &mfd->start, &mfd->end);
            optstr_get(options, "fade",     "%u-%u", &mfd->fadein, &mfd->fadeout);

            if (optstr_lookup(options, "ignoredelay") != NULL)
                mfd->ignoredelay = !mfd->ignoredelay;
            if (optstr_lookup(options, "flip") != NULL)
                mfd->flip    = !mfd->flip;
            if (optstr_lookup(options, "rgbswap") != NULL)
                mfd->rgbswap = !mfd->rgbswap;
            if (optstr_lookup(options, "grayout") != NULL)
                mfd->grayout = !mfd->grayout;
            if (optstr_lookup(options, "hqconv") != NULL)
                mfd->hqconv  = !mfd->hqconv;

            if (optstr_lookup (options, "help") != NULL)
                flogo_help_optstr();
        }

        if (verbose > 1) {
            tc_log_info(MOD_NAME, " Logo renderer Settings:");
            tc_log_info(MOD_NAME, "         file = %s",    mfd->file);
            tc_log_info(MOD_NAME, "       posdef = %d",    mfd->pos);
            tc_log_info(MOD_NAME, "          pos = %dx%d", mfd->posx,
                                                           mfd->posy);
            tc_log_info(MOD_NAME, "        range = %u-%u", mfd->start,
                                                           mfd->end);
            tc_log_info(MOD_NAME, "         fade = %u-%u", mfd->fadein,
                                                           mfd->fadeout);
            tc_log_info(MOD_NAME, "         flip = %d",    mfd->flip);
            tc_log_info(MOD_NAME, "  ignoredelay = %d",    mfd->ignoredelay);
            tc_log_info(MOD_NAME, "      rgbswap = %d",    mfd->rgbswap);
            tc_log_info(MOD_NAME, "      grayout = %d",    mfd->grayout);
            tc_log_info(MOD_NAME, "       hqconv = %d",    mfd->hqconv);
        }

        /* Transcode serializes module execution, so this does not need a
         * semaphore.
         */
        magick_usecount++;
        if (!IsMagickInstantiated()) {
            InitializeMagick("");
        }

        GetExceptionInfo(&exception_info);
        image_info = CloneImageInfo((ImageInfo *) NULL);
        strlcpy(image_info->filename, mfd->file, MaxTextExtent);

        mfd->image = ReadImage(image_info, &exception_info);
        if (mfd->image == (Image *) NULL) {
            MagickWarning(exception_info.severity,
                          exception_info.reason,
                          exception_info.description);
            strlcpy(mfd->file, "/dev/null", PATH_MAX);
            return 0;
        }
        DestroyImageInfo(image_info);

        if (mfd->image->columns > vob->ex_v_width
         || mfd->image->rows    > vob->ex_v_height
        ) {
            tc_log_error(MOD_NAME, "\"%s\" is too large", mfd->file);
            return -1;
        }

        if (vob->im_v_codec == TC_CODEC_YUV420P) {
            if ((mfd->image->columns & 1) || (mfd->image->rows & 1)) {
                tc_log_error(MOD_NAME, "\"%s\" has odd sizes", mfd->file);
                return -1;
            }
        }

        mfd->images = (Image *)GetFirstImageInList(mfd->image);
        nimg = NewImageList();

        while (mfd->images != (Image *)NULL) {
            if (mfd->flip || flip) {
                timg = FlipImage(mfd->images, &exception_info);
                if (timg == (Image *) NULL) {
                    MagickError(exception_info.severity,
                                exception_info.reason,
                                exception_info.description);
                    return -1;
                }
                AppendImageToList(&nimg, timg);
            }

            mfd->images = GetNextImageInList(mfd->images);
            mfd->nr_of_images++;
        }

        // check for memleaks;
        //DestroyImageList(image);
        if (mfd->flip || flip) {
            mfd->image = nimg;
        }

        /* initial delay. real delay = 1/100 sec * delay */
        mfd->cur_delay = mfd->image->delay*vob->fps/100;

        if (verbose & TC_DEBUG)
            tc_log_info(MOD_NAME, "Nr: %d Delay: %d mfd->image->del %lu|",
                        mfd->nr_of_images, mfd->cur_delay, mfd->image->delay);

        if (vob->im_v_codec == TC_CODEC_YUV420P) {
            /* convert Magick RGB image format to YUV */
            /* todo: convert the magick image if it's not rgb! (e.g. cmyk) */
            Image   *image;
            uint8_t *yuv_hqbuf = NULL;

            /* Round up for odd-size images */
            unsigned long width  = mfd->image->columns;
            unsigned long height = mfd->image->rows;
            int do_rgbswap  = (rgbswap || mfd->rgbswap);
            int i;

            /* Allocate buffers for the YUV420P frames. mfd->nr_of_images
             * will be 1 unless this is an animated GIF or MNG.
             * This buffer needs to be large enough to store a temporary
             * 24-bit RGB image (extracted from the ImageMagick handle).
             */
            mfd->yuv = flogo_yuvbuf_alloc(width*height * 3, mfd->nr_of_images);
            if (mfd->yuv == NULL) {
                tc_log_error(MOD_NAME, "(%d) out of memory\n", __LINE__);
                return -1;
            }

            if (mfd->hqconv) {
                /* One temporary buffer, to hold full Y, U, and V planes. */
                yuv_hqbuf = tc_malloc(width*height * 3);
                if (yuv_hqbuf == NULL) {
                    tc_log_error(MOD_NAME, "(%d) out of memory\n", __LINE__);
                    return -1;
                }
            }

            mfd->tcvhandle = tcv_init();
            if (mfd->tcvhandle == NULL) {
                tc_log_error(MOD_NAME, "image conversion init failed");
                return -1;
            }

            image = GetFirstImageInList(mfd->image);

            for (i = 0; i < mfd->nr_of_images; i++) {
                if (!mfd->hqconv) {
                    flogo_convert_image(mfd->tcvhandle, image, mfd->yuv[i],
                                        IMG_YUV420P, do_rgbswap);
                } else {
                    flogo_convert_image(mfd->tcvhandle, image, yuv_hqbuf,
                                        IMG_YUV444P, do_rgbswap);

                    // Copy over Y data from the 444 image
                    ac_memcpy(mfd->yuv[i], yuv_hqbuf, width * height);

                    // Resize U plane by 1/2 in each dimension, into the
                    // mfd YUV buffer
                    tcv_zoom(mfd->tcvhandle,
                             yuv_hqbuf + (width * height),
                             mfd->yuv[i] + (width * height),
                             width,
                             height,
                             1,
                             width / 2,
                             height / 2,
                             TCV_ZOOM_LANCZOS3
                    );

                    // Do the same with the V plane
                    tcv_zoom(mfd->tcvhandle,
                             yuv_hqbuf + 2*width*height,
                             mfd->yuv[i] + width*height + (width/2)*(height/2),
                             width,
                             height,
                             1,
                             width / 2,
                             height / 2,
                             TCV_ZOOM_LANCZOS3
                    );
                }
                image = GetNextImageInList(image);
            }

            if (mfd->hqconv)
                tc_free(yuv_hqbuf);

            tcv_free(mfd->tcvhandle);
        } else {
            /* for RGB format is origin bottom left */
            /* for RGB, rgbswap is done in the frame routine */
            rgb_off = vob->ex_v_height - mfd->image->rows;
            mfd->posy = rgb_off - mfd->posy;
        }

        switch (mfd->pos) {
          case NONE: /* 0 */
            break;
          case TOP_LEFT:
            mfd->posx = 0;
            mfd->posy = rgb_off;
            break;
          case TOP_RIGHT:
            mfd->posx = vob->ex_v_width  - mfd->image->columns;
            break;
          case BOT_LEFT:
            mfd->posy = vob->ex_v_height - mfd->image->rows - rgb_off;
            break;
          case BOT_RIGHT:
            mfd->posx = vob->ex_v_width  - mfd->image->columns;
            mfd->posy = vob->ex_v_height - mfd->image->rows - rgb_off;
            break;
          case CENTER:
            mfd->posx = (vob->ex_v_width - mfd->image->columns)/2;
            mfd->posy = (vob->ex_v_height- mfd->image->rows)/2;
            /* align to not cause color disruption */
            if (mfd->posx & 1)
                mfd->posx++;
            if (mfd->posy & 1)
                mfd->posy++;
            break;
        }


        if (mfd->posy < 0 || mfd->posx < 0
         || (mfd->posx + mfd->image->columns) > vob->ex_v_width
         || (mfd->posy + mfd->image->rows)    > vob->ex_v_height) {
            tc_log_error(MOD_NAME, "invalid position");
            return -1;
        }

        /* for running through image sequence */
        mfd->images = mfd->image;


        /* Set up image/video coefficient lookup tables */
        if (img_coeff_lookup[0] < 0) {
            int i;
            float maxrgbval = (float)MaxRGB; // from ImageMagick

            for (i = 0; i <= MAX_UINT8_VAL; i++) {
                float x = (float)ScaleCharToQuantum(i);

                /* Alternatively:
                 *  img_coeff = (maxrgbval - x) / maxrgbval;
                 *  vid_coeff = x / maxrgbval;
                 */
                img_coeff_lookup[i] = 1.0 - (x / maxrgbval);
                vid_coeff_lookup[i] = 1.0 - img_coeff_lookup[i];
            }
        }

        // filter init ok.
        if (verbose)
            tc_log_info(MOD_NAME, "%s %s", MOD_VERSION, MOD_CAP);

        return 0;
    }


    //----------------------------------
    //
    // filter close
    //
    //----------------------------------
    if (ptr->tag & TC_FILTER_CLOSE) {
        if (mfd) {
            flogo_yuvbuf_free(mfd->yuv, mfd->nr_of_images);
            mfd->yuv = NULL;

            if (mfd->image) {
                DestroyImage(mfd->image);
            }

            tc_free(mfd);
            mfd = NULL;
            mfd_all[instance] = NULL;
        }

        magick_usecount--;
        if (magick_usecount == 0 && IsMagickInstantiated()) {
            DestroyMagick();
        }

        return 0;
    } /* filter close */


    //----------------------------------
    //
    // filter frame routine
    //
    //----------------------------------


    // tag variable indicates, if we are called before
    // transcodes internal video/audo frame processing routines
    // or after and determines video/audio context

    if ((ptr->tag & TC_POST_M_PROCESS)
        && (ptr->tag & TC_VIDEO)
        && !(ptr->attributes & TC_FRAME_IS_SKIPPED)
    ) {
        PixelPacket *pixel_packet;
        uint8_t     *video_buf;

        int   do_fade    = 0;
        float fade_coeff = 0.0;
        float img_coeff, vid_coeff;

        /* Note: ImageMagick defines opacity = 0 as fully visible, and
         * opacity = MaxRGB as fully transparent.
         */
        Quantum opacity;

        int row, col;

        if (ptr->id < mfd->start || ptr->id > mfd->end)
            return 0;

        if (strcmp(mfd->file, "/dev/null") == 0)
            return 0;

        if (ptr->id - mfd->start < mfd->fadein) {
            // fading-in
            fade_coeff = (float)(mfd->start - ptr->id + mfd->fadein) / (float)(mfd->fadein);
            do_fade = 1;
        } else if (mfd->end - ptr->id < mfd->fadeout) {
            // fading-out
            fade_coeff = (float)(ptr->id - mfd->end + mfd->fadeout) / (float)(mfd->fadeout);
            do_fade = 1;
        }

        mfd->cur_delay--;

        if (mfd->cur_delay < 0 || mfd->ignoredelay) {
            int seq;

            mfd->cur_seq = (mfd->cur_seq + 1) % mfd->nr_of_images;

            mfd->images = mfd->image;
            for (seq=0; seq<mfd->cur_seq; seq++)
                mfd->images = mfd->images->next;

            mfd->cur_delay = mfd->images->delay * vob->fps/100;
        }

        pixel_packet = GetImagePixels(mfd->images, 0, 0,
                                      mfd->images->columns,
                                      mfd->images->rows);

        if (vob->im_v_codec == TC_CODEC_RGB24) {
            unsigned long r_off, g_off, b_off;

            if (!(rgbswap || mfd->rgbswap)) {
                r_off = 0;
                b_off = 2;
            } else {
                r_off = 2;
                b_off = 0;
            }
            g_off = 1;

            for (row = 0; row < mfd->image->rows; row++) {
                video_buf = ptr->video_buf + 3 * ((row + mfd->posy) * vob->ex_v_width + mfd->posx);

                for (col = 0; col < mfd->image->columns; col++) {
                    opacity = pixel_packet->opacity;

                    if (do_fade)
                        opacity += (Quantum)((MaxRGB - opacity) * fade_coeff);

                    if (opacity == 0) {
                        *(video_buf + r_off) = ScaleQuantumToChar(pixel_packet->red);
                        *(video_buf + g_off) = ScaleQuantumToChar(pixel_packet->green);
                        *(video_buf + b_off) = ScaleQuantumToChar(pixel_packet->blue);
                    } else if (opacity < MaxRGB) {
                        unsigned char opacity_uchar = ScaleQuantumToChar(opacity);
                        img_coeff = img_coeff_lookup[opacity_uchar];
                        vid_coeff = vid_coeff_lookup[opacity_uchar];

                        *(video_buf + r_off) = (uint8_t)((*(video_buf + r_off)) * vid_coeff)
                                                + (uint8_t)(ScaleQuantumToChar(pixel_packet->red)   * img_coeff);
                        *(video_buf + g_off) = (uint8_t)((*(video_buf + g_off)) * vid_coeff)
                                                + (uint8_t)(ScaleQuantumToChar(pixel_packet->green) * img_coeff);
                        *(video_buf + b_off) = (uint8_t)((*(video_buf + b_off)) * vid_coeff)
                                                + (uint8_t)(ScaleQuantumToChar(pixel_packet->blue)  * img_coeff);
                    }

                    video_buf += 3;
                    pixel_packet++;
                }
            }
        } else { /* !RGB */
            unsigned long vid_size = vob->ex_v_width * vob->ex_v_height;
            unsigned long img_size = mfd->images->columns * mfd->images->rows;

            uint8_t *img_pixel_Y, *img_pixel_U, *img_pixel_V;
            uint8_t *vid_pixel_Y, *vid_pixel_U, *vid_pixel_V;

            img_pixel_Y = mfd->yuv[mfd->cur_seq];
            img_pixel_U = img_pixel_Y + img_size;
            img_pixel_V = img_pixel_U + img_size/4;

            for (row = 0; row < mfd->images->rows; row++) {
                vid_pixel_Y = ptr->video_buf + (row + mfd->posy)*mfd->vob->ex_v_width + mfd->posx;
                vid_pixel_U = ptr->video_buf + vid_size + (row/2 + mfd->posy/2)*(mfd->vob->ex_v_width/2) + mfd->posx/2;
                vid_pixel_V = vid_pixel_U + vid_size/4;
                for (col = 0; col < mfd->images->columns; col++) {
                    int do_UV_pixels = (mfd->grayout == 0 && !(row % 2) && !(col % 2)) ? 1 : 0;
                    opacity = pixel_packet->opacity;

                    if (do_fade)
                        opacity += (Quantum)((MaxRGB - opacity) * fade_coeff);

                    if (opacity == 0) {
                        *vid_pixel_Y = *img_pixel_Y;
                        if (do_UV_pixels) {
                                *vid_pixel_U = *img_pixel_U;
                                *vid_pixel_V = *img_pixel_V;
                        }
                    } else if (opacity < MaxRGB) {
                        unsigned char opacity_uchar = ScaleQuantumToChar(opacity);
                        img_coeff = img_coeff_lookup[opacity_uchar];
                        vid_coeff = vid_coeff_lookup[opacity_uchar];

                        *vid_pixel_Y = (uint8_t)(*vid_pixel_Y * vid_coeff) + (uint8_t)(*img_pixel_Y * img_coeff);

                        if (do_UV_pixels) {
                            *vid_pixel_U = (uint8_t)(*vid_pixel_U * vid_coeff) + (uint8_t)(*img_pixel_U * img_coeff);
                            *vid_pixel_V = (uint8_t)(*vid_pixel_V * vid_coeff) + (uint8_t)(*img_pixel_V * img_coeff);
                        }
                    }

                    vid_pixel_Y++;
                    img_pixel_Y++;
                    if (do_UV_pixels) {
                        vid_pixel_U++;
                        img_pixel_U++;
                        vid_pixel_V++;
                        img_pixel_V++;
                    }
                    pixel_packet++;
                }
            }
        }
    }

    return 0;
}
int tc_filter(frame_list_t *ptr_, char *options)
{
    vframe_list_t *ptr = (vframe_list_t *)ptr_;
    vob_t *vob = NULL;
    tomsmocomp_t *tmc = tmc_global;

    //----------------------------------
    // filter init
    //----------------------------------

    if (ptr->tag & TC_FILTER_INIT) {

	if (! (vob = tc_get_vob ()))
	    return -1;

	if (! (tmc = tmc_global = tc_zalloc (sizeof (tomsmocomp_t)))) {
	    return -1;
	}

	if (! (tmc->tcvhandle = tcv_init())) {
	    tc_log_error(MOD_NAME, "tcv_init() failed");
	    return -1;
	}

	if (verbose)
	    tc_log_info(MOD_NAME, "%s %s", MOD_VERSION, MOD_CAP);

	/* default values */
	tmc->SearchEffort   = 11;
	tmc->UseStrangeBob  = 0;
	tmc->TopFirst       = 1;

	/* video parameters */
	switch (vob->im_v_codec) {
	case CODEC_YUY2:
	case CODEC_YUV:
	case CODEC_YUV422:
	    break;
	default:
	    tc_log_error (MOD_NAME, "only working with YUV (4:2:2 and 4:2:0) and YUY2 frame data...");
	    return -1;
	}
	tmc->codec     = vob->im_v_codec;
	tmc->width     = vob->im_v_width;
	tmc->height    = vob->im_v_height;
	tmc->size      = vob->im_v_width * vob->im_v_height * 2;
	tmc->cpuflags  = tc_accel;

	tmc->rowsize   = vob->im_v_width * 2;

	if (options) {
	    optstr_get (options, "topfirst",       "%d",
			&tmc->TopFirst);
	    optstr_get (options, "searcheffort",   "%d",
			&tmc->SearchEffort);
	    optstr_get (options, "usestrangebob",  "%d",
			&tmc->UseStrangeBob);
	    optstr_get (options, "cpuflags",  "%x",
			&tmc->cpuflags);

	    if (optstr_lookup(options, "help")) {
		help_optstr ();
	    }
	}

	/* frame memory */
	if (! (tmc->framePrev = calloc (1, tmc->size)) ||
	    ! (tmc->frameIn   = calloc (1, tmc->size)) ||
	    ! (tmc->frameOut  = calloc (1, tmc->size))) {
	    tc_log_msg(MOD_NAME, "calloc() failed");
	    return -1;
	}

	tmc->DSinfo.Overlay      = tmc->frameOut;
	tmc->DSinfo.OverlayPitch = tmc->rowsize;
	tmc->DSinfo.LineLength   = tmc->rowsize;
	tmc->DSinfo.FrameWidth   = tmc->width;
	tmc->DSinfo.FrameHeight  = tmc->height;
	tmc->DSinfo.FieldHeight  = tmc->height / 2;
	tmc->DSinfo.InputPitch   = 2* tmc->rowsize;

	tmc->DSinfo.pMemcpy = ac_memcpy;

	if (verbose) {
	    tc_log_info(MOD_NAME, "topfirst %s,  searcheffort %d,  usestrangebob %s",
		   tmc->TopFirst ? "True":"False", tmc->SearchEffort,
		   tmc->UseStrangeBob ? "True":"False");
	    tc_log_info(MOD_NAME, "cpuflags%s%s%s%s",
		   tmc->cpuflags & AC_SSE ? " SSE":"",
		   tmc->cpuflags & AC_3DNOW ? " 3DNOW":"",
		   tmc->cpuflags & AC_MMX ? " MMX":"",
		   !(tmc->cpuflags & (AC_SSE|AC_3DNOW|AC_MMX)) ? " None":"");
	}

	return 0;
    }

    //----------------------------------
    // filter close
    //----------------------------------

    if (ptr->tag & TC_FILTER_CLOSE) {
	free (tmc->framePrev);
	free (tmc->frameIn);
	free (tmc->frameOut);
	tmc->framePrev = tmc->frameIn = tmc->frameOut = NULL;
	tcv_free(tmc->tcvhandle);
	tmc->tcvhandle = 0;
	return 0;
    }

    //----------------------------------
    // filter description
    //----------------------------------
    if (ptr->tag & TC_FILTER_GET_CONFIG) {
	char buf[255];
	optstr_filter_desc (options, MOD_NAME, MOD_CAP, MOD_VERSION,
			    MOD_AUTHOR, "VY4E", "1");
	tc_snprintf (buf, sizeof(buf), "%d", tmc->TopFirst);
	optstr_param (options, "topfirst", "Assume the top field should be displayed first" ,"%d", buf, "0", "1");
	tc_snprintf (buf, sizeof(buf), "%d", tmc->SearchEffort);
	optstr_param (options, "searcheffort", "CPU time used to find moved pixels" ,"%d", buf, "0", "30");
	tc_snprintf (buf, sizeof(buf), "%d", tmc->UseStrangeBob);
	optstr_param (options, "usestrangebob", "?Unknown?" ,"%d", buf, "0", "1");
	tc_snprintf (buf, sizeof(buf), "%02x", tmc->cpuflags);
	optstr_param (options, "cpuflags", "Manual specification of CPU capabilities" ,"%x", buf, "00", "ff");
    }

    //----------------------------------
    // filter frame routine
    //----------------------------------

    // need to process frames in-order
    if ((ptr->tag & TC_PRE_S_PROCESS) && (ptr->tag & TC_VIDEO)) {

	uint8_t *tmp;
	uint8_t *planes[3];
	YUV_INIT_PLANES(planes, ptr->video_buf, IMG_YUV_DEFAULT,
			tmc->width, tmc->height);

	/* Convert / Copy to yuy2 */
	switch (tmc->codec) {
	case CODEC_YUY2:
	    ac_memcpy (tmc->frameIn, ptr->video_buf, tmc->size);
	    break;
	case CODEC_YUV:
	    tcv_convert(tmc->tcvhandle, ptr->video_buf, tmc->frameIn,
			tmc->width, tmc->height, IMG_YUV_DEFAULT, IMG_YUY2);
	    break;
	case CODEC_YUV422:
	    tcv_convert(tmc->tcvhandle, ptr->video_buf, tmc->frameIn,
			tmc->width, tmc->height, IMG_YUV422P, IMG_YUY2);
	    break;
	}

	if (! (ptr->tag & TC_FRAME_IS_SKIPPED)) {

	    /* Do the deinterlacing */
	    do_deinterlace (tmc);

	    /* Now convert back */
	    switch (tmc->codec) {
	    case CODEC_YUY2:
		ac_memcpy (ptr->video_buf, tmc->frameOut, tmc->size);
		break;
	    case CODEC_YUV:
		tcv_convert(tmc->tcvhandle, tmc->frameOut,  ptr->video_buf,
			    tmc->width, tmc->height, IMG_YUY2, IMG_YUV_DEFAULT);
		break;
	    case CODEC_YUV422:
		tcv_convert(tmc->tcvhandle, tmc->frameOut,  ptr->video_buf,
			    tmc->width, tmc->height, IMG_YUY2, IMG_YUV422P);
		break;
	    default:
		tc_log_error(MOD_NAME, "codec: %x\n", tmc->codec);
		assert (0);
	    }
	}

	// The current frame gets the next previous frame
	tmp = tmc->framePrev;
	tmc->framePrev = tmc->frameIn;
	tmc->frameIn   = tmp;
    }

    return 0;
}
Beispiel #28
0
/*
 * deshake_configure:  Configure this instance of the module.  See
 * tcmodule-data.h for function details.
 */
static int deshake_configure(TCModuleInstance *self,
			     const char *options, vob_t *vob)
{
  DeshakeData *sd = NULL;
  TC_MODULE_SELF_CHECK(self, "configure");
  char* filenamecopy, *filebasename;

  sd = self->userdata;

  /*    sd->framesize = sd->vob->im_v_width * MAX_PLANES *
	sizeof(char) * 2 * sd->vob->im_v_height * 2;     */

  MotionDetect* md = &(sd->md);
  TransformData* td = &(sd->td);

  // init MotionDetect part
  VSFrameInfo fi;
  initFrameInfo(&fi, sd->vob->ex_v_width, sd->vob->ex_v_height,
                transcode2ourPF(sd->vob->im_v_codec));

  if(initMotionDetect(md, &fi, MOD_NAME) != VS_OK){
    tc_log_error(MOD_NAME, "initialization of Motion Detection failed");
    return TC_ERROR;
  }

  sd->result = tc_malloc(TC_BUF_LINE);
  filenamecopy = tc_strdup(sd->vob->video_in_file);
  filebasename = basename(filenamecopy);
  if (strlen(filebasename) < TC_BUF_LINE - 4) {
    tc_snprintf(sd->result, TC_BUF_LINE, "%s.trf", filebasename);
  } else {
    tc_log_warn(MOD_NAME, "input name too long, using default `%s'",
		DEFAULT_TRANS_FILE_NAME);
    tc_snprintf(sd->result, TC_BUF_LINE, DEFAULT_TRANS_FILE_NAME);
  }

  // init trasform part
  VSFrameInfo fi_dest;
  initFrameInfo(&fi_dest, sd->vob->ex_v_width, sd->vob->ex_v_height,
                transcode2ourPF(sd->vob->im_v_codec));

  if(initTransformData(td, &fi, &fi_dest, MOD_NAME) != VS_OK){
    tc_log_error(MOD_NAME, "initialization of TransformData failed");
    return TC_ERROR;
  }
  td->verbose=verbose;


  if (options != NULL) {
    // for some reason this plugin is called in the old fashion
    //  (not with inspect). Anyway we support both ways of getting help.
    if(optstr_lookup(options, "help")) {
      tc_log_info(MOD_NAME,deshake_help);
      return(TC_IMPORT_ERROR);
    }

    optstr_get(options, "result",     "%[^:]", sd->result);
    optstr_get(options, "shakiness",  "%d", &md->shakiness);
    optstr_get(options, "accuracy",   "%d", &md->accuracy);
    optstr_get(options, "stepsize",   "%d", &md->stepSize);
    optstr_get(options, "algo",       "%d", &md->algo);
    optstr_get(options, "mincontrast","%lf",&md->contrastThreshold);
    md->show = 0;

    optstr_get(options, "maxshift",  "%d", &td->maxShift);
    optstr_get(options, "maxangle",  "%lf", &td->maxAngle);
    optstr_get(options, "smoothing", "%d", &td->smoothing);
    optstr_get(options, "crop"     , "%d", (int*)&td->crop);
    optstr_get(options, "zoom"     , "%lf",&td->zoom);
    optstr_get(options, "optzoom"  , "%d", &td->optZoom);
    optstr_get(options, "interpol" , "%d", (int*)(&td->interpolType));
    optstr_get(options, "sharpen"  , "%lf",&td->sharpen);
    td->relative=1;
    td->invert=0;
  }

  if(configureMotionDetect(md)!= VS_OK){
    tc_log_error(MOD_NAME, "configuration of Motion Detection failed");
    return TC_ERROR;
  }
  if(configureTransformData(td)!= VS_OK){
    tc_log_error(MOD_NAME, "configuration of Tranform failed");
    return TC_ERROR;
  }

  if (verbose) {
    tc_log_info(MOD_NAME, "Video Deshake  Settings:");
    tc_log_info(MOD_NAME, "    smoothing = %d", td->smoothing);
    tc_log_info(MOD_NAME, "    shakiness = %d", md->shakiness);
    tc_log_info(MOD_NAME, "     accuracy = %d", md->accuracy);
    tc_log_info(MOD_NAME, "     stepsize = %d", md->stepSize);
    tc_log_info(MOD_NAME, "         algo = %d", md->algo);
    tc_log_info(MOD_NAME, "  mincontrast = %f", md->contrastThreshold);
    tc_log_info(MOD_NAME, "         show = %d", md->show);
    tc_log_info(MOD_NAME, "       result = %s", sd->result);
    tc_log_info(MOD_NAME, "    maxshift  = %d", td->maxShift);
    tc_log_info(MOD_NAME, "    maxangle  = %f", td->maxAngle);
    tc_log_info(MOD_NAME, "         crop = %s",
		td->crop ? "Black" : "Keep");
    tc_log_info(MOD_NAME, "         zoom = %f", td->zoom);
    tc_log_info(MOD_NAME, "      optzoom = %s",
		td->optZoom ? "On" : "Off");
    tc_log_info(MOD_NAME, "     interpol = %s",
		interpolTypes[td->interpolType]);
    tc_log_info(MOD_NAME, "      sharpen = %f", td->sharpen);

  }

  sd->avg.initialized=0;

  sd->f = fopen(sd->result, "w");
  if (sd->f == NULL) {
    tc_log_error(MOD_NAME, "cannot open result file %s!\n", sd->result);
    return TC_ERROR;
  }

  return TC_OK;
}
int tc_filter(frame_list_t *ptr_, char *options){
	vframe_list_t *		ptr = (vframe_list_t *)ptr_;
	int 			frame_slot = 0;
	static 			vob_t *vob=NULL;
	static int		slots[TC_FRAME_THREADS_MAX];

  if(ptr->tag & TC_FILTER_GET_CONFIG) {

	optstr_filter_desc (options, MOD_NAME, MOD_CAP, MOD_VERSION, "Julien Tierny", "VRYMO", "1");
    optstr_param (options, "font", "Valid PSF font file (provided with the `aart` package)", "%s", "default8x9.psf");
	optstr_param (options, "pallete", "Valid pallete file (provided with the `aart` package)", "%s", "colors.pal");
	optstr_param(options, "threads", "Use multiple-threaded routine for picture rendering", "%d", "0", "1", "oo");

	/* Boolean parameter */
	optstr_param(options, "buffer", "Use `aart` internal buffer for output", "", "-1");

	return 0;
  }

  //----------------------------------
  //
  // filter init
  //
  //----------------------------------


  if(ptr->tag & TC_FILTER_INIT) {

    if((vob = tc_get_vob())==NULL)
		return(-1);

	/* aart sanity check */
	if (tc_test_program("aart") !=0 )
		return -1;

	/* Now, let's handle the options ... */
	if((parameters = tc_malloc (sizeof(parameter_struct))) == NULL){
		tc_log_error(MOD_NAME, "Out of memory !!!");
		return -1;
	}

	/* Filter default options */
	if (verbose & TC_DEBUG)
		tc_log_info(MOD_NAME, "Preparing default options.");
	strncpy(parameters->aart_font, "default8x9.psf", strlen("default8x9.psf"));
	if (verbose & TC_DEBUG)
		tc_log_info(MOD_NAME, "Default options correctly formated.");
	strncpy(parameters->aart_pallete, "colors.pal", strlen("colors.pal"));
	parameters->aart_threads 		= 1;
	parameters->aart_buffer 		= -1;
	parameters->tcvhandle			= 0;

	if (options){
		/* Get filter options via transcode core */
		if (verbose & TC_DEBUG)
			tc_log_info(MOD_NAME, "Merging options from transcode.");
		optstr_get(options, "font",			"%s",		parameters->aart_font);
		clean_parameter(parameters->aart_font);
		optstr_get(options, "pallete",		"%s",		parameters->aart_pallete);
		clean_parameter(parameters->aart_pallete);
		optstr_get(options, "threads",   	"%d",		&parameters->aart_threads);

		if (optstr_lookup(options, "buffer") != NULL)
			parameters->aart_buffer=1;
		if (optstr_lookup(options, "help") != NULL)
			help_optstr();
		if (verbose & TC_DEBUG)
			tc_log_info(MOD_NAME, "Options correctly merged.");
	}

	if (vob->im_v_codec == CODEC_YUV){
		if (!(parameters->tcvhandle = tcv_init())) {
			tc_log_error(MOD_NAME, "Error at image conversion initialization.");
			return(-1);
		}
	}

	/* Init thread slots (multithread support)*/
	init_slots(slots);

	if(verbose)
		tc_log_info(MOD_NAME, "%s %s", MOD_VERSION, MOD_CAP);

    return(0);
  }

  //----------------------------------
  //
  // filter close
  //
  //----------------------------------


  if(ptr->tag & TC_FILTER_CLOSE) {

  	/*
	 * TODO :
	 * Provide a `aart` kill routine in case of cancel.
	 * For the moment, transcode waits for the `aart`
	 * process to finish before exiting.
	 */

	tcv_free(parameters->tcvhandle);

	/* Let's free the parameter structure */
	free(parameters);
	parameters = NULL;

    return(0);
  }

  //----------------------------------
  //
  // filter frame routine
  //
  //----------------------------------

	if(ptr->tag & TC_POST_M_PROCESS && ptr->tag & TC_VIDEO && !(ptr->attributes & TC_FRAME_IS_SKIPPED)) {

		frame_slot = find_empty_slot(ptr->id, slots);
		switch(vob->im_v_codec){
			case CODEC_RGB:
				return aart_render(ptr->video_buf, ptr->v_width, ptr->v_height, frame_slot, parameters->aart_font, parameters->aart_pallete, parameters->aart_threads, parameters->aart_buffer);
				break;

			case CODEC_YUV:

				if (!tcv_convert(parameters->tcvhandle, ptr->video_buf, ptr->video_buf, ptr->v_width, ptr->v_height, IMG_YUV_DEFAULT, IMG_RGB24)){
					tc_log_error(MOD_NAME, "cannot convert YUV stream to RGB format !");
					return -1;
				}

				if (aart_render(ptr->video_buf, ptr->v_width, ptr->v_height, frame_slot, parameters->aart_font, parameters->aart_pallete, parameters->aart_threads, parameters->aart_buffer) == -1){return -1;}
				if (!tcv_convert(parameters->tcvhandle, ptr->video_buf, ptr->video_buf, ptr->v_width, ptr->v_height, IMG_RGB24, IMG_YUV_DEFAULT)){
					tc_log_error(MOD_NAME, "cannot convert RGB stream to YUV format !");
					return -1;
				}
				break;

			default:
				tc_log_error(MOD_NAME, "Internal video codec is not supported.");
				return -1;
		}
		free_slot(ptr->id, slots);
	}
	return(0);
}
Beispiel #30
0
int tc_filter(frame_list_t *ptr_, char *options)
{
    vframe_list_t *ptr = (vframe_list_t *)ptr_;
    static vob_t *vob = NULL;
    static char *lastFrames[FRBUFSIZ];
    static int frameIn = 0;
    static int frameCount = 0;
    static int field = 0;
    static int magic = 0;

    //----------------------------------
    //
    // filter init
    //
    //----------------------------------


    if (ptr->tag & TC_FILTER_GET_CONFIG) {
	if (options) {
	    optstr_filter_desc (options, MOD_NAME, MOD_CAP, MOD_VERSION, "Thanassis Tsiodras", "VYE", "1");
	    optstr_param (options, "verbose", "print verbose information", "", "0");
	    optstr_param (options, "field", "which field to replace (0=top 1=bottom)",  "%d", "0",  "0", "1");
	    optstr_param (options, "magic", "perform magic? (0=no 1=yes)",  "%d", "0",  "0", "1");
	}
    }

    if (ptr->tag & TC_FILTER_INIT) {

	int i;

	if ((vob = tc_get_vob()) == NULL)
	    return (-1);

	if (vob->im_v_codec != TC_CODEC_YUV420P) {
		tc_log_error(MOD_NAME, "Sorry, only YUV 420 input allowed for now");
		return (-1);
	}

	// filter init ok.
	if (options != NULL) {

	    if (optstr_lookup (options, "verbose") != NULL) {
		show_results=1;
	    }

	    optstr_get(options, "field", "%d", &field);
	    optstr_get(options, "magic", "%d", &magic);

	}

	if (verbose)
	    tc_log_info(MOD_NAME, "%s %s", MOD_VERSION, MOD_CAP);

	for(i=0; i<FRBUFSIZ; i++) {
	    lastFrames[i] = tc_malloc(SIZE_RGB_FRAME);
    	}

	return (0);
    }
    //----------------------------------
    //
    // filter close
    //
    //----------------------------------


    if (ptr->tag & TC_FILTER_CLOSE) {
	int i;

	for(i=0; i<FRBUFSIZ; i++)
	    free(lastFrames[i]);
	return (0);
    }
    //----------------------------------
    //
    // filter frame routine
    //
    //----------------------------------


    // tag variable indicates, if we are called before
    // transcodes internal video/audio frame processing routines
    // or after and determines video/audio context

    if ((ptr->tag & TC_PRE_S_PROCESS) && (ptr->tag & TC_VIDEO)) {

	ac_memcpy(	lastFrames[frameIn],
		ptr->video_buf,
		ptr->v_width*ptr->v_height*3);
	if (show_results)
	    tc_log_info(MOD_NAME, "Inserted frame %d into slot %d",
		    frameCount, frameIn);
	frameIn = (frameIn+1) % FRBUFSIZ;
	frameCount++;

	// The first 2 frames are not output - they are only buffered
	if (frameCount <= 2) {
	    ptr->attributes |= TC_FRAME_IS_SKIPPED;
	} else {
	    // We have the last 3 frames in the buffer...
	    //
	    //		Previous Current Next
	    //
	    // OK, time to work...

	    unsigned char *curr,
		*pprev, *pnext, *cprev, *cnext, *nprev, *nnext, *dstp;
	    int idxp, idxc, idxn;
	    int p, c, n, lowest, chosen;
	    int C, x, y;
	    int comb;

	    idxn = frameIn-1; while(idxn<0) idxn+=FRBUFSIZ;
	    idxc = frameIn-2; while(idxc<0) idxc+=FRBUFSIZ;
	    idxp = frameIn-3; while(idxp<0) idxp+=FRBUFSIZ;

            y = (field ? 2 : 1) * ptr->v_width;

	    // bottom field of current
	    curr =  &lastFrames[idxc][y];
	    // top field of previous
	    pprev = &lastFrames[idxp][y - ptr->v_width];
	    // top field of previous - 2nd scanline
	    pnext = &lastFrames[idxp][y + ptr->v_width];
	    // top field of current
	    cprev = &lastFrames[idxc][y - ptr->v_width];
	    // top field of current - 2nd scanline
	    cnext = &lastFrames[idxc][y + ptr->v_width];
	    // top field of next
	    nprev = &lastFrames[idxn][y - ptr->v_width];
	    // top field of next - 2nd scanline
	    nnext = &lastFrames[idxn][y + ptr->v_width];

	    // Blatant copy begins...

	    p = c = n = 0;
	    /* Try to match the top field of the current frame to the
	       bottom fields of the previous, current, and next frames.
	       Output the assembled frame that matches up best. For
	       matching, subsample the frames in the x dimension
	       for speed. */
	    for (y = 0; y < ptr->v_height-2; y+=4)
	    {
		for (x = 0; x < ptr->v_width;)
		{
		    C = curr[x];
#define T 100
		    /* This combing metric is based on
		       an original idea of Gunnar Thalin. */
		    comb = ((long)pprev[x] - C) * ((long)pnext[x] - C);
		    if (comb > T) p++;

		    comb = ((long)cprev[x] - C) * ((long)cnext[x] - C);
		    if (comb > T) c++;

		    comb = ((long)nprev[x] - C) * ((long)nnext[x] - C);
		    if (comb > T) n++;

		    if (!(++x&3)) x += 12;
		}
		curr  += ptr->v_width*4;
		pprev += ptr->v_width*4;
		pnext += ptr->v_width*4;
		cprev += ptr->v_width*4;
		cnext += ptr->v_width*4;
		nprev += ptr->v_width*4;
		nnext += ptr->v_width*4;
	    }

	    lowest = c;
	    chosen = 1;
	    if (p < lowest)
	    {
		    lowest = p;
		    chosen = 0;
	    }
	    if (n < lowest)
	    {
		    lowest = n;
		    chosen = 2;
	    }

	    if (magic && c < 50 && abs(lowest - c) < 10 && (p+c+n) > 1000) {
		lowest = c;
		chosen = 1;
            }

	    // Blatant copy ends... :)

	    if (show_results)
		tc_log_info(MOD_NAME,
		    "Telecide => frame %d: p=%u  c=%u  n=%u [using %d]",
		    frameCount, p, c, n, chosen);

	    // Set up the pointers in preparation to output final frame.

	    // First, the Y plane
	    if (chosen == 0)
		curr = lastFrames[idxp];
	    else if (chosen == 1)
		curr = lastFrames[idxc];
	    else
		curr = lastFrames[idxn];

	    dstp = ptr->video_buf;

	    // First output the top field selected
	    // from the set of three stored frames.
	    ivtc_copy_field(dstp, curr, ptr, field);

	    // The bottom field of the current frame unchanged
	    ivtc_copy_field(dstp, lastFrames[idxc], ptr, 1-field);

	}
    }

    return (0);
}