--- branches/dev-api-4/xvidcore/src/plugins/plugin_2pass1.c 2003/11/19 15:42:38 1216 +++ branches/dev-api-4/xvidcore/src/plugins/plugin_2pass1.c 2003/12/20 15:30:03 1286 @@ -22,11 +22,13 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * $Id: plugin_2pass1.c,v 1.1.2.9 2003-11-19 15:42:38 syskin Exp $ + * $Id: plugin_2pass1.c,v 1.1.2.12 2003-12-20 15:30:03 edgomez Exp $ * *****************************************************************************/ #include +#include /* errno var (or function with recent libc) */ +#include /* strerror() */ #include "../xvid.h" #include "../image/image.h" @@ -63,6 +65,33 @@ 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 */ @@ -81,34 +110,39 @@ static int rc_2pass1_destroy(rc_2pass1_t * rc, xvid_plg_destroy_t * destroy) { - fclose(rc->stat_file); - free(rc); + if (rc->stat_file) { + if (fclose(rc->stat_file) == EOF) { + DPRINTF(XVID_DEBUG_RC, "Error closing stats file (%s)", strerror(errno)); + } + } + rc->stat_file = NULL; /* Just a paranoid reset */ + free(rc); /* as the container structure is freed anyway */ return(0); } static int rc_2pass1_before(rc_2pass1_t * rc, xvid_plg_data_t * data) { - if (data->quant <= 0) { - if (data->zone && data->zone->mode == XVID_ZONE_QUANT) { - rc->fq_error += (double)data->zone->increment / (double)data->zone->base; - data->quant = (int)rc->fq_error; - rc->fq_error -= data->quant; - - }else { - data->quant = 2; - } - } - return 0; + if (data->quant <= 0) { + if (data->zone && data->zone->mode == XVID_ZONE_QUANT) { + rc->fq_error += (double)data->zone->increment / (double)data->zone->base; + data->quant = (int)rc->fq_error; + rc->fq_error -= data->quant; + } else { + data->quant = 2; + } + } + return(0); } static int rc_2pass1_after(rc_2pass1_t * rc, xvid_plg_data_t * data) { char type; + xvid_enc_stats_t *stats = &data->stats; /* Frame type in ascii I/P/B */ - switch(data->type) { + switch(stats->type) { case XVID_TYPE_IVOP: type = 'i'; break; @@ -127,13 +161,14 @@ /* write the resulting statistics */ - fprintf(rc->stat_file, "%c %d %d %d %d %d\n", - type, - data->quant, - data->kblks, - data->mblks, - data->ublks, - data->length); + fprintf(rc->stat_file, "%c %d %d %d %d %d %d\n", + type, + stats->quant, + stats->kblks, + stats->mblks, + stats->ublks, + stats->length, + stats->hlength); return(0); }