[svn] / trunk / xvidcore / src / plugins / plugin_2pass1.c Repository:
ViewVC logotype

Annotation of /trunk/xvidcore/src/plugins/plugin_2pass1.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1988 - (view) (download)

1 : edgomez 1382 /******************************************************************************
2 :     *
3 : Isibaar 1883 * Xvid Bit Rate Controller Library
4 : edgomez 1382 * - 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 : Isibaar 1883 * Dirk Knop <dknop@gwdg.de> for the Xvid vfw dynamic library.
10 : edgomez 1382 *
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 : Isibaar 1988 * $Id$
26 : edgomez 1382 *
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 :    
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 :    
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 :    
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 : syskin 1511 data->vop_flags &= ~XVID_VOP_RD_BVOP;
165 : edgomez 1382 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 :    
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 :    
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 :     }

No admin address has been configured
ViewVC Help
Powered by ViewVC 1.0.4