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"
14 hb_job_t
** current_job
;
21 static void work_func();
22 static void do_job( hb_job_t
*, int cpu_count
);
23 static void work_loop( void * );
25 #define FIFO_CPU_MULT 8
28 * Allocates work object and launches work thread with work_func.
29 * @param jobs Handle to hb_list_t.
30 * @param cpu_count Humber of CPUs found in system.
31 * @param die Handle to user inititated exit indicator.
32 * @param error Handle to error indicator.
34 hb_thread_t
* hb_work_init( hb_list_t
* jobs
, int cpu_count
,
35 volatile int * die
, int * error
, hb_job_t
** job
)
37 hb_work_t
* work
= calloc( sizeof( hb_work_t
), 1 );
40 work
->current_job
= job
;
41 work
->cpu_count
= cpu_count
;
45 return hb_thread_init( "work", work_func
, work
, HB_LOW_PRIORITY
);
49 * Iterates through job list and calls do_job for each job.
50 * @param _work Handle work object.
52 static void work_func( void * _work
)
54 hb_work_t
* work
= _work
;
57 hb_log( "%d job(s) to process", hb_list_count( work
->jobs
) );
59 while( !*work
->die
&& ( job
= hb_list_item( work
->jobs
, 0 ) ) )
61 hb_list_rem( work
->jobs
, job
);
63 *(work
->current_job
) = job
;
64 do_job( job
, work
->cpu_count
);
65 *(work
->current_job
) = NULL
;
68 *(work
->error
) = HB_ERROR_NONE
;
73 static hb_work_object_t
* getWork( int id
)
76 for( w
= hb_objects
; w
; w
= w
->next
)
87 * Job initialization rountine.
89 * Creates work objects for synchronizer, video decoder, video renderer, video decoder, audio decoder, audio encoder, reader, muxer.
90 * Launches thread for each work object with work_loop.
91 * Loops while monitoring status of work threads and fifos.
92 * Exits loop when conversion is done and fifos are empty.
93 * Closes threads and frees fifos.
94 * @param job Handle work hb_job_t.
95 * @param cpu_count number of CPUs found in system.
97 static void do_job( hb_job_t
* job
, int cpu_count
)
101 hb_work_object_t
* w
;
103 /* FIXME: This feels really hackish, anything better? */
104 hb_work_object_t
* audio_w
= NULL
;
105 hb_work_object_t
* sub_w
= NULL
;
108 hb_subtitle_t
* subtitle
;
110 unsigned int subtitle_highest
= 0;
111 unsigned int subtitle_highest_id
= 0;
112 unsigned int subtitle_lowest
= -1;
113 unsigned int subtitle_lowest_id
= 0;
114 unsigned int subtitle_forced_id
= 0;
115 unsigned int subtitle_hit
= 0;
119 job
->list_work
= hb_list_init();
121 hb_log( "starting job" );
122 hb_log( " + device %s", title
->dvd
);
123 hb_log( " + title %d, chapter(s) %d to %d", title
->index
,
124 job
->chapter_start
, job
->chapter_end
);
125 if ( job
->pixel_ratio
== 1 )
127 /* Correct the geometry of the output movie when using PixelRatio */
128 job
->height
=title
->height
-job
->crop
[0]-job
->crop
[1];
129 job
->width
=title
->width
-job
->crop
[2]-job
->crop
[3];
131 else if ( job
->pixel_ratio
== 2 )
134 /* While keeping the DVD storage aspect, resize the job width and height
135 so they fit into the user's specified dimensions. */
136 hb_set_anamorphic_size(job
, &job
->width
, &job
->height
, &job
->pixel_aspect_width
, &job
->pixel_aspect_height
);
139 /* Keep width and height within these boundaries,
140 but ignore for "loose" anamorphic encodes, for
141 which this stuff is covered in the pixel_ratio
142 section right above.*/
143 if (job
->maxHeight
&& (job
->height
> job
->maxHeight
) && (job
->pixel_ratio
!= 2))
145 job
->height
= job
->maxHeight
;
146 hb_fix_aspect( job
, HB_KEEP_HEIGHT
);
147 hb_log("Height out of bounds, scaling down to %i", job
->maxHeight
);
148 hb_log("New dimensions %i * %i", job
->width
, job
->height
);
150 if (job
->maxWidth
&& (job
->width
> job
->maxWidth
) && (job
->pixel_ratio
!= 2))
152 job
->width
= job
->maxWidth
;
153 hb_fix_aspect( job
, HB_KEEP_WIDTH
);
154 hb_log("Width out of bounds, scaling down to %i", job
->maxWidth
);
155 hb_log("New dimensions %i * %i", job
->width
, job
->height
);
158 hb_log( " + %dx%d -> %dx%d, crop %d/%d/%d/%d",
159 title
->width
, title
->height
, job
->width
, job
->height
,
160 job
->crop
[0], job
->crop
[1], job
->crop
[2], job
->crop
[3] );
162 if ( job
->grayscale
)
163 hb_log( " + grayscale mode" );
167 int detelecine_present
= 0;
170 for( i
= 0; i
< hb_list_count( job
->filters
); i
++ )
172 hb_filter_object_t
* filter
= hb_list_item( job
->filters
, i
);
173 if (filter
->id
== FILTER_DETELECINE
)
174 detelecine_present
= 1;
178 if (!detelecine_present
)
180 /* Allocate the filter. */
181 hb_filter_object_t
* filter
= malloc( sizeof( hb_filter_object_t
) );
183 /* Copy in the contents of the detelecine struct. */
184 memcpy( filter
, &hb_filter_detelecine
, sizeof( hb_filter_object_t
) );
186 /* Set the name to a copy of the template name so render.c has something to free. */
187 filter
->name
= strdup(hb_filter_detelecine
.name
);
189 /* Add it to the list. */
190 hb_list_add( job
->filters
, filter
);
192 hb_log("work: VFR mode -- adding detelecine filter");
198 hb_log(" + filters");
199 for( i
= 0; i
< hb_list_count( job
->filters
); i
++ )
201 hb_filter_object_t
* filter
= hb_list_item( job
->filters
, i
);
202 if (filter
->settings
)
203 hb_log(" + %s (%s)", filter
->name
, filter
->settings
);
205 hb_log(" + %s (default settings)", filter
->name
);
211 hb_log( " + video frame rate: variable (detected %.3f fps)", (float) job
->vrate
/
212 (float) job
->vrate_base
);
216 hb_log( " + video frame rate: %.3f fps", (float) job
->vrate
/ (float) job
->vrate_base
);
219 if( job
->vquality
>= 0.0 && job
->vquality
<= 1.0 )
221 hb_log( " + video quality %.2f", job
->vquality
);
225 hb_log( " + video bitrate %d kbps, pass %d", job
->vbitrate
, job
->pass
);
228 hb_log (" + PixelRatio: %d, width:%d, height: %d",job
->pixel_ratio
,job
->width
, job
->height
);
229 job
->fifo_mpeg2
= hb_fifo_init( 2048 );
230 job
->fifo_raw
= hb_fifo_init( FIFO_CPU_MULT
* cpu_count
);
231 job
->fifo_sync
= hb_fifo_init( FIFO_CPU_MULT
* cpu_count
);
232 job
->fifo_render
= hb_fifo_init( FIFO_CPU_MULT
* cpu_count
);
233 job
->fifo_mpeg4
= hb_fifo_init( FIFO_CPU_MULT
* cpu_count
);
235 /* Synchronization */
236 hb_list_add( job
->list_work
, ( w
= getWork( WORK_SYNC
) ) );
241 hb_list_add( job
->list_work
, ( w
= getWork( WORK_DECMPEG2
) ) );
242 w
->fifo_in
= job
->fifo_mpeg2
;
243 w
->fifo_out
= job
->fifo_raw
;
246 hb_list_add( job
->list_work
, ( w
= getWork( WORK_RENDER
) ) );
247 w
->fifo_in
= job
->fifo_sync
;
248 w
->fifo_out
= job
->fifo_render
;
251 switch( job
->vcodec
)
253 case HB_VCODEC_FFMPEG
:
254 hb_log( " + encoder FFmpeg" );
255 w
= getWork( WORK_ENCAVCODEC
);
258 hb_log( " + encoder XviD" );
259 w
= getWork( WORK_ENCXVID
);
262 hb_log( " + encoder x264" );
263 if( job
->x264opts
!= NULL
&& *job
->x264opts
!= '\0' )
264 hb_log( " + x264 options: %s", job
->x264opts
);
265 w
= getWork( WORK_ENCX264
);
268 w
->fifo_in
= job
->fifo_render
;
269 w
->fifo_out
= job
->fifo_mpeg4
;
270 w
->config
= &job
->config
;
272 hb_list_add( job
->list_work
, w
);
274 if( job
->select_subtitle
&& !job
->indepth_scan
)
277 * Must be second pass of a two pass with subtitle scan enabled, so
278 * add the subtitle that we found on the first pass for use in this
281 if (*(job
->select_subtitle
))
283 hb_list_add( title
->list_subtitle
, *( job
->select_subtitle
) );
287 for( i
=0; i
< hb_list_count(title
->list_subtitle
); i
++ )
289 subtitle
= hb_list_item( title
->list_subtitle
, i
);
293 hb_log( " + subtitle %x, %s", subtitle
->id
, subtitle
->lang
);
295 subtitle
->fifo_in
= hb_fifo_init( FIFO_CPU_MULT
* cpu_count
);
296 subtitle
->fifo_raw
= hb_fifo_init( FIFO_CPU_MULT
* cpu_count
);
299 * Disable forced subtitles if we didn't find any in the scan
300 * so that we display normal subtitles instead.
302 * select_subtitle implies that we did a scan.
304 if( !job
->indepth_scan
&& job
->subtitle_force
&&
305 job
->select_subtitle
)
307 if( subtitle
->forced_hits
== 0 )
309 job
->subtitle_force
= 0;
313 if (!job
->indepth_scan
|| job
->subtitle_force
) {
315 * Don't add threads for subtitles when we are scanning, unless
316 * looking for forced subtitles.
321 * Need to copy the prior subtitle structure so that we
322 * don't overwrite the fifos.
324 sub_w
= calloc( sizeof( hb_work_object_t
), 1 );
325 sub_w
= memcpy( sub_w
, w
, sizeof( hb_work_object_t
));
327 w
= sub_w
= getWork( WORK_DECSUB
);
329 hb_list_add( job
->list_work
, sub_w
);
330 sub_w
->fifo_in
= subtitle
->fifo_in
;
331 sub_w
->fifo_out
= subtitle
->fifo_raw
;
336 if( job
->acodec
& HB_ACODEC_AC3
)
338 hb_log( " + audio AC3 passthrough" );
342 hb_log( " + audio %d kbps, %d Hz", job
->abitrate
, job
->arate
);
343 hb_log( " + encoder %s", ( job
->acodec
& HB_ACODEC_FAAC
) ?
344 "faac" : ( ( job
->acodec
& HB_ACODEC_LAME
) ? "lame" :
348 if ( job
->dynamic_range_compression
)
349 hb_log(" + dynamic range compression: %f", job
->dynamic_range_compression
);
351 /* if we are doing AC3 passthru, then remove any non-AC3 audios from the job */
352 /* otherwise, Bad Things will happen */
353 for( i
= 0; i
< hb_list_count( title
->list_audio
); )
355 audio
= hb_list_item( title
->list_audio
, i
);
356 if( ( job
->acodec
& HB_ACODEC_AC3
) && ( audio
->codec
!= HB_ACODEC_AC3
) )
358 hb_list_rem( title
->list_audio
, audio
);
365 for( i
= 0; i
< hb_list_count( title
->list_audio
); i
++ )
367 audio
= hb_list_item( title
->list_audio
, i
);
368 hb_log( " + %x, %s", audio
->id
, audio
->lang
);
370 /* sense-check the current mixdown options */
372 /* log the requested mixdown */
373 for (j
= 0; j
< hb_audio_mixdowns_count
; j
++) {
374 if (hb_audio_mixdowns
[j
].amixdown
== job
->audio_mixdowns
[i
]) {
375 hb_log( " + Requested mixdown: %s (%s)", hb_audio_mixdowns
[j
].human_readable_name
, hb_audio_mixdowns
[j
].internal_name
);
380 /* sense-check the requested mixdown */
382 /* audioCodecsSupportMono and audioCodecsSupport6Ch are the same for now,
383 but this may change in the future, so they are separated for flexibility */
384 int audioCodecsSupportMono
= ((audio
->codec
== HB_ACODEC_AC3
||
385 audio
->codec
== HB_ACODEC_DCA
) && (job
->acodec
== HB_ACODEC_FAAC
|| job
->acodec
== HB_ACODEC_VORBIS
));
386 int audioCodecsSupport6Ch
= ((audio
->codec
== HB_ACODEC_AC3
||
387 audio
->codec
== HB_ACODEC_DCA
) && (job
->acodec
== HB_ACODEC_FAAC
|| job
->acodec
== HB_ACODEC_VORBIS
));
389 /* find out what the format of our source audio is */
390 switch (audio
->input_channel_layout
& HB_INPUT_CH_LAYOUT_DISCRETE_NO_LFE_MASK
) {
393 case HB_INPUT_CH_LAYOUT_MONO
:
394 /* regardless of what stereo mixdown we've requested, a mono source always get mixed down
395 to mono if we can, and mixed up to stereo if we can't */
396 if (job
->audio_mixdowns
[i
] == HB_AMIXDOWN_MONO
&& audioCodecsSupportMono
== 1) {
397 job
->audio_mixdowns
[i
] = HB_AMIXDOWN_MONO
;
399 job
->audio_mixdowns
[i
] = HB_AMIXDOWN_STEREO
;
404 case HB_INPUT_CH_LAYOUT_STEREO
:
405 /* if we've requested a mono mixdown, and it is supported, then do the mix */
406 /* use stereo if not supported */
407 if (job
->audio_mixdowns
[i
] == HB_AMIXDOWN_MONO
&& audioCodecsSupportMono
== 0) {
408 job
->audio_mixdowns
[i
] = HB_AMIXDOWN_STEREO
;
409 /* otherwise, preserve stereo regardless of if we requested something higher */
410 } else if (job
->audio_mixdowns
[i
] > HB_AMIXDOWN_STEREO
) {
411 job
->audio_mixdowns
[i
] = HB_AMIXDOWN_STEREO
;
415 /* dolby (DPL1 aka Dolby Surround = 4.0 matrix-encoded) input */
416 /* the A52 flags don't allow for a way to distinguish between DPL1 and DPL2 on a DVD,
417 so we always assume a DPL1 source for A52_DOLBY */
418 case HB_INPUT_CH_LAYOUT_DOLBY
:
419 /* if we've requested a mono mixdown, and it is supported, then do the mix */
420 /* preserve dolby if not supported */
421 if (job
->audio_mixdowns
[i
] == HB_AMIXDOWN_MONO
&& audioCodecsSupportMono
== 0) {
422 job
->audio_mixdowns
[i
] = HB_AMIXDOWN_DOLBY
;
423 /* otherwise, preserve dolby even if we requested something higher */
424 /* a stereo mixdown will still be honoured here */
425 } else if (job
->audio_mixdowns
[i
] > HB_AMIXDOWN_DOLBY
) {
426 job
->audio_mixdowns
[i
] = HB_AMIXDOWN_DOLBY
;
431 case HB_INPUT_CH_LAYOUT_3F2R
:
432 /* if we've requested a mono mixdown, and it is supported, then do the mix */
433 /* use dpl2 if not supported */
434 if (job
->audio_mixdowns
[i
] == HB_AMIXDOWN_MONO
&& audioCodecsSupportMono
== 0) {
435 job
->audio_mixdowns
[i
] = HB_AMIXDOWN_DOLBYPLII
;
437 /* check if we have 3F2R input and also have an LFE - i.e. we have a 5.1 source) */
438 if (audio
->input_channel_layout
& HB_INPUT_CH_LAYOUT_HAS_LFE
) {
439 /* we have a 5.1 source */
440 /* if we requested 6ch, but our audio format doesn't support it, then mix to DPLII instead */
441 if (job
->audio_mixdowns
[i
] == HB_AMIXDOWN_6CH
&& audioCodecsSupport6Ch
== 0) {
442 job
->audio_mixdowns
[i
] = HB_AMIXDOWN_DOLBYPLII
;
445 /* we have a 5.0 source, so we can't do 6ch conversion
446 default to DPL II instead */
447 if (job
->audio_mixdowns
[i
] > HB_AMIXDOWN_DOLBYPLII
) {
448 job
->audio_mixdowns
[i
] = HB_AMIXDOWN_DOLBYPLII
;
452 /* all other mixdowns will have been preserved here */
456 case HB_INPUT_CH_LAYOUT_3F1R
:
457 /* if we've requested a mono mixdown, and it is supported, then do the mix */
458 /* use dpl1 if not supported */
459 if (job
->audio_mixdowns
[i
] == HB_AMIXDOWN_MONO
&& audioCodecsSupportMono
== 0) {
460 job
->audio_mixdowns
[i
] = HB_AMIXDOWN_DOLBY
;
462 /* we have a 4.0 or 4.1 source, so we can't do DPLII or 6ch conversion
463 default to DPL I instead */
464 if (job
->audio_mixdowns
[i
] > HB_AMIXDOWN_DOLBY
) {
465 job
->audio_mixdowns
[i
] = HB_AMIXDOWN_DOLBY
;
468 /* all other mixdowns will have been preserved here */
472 /* if we've requested a mono mixdown, and it is supported, then do the mix */
473 if (job
->audio_mixdowns
[i
] == HB_AMIXDOWN_MONO
&& audioCodecsSupportMono
== 1) {
474 job
->audio_mixdowns
[i
] = HB_AMIXDOWN_MONO
;
475 /* mix everything else down to stereo */
477 job
->audio_mixdowns
[i
] = HB_AMIXDOWN_STEREO
;
482 /* log the output mixdown */
483 for (j
= 0; j
< hb_audio_mixdowns_count
; j
++) {
484 if (hb_audio_mixdowns
[j
].amixdown
== job
->audio_mixdowns
[i
]) {
485 hb_log( " + Actual mixdown: %s (%s)", hb_audio_mixdowns
[j
].human_readable_name
, hb_audio_mixdowns
[j
].internal_name
);
490 /* we now know we have a valid mixdown for the input source and the audio output format */
491 /* remember the mixdown for this track */
492 audio
->amixdown
= job
->audio_mixdowns
[i
];
494 audio
->config
.vorbis
.language
= audio
->lang_simple
;
496 /* set up the audio work structures */
497 audio
->fifo_in
= hb_fifo_init( 2048 );
498 audio
->fifo_raw
= hb_fifo_init( FIFO_CPU_MULT
* cpu_count
);
499 audio
->fifo_sync
= hb_fifo_init( FIFO_CPU_MULT
* cpu_count
);
500 audio
->fifo_out
= hb_fifo_init( FIFO_CPU_MULT
* cpu_count
);
502 switch( audio
->codec
)
505 w
= getWork( WORK_DECA52
);
508 w
= getWork( WORK_DECDCA
);
511 w
= getWork( WORK_DECAVCODEC
);
514 w
= getWork( WORK_DECLPCM
);
517 w
->fifo_in
= audio
->fifo_in
;
518 w
->fifo_out
= audio
->fifo_raw
;
519 w
->config
= &audio
->config
;
520 w
->amixdown
= audio
->amixdown
;
521 w
->source_acodec
= audio
->codec
;
523 /* FIXME: This feels really hackish, anything better? */
524 audio_w
= calloc( sizeof( hb_work_object_t
), 1 );
525 audio_w
= memcpy( audio_w
, w
, sizeof( hb_work_object_t
));
527 hb_list_add( job
->list_work
, audio_w
);
529 switch( job
->acodec
)
532 w
= getWork( WORK_ENCFAAC
);
535 w
= getWork( WORK_ENCLAME
);
537 case HB_ACODEC_VORBIS
:
538 w
= getWork( WORK_ENCVORBIS
);
542 if( job
->acodec
!= HB_ACODEC_AC3
)
544 w
->fifo_in
= audio
->fifo_sync
;
545 w
->fifo_out
= audio
->fifo_out
;
546 w
->config
= &audio
->config
;
547 w
->amixdown
= audio
->amixdown
;
548 w
->source_acodec
= audio
->codec
;
550 /* FIXME: This feels really hackish, anything better? */
551 audio_w
= calloc( sizeof( hb_work_object_t
), 1 );
552 audio_w
= memcpy( audio_w
, w
, sizeof( hb_work_object_t
));
554 hb_list_add( job
->list_work
, audio_w
);
560 /* Init read & write threads */
561 job
->reader
= hb_reader_init( job
);
563 hb_log( " + output: %s", job
->file
);
564 job
->muxer
= hb_muxer_init( job
);
568 /* Launch processing threads */
569 for( i
= 1; i
< hb_list_count( job
->list_work
); i
++ )
571 w
= hb_list_item( job
->list_work
, i
);
572 w
->done
= &job
->done
;
573 w
->thread_sleep_interval
= 10;
575 w
->thread
= hb_thread_init( w
->name
, work_loop
, w
,
580 w
= hb_list_item( job
->list_work
, 0 );
581 w
->thread_sleep_interval
= 50;
585 if( w
->work( w
, NULL
, NULL
) == HB_WORK_DONE
)
590 !hb_fifo_size( job
->fifo_sync
) &&
591 !hb_fifo_size( job
->fifo_render
) &&
592 !hb_fifo_size( job
->fifo_mpeg4
) )
596 hb_snooze( w
->thread_sleep_interval
);
598 hb_list_rem( job
->list_work
, w
);
602 /* Close work objects */
603 while( ( w
= hb_list_item( job
->list_work
, 0 ) ) )
605 hb_list_rem( job
->list_work
, w
);
606 hb_thread_close( &w
->thread
);
609 /* FIXME: This feels really hackish, anything better? */
610 if ( w
->id
== WORK_DECA52
||
611 w
->id
== WORK_DECDCA
||
612 w
->id
== WORK_DECLPCM
||
613 w
->id
== WORK_ENCFAAC
||
614 w
->id
== WORK_ENCLAME
||
615 w
->id
== WORK_ENCVORBIS
)
622 hb_list_close( &job
->list_work
);
624 /* Stop read & write threads */
625 hb_thread_close( &job
->reader
);
626 hb_thread_close( &job
->muxer
);
629 hb_fifo_close( &job
->fifo_mpeg2
);
630 hb_fifo_close( &job
->fifo_raw
);
631 hb_fifo_close( &job
->fifo_sync
);
632 hb_fifo_close( &job
->fifo_render
);
633 hb_fifo_close( &job
->fifo_mpeg4
);
635 for (i
=0; i
< hb_list_count(title
->list_subtitle
); i
++) {
636 subtitle
= hb_list_item( title
->list_subtitle
, i
);
639 hb_fifo_close( &subtitle
->fifo_in
);
640 hb_fifo_close( &subtitle
->fifo_raw
);
643 for( i
= 0; i
< hb_list_count( title
->list_audio
); i
++ )
645 audio
= hb_list_item( title
->list_audio
, i
);
646 hb_fifo_close( &audio
->fifo_in
);
647 hb_fifo_close( &audio
->fifo_raw
);
648 hb_fifo_close( &audio
->fifo_sync
);
649 hb_fifo_close( &audio
->fifo_out
);
652 if( job
->indepth_scan
)
655 * Before closing the title print out our subtitle stats if we need to
656 * Find the highest and lowest.
658 for( i
=0; i
< hb_list_count( title
->list_subtitle
); i
++ )
660 subtitle
= hb_list_item( title
->list_subtitle
, i
);
661 hb_log( "Subtitle stream 0x%x '%s': %d hits (%d forced)",
662 subtitle
->id
, subtitle
->lang
, subtitle
->hits
,
663 subtitle
->forced_hits
);
664 if( subtitle
->hits
> subtitle_highest
)
666 subtitle_highest
= subtitle
->hits
;
667 subtitle_highest_id
= subtitle
->id
;
670 if( subtitle
->hits
< subtitle_lowest
)
672 subtitle_lowest
= subtitle
->hits
;
673 subtitle_lowest_id
= subtitle
->id
;
676 if( subtitle
->forced_hits
> 0 )
678 if( subtitle_forced_id
== 0 )
680 subtitle_forced_id
= subtitle
->id
;
685 if( job
->native_language
) {
687 * We still have a native_language, so the audio and subtitles are
688 * different, so in this case it is a foreign film and we want to
689 * select the subtitle with the highest hits in our language.
691 subtitle_hit
= subtitle_highest_id
;
692 hb_log( "Found a native-language subtitle id 0x%x", subtitle_hit
);
694 if( subtitle_forced_id
)
697 * If there are any subtitle streams with forced subtitles
698 * then select it in preference to the lowest.
700 subtitle_hit
= subtitle_forced_id
;
701 hb_log("Found a subtitle candidate id 0x%x (contains forced subs)",
703 } else if( subtitle_lowest
< subtitle_highest
)
706 * OK we have more than one, and the lowest is lower,
707 * but how much lower to qualify for turning it on by
710 * Let's say 10% as a default.
712 if( subtitle_lowest
< ( subtitle_highest
* 0.1 ) )
714 subtitle_hit
= subtitle_lowest_id
;
715 hb_log( "Found a subtitle candidate id 0x%x",
718 hb_log( "No candidate subtitle detected during subtitle-scan");
724 if( job
->select_subtitle
)
726 if( job
->indepth_scan
)
728 for( i
=0; i
< hb_list_count( title
->list_subtitle
); i
++ )
730 subtitle
= hb_list_item( title
->list_subtitle
, i
);
731 if( subtitle
->id
== subtitle_hit
)
733 hb_list_rem( title
->list_subtitle
, subtitle
);
734 *( job
->select_subtitle
) = subtitle
;
739 * Must be the end of pass 0 or 2 - we don't need this anymore.
741 * Have to put the subtitle list back together in the title though
742 * or the GUI will have a hissy fit.
744 free( job
->select_subtitle
);
745 job
->select_subtitle
= NULL
;
751 for( i
= 0; i
< hb_list_count( job
->filters
); i
++ )
753 hb_filter_object_t
* filter
= hb_list_item( job
->filters
, i
);
754 hb_filter_close( &filter
);
756 hb_list_close( &job
->filters
);
759 hb_buffer_pool_free();
761 hb_title_close( &job
->title
);
766 * Performs the work objects specific work function.
767 * Loops calling work function for associated work object. Sleeps when fifo is full.
768 * Monitors work done indicator.
769 * Exits loop when work indiactor is set.
770 * @param _w Handle to work object.
772 static void work_loop( void * _w
)
774 hb_work_object_t
* w
= _w
;
775 hb_buffer_t
* buf_in
, * buf_out
;
780 hb_lock( job
->pause
);
781 hb_unlock( job
->pause
);
783 if( hb_fifo_is_full( w
->fifo_out
) ||
784 // if( (hb_fifo_percent_full( w->fifo_out ) > 0.8) ||
785 !( buf_in
= hb_fifo_get( w
->fifo_in
) ) )
787 hb_snooze( w
->thread_sleep_interval
);
788 // w->thread_sleep_interval += 1;
791 // w->thread_sleep_interval = MAX(1, (w->thread_sleep_interval - 1));
793 w
->work( w
, &buf_in
, &buf_out
);
795 // Propagate any chapter breaks for the worker if and only if the
796 // output frame has the same time stamp as the input frame (any
797 // worker that delays frames has to propagate the chapter marks itself
798 // and workers that move chapter marks to a different time should set
799 // 'buf_in' to NULL so that this code won't generate spurious duplicates.)
800 if( buf_in
&& buf_out
&& buf_in
->new_chap
&& buf_in
->start
== buf_out
->start
)
802 hb_log("work %s: Copying Chapter Break @ %lld", w
->name
, buf_in
->start
);
803 buf_out
->new_chap
= 1;
808 hb_buffer_close( &buf_in
);
812 hb_fifo_push( w
->fifo_out
, buf_out
);