1 /******************************************************************************
2  *
3  *  Xvid Bit Rate Controller Library
4  *  - VBR 2 pass bitrate controler implementation -
5  *
6  *  Copyright (C) 2002-2003 Edouard Gomez <ed.gomez@free.fr>
7  *
8  *  The curve treatment algorithm is the one implemented by Foxer <email?> and
9  *  Dirk Knop <dknop@gwdg.de> for the Xvid vfw dynamic library.
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 2 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, write to the Free Software
23  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24  *
25  * $Id: plugin_2pass1.c 1985 2011-05-18 09:02:35Z Isibaar $
26  *
27  *****************************************************************************/
28 
29 #include <stdio.h>
30 #include <errno.h> /* errno var (or function with recent libc) */
31 #include <string.h> /* strerror() */
32 
33 #include "../xvid.h"
34 #include "../image/image.h"
35 
36 
37 /* This preprocessor constant controls wheteher or not, first pass is done
38  * using fast ME routines to speed up the 2pass process at the expense of
39  * less precise first pass stats */
40 #define FAST1PASS
41 #define FAST1PASS_QPEL_TOO
42 
43 
44 /* context struct */
45 typedef struct
46 {
47 	FILE * stat_file;
48 
49     double fq_error;
50 } rc_2pass1_t;
51 
52 
53 
rc_2pass1_create(xvid_plg_create_t * create,rc_2pass1_t ** handle)54 static int rc_2pass1_create(xvid_plg_create_t * create, rc_2pass1_t ** handle)
55 {
56     xvid_plugin_2pass1_t * param = (xvid_plugin_2pass1_t *)create->param;
57 	rc_2pass1_t * rc;
58 
59     /* check filename */
60     if ((param->filename == NULL) ||
61 		(param->filename != NULL && param->filename[0] == '\0'))
62         return XVID_ERR_FAIL;
63 
64     /* allocate context struct */
65 	if((rc = malloc(sizeof(rc_2pass1_t))) == NULL)
66 		return(XVID_ERR_MEMORY);
67 
68     /* Initialize safe defaults for 2pass 1 */
69     rc->stat_file = NULL;
70 
71 	/* Open the 1st pass file */
72 	if((rc->stat_file = fopen(param->filename, "w+b")) == NULL)
73 		return(XVID_ERR_FAIL);
74 
75 	/* I swear xvidcore isn't buggy, but when using mencoder+xvid4 i observe
76 	 * this weird bug.
77 	 *
78 	 * Symptoms: The stats file grows until it's fclosed, but at this moment
79 	 *           a large part of the file is filled by 0x00 bytes w/o any
80 	 *           reasonable cause. The stats file is then completly unusable
81 	 *
82 	 * So far, i think i found "the why":
83 	 *  - take a MPEG stream containing 2 sequences (concatenate 2 MPEG files
84 	 *    together)
85 	 *  - Encode this MPEG file
86 	 *
87 	 * It should trigger the bug
88 	 *
89 	 * I think this is caused by some kind of race condition on mencoder module
90 	 * start/stop.
91 	 *  - mencoder encodes the first sequence
92 	 *    + xvid4 module opens xvid-twopass.stats and writes stats in it.
93 	 *  - mencoder detects the second sequence and initialize a second
94 	 *    module and stops the old encoder
95 	 *    + new xvid4 module opens a new xvid-twopass.stats, old xvid4
96 	 *      module closes it
97 	 *
98 	 * This is IT, got a racing condition.
99 	 * Unbuffered IO, may help ... */
100 	setbuf(rc->stat_file, NULL);
101 
102 	/*
103 	 * The File Header
104 	 */
105 	fprintf(rc->stat_file, "# XviD 2pass stat file (core version %d.%d.%d)\n",
106 			XVID_VERSION_MAJOR(XVID_VERSION),
107 			XVID_VERSION_MINOR(XVID_VERSION),
108 			XVID_VERSION_PATCH(XVID_VERSION));
109 	fprintf(rc->stat_file, "# Please do not modify this file\n\n");
110 
111     rc->fq_error = 0;
112 
113     *handle = rc;
114 	return(0);
115 }
116 
117 
rc_2pass1_destroy(rc_2pass1_t * rc,xvid_plg_destroy_t * destroy)118 static int rc_2pass1_destroy(rc_2pass1_t * rc, xvid_plg_destroy_t * destroy)
119 {
120 	if (rc->stat_file) {
121 		if (fclose(rc->stat_file) == EOF) {
122 			DPRINTF(XVID_DEBUG_RC, "Error closing stats file (%s)", strerror(errno));
123 		}
124 	}
125 	rc->stat_file = NULL; /* Just a paranoid reset */
126 	free(rc); /* as the container structure is freed anyway */
127 	return(0);
128 }
129 
130 
rc_2pass1_before(rc_2pass1_t * rc,xvid_plg_data_t * data)131 static int rc_2pass1_before(rc_2pass1_t * rc, xvid_plg_data_t * data)
132 {
133 	 if (data->quant <= 0) {
134 		if (data->zone && data->zone->mode == XVID_ZONE_QUANT) {
135 			/* We disable no options in quant zones, as their implementation is
136 			 * based on the fact we do first pass exactly the same way as the
137 			 * second one to have exact zone size */
138 			rc->fq_error += (double)data->zone->increment / (double)data->zone->base;
139 			data->quant = (int)rc->fq_error;
140 			rc->fq_error -= data->quant;
141 		} else {
142 			data->quant = 2;
143 
144 #ifdef FAST1PASS
145 			/* Given the fact our 2pass algorithm is based on very simple
146 			 * rules, we can disable some options that are too CPU intensive
147 			 * and do not provide the 2nd pass any benefit */
148 
149 			/* First disable some motion flags */
150 			data->motion_flags &= ~XVID_ME_CHROMA_PVOP;
151 			data->motion_flags &= ~XVID_ME_CHROMA_BVOP;
152 			data->motion_flags &= ~XVID_ME_USESQUARES16;
153 			data->motion_flags &= ~XVID_ME_ADVANCEDDIAMOND16;
154 			data->motion_flags &= ~XVID_ME_EXTSEARCH16;
155 
156 			/* And enable fast replacements */
157 			data->motion_flags |= XVID_ME_FAST_MODEINTERPOLATE;
158 			data->motion_flags |= XVID_ME_SKIP_DELTASEARCH;
159 			data->motion_flags |= XVID_ME_FASTREFINE16;
160 			data->motion_flags |= XVID_ME_BFRAME_EARLYSTOP;
161 
162 			/* Now VOP flags (no fast replacements) */
163 			data->vop_flags &= ~XVID_VOP_MODEDECISION_RD;
164 			data->vop_flags &= ~XVID_VOP_RD_BVOP;
165 			data->vop_flags &= ~XVID_VOP_FAST_MODEDECISION_RD;
166 			data->vop_flags &= ~XVID_VOP_TRELLISQUANT;
167 			data->vop_flags &= ~XVID_VOP_INTER4V;
168 			data->vop_flags &= ~XVID_VOP_HQACPRED;
169 
170 			/* Finnaly VOL flags
171 			 *
172 			 * NB: Qpel cannot be disable because this option really changes
173 			 *     too much the texture data compressibility, and thus the
174 			 *     second pass gets confused by too much impredictability
175 			 *     of frame sizes, and actually hurts quality */
176 #ifdef FAST1PASS_QPEL_TOO
177 			/* or maybe we can disable it after all? */
178 			data->vol_flags &= ~XVID_VOL_QUARTERPEL;
179 #endif
180 			data->vol_flags &= ~XVID_VOL_GMC;
181 #endif
182 		}
183 	}
184 	 return(0);
185 }
186 
187 
rc_2pass1_after(rc_2pass1_t * rc,xvid_plg_data_t * data)188 static int rc_2pass1_after(rc_2pass1_t * rc, xvid_plg_data_t * data)
189 {
190 	char type;
191 	xvid_enc_stats_t *stats = &data->stats;
192 
193 	/* Frame type in ascii I/P/B */
194 	switch(stats->type) {
195 	case XVID_TYPE_IVOP:
196 		type = 'i';
197 		break;
198 	case XVID_TYPE_PVOP:
199 		type = 'p';
200 		break;
201 	case XVID_TYPE_BVOP:
202 		type = 'b';
203 		break;
204 	case XVID_TYPE_SVOP:
205 		type = 's';
206 		break;
207 	default: /* Should not go here */
208 		return(XVID_ERR_FAIL);
209 	}
210 
211 	/* write the resulting statistics */
212 
213 	fprintf(rc->stat_file, "%c %d %d %d %d %d %d\n",
214 			type,
215 			stats->quant,
216 			stats->kblks,
217 			stats->mblks,
218 			stats->ublks,
219 			stats->length,
220 			stats->hlength);
221 
222 	return(0);
223 }
224 
225 
226 
xvid_plugin_2pass1(void * handle,int opt,void * param1,void * param2)227 int xvid_plugin_2pass1(void * handle, int opt, void * param1, void * param2)
228 {
229     switch(opt)
230     {
231     case XVID_PLG_INFO :
232 	case XVID_PLG_FRAME :
233         return 0;
234 
235     case XVID_PLG_CREATE :
236         return rc_2pass1_create((xvid_plg_create_t*)param1, param2);
237 
238     case XVID_PLG_DESTROY :
239         return rc_2pass1_destroy((rc_2pass1_t*)handle, (xvid_plg_destroy_t*)param1);
240 
241     case XVID_PLG_BEFORE :
242         return rc_2pass1_before((rc_2pass1_t*)handle, (xvid_plg_data_t*)param1);
243 
244     case XVID_PLG_AFTER :
245         return rc_2pass1_after((rc_2pass1_t*)handle, (xvid_plg_data_t*)param1);
246     }
247 
248     return XVID_ERR_FAIL;
249 }
250