1 /* $Id: work.c,v 1.43 2005/03/17 16:38:49 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. */
18 static void work_func();
19 static void do_job( hb_job_t *, int cpu_count );
20 static void work_loop( void * );
23 * Allocates work object and launches work thread with work_func.
24 * @param jobs Handle to hb_list_t.
25 * @param cpu_count Humber of CPUs found in system.
26 * @param die Handle to user inititated exit indicator.
27 * @param error Handle to error indicator.
29 hb_thread_t * hb_work_init( hb_list_t * jobs, int cpu_count,
30 volatile int * die, int * error )
32 hb_work_t * work = calloc( sizeof( hb_work_t ), 1 );
35 work->cpu_count = cpu_count;
39 return hb_thread_init( "work", work_func, work, HB_LOW_PRIORITY );
43 * Iterates through job list and calls do_job for each job.
44 * @param _work Handle work object.
46 static void work_func( void * _work )
48 hb_work_t * work = _work;
51 hb_log( "%d job(s) to process", hb_list_count( work->jobs ) );
53 while( !*work->die && ( job = hb_list_item( work->jobs, 0 ) ) )
55 hb_list_rem( work->jobs, job );
57 do_job( job, work->cpu_count );
60 *(work->error) = HB_ERROR_NONE;
65 static hb_work_object_t * getWork( int id )
68 for( w = hb_objects; w; w = w->next )
79 * Job initialization rountine.
81 * Creates work objects for synchronizer, video decoder, video renderer, video decoder, audio decoder, audio encoder, reader, muxer.
82 * Launches thread for each work object with work_loop.
83 * Loops while monitoring status of work threads and fifos.
84 * Exits loop when conversion is done and fifos are empty.
85 * Closes threads and frees fifos.
86 * @param job Handle work hb_job_t.
87 * @param cpu_count number of CPUs found in system.
89 static void do_job( hb_job_t * job, int cpu_count )
95 hb_subtitle_t * subtitle;
100 job->list_work = hb_list_init();
102 hb_log( "starting job" );
103 hb_log( " + device %s", title->dvd );
104 hb_log( " + title %d, chapter(s) %d to %d", title->index,
105 job->chapter_start, job->chapter_end );
106 if ( job->pixel_ratio == 1 )
108 /* Correct the geometry of the output movie when using PixelRatio */
109 job->height=title->height-job->crop[0]-job->crop[1];
110 job->width=title->width-job->crop[2]-job->crop[3];
113 /* Keep width and height within these boundaries */
114 if (job->maxHeight && (job->height > job->maxHeight) )
116 job->height = job->maxHeight;
117 hb_fix_aspect( job, HB_KEEP_HEIGHT );
118 hb_log("Height out of bounds, scaling down to %i", job->maxHeight);
119 hb_log("New dimensions %i * %i", job->width, job->height);
121 if (job->maxWidth && (job->width > job->maxWidth) )
123 job->width = job->maxWidth;
124 hb_fix_aspect( job, HB_KEEP_WIDTH );
125 hb_log("Width out of bounds, scaling down to %i", job->maxWidth);
126 hb_log("New dimensions %i * %i", job->width, job->height);
129 hb_log( " + %dx%d -> %dx%d, crop %d/%d/%d/%d",
130 title->width, title->height, job->width, job->height,
131 job->crop[0], job->crop[1], job->crop[2], job->crop[3] );
132 hb_log( " + deinterlace %s", job->deinterlace ? "on" : "off" );
133 hb_log( " + grayscale %s", job->grayscale ? "on" : "off" );
134 if( job->vquality >= 0.0 && job->vquality <= 1.0 )
136 hb_log( " + %.3f fps, video quality %.2f", (float) job->vrate /
137 (float) job->vrate_base, job->vquality );
141 hb_log( " + %.3f fps, video bitrate %d kbps, pass %d",
142 (float) job->vrate / (float) job->vrate_base,
143 job->vbitrate, job->pass );
145 hb_log (" + PixelRatio: %d, width:%d, height: %d",job->pixel_ratio,job->width, job->height);
146 job->fifo_mpeg2 = hb_fifo_init( 2048 );
147 job->fifo_raw = hb_fifo_init( 8 );
148 job->fifo_sync = hb_fifo_init( 8 );
149 job->fifo_render = hb_fifo_init( 8 );
150 job->fifo_mpeg4 = hb_fifo_init( 8 );
152 /* Synchronization */
153 hb_list_add( job->list_work, ( w = getWork( WORK_SYNC ) ) );
158 hb_list_add( job->list_work, ( w = getWork( WORK_DECMPEG2 ) ) );
159 w->fifo_in = job->fifo_mpeg2;
160 w->fifo_out = job->fifo_raw;
163 hb_list_add( job->list_work, ( w = getWork( WORK_RENDER ) ) );
164 w->fifo_in = job->fifo_sync;
165 w->fifo_out = job->fifo_render;
168 switch( job->vcodec )
170 case HB_VCODEC_FFMPEG:
171 hb_log( " + encoder FFmpeg" );
172 w = getWork( WORK_ENCAVCODEC );
175 hb_log( " + encoder XviD" );
176 w = getWork( WORK_ENCXVID );
179 hb_log( " + encoder x264" );
180 w = getWork( WORK_ENCX264 );
183 w->fifo_in = job->fifo_render;
184 w->fifo_out = job->fifo_mpeg4;
185 w->config = &job->config;
186 hb_list_add( job->list_work, w );
188 subtitle = hb_list_item( title->list_subtitle, 0 );
191 hb_log( " + subtitle %x, %s", subtitle->id, subtitle->lang );
193 subtitle->fifo_in = hb_fifo_init( 8 );
194 subtitle->fifo_raw = hb_fifo_init( 8 );
196 hb_list_add( job->list_work, ( w = getWork( WORK_DECSUB ) ) );
197 w->fifo_in = subtitle->fifo_in;
198 w->fifo_out = subtitle->fifo_raw;
201 if( job->acodec & HB_ACODEC_AC3 )
203 hb_log( " + audio AC3 passthrough" );
207 hb_log( " + audio %d kbps, %d Hz", job->abitrate, job->arate );
208 hb_log( " + encoder %s", ( job->acodec & HB_ACODEC_FAAC ) ?
209 "faac" : ( ( job->acodec & HB_ACODEC_LAME ) ? "lame" :
213 for( i = 0; i < hb_list_count( title->list_audio ); i++ )
215 audio = hb_list_item( title->list_audio, i );
216 hb_log( " + %x, %s", audio->id, audio->lang );
218 audio->fifo_in = hb_fifo_init( 2048 );
219 audio->fifo_raw = hb_fifo_init( 8 );
220 audio->fifo_sync = hb_fifo_init( 8 );
221 audio->fifo_out = hb_fifo_init( 8 );
223 switch( audio->codec )
226 w = getWork( WORK_DECA52 );
229 w = getWork( WORK_DECAVCODEC );
232 w = getWork( WORK_DECLPCM );
235 w->fifo_in = audio->fifo_in;
236 w->fifo_out = audio->fifo_raw;
237 hb_list_add( job->list_work, w );
239 switch( job->acodec )
242 w = getWork( WORK_ENCFAAC );
245 w = getWork( WORK_ENCLAME );
247 case HB_ACODEC_VORBIS:
248 w = getWork( WORK_ENCVORBIS );
251 if( job->acodec != HB_ACODEC_AC3 )
253 w->fifo_in = audio->fifo_sync;
254 w->fifo_out = audio->fifo_out;
255 w->config = &audio->config;
256 hb_list_add( job->list_work, w );
259 /* store this audio's channel counts with the job */
260 /* this should be an array -
261 we just use the last channel count for now */
263 /* we will only end up with a channelsused value other than 2
264 if we are encoding to AAC. All other audio encodings will get
267 if (audio->channels == 5 && audio->lfechannels == 1) {
268 /* we have a 5.1 AC-3 source soundtrack */
269 if (job->acodec == HB_ACODEC_FAAC && job->surround) {
270 /* we're going to be encoding to AAC,
271 and have turned on the "preserve 5.1" flag */
272 job->channelsused = 6;
274 /* mix 5.1 down to Dolby Digital (2-channel) for
275 non-AAC audio, or for AAC without 5.1 preservation */
276 job->channelsused = 2;
278 } else if (audio->channels == 1 && audio->lfechannels == 0) {
279 /* we have a 1.0 mono AC-3 source soundtrack */
280 if (job->acodec == HB_ACODEC_FAAC) {
281 /* we're going to be encoding to AAC,
282 so mix down to a mono AAC track */
283 job->channelsused = 1;
285 /* mix up the mono track to stereo for non-AAC formats */
286 job->channelsused = 2;
289 /* mix everything else down to stereo */
290 /* dolby pro-logic will be preserved in deca52.c if necessary
291 by referring to the value of job->ac3flags stored below */
292 job->channelsused = 2;
295 /* remember the actual number of channels and lfe channels */
296 /* again, we are using the last channel's count for now */
297 job->channels = audio->channels;
298 job->lfechannels = audio->lfechannels;
300 /* remember the AC3 flags for future reference */
301 /* again, we are using the last channel's flags for now */
302 job->ac3flags = audio->ac3flags;
306 /* Init read & write threads */
307 job->reader = hb_reader_init( job );
309 hb_log( " + output: %s", job->file );
310 job->muxer = hb_muxer_init( job );
314 /* Launch processing threads */
315 for( i = 1; i < hb_list_count( job->list_work ); i++ )
317 w = hb_list_item( job->list_work, i );
318 w->done = &job->done;
319 w->thread_sleep_interval = 10;
321 w->thread = hb_thread_init( w->name, work_loop, w,
326 w = hb_list_item( job->list_work, 0 );
327 w->thread_sleep_interval = 50;
331 if( w->work( w, NULL, NULL ) == HB_WORK_DONE )
336 !hb_fifo_size( job->fifo_sync ) &&
337 !hb_fifo_size( job->fifo_render ) &&
338 hb_fifo_size( job->fifo_mpeg4 ) < 2 )
342 hb_snooze( w->thread_sleep_interval );
344 hb_list_rem( job->list_work, w );
348 /* Close work objects */
349 while( ( w = hb_list_item( job->list_work, 0 ) ) )
351 hb_list_rem( job->list_work, w );
352 hb_thread_close( &w->thread );
356 /* Stop read & write threads */
357 hb_thread_close( &job->reader );
358 hb_thread_close( &job->muxer );
361 hb_fifo_close( &job->fifo_mpeg2 );
362 hb_fifo_close( &job->fifo_raw );
363 hb_fifo_close( &job->fifo_sync );
364 hb_fifo_close( &job->fifo_render );
365 hb_fifo_close( &job->fifo_mpeg4 );
368 hb_fifo_close( &subtitle->fifo_in );
369 hb_fifo_close( &subtitle->fifo_raw );
371 for( i = 0; i < hb_list_count( title->list_audio ); i++ )
373 audio = hb_list_item( title->list_audio, i );
374 hb_fifo_close( &audio->fifo_in );
375 hb_fifo_close( &audio->fifo_raw );
376 hb_fifo_close( &audio->fifo_sync );
377 hb_fifo_close( &audio->fifo_out );
382 * Performs the work objects specific work function.
383 * Loops calling work function for associated work object. Sleeps when fifo is full.
384 * Monitors work done indicator.
385 * Exits loop when work indiactor is set.
386 * @param _w Handle to work object.
388 static void work_loop( void * _w )
390 hb_work_object_t * w = _w;
391 hb_buffer_t * buf_in, * buf_out;
396 hb_lock( job->pause );
397 hb_unlock( job->pause );
399 if( hb_fifo_is_full( w->fifo_out ) ||
400 // if( (hb_fifo_percent_full( w->fifo_out ) > 0.8) ||
401 !( buf_in = hb_fifo_get( w->fifo_in ) ) )
403 hb_snooze( w->thread_sleep_interval );
404 // w->thread_sleep_interval += 1;
407 // w->thread_sleep_interval = MAX(1, (w->thread_sleep_interval - 1));
409 w->work( w, &buf_in, &buf_out );
412 hb_buffer_close( &buf_in );
416 hb_fifo_push( w->fifo_out, buf_out );