Modifies CLI help message for audio track selection, to make it clearer how to specif...
[HandBrake.git] / libhb / encxvid.c
blob7bdee7b964d8fdf64fc04a058c59fc9fd0a7c039
1 /* $Id: encxvid.c,v 1.10 2005/03/09 23:28:39 titer Exp $
3 This file is part of the HandBrake source code.
4 Homepage: <http://handbrake.m0k.org/>.
5 It may be used under the terms of the GNU General Public License. */
7 #include "hb.h"
9 #include "xvid.h"
11 int encxvidInit( hb_work_object_t *, hb_job_t * );
12 int encxvidWork( hb_work_object_t *, hb_buffer_t **, hb_buffer_t ** );
13 void encxvidClose( hb_work_object_t * );
15 hb_work_object_t hb_encxvid =
17 WORK_ENCXVID,
18 "MPEG-4 encoder (libxvidcore)",
19 encxvidInit,
20 encxvidWork,
21 encxvidClose
24 struct hb_work_private_s
26 hb_job_t * job;
27 void * xvid;
28 char filename[1024];
29 int quant;
30 int configDone;
33 int encxvidInit( hb_work_object_t * w, hb_job_t * job )
35 xvid_gbl_init_t xvid_gbl_init;
36 xvid_enc_create_t create;
37 xvid_plugin_single_t single;
38 xvid_plugin_2pass1_t rc2pass1;
39 xvid_plugin_2pass2_t rc2pass2;
40 xvid_enc_plugin_t plugins[1];
42 hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) );
43 w->private_data = pv;
45 pv->job = job;
47 memset( pv->filename, 0, 1024 );
48 hb_get_tempory_filename( job->h, pv->filename, "xvid.log" );
50 memset( &xvid_gbl_init, 0, sizeof( xvid_gbl_init ) );
51 xvid_gbl_init.version = XVID_VERSION;
52 xvid_global( NULL, XVID_GBL_INIT, &xvid_gbl_init, NULL );
54 memset( &create, 0, sizeof( create ) );
55 create.version = XVID_VERSION;
56 create.width = job->width;
57 create.height = job->height;
58 create.zones = NULL;
59 create.num_zones = 0;
61 switch( job->pass )
63 case 0:
64 memset( &single, 0, sizeof( single ) );
65 single.version = XVID_VERSION;
66 if( job->vquality < 0.0 || job->vquality > 1.0 )
68 /* Rate control */
69 single.bitrate = 1000 * job->vbitrate;
70 pv->quant = 0;
72 else
74 /* Constant quantizer */
75 pv->quant = 31 - job->vquality * 30;
76 hb_log( "encxvid: encoding at constant quantizer %d",
77 pv->quant );
79 plugins[0].func = xvid_plugin_single;
80 plugins[0].param = &single;
81 break;
83 case 1:
84 memset( &rc2pass1, 0, sizeof( rc2pass1 ) );
85 rc2pass1.version = XVID_VERSION;
86 rc2pass1.filename = pv->filename;
87 plugins[0].func = xvid_plugin_2pass1;
88 plugins[0].param = &rc2pass1;
89 break;
91 case 2:
92 memset( &rc2pass2, 0, sizeof( rc2pass2 ) );
93 rc2pass2.version = XVID_VERSION;
94 rc2pass2.filename = pv->filename;
95 rc2pass2.bitrate = 1000 * job->vbitrate;
96 plugins[0].func = xvid_plugin_2pass2;
97 plugins[0].param = &rc2pass2;
98 break;
101 create.plugins = plugins;
102 create.num_plugins = 1;
104 create.num_threads = 0;
105 create.fincr = job->vrate_base;
106 create.fbase = job->vrate;
107 create.max_key_interval = 10 * job->vrate / job->vrate_base;
108 create.max_bframes = 0;
109 create.bquant_ratio = 150;
110 create.bquant_offset = 100;
111 create.frame_drop_ratio = 0;
112 create.global = 0;
114 xvid_encore( NULL, XVID_ENC_CREATE, &create, NULL );
115 pv->xvid = create.handle;
117 return 0;
120 /***********************************************************************
121 * Close
122 ***********************************************************************
124 **********************************************************************/
125 void encxvidClose( hb_work_object_t * w )
127 hb_work_private_t * pv = w->private_data;
129 if( pv->xvid )
131 hb_log( "encxvid: closing libxvidcore" );
132 xvid_encore( pv->xvid, XVID_ENC_DESTROY, NULL, NULL);
135 free( pv );
136 w->private_data = NULL;
139 /***********************************************************************
140 * Work
141 ***********************************************************************
143 **********************************************************************/
144 int encxvidWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
145 hb_buffer_t ** buf_out )
147 hb_work_private_t * pv = w->private_data;
148 hb_job_t * job = pv->job;
149 xvid_enc_frame_t frame;
150 hb_buffer_t * in = *buf_in, * buf;
152 /* If this is the last empty frame, we're done */
153 if(!in->data)
155 *buf_out = NULL;
156 return HB_WORK_DONE;
159 /* Should be way too large */
160 buf = hb_buffer_init( 3 * job->width * job->height / 2 );
161 buf->start = in->start;
162 buf->stop = in->stop;
163 //buf->chap = in->chap;
165 memset( &frame, 0, sizeof( frame ) );
167 frame.version = XVID_VERSION;
168 frame.bitstream = buf->data;
169 frame.length = -1;
170 frame.input.plane[0] = in->data;
171 frame.input.csp = XVID_CSP_I420;
172 frame.input.stride[0] = job->width;
173 frame.vol_flags = 0;
174 frame.vop_flags = XVID_VOP_HALFPEL | XVID_VOP_INTER4V |
175 XVID_VOP_TRELLISQUANT | XVID_VOP_HQACPRED;
176 if( job->pixel_ratio )
178 frame.par = XVID_PAR_EXT;
179 frame.par_width = job->pixel_aspect_width;
180 frame.par_height = job->pixel_aspect_height;
183 if( job->grayscale )
185 frame.vop_flags |= XVID_VOP_GREYSCALE;
187 frame.type = XVID_TYPE_AUTO;
188 frame.quant = pv->quant;
189 frame.motion = XVID_ME_ADVANCEDDIAMOND16 | XVID_ME_HALFPELREFINE16 |
190 XVID_ME_EXTSEARCH16 | XVID_ME_ADVANCEDDIAMOND8 |
191 XVID_ME_HALFPELREFINE8 | XVID_ME_EXTSEARCH8 |
192 XVID_ME_CHROMA_PVOP | XVID_ME_CHROMA_BVOP;
193 frame.quant_intra_matrix = NULL;
194 frame.quant_inter_matrix = NULL;
196 buf->size = xvid_encore( pv->xvid, XVID_ENC_ENCODE, &frame, NULL );
197 buf->frametype = ( frame.out_flags & XVID_KEYFRAME ) ? HB_FRAME_KEY : HB_FRAME_REF;
199 if( !pv->configDone )
201 int vol_start, vop_start;
202 for( vol_start = 0; ; vol_start++ )
204 if( buf->data[vol_start] == 0x0 &&
205 buf->data[vol_start+1] == 0x0 &&
206 buf->data[vol_start+2] == 0x1 &&
207 buf->data[vol_start+3] == 0x20 )
209 break;
212 for( vop_start = vol_start + 4; ; vop_start++ )
214 if( buf->data[vop_start] == 0x0 &&
215 buf->data[vop_start+1] == 0x0 &&
216 buf->data[vop_start+2] == 0x1 &&
217 buf->data[vop_start+3] == 0xB6 )
219 break;
223 hb_log( "encxvid: VOL size is %d bytes", vop_start - vol_start );
224 job->config.mpeg4.length = vop_start - vol_start;
225 memcpy( job->config.mpeg4.bytes, &buf->data[vol_start],
226 job->config.mpeg4.length );
227 pv->configDone = 1;
230 *buf_out = buf;
232 return HB_WORK_OK;