gboolean gst_xvid_init (void) { xvid_gbl_init_t xinit; gint ret; static gboolean is_init = FALSE; /* only init once */ if (is_init == TRUE) { return TRUE; } /* set up xvid initially (function pointers, CPU flags) */ gst_xvid_init_struct (xinit); if ((ret = xvid_global (NULL, XVID_GBL_INIT, &xinit, NULL)) < 0) { g_warning ("Failed to initialize XviD: %s (%d)", gst_xvid_error (ret), ret); return FALSE; } GST_LOG ("Initted XviD version %d.%d.%d (API %d.%d)", XVID_VERSION_MAJOR (XVID_VERSION), XVID_VERSION_MINOR (XVID_VERSION), XVID_VERSION_PATCH (XVID_VERSION), XVID_API_MAJOR (XVID_API), XVID_API_MINOR (XVID_API)); is_init = TRUE; return TRUE; }
/** * Initialize the two-pass plugin and context. * * @param param Input construction parameter structure * @param handle Private context handle * @return Returns XVID_ERR_xxxx on failure, or 0 on success. */ static int xvid_ff_2pass_create(xvid_plg_create_t * param, void ** handle) { struct xvid_ff_pass1 *x = (struct xvid_ff_pass1 *)param->param; char *log = x->context->twopassbuffer; /* Do a quick bounds check */ if( log == NULL ) return XVID_ERR_FAIL; /* We use snprintf() */ /* This is because we can safely prevent a buffer overflow */ log[0] = 0; snprintf(log, BUFFER_REMAINING(log), "# ffmpeg 2-pass log file, using xvid codec\n"); snprintf(BUFFER_CAT(log), BUFFER_REMAINING(log), "# Do not modify. libxvidcore version: %d.%d.%d\n\n", XVID_VERSION_MAJOR(XVID_VERSION), XVID_VERSION_MINOR(XVID_VERSION), XVID_VERSION_PATCH(XVID_VERSION)); *handle = x->context; return 0; }
static int init(sh_video_t *sh) { xvid_gbl_info_t xvid_gbl_info; xvid_gbl_init_t xvid_ini; xvid_dec_create_t dec_p; priv_t* p; int cs; memset(&xvid_gbl_info, 0, sizeof(xvid_gbl_info_t)); xvid_gbl_info.version = XVID_VERSION; memset(&xvid_ini, 0, sizeof(xvid_gbl_init_t)); xvid_ini.version = XVID_VERSION; memset(&dec_p, 0, sizeof(xvid_dec_create_t)); dec_p.version = XVID_VERSION; switch(sh->codec->outfmt[sh->outfmtidx]){ case IMGFMT_YV12: /* We will use our own buffers, this speeds decoding avoiding * frame memcpy's overhead */ cs = (do_dr2)?XVID_CSP_INTERNAL:XVID_CSP_USER; break; case IMGFMT_YUY2: cs = XVID_CSP_YUY2; break; case IMGFMT_UYVY: cs = XVID_CSP_UYVY; break; case IMGFMT_I420: case IMGFMT_IYUV: /* We will use our own buffers, this speeds decoding avoiding * frame memcpy's overhead */ cs = (do_dr2)?XVID_CSP_INTERNAL:XVID_CSP_USER; break; case IMGFMT_BGR15: cs = XVID_CSP_RGB555; break; case IMGFMT_BGR16: cs = XVID_CSP_RGB565; break; case IMGFMT_BGR32: cs = XVID_CSP_BGRA; break; case IMGFMT_YVYU: cs = XVID_CSP_YVYU; break; default: mp_msg(MSGT_DECVIDEO, MSGL_ERR, "Unsupported out_fmt: 0x%X\n", sh->codec->outfmt[sh->outfmtidx]); return 0; } /* Gather some information about the host library */ if(xvid_global(NULL, XVID_GBL_INFO, &xvid_gbl_info, NULL) < 0) { mp_msg(MSGT_MENCODER,MSGL_INFO, "xvid: could not get information about the library\n"); } else { mp_msg(MSGT_MENCODER,MSGL_INFO, "xvid: using library version %d.%d.%d (build %s)\n", XVID_VERSION_MAJOR(xvid_gbl_info.actual_version), XVID_VERSION_MINOR(xvid_gbl_info.actual_version), XVID_VERSION_PATCH(xvid_gbl_info.actual_version), xvid_gbl_info.build); } /* Initialize the xvidcore library */ if(xvid_global(NULL, XVID_GBL_INIT, &xvid_ini, NULL)) return 0; /* We use 0 width and height so xvidcore will resize its buffers * if required. That allows this vd plugin to do resize on first * VOL encountered (don't trust containers' width and height) */ dec_p.width = 0; dec_p.height = 0; /* Get a decoder instance */ if(xvid_decore(0, XVID_DEC_CREATE, &dec_p, NULL)<0) { mp_msg(MSGT_DECVIDEO, MSGL_ERR, "XviD init failed\n"); return 0; } p = malloc(sizeof(priv_t)); p->cs = cs; p->hdl = dec_p.handle; p->vo_initialized = 0; sh->context = p; switch(cs) { case XVID_CSP_INTERNAL: p->img_type = MP_IMGTYPE_EXPORT; break; case XVID_CSP_USER: p->img_type = MP_IMGTYPE_STATIC; break; default: p->img_type = MP_IMGTYPE_TEMP; break; } return 1; }
/* ------------------------------------ * gap_gve_xvid_init * ------------------------------------ * init XVID and create the encoder instance * */ GapGveXvidControl * gap_gve_xvid_init(gint32 width, gint32 height, gdouble framerate, GapGveXvidValues *xvid_val) { GapGveXvidControl *xvid_control; xvid_gbl_init_t *xvid_gbl_init; xvid_enc_create_t *xvid_enc_create; xvid_enc_frame_t *xvid_enc_frame; int xerr; gdouble l_framerate_x1000; l_framerate_x1000 = framerate * 1000.0; xvid_control = g_malloc0(sizeof(GapGveXvidControl)); xvid_gbl_init = &xvid_control->xvid_gbl_init; xvid_enc_create = &xvid_control->xvid_enc_create; xvid_enc_frame = &xvid_control->xvid_enc_frame; /* ------------------------ * XviD core initialization * ------------------------- */ memset(xvid_gbl_init, 0, sizeof(xvid_gbl_init_t)); xvid_gbl_init->version = XVID_VERSION; xvid_gbl_init->debug = 0; xvid_gbl_init->cpu_flags = 0; xvid_gbl_init->cpu_flags = XVID_CPU_FORCE; if(gap_debug) { printf("gap_gve_xvid_init XVID_VERSION: %d (%d.%d.%d)\n" ,(int)xvid_gbl_init->version ,(int)XVID_VERSION_MAJOR(xvid_gbl_init->version) ,(int)XVID_VERSION_MINOR(xvid_gbl_init->version) ,(int)XVID_VERSION_PATCH(xvid_gbl_init->version) ); } /* Initialize XviD core -- Should be done once per __process__ */ xvid_global(NULL, XVID_GBL_INIT, xvid_gbl_init, NULL); /* ------------------------ * XviD encoder initialization * ------------------------- */ /* Version again */ memset(xvid_enc_create, 0, sizeof(xvid_enc_create_t)); xvid_enc_create->version = XVID_VERSION; /* Width and Height of input frames */ xvid_enc_create->width = width; xvid_enc_create->height = height; xvid_enc_create->profile = XVID_PROFILE_AS_L4; xvid_enc_create->fincr = 1000; xvid_enc_create->fbase = l_framerate_x1000; /* init zones */ xvid_control->num_zones = 0; if(FALSE) { /* the current implementation does not use zones * but here is an example what to initialize per zone * for later use */ if(TRUE) { xvid_control->zones[xvid_control->num_zones].mode = XVID_ZONE_QUANT; } else { xvid_control->zones[xvid_control->num_zones].mode = XVID_ZONE_WEIGHT; } xvid_control->zones[xvid_control->num_zones].frame = 0; xvid_control->zones[xvid_control->num_zones].increment = 100 * 1; xvid_control->zones[xvid_control->num_zones].base = 100; xvid_control->num_zones++; } xvid_enc_create->zones = &xvid_control->zones[0]; xvid_enc_create->num_zones = xvid_control->num_zones; /* init plugins */ xvid_enc_create->plugins = xvid_control->plugins; xvid_enc_create->num_plugins = 0; /* this implementation only uses SINGLE PASS */ { memset(&xvid_control->single, 0, sizeof(xvid_plugin_single_t)); xvid_control->single.version = XVID_VERSION; xvid_control->single.bitrate = xvid_val->rc_bitrate; xvid_control->plugins[xvid_enc_create->num_plugins].func = xvid_plugin_single; xvid_control->plugins[xvid_enc_create->num_plugins].param = &xvid_control->single; xvid_enc_create->num_plugins++; } /* TODO: lumimasking should be a Parameter */ if(FALSE) { xvid_control->plugins[xvid_enc_create->num_plugins].func = xvid_plugin_lumimasking; xvid_control->plugins[xvid_enc_create->num_plugins].param = NULL; xvid_enc_create->num_plugins++; } /* TODO: Dump should be a Parameter */ if(FALSE) { xvid_control->plugins[xvid_enc_create->num_plugins].func = xvid_plugin_dump; xvid_control->plugins[xvid_enc_create->num_plugins].param = NULL; xvid_enc_create->num_plugins++; } /* parameters of older xvid version (dont know how to migrate to v1.0) */ // xvid_encparam->rc_reaction_delay_factor = xvid_val->rc_reaction_delay_factor; // xvid_encparam->rc_averaging_period = xvid_val->rc_averaging_period; // xvid_encparam->rc_buffer = xvid_val->rc_buffer; // xvid_encparam->max_quantizer = xvid_val->max_quantizer; // xvid_encparam->min_quantizer = xvid_val->min_quantizer; /* Maximum key frame interval */ xvid_enc_create->max_key_interval = xvid_val->max_key_interval; /* No fancy thread tests */ xvid_enc_create->num_threads = 0; /* Bframes settings TODO: pass params for Bframe settings */ xvid_enc_create->max_bframes = 0; // ARG_MAXBFRAMES; xvid_enc_create->bquant_ratio = 150; // ARG_BQRATIO; xvid_enc_create->bquant_offset = 100; // ARG_BQOFFSET; /* Dropping ratio frame -- we don't need that */ xvid_enc_create->frame_drop_ratio = 0; /* Global encoder options TODO: pass params for Global options */ xvid_enc_create->global = 0; if (FALSE) { xvid_enc_create->global |= XVID_GLOBAL_PACKED; } if (FALSE) { xvid_enc_create->global |= XVID_GLOBAL_CLOSED_GOP; } if (FALSE) { xvid_enc_create->global |= XVID_GLOBAL_EXTRASTATS_ENABLE; } xvid_enc_create->handle = NULL; /* out param The encoder instance */ xvid_enc_frame->version = XVID_VERSION; xvid_enc_frame->length = -1; /* out: length returned by encoder */ xvid_enc_frame->input.csp = XVID_CSP_YV12; /*XVID_CSP_I420 XVID_CSP_BGR | XVID_CSP_VFLIP */ /* Set up core's general features */ xvid_enc_frame->vol_flags = 0; if (FALSE) { xvid_enc_frame->vol_flags |= XVID_VOL_EXTRASTATS; } if (FALSE) { xvid_enc_frame->vol_flags |= XVID_VOL_QUARTERPEL; } if (FALSE) { xvid_enc_frame->vol_flags |= XVID_VOL_GMC; } xvid_enc_frame->vop_flags = xvid_val->general; xvid_enc_frame->motion = xvid_val->motion; if(FALSE) { xvid_enc_frame->motion |= XVID_ME_GME_REFINE; } if(FALSE) { xvid_enc_frame->motion |= XVID_ME_QUARTERPELREFINE16; } if(FALSE && (xvid_enc_frame->vop_flags & XVID_VOP_INTER4V)) { xvid_enc_frame->motion |= XVID_ME_QUARTERPELREFINE8; } xvid_enc_frame->quant_intra_matrix = NULL; /* use built in default Matrix */ xvid_enc_frame->quant_inter_matrix = NULL; /* use built in default Matrix */ xvid_enc_frame->quant = 0; /* 0: codec decides, 1..31 force quant for this frame */ xvid_enc_frame->type = XVID_TYPE_AUTO; /* Frame type -- let core decide for us */ /* create the encoder instance */ xerr = xvid_encore(NULL, XVID_ENC_CREATE, xvid_enc_create, NULL); if(xerr) { printf("gap_gve_xvid_init create encoder instance failed. ERRORCODE: %d\n", (int)xerr); g_free(xvid_control); return (NULL); } return(xvid_control); } /* end gap_gve_xvid_init */
static int rc_2pass1_create(xvid_plg_create_t * create, rc_2pass1_t ** handle) { xvid_plugin_2pass1_t * param = (xvid_plugin_2pass1_t *)create->param; rc_2pass1_t * rc; /* check filename */ if ((param->filename == NULL) || (param->filename != NULL && param->filename[0] == '\0')) return XVID_ERR_FAIL; /* allocate context struct */ if((rc = malloc(sizeof(rc_2pass1_t))) == NULL) return(XVID_ERR_MEMORY); /* Initialize safe defaults for 2pass 1 */ rc->stat_file = NULL; /* Open the 1st pass file */ if((rc->stat_file = fopen(param->filename, "w+b")) == NULL) return(XVID_ERR_FAIL); /* I swear xvidcore isn't buggy, but when using mencoder+xvid4 i observe * this weird bug. * * Symptoms: The stats file grows until it's fclosed, but at this moment * a large part of the file is filled by 0x00 bytes w/o any * reasonable cause. The stats file is then completly unusable * * So far, i think i found "the why": * - take a MPEG stream containing 2 sequences (concatenate 2 MPEG files * together) * - Encode this MPEG file * * It should trigger the bug * * I think this is caused by some kind of race condition on mencoder module * start/stop. * - mencoder encodes the first sequence * + xvid4 module opens xvid-twopass.stats and writes stats in it. * - mencoder detects the second sequence and initialize a second * module and stops the old encoder * + new xvid4 module opens a new xvid-twopass.stats, old xvid4 * module closes it * * This is IT, got a racing condition. * Unbuffered IO, may help ... */ setbuf(rc->stat_file, NULL); /* * The File Header */ fprintf(rc->stat_file, "# XviD 2pass stat file (core version %d.%d.%d)\n", XVID_VERSION_MAJOR(XVID_VERSION), XVID_VERSION_MINOR(XVID_VERSION), XVID_VERSION_PATCH(XVID_VERSION)); fprintf(rc->stat_file, "# Please do not modify this file\n\n"); rc->fq_error = 0; *handle = rc; return(0); }