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. */
8 #include "a52dec/a52.h"
20 static void work_func();
21 static void do_job( hb_job_t
*, int cpu_count
);
22 static void work_loop( void * );
25 * Allocates work object and launches work thread with work_func.
26 * @param jobs Handle to hb_list_t.
27 * @param cpu_count Humber of CPUs found in system.
28 * @param die Handle to user inititated exit indicator.
29 * @param error Handle to error indicator.
31 hb_thread_t
* hb_work_init( hb_list_t
* jobs
, int cpu_count
,
32 volatile int * die
, int * error
)
34 hb_work_t
* work
= calloc( sizeof( hb_work_t
), 1 );
37 work
->cpu_count
= cpu_count
;
41 return hb_thread_init( "work", work_func
, work
, HB_LOW_PRIORITY
);
45 * Iterates through job list and calls do_job for each job.
46 * @param _work Handle work object.
48 static void work_func( void * _work
)
50 hb_work_t
* work
= _work
;
53 hb_log( "%d job(s) to process", hb_list_count( work
->jobs
) );
55 while( !*work
->die
&& ( job
= hb_list_item( work
->jobs
, 0 ) ) )
57 hb_list_rem( work
->jobs
, job
);
59 do_job( job
, work
->cpu_count
);
62 *(work
->error
) = HB_ERROR_NONE
;
67 static hb_work_object_t
* getWork( int id
)
70 for( w
= hb_objects
; w
; w
= w
->next
)
81 * Job initialization rountine.
83 * Creates work objects for synchronizer, video decoder, video renderer, video decoder, audio decoder, audio encoder, reader, muxer.
84 * Launches thread for each work object with work_loop.
85 * Loops while monitoring status of work threads and fifos.
86 * Exits loop when conversion is done and fifos are empty.
87 * Closes threads and frees fifos.
88 * @param job Handle work hb_job_t.
89 * @param cpu_count number of CPUs found in system.
91 static void do_job( hb_job_t
* job
, int cpu_count
)
97 /* FIXME: This feels really hackish, anything better? */
98 hb_work_object_t
* audio_w
= NULL
;
101 hb_subtitle_t
* subtitle
;
103 unsigned int subtitle_highest
= 0;
104 unsigned int subtitle_highest_id
= 0;
105 unsigned int subtitle_lowest
= -1;
106 unsigned int subtitle_lowest_id
= 0;
107 unsigned int subtitle_hit
= 0;
111 job
->list_work
= hb_list_init();
113 hb_log( "starting job" );
114 hb_log( " + device %s", title
->dvd
);
115 hb_log( " + title %d, chapter(s) %d to %d", title
->index
,
116 job
->chapter_start
, job
->chapter_end
);
117 if ( job
->pixel_ratio
== 1 )
119 /* Correct the geometry of the output movie when using PixelRatio */
120 job
->height
=title
->height
-job
->crop
[0]-job
->crop
[1];
121 job
->width
=title
->width
-job
->crop
[2]-job
->crop
[3];
124 /* Keep width and height within these boundaries */
125 if (job
->maxHeight
&& (job
->height
> job
->maxHeight
) )
127 job
->height
= job
->maxHeight
;
128 hb_fix_aspect( job
, HB_KEEP_HEIGHT
);
129 hb_log("Height out of bounds, scaling down to %i", job
->maxHeight
);
130 hb_log("New dimensions %i * %i", job
->width
, job
->height
);
132 if (job
->maxWidth
&& (job
->width
> job
->maxWidth
) )
134 job
->width
= job
->maxWidth
;
135 hb_fix_aspect( job
, HB_KEEP_WIDTH
);
136 hb_log("Width out of bounds, scaling down to %i", job
->maxWidth
);
137 hb_log("New dimensions %i * %i", job
->width
, job
->height
);
140 hb_log( " + %dx%d -> %dx%d, crop %d/%d/%d/%d",
141 title
->width
, title
->height
, job
->width
, job
->height
,
142 job
->crop
[0], job
->crop
[1], job
->crop
[2], job
->crop
[3] );
143 hb_log( " + grayscale %s", job
->grayscale
? "on" : "off" );
147 for( i
= 0; i
< hb_list_count( job
->filters
); i
++ )
149 hb_filter_object_t
* filter
= hb_list_item( job
->filters
, i
);
150 hb_log(" + filter: %s", filter
->name
);
151 if (filter
->settings
)
152 hb_log(" + settings: %s", filter
->settings
);
154 hb_log(" + settings: default");
158 if( job
->vquality
>= 0.0 && job
->vquality
<= 1.0 )
160 hb_log( " + %.3f fps, video quality %.2f", (float) job
->vrate
/
161 (float) job
->vrate_base
, job
->vquality
);
165 hb_log( " + %.3f fps, video bitrate %d kbps, pass %d",
166 (float) job
->vrate
/ (float) job
->vrate_base
,
167 job
->vbitrate
, job
->pass
);
169 hb_log (" + PixelRatio: %d, width:%d, height: %d",job
->pixel_ratio
,job
->width
, job
->height
);
170 job
->fifo_mpeg2
= hb_fifo_init( 2048 );
171 job
->fifo_raw
= hb_fifo_init( 8 );
172 job
->fifo_sync
= hb_fifo_init( 8 );
173 job
->fifo_render
= hb_fifo_init( 8 );
174 job
->fifo_mpeg4
= hb_fifo_init( 8 );
176 /* Synchronization */
177 hb_list_add( job
->list_work
, ( w
= getWork( WORK_SYNC
) ) );
182 hb_list_add( job
->list_work
, ( w
= getWork( WORK_DECMPEG2
) ) );
183 w
->fifo_in
= job
->fifo_mpeg2
;
184 w
->fifo_out
= job
->fifo_raw
;
187 hb_list_add( job
->list_work
, ( w
= getWork( WORK_RENDER
) ) );
188 w
->fifo_in
= job
->fifo_sync
;
189 w
->fifo_out
= job
->fifo_render
;
192 switch( job
->vcodec
)
194 case HB_VCODEC_FFMPEG
:
195 hb_log( " + encoder FFmpeg" );
196 w
= getWork( WORK_ENCAVCODEC
);
199 hb_log( " + encoder XviD" );
200 w
= getWork( WORK_ENCXVID
);
203 hb_log( " + encoder x264" );
204 w
= getWork( WORK_ENCX264
);
207 w
->fifo_in
= job
->fifo_render
;
208 w
->fifo_out
= job
->fifo_mpeg4
;
209 w
->config
= &job
->config
;
211 hb_list_add( job
->list_work
, w
);
213 if( job
->select_subtitle
&& !job
->subtitle_scan
)
216 * Must be second pass of a two pass with subtitle scan enabled, so
217 * add the subtitle that we found on the first pass for use in this
220 hb_list_add( title
->list_subtitle
, *( job
->select_subtitle
) );
223 for( i
=0; i
< hb_list_count(title
->list_subtitle
); i
++ )
225 subtitle
= hb_list_item( title
->list_subtitle
, i
);
229 hb_log( " + subtitle %x, %s", subtitle
->id
, subtitle
->lang
);
231 subtitle
->fifo_in
= hb_fifo_init( 8 );
232 subtitle
->fifo_raw
= hb_fifo_init( 8 );
234 if (!job
->subtitle_scan
) {
236 * Don't add threads for subtitles when we are scanning
238 hb_list_add( job
->list_work
, ( w
= getWork( WORK_DECSUB
) ) );
239 w
->fifo_in
= subtitle
->fifo_in
;
240 w
->fifo_out
= subtitle
->fifo_raw
;
245 if( job
->acodec
& HB_ACODEC_AC3
)
247 hb_log( " + audio AC3 passthrough" );
251 hb_log( " + audio %d kbps, %d Hz", job
->abitrate
, job
->arate
);
252 hb_log( " + encoder %s", ( job
->acodec
& HB_ACODEC_FAAC
) ?
253 "faac" : ( ( job
->acodec
& HB_ACODEC_LAME
) ? "lame" :
257 /* if we are doing AC3 passthru, then remove any non-AC3 audios from the job */
258 /* otherwise, Bad Things will happen */
259 for( i
= 0; i
< hb_list_count( title
->list_audio
); )
261 audio
= hb_list_item( title
->list_audio
, i
);
262 if( ( job
->acodec
& HB_ACODEC_AC3
) && ( audio
->codec
!= HB_ACODEC_AC3
) )
264 hb_list_rem( title
->list_audio
, audio
);
271 for( i
= 0; i
< hb_list_count( title
->list_audio
); i
++ )
273 audio
= hb_list_item( title
->list_audio
, i
);
274 hb_log( " + %x, %s", audio
->id
, audio
->lang
);
276 /* sense-check the current mixdown options */
278 /* log the requested mixdown */
279 for (j
= 0; j
< hb_audio_mixdowns_count
; j
++) {
280 if (hb_audio_mixdowns
[j
].amixdown
== job
->audio_mixdowns
[i
]) {
281 hb_log( " + Requested mixdown: %s (%s)", hb_audio_mixdowns
[j
].human_readable_name
, hb_audio_mixdowns
[j
].internal_name
);
286 /* sense-check the requested mixdown */
288 /* audioCodecsSupportMono and audioCodecsSupport6Ch are the same for now,
289 but this may change in the future, so they are separated for flexibility */
290 int audioCodecsSupportMono
= ((audio
->codec
== HB_ACODEC_AC3
||
291 audio
->codec
== HB_ACODEC_DCA
) && job
->acodec
== HB_ACODEC_FAAC
);
292 int audioCodecsSupport6Ch
= ((audio
->codec
== HB_ACODEC_AC3
||
293 audio
->codec
== HB_ACODEC_DCA
) && job
->acodec
== HB_ACODEC_FAAC
);
295 /* find out what the format of our source audio is */
296 switch (audio
->input_channel_layout
& HB_INPUT_CH_LAYOUT_DISCRETE_NO_LFE_MASK
) {
299 case HB_INPUT_CH_LAYOUT_MONO
:
300 /* regardless of what stereo mixdown we've requested, a mono source always get mixed down
301 to mono if we can, and mixed up to stereo if we can't */
302 if (job
->audio_mixdowns
[i
] == HB_AMIXDOWN_MONO
&& audioCodecsSupportMono
== 1) {
303 job
->audio_mixdowns
[i
] = HB_AMIXDOWN_MONO
;
305 job
->audio_mixdowns
[i
] = HB_AMIXDOWN_STEREO
;
310 case HB_INPUT_CH_LAYOUT_STEREO
:
311 /* if we've requested a mono mixdown, and it is supported, then do the mix */
312 /* use stereo if not supported */
313 if (job
->audio_mixdowns
[i
] == HB_AMIXDOWN_MONO
&& audioCodecsSupportMono
== 0) {
314 job
->audio_mixdowns
[i
] = HB_AMIXDOWN_STEREO
;
315 /* otherwise, preserve stereo regardless of if we requested something higher */
316 } else if (job
->audio_mixdowns
[i
] > HB_AMIXDOWN_STEREO
) {
317 job
->audio_mixdowns
[i
] = HB_AMIXDOWN_STEREO
;
321 /* dolby (DPL1 aka Dolby Surround = 4.0 matrix-encoded) input */
322 /* the A52 flags don't allow for a way to distinguish between DPL1 and DPL2 on a DVD,
323 so we always assume a DPL1 source for A52_DOLBY */
324 case HB_INPUT_CH_LAYOUT_DOLBY
:
325 /* if we've requested a mono mixdown, and it is supported, then do the mix */
326 /* preserve dolby if not supported */
327 if (job
->audio_mixdowns
[i
] == HB_AMIXDOWN_MONO
&& audioCodecsSupportMono
== 0) {
328 job
->audio_mixdowns
[i
] = HB_AMIXDOWN_DOLBY
;
329 /* otherwise, preserve dolby even if we requested something higher */
330 /* a stereo mixdown will still be honoured here */
331 } else if (job
->audio_mixdowns
[i
] > HB_AMIXDOWN_DOLBY
) {
332 job
->audio_mixdowns
[i
] = HB_AMIXDOWN_DOLBY
;
337 case HB_INPUT_CH_LAYOUT_3F2R
:
338 /* if we've requested a mono mixdown, and it is supported, then do the mix */
339 /* use dpl2 if not supported */
340 if (job
->audio_mixdowns
[i
] == HB_AMIXDOWN_MONO
&& audioCodecsSupportMono
== 0) {
341 job
->audio_mixdowns
[i
] = HB_AMIXDOWN_DOLBYPLII
;
343 /* check if we have 3F2R input and also have an LFE - i.e. we have a 5.1 source) */
344 if (audio
->input_channel_layout
& HB_INPUT_CH_LAYOUT_HAS_LFE
) {
345 /* we have a 5.1 source */
346 /* if we requested 6ch, but our audio format doesn't support it, then mix to DPLII instead */
347 if (job
->audio_mixdowns
[i
] == HB_AMIXDOWN_6CH
&& audioCodecsSupport6Ch
== 0) {
348 job
->audio_mixdowns
[i
] = HB_AMIXDOWN_DOLBYPLII
;
351 /* we have a 5.0 source, so we can't do 6ch conversion
352 default to DPL II instead */
353 if (job
->audio_mixdowns
[i
] > HB_AMIXDOWN_DOLBYPLII
) {
354 job
->audio_mixdowns
[i
] = HB_AMIXDOWN_DOLBYPLII
;
358 /* all other mixdowns will have been preserved here */
362 case HB_INPUT_CH_LAYOUT_3F1R
:
363 /* if we've requested a mono mixdown, and it is supported, then do the mix */
364 /* use dpl1 if not supported */
365 if (job
->audio_mixdowns
[i
] == HB_AMIXDOWN_MONO
&& audioCodecsSupportMono
== 0) {
366 job
->audio_mixdowns
[i
] = HB_AMIXDOWN_DOLBY
;
368 /* we have a 4.0 or 4.1 source, so we can't do DPLII or 6ch conversion
369 default to DPL I instead */
370 if (job
->audio_mixdowns
[i
] > HB_AMIXDOWN_DOLBY
) {
371 job
->audio_mixdowns
[i
] = HB_AMIXDOWN_DOLBY
;
374 /* all other mixdowns will have been preserved here */
378 /* if we've requested a mono mixdown, and it is supported, then do the mix */
379 if (job
->audio_mixdowns
[i
] == HB_AMIXDOWN_MONO
&& audioCodecsSupportMono
== 1) {
380 job
->audio_mixdowns
[i
] = HB_AMIXDOWN_MONO
;
381 /* mix everything else down to stereo */
383 job
->audio_mixdowns
[i
] = HB_AMIXDOWN_STEREO
;
388 /* log the output mixdown */
389 for (j
= 0; j
< hb_audio_mixdowns_count
; j
++) {
390 if (hb_audio_mixdowns
[j
].amixdown
== job
->audio_mixdowns
[i
]) {
391 hb_log( " + Actual mixdown: %s (%s)", hb_audio_mixdowns
[j
].human_readable_name
, hb_audio_mixdowns
[j
].internal_name
);
396 /* we now know we have a valid mixdown for the input source and the audio output format */
397 /* remember the mixdown for this track */
398 audio
->amixdown
= job
->audio_mixdowns
[i
];
400 audio
->config
.vorbis
.language
= audio
->lang_simple
;
402 /* set up the audio work structures */
403 audio
->fifo_in
= hb_fifo_init( 2048 );
404 audio
->fifo_raw
= hb_fifo_init( 8 );
405 audio
->fifo_sync
= hb_fifo_init( 8 );
406 audio
->fifo_out
= hb_fifo_init( 8 );
408 switch( audio
->codec
)
411 w
= getWork( WORK_DECA52
);
414 w
= getWork( WORK_DECDCA
);
417 w
= getWork( WORK_DECAVCODEC
);
420 w
= getWork( WORK_DECLPCM
);
423 w
->fifo_in
= audio
->fifo_in
;
424 w
->fifo_out
= audio
->fifo_raw
;
425 w
->config
= &audio
->config
;
426 w
->amixdown
= audio
->amixdown
;
427 w
->source_acodec
= audio
->codec
;
429 /* FIXME: This feels really hackish, anything better? */
430 audio_w
= calloc( sizeof( hb_work_object_t
), 1 );
431 audio_w
= memcpy( audio_w
, w
, sizeof( hb_work_object_t
));
433 hb_list_add( job
->list_work
, audio_w
);
435 switch( job
->acodec
)
438 w
= getWork( WORK_ENCFAAC
);
441 w
= getWork( WORK_ENCLAME
);
443 case HB_ACODEC_VORBIS
:
444 w
= getWork( WORK_ENCVORBIS
);
448 if( job
->acodec
!= HB_ACODEC_AC3
)
450 w
->fifo_in
= audio
->fifo_sync
;
451 w
->fifo_out
= audio
->fifo_out
;
452 w
->config
= &audio
->config
;
453 w
->amixdown
= audio
->amixdown
;
454 w
->source_acodec
= audio
->codec
;
456 /* FIXME: This feels really hackish, anything better? */
457 audio_w
= calloc( sizeof( hb_work_object_t
), 1 );
458 audio_w
= memcpy( audio_w
, w
, sizeof( hb_work_object_t
));
460 hb_list_add( job
->list_work
, audio_w
);
466 /* Init read & write threads */
467 job
->reader
= hb_reader_init( job
);
469 hb_log( " + output: %s", job
->file
);
470 job
->muxer
= hb_muxer_init( job
);
474 /* Launch processing threads */
475 for( i
= 1; i
< hb_list_count( job
->list_work
); i
++ )
477 w
= hb_list_item( job
->list_work
, i
);
478 w
->done
= &job
->done
;
479 w
->thread_sleep_interval
= 10;
481 w
->thread
= hb_thread_init( w
->name
, work_loop
, w
,
486 w
= hb_list_item( job
->list_work
, 0 );
487 w
->thread_sleep_interval
= 50;
491 if( w
->work( w
, NULL
, NULL
) == HB_WORK_DONE
)
496 !hb_fifo_size( job
->fifo_sync
) &&
497 !hb_fifo_size( job
->fifo_render
) &&
498 !hb_fifo_size( job
->fifo_mpeg4
) )
502 hb_snooze( w
->thread_sleep_interval
);
504 hb_list_rem( job
->list_work
, w
);
508 /* Close work objects */
509 while( ( w
= hb_list_item( job
->list_work
, 0 ) ) )
511 hb_list_rem( job
->list_work
, w
);
512 hb_thread_close( &w
->thread
);
515 /* FIXME: This feels really hackish, anything better? */
516 if ( w
->id
== WORK_DECA52
||
517 w
->id
== WORK_DECDCA
||
518 w
->id
== WORK_DECLPCM
||
519 w
->id
== WORK_ENCFAAC
||
520 w
->id
== WORK_ENCLAME
||
521 w
->id
== WORK_ENCVORBIS
)
528 hb_list_close( &job
->list_work
);
530 /* Stop read & write threads */
531 hb_thread_close( &job
->reader
);
532 hb_thread_close( &job
->muxer
);
535 hb_fifo_close( &job
->fifo_mpeg2
);
536 hb_fifo_close( &job
->fifo_raw
);
537 hb_fifo_close( &job
->fifo_sync
);
538 hb_fifo_close( &job
->fifo_render
);
539 hb_fifo_close( &job
->fifo_mpeg4
);
540 for (i
=0; i
< hb_list_count(title
->list_subtitle
); i
++) {
541 subtitle
= hb_list_item( title
->list_subtitle
, i
);
544 hb_fifo_close( &subtitle
->fifo_in
);
545 hb_fifo_close( &subtitle
->fifo_raw
);
548 for( i
= 0; i
< hb_list_count( title
->list_audio
); i
++ )
550 audio
= hb_list_item( title
->list_audio
, i
);
551 hb_fifo_close( &audio
->fifo_in
);
552 hb_fifo_close( &audio
->fifo_raw
);
553 hb_fifo_close( &audio
->fifo_sync
);
554 hb_fifo_close( &audio
->fifo_out
);
557 if( job
->subtitle_scan
)
560 * Before closing the title print out our subtitle stats if we need to
561 * Find the highest and lowest.
563 for( i
=0; i
< hb_list_count( title
->list_subtitle
); i
++ )
565 subtitle
= hb_list_item( title
->list_subtitle
, i
);
566 hb_log( "Subtitle stream 0x%x '%s': %d hits",
567 subtitle
->id
, subtitle
->lang
, subtitle
->hits
);
568 if( subtitle
->hits
> subtitle_highest
)
570 subtitle_highest
= subtitle
->hits
;
571 subtitle_highest_id
= subtitle
->id
;
574 if( subtitle
->hits
< subtitle_lowest
)
576 subtitle_lowest
= subtitle
->hits
;
577 subtitle_lowest_id
= subtitle
->id
;
581 if( job
->native_language
) {
583 * We still have a native_language, so the audio and subtitles are
584 * different, so in this case it is a foreign film and we want to
585 * select the subtitle with the highest hits in our language.
587 subtitle_hit
= subtitle_highest_id
;
588 hb_log( "Found a native-language subtitle id 0x%x", subtitle_hit
);
590 if( subtitle_lowest
< subtitle_highest
)
593 * OK we have more than one, and the lowest is lower, but how much
594 * lower to qualify for turning it on by default?
596 * Let's say 10% as a default.
598 if( subtitle_lowest
< ( subtitle_highest
* 0.1 ) )
600 subtitle_hit
= subtitle_lowest_id
;
601 hb_log( "Found a subtitle candidate id 0x%x",
604 hb_log( "No candidate subtitle detected during subtitle-scan");
610 if( job
->select_subtitle
)
612 if( job
->subtitle_scan
)
614 for( i
=0; i
< hb_list_count( title
->list_subtitle
); i
++ )
616 subtitle
= hb_list_item( title
->list_subtitle
, i
);
617 if( subtitle
->id
= subtitle_hit
)
619 hb_list_rem( title
->list_subtitle
, subtitle
);
620 *( job
->select_subtitle
) = subtitle
;
625 * Must be the second pass - we don't need this anymore.
627 free( job
->select_subtitle
);
628 job
->select_subtitle
= NULL
;
632 hb_title_close( &job
->title
);
637 * Performs the work objects specific work function.
638 * Loops calling work function for associated work object. Sleeps when fifo is full.
639 * Monitors work done indicator.
640 * Exits loop when work indiactor is set.
641 * @param _w Handle to work object.
643 static void work_loop( void * _w
)
645 hb_work_object_t
* w
= _w
;
646 hb_buffer_t
* buf_in
, * buf_out
;
651 hb_lock( job
->pause
);
652 hb_unlock( job
->pause
);
654 if( hb_fifo_is_full( w
->fifo_out
) ||
655 // if( (hb_fifo_percent_full( w->fifo_out ) > 0.8) ||
656 !( buf_in
= hb_fifo_get( w
->fifo_in
) ) )
658 hb_snooze( w
->thread_sleep_interval
);
659 // w->thread_sleep_interval += 1;
662 // w->thread_sleep_interval = MAX(1, (w->thread_sleep_interval - 1));
664 w
->work( w
, &buf_in
, &buf_out
);
666 // Propogate any chapter breaks for the worker
667 if( buf_in
&& buf_out
&& buf_in
->new_chap
)
669 printf("WORK: Copying Chapter Break\n");
670 buf_out
->new_chap
= 1;
675 hb_buffer_close( &buf_in
);
679 hb_fifo_push( w
->fifo_out
, buf_out
);