OSDN Git Service

0c951f41d79c077544cd3c38b09495813c97b8f9
[handbrake-jp/handbrake-jp-git.git] / libhb / hb.c
1 #include "hb.h"
2 #include "hbffmpeg.h"
3
4 #if defined( SYS_MINGW ) && defined( PTW32_STATIC_LIB )
5 #include <pthread.h>
6 #endif
7
8 struct hb_handle_s
9 {
10     int            id;
11     
12     /* The "Check for update" thread */
13     int            build;
14     char           version[32];
15     hb_thread_t  * update_thread;
16
17     /* This thread's only purpose is to check other threads'
18        states */
19     volatile int   die;
20     hb_thread_t  * main_thread;
21     int            pid;
22
23     /* DVD/file scan thread */
24     hb_list_t    * list_title;
25     hb_thread_t  * scan_thread;
26
27     /* The thread which processes the jobs. Others threads are launched
28        from this one (see work.c) */
29     hb_list_t    * jobs;
30     hb_job_t     * current_job;
31     int            job_count;
32     int            job_count_permanent;
33     volatile int   work_die;
34     int            work_error;
35     hb_thread_t  * work_thread;
36
37     int            cpu_count;
38
39     hb_lock_t    * state_lock;
40     hb_state_t     state;
41
42     int            paused;
43     hb_lock_t    * pause_lock;
44     /* For MacGui active queue
45        increments each time the scan thread completes*/
46     int            scanCount;
47     volatile int   scan_die;
48     
49     /* Stash of persistent data between jobs, for stuff
50        like correcting frame count and framerate estimates
51        on multi-pass encodes where frames get dropped.     */
52     hb_interjob_t * interjob;
53
54 };
55
56 hb_lock_t *hb_avcodec_lock;
57 hb_work_object_t * hb_objects = NULL;
58 int hb_instance_counter = 0;
59 int hb_process_initialized = 0;
60
61 static void thread_func( void * );
62
63 void hb_avcodec_init()
64 {
65     hb_avcodec_lock  = hb_lock_init();
66     av_register_all();
67 }
68
69 int hb_avcodec_open(AVCodecContext *avctx, AVCodec *codec)
70 {
71     int ret;
72     hb_lock( hb_avcodec_lock );
73     ret = avcodec_open(avctx, codec);
74     hb_unlock( hb_avcodec_lock );
75     return ret;
76 }
77
78 int hb_avcodec_close(AVCodecContext *avctx)
79 {
80     int ret;
81     hb_lock( hb_avcodec_lock );
82     ret = avcodec_close(avctx);
83     hb_unlock( hb_avcodec_lock );
84     return ret;
85 }
86
87 int hb_ff_layout_xlat(int64_t ff_channel_layout, int channels)
88 {
89     int hb_layout;
90
91     switch (ff_channel_layout)
92     {
93         case CH_LAYOUT_MONO:
94             hb_layout = HB_INPUT_CH_LAYOUT_MONO;
95             break;
96         case CH_LAYOUT_STEREO:
97             hb_layout = HB_INPUT_CH_LAYOUT_STEREO;
98             break;
99         case CH_LAYOUT_SURROUND:
100             hb_layout = HB_INPUT_CH_LAYOUT_3F;
101             break;
102         case CH_LAYOUT_4POINT0:
103             hb_layout = HB_INPUT_CH_LAYOUT_3F1R;
104             break;
105         case CH_LAYOUT_2_2:
106             hb_layout = HB_INPUT_CH_LAYOUT_2F2R;
107             break;
108         case CH_LAYOUT_QUAD:
109             hb_layout = HB_INPUT_CH_LAYOUT_2F2R;
110             break;
111         case CH_LAYOUT_5POINT0:
112             hb_layout = HB_INPUT_CH_LAYOUT_3F2R;
113             break;
114         case CH_LAYOUT_5POINT1:
115             hb_layout = HB_INPUT_CH_LAYOUT_3F2R|HB_INPUT_CH_LAYOUT_HAS_LFE;
116             break;
117         case CH_LAYOUT_5POINT0_BACK:
118             hb_layout = HB_INPUT_CH_LAYOUT_3F2R;
119             break;
120         case CH_LAYOUT_5POINT1_BACK:
121             hb_layout = HB_INPUT_CH_LAYOUT_3F2R|HB_INPUT_CH_LAYOUT_HAS_LFE;
122             break;
123         case CH_LAYOUT_7POINT0:
124             hb_layout = HB_INPUT_CH_LAYOUT_3F4R;
125             break;
126         case CH_LAYOUT_7POINT1:
127             hb_layout = HB_INPUT_CH_LAYOUT_3F4R|HB_INPUT_CH_LAYOUT_HAS_LFE;
128             break;
129         case CH_LAYOUT_STEREO_DOWNMIX:
130             hb_layout = HB_INPUT_CH_LAYOUT_STEREO;
131             break;
132         default:
133             hb_layout = HB_INPUT_CH_LAYOUT_STEREO;
134             break;
135     }
136     // Now make sure the chosen layout agrees with the number of channels
137     // ffmpeg tells us there are.  It seems ffmpeg is sometimes confused
138     // about this. So we will make a best guess based on the number
139     // of channels.
140     int chans = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT( hb_layout );
141     if ( chans == channels )
142     {
143         return hb_layout;
144     }
145     hb_log( "Channels reported by ffmpeg (%d) != computed layout channels (%d).", channels, chans );
146     switch (channels)
147     {
148         case 1:
149             hb_layout = HB_INPUT_CH_LAYOUT_MONO;
150             break;
151         case 2:
152             hb_layout = HB_INPUT_CH_LAYOUT_STEREO;
153             break;
154         case 3:
155             hb_layout = HB_INPUT_CH_LAYOUT_3F;
156             break;
157         case 4:
158             hb_layout = HB_INPUT_CH_LAYOUT_3F1R;
159             break;
160         case 5:
161             hb_layout = HB_INPUT_CH_LAYOUT_3F2R;
162             break;
163         case 6:
164             hb_layout = HB_INPUT_CH_LAYOUT_3F2R|HB_INPUT_CH_LAYOUT_HAS_LFE;
165             break;
166         case 7:
167             hb_layout = HB_INPUT_CH_LAYOUT_3F4R;
168             break;
169         case 8:
170             hb_layout = HB_INPUT_CH_LAYOUT_3F4R|HB_INPUT_CH_LAYOUT_HAS_LFE;
171             break;
172         default:
173             hb_log("Unsupported number of audio channels (%d).\n", channels);
174             hb_layout = 0;
175             break;
176     }
177     return hb_layout;
178 }
179
180 /**
181  * Registers work objects, by adding the work object to a liked list.
182  * @param w Handle to hb_work_object_t to register.
183  */
184 void hb_register( hb_work_object_t * w )
185 {
186     w->next    = hb_objects;
187     hb_objects = w;
188 }
189
190 /**
191  * libhb initialization routine.
192  * @param verbose HB_DEBUG_NONE or HB_DEBUG_ALL.
193  * @param update_check signals libhb to check for updated version from HandBrake website.
194  * @return Handle to hb_handle_t for use on all subsequent calls to libhb.
195  */
196 hb_handle_t * hb_init( int verbose, int update_check )
197 {
198     if (!hb_process_initialized)
199     {
200 #if defined( SYS_MINGW ) && defined( PTW32_STATIC_LIB )
201         pthread_win32_process_attach_np();
202 #endif
203         hb_process_initialized =1;
204     }
205     
206     hb_handle_t * h = calloc( sizeof( hb_handle_t ), 1 );
207     uint64_t      date;
208
209     /* See hb_deep_log() and hb_log() in common.c */
210     global_verbosity_level = verbose;
211     if( verbose )
212         putenv( "HB_DEBUG=1" );
213     
214     h->id = hb_instance_counter++;
215     
216     /* Check for an update on the website if asked to */
217     h->build = -1;
218
219     if( update_check )
220     {
221         hb_log( "hb_init: checking for updates" );
222         date             = hb_get_date();
223         h->update_thread = hb_update_init( &h->build, h->version );
224
225         for( ;; )
226         {
227             if( hb_thread_has_exited( h->update_thread ) )
228             {
229                 /* Immediate success or failure */
230                 hb_thread_close( &h->update_thread );
231                 break;
232             }
233             if( hb_get_date() > date + 1000 )
234             {
235                 /* Still nothing after one second. Connection problem,
236                    let the thread die */
237                 hb_log( "hb_init: connection problem, not waiting for "
238                         "update_thread" );
239                 break;
240             }
241             hb_snooze( 500 );
242         }
243     }
244
245     /*
246      * Initialise buffer pool
247      */
248     hb_buffer_pool_init();
249
250     /* CPU count detection */
251     hb_log( "hb_init: checking cpu count" );
252     h->cpu_count = hb_get_cpu_count();
253
254     h->list_title = hb_list_init();
255     h->jobs       = hb_list_init();
256
257     h->state_lock  = hb_lock_init();
258     h->state.state = HB_STATE_IDLE;
259
260     h->pause_lock = hb_lock_init();
261
262     h->interjob = calloc( sizeof( hb_interjob_t ), 1 );
263
264     /* libavcodec */
265     hb_avcodec_init();
266
267     /* Start library thread */
268     hb_log( "hb_init: starting libhb thread" );
269     h->die         = 0;
270     h->main_thread = hb_thread_init( "libhb", thread_func, h,
271                                      HB_NORMAL_PRIORITY );
272     hb_register( &hb_sync_video );
273     hb_register( &hb_sync_audio );
274         hb_register( &hb_decmpeg2 );
275         hb_register( &hb_decvobsub );
276     hb_register( &hb_encvobsub );
277     hb_register( &hb_deccc608 );
278     hb_register( &hb_decsrtsub );
279     hb_register( &hb_decutf8sub );
280     hb_register( &hb_dectx3gsub );
281         hb_register( &hb_render );
282         hb_register( &hb_encavcodec );
283         hb_register( &hb_encx264 );
284     hb_register( &hb_enctheora );
285         hb_register( &hb_deca52 );
286         hb_register( &hb_decdca );
287         hb_register( &hb_decavcodec );
288         hb_register( &hb_decavcodecv );
289         hb_register( &hb_decavcodecvi );
290         hb_register( &hb_decavcodecai );
291         hb_register( &hb_declpcm );
292         hb_register( &hb_encfaac );
293         hb_register( &hb_enclame );
294         hb_register( &hb_encvorbis );
295         hb_register( &hb_muxer );
296 #ifdef __APPLE__
297         hb_register( &hb_encca_aac );
298 #endif
299     
300     return h;
301 }
302
303 /**
304  * libhb initialization routine.
305  * This version is to use when calling the dylib, the macro hb_init isn't available from a dylib call!
306  * @param verbose HB_DEBUG_NONE or HB_DEBUG_ALL.
307  * @param update_check signals libhb to check for updated version from HandBrake website.
308  * @return Handle to hb_handle_t for use on all subsequent calls to libhb.
309  */
310 hb_handle_t * hb_init_dl( int verbose, int update_check )
311 {
312     hb_handle_t * h = calloc( sizeof( hb_handle_t ), 1 );
313     uint64_t      date;
314
315     /* See hb_log() in common.c */
316     if( verbose > HB_DEBUG_NONE )
317     {
318         putenv( "HB_DEBUG=1" );
319     }
320
321     h->id = hb_instance_counter++;
322
323     /* Check for an update on the website if asked to */
324     h->build = -1;
325
326     if( update_check )
327     {
328         hb_log( "hb_init: checking for updates" );
329         date             = hb_get_date();
330         h->update_thread = hb_update_init( &h->build, h->version );
331
332         for( ;; )
333         {
334             if( hb_thread_has_exited( h->update_thread ) )
335             {
336                 /* Immediate success or failure */
337                 hb_thread_close( &h->update_thread );
338                 break;
339             }
340             if( hb_get_date() > date + 1000 )
341             {
342                 /* Still nothing after one second. Connection problem,
343                    let the thread die */
344                 hb_log( "hb_init: connection problem, not waiting for "
345                         "update_thread" );
346                 break;
347             }
348             hb_snooze( 500 );
349         }
350     }
351
352     /* CPU count detection */
353     hb_log( "hb_init: checking cpu count" );
354     h->cpu_count = hb_get_cpu_count();
355
356     h->list_title = hb_list_init();
357     h->jobs       = hb_list_init();
358     h->current_job = NULL;
359
360     h->state_lock  = hb_lock_init();
361     h->state.state = HB_STATE_IDLE;
362
363     h->pause_lock = hb_lock_init();
364
365     /* libavcodec */
366     avcodec_init();
367     avcodec_register_all();
368
369     /* Start library thread */
370     hb_log( "hb_init: starting libhb thread" );
371     h->die         = 0;
372     h->main_thread = hb_thread_init( "libhb", thread_func, h,
373                                      HB_NORMAL_PRIORITY );
374
375     hb_register( &hb_sync_video );
376     hb_register( &hb_sync_audio );
377         hb_register( &hb_decmpeg2 );
378         hb_register( &hb_decvobsub );
379     hb_register( &hb_encvobsub );
380     hb_register( &hb_deccc608 );
381     hb_register( &hb_decsrtsub );
382     hb_register( &hb_decutf8sub );
383     hb_register( &hb_dectx3gsub );
384         hb_register( &hb_render );
385         hb_register( &hb_encavcodec );
386         hb_register( &hb_encx264 );
387     hb_register( &hb_enctheora );
388         hb_register( &hb_deca52 );
389         hb_register( &hb_decdca );
390         hb_register( &hb_decavcodec );
391         hb_register( &hb_decavcodecv );
392         hb_register( &hb_decavcodecvi );
393         hb_register( &hb_decavcodecai );
394         hb_register( &hb_declpcm );
395         hb_register( &hb_encfaac );
396         hb_register( &hb_enclame );
397         hb_register( &hb_encvorbis );
398         hb_register( &hb_muxer );
399 #ifdef __APPLE__
400         hb_register( &hb_encca_aac );
401 #endif
402
403         return h;
404 }
405
406
407 /**
408  * Returns current version of libhb.
409  * @param h Handle to hb_handle_t.
410  * @return character array of version number.
411  */
412 char * hb_get_version( hb_handle_t * h )
413 {
414     return HB_PROJECT_VERSION;
415 }
416
417 /**
418  * Returns current build of libhb.
419  * @param h Handle to hb_handle_t.
420  * @return character array of build number.
421  */
422 int hb_get_build( hb_handle_t * h )
423 {
424     return HB_PROJECT_BUILD;
425 }
426
427 /**
428  * Checks for needed update.
429  * @param h Handle to hb_handle_t.
430  * @param version Pointer to handle where version will be copied.
431  * @return update indicator.
432  */
433 int hb_check_update( hb_handle_t * h, char ** version )
434 {
435     *version = ( h->build < 0 ) ? NULL : h->version;
436     return h->build;
437 }
438
439 /**
440  * Sets the cpu count to the desired value.
441  * @param h Handle to hb_handle_t
442  * @param cpu_count Number of CPUs to use.
443  */
444 void hb_set_cpu_count( hb_handle_t * h, int cpu_count )
445 {
446     cpu_count    = MAX( 1, cpu_count );
447     cpu_count    = MIN( cpu_count, 8 );
448     h->cpu_count = cpu_count;
449 }
450
451 /**
452  * Deletes current previews associated with titles
453  * @param h Handle to hb_handle_t
454  */
455 void hb_remove_previews( hb_handle_t * h )
456 {
457     char            filename[1024];
458     char            dirname[1024];
459     hb_title_t    * title;
460     int             i, count, len;
461     DIR           * dir;
462     struct dirent * entry;
463
464     memset( dirname, 0, 1024 );
465     hb_get_temporary_directory( dirname );
466     dir = opendir( dirname );
467     if (dir == NULL) return;
468
469     count = hb_list_count( h->list_title );
470     while( ( entry = readdir( dir ) ) )
471     {
472         if( entry->d_name[0] == '.' )
473         {
474             continue;
475         }
476         for( i = 0; i < count; i++ )
477         {
478             title = hb_list_item( h->list_title, i );
479             len = snprintf( filename, 1024, "%d_%d", h->id, title->index );
480             if (strncmp(entry->d_name, filename, len) == 0)
481             {
482                 snprintf( filename, 1024, "%s/%s", dirname, entry->d_name );
483                 unlink( filename );
484                 break;
485             }
486         }
487     }
488     closedir( dir );
489 }
490
491 /**
492  * Initializes a scan of the by calling hb_scan_init
493  * @param h Handle to hb_handle_t
494  * @param path location of VIDEO_TS folder.
495  * @param title_index Desired title to scan.  0 for all titles.
496  * @param preview_count Number of preview images to generate.
497  * @param store_previews Whether or not to write previews to disk.
498  */
499 void hb_scan( hb_handle_t * h, const char * path, int title_index,
500               int preview_count, int store_previews )
501 {
502     hb_title_t * title;
503
504     h->scan_die = 0;
505
506     /* Clean up from previous scan */
507     hb_remove_previews( h );
508     while( ( title = hb_list_item( h->list_title, 0 ) ) )
509     {
510         hb_list_rem( h->list_title, title );
511         hb_title_close( &title );
512     }
513
514     hb_log( "hb_scan: path=%s, title_index=%d", path, title_index );
515     h->scan_thread = hb_scan_init( h, &h->scan_die, path, title_index, 
516                                    h->list_title, preview_count, 
517                                    store_previews );
518 }
519
520 /**
521  * Returns the list of titles found.
522  * @param h Handle to hb_handle_t
523  * @return Handle to hb_list_t of the title list.
524  */
525 hb_list_t * hb_get_titles( hb_handle_t * h )
526 {
527     return h->list_title;
528 }
529
530 /**
531  * Create preview image of desired title a index of picture.
532  * @param h Handle to hb_handle_t.
533  * @param title Handle to hb_title_t of desired title.
534  * @param picture Index in title.
535  * @param buffer Handle to buufer were inage will be drawn.
536  */
537 void hb_get_preview( hb_handle_t * h, hb_title_t * title, int picture,
538                      uint8_t * buffer )
539 {
540     hb_job_t           * job = title->job;
541     char                 filename[1024];
542     FILE               * file;
543     uint8_t            * buf1, * buf2, * buf3, * buf4, * pen;
544     uint32_t             swsflags;
545     AVPicture            pic_in, pic_preview, pic_deint, pic_crop, pic_scale;
546     struct SwsContext  * context;
547     int                  i;
548     int                  rgb_width = ((job->width + 7) >> 3) << 3;
549     int                  preview_size;
550
551     swsflags = SWS_LANCZOS | SWS_ACCURATE_RND;
552
553     buf1 = av_malloc( avpicture_get_size( PIX_FMT_YUV420P, title->width, title->height ) );
554     buf2 = av_malloc( avpicture_get_size( PIX_FMT_YUV420P, title->width, title->height ) );
555     buf3 = av_malloc( avpicture_get_size( PIX_FMT_YUV420P, rgb_width, job->height ) );
556     buf4 = av_malloc( avpicture_get_size( PIX_FMT_RGB32, rgb_width, job->height ) );
557     avpicture_fill( &pic_in, buf1, PIX_FMT_YUV420P,
558                     title->width, title->height );
559     avpicture_fill( &pic_deint, buf2, PIX_FMT_YUV420P,
560                     title->width, title->height );
561     avpicture_fill( &pic_scale, buf3, PIX_FMT_YUV420P,
562                     rgb_width, job->height );
563     avpicture_fill( &pic_preview, buf4, PIX_FMT_RGB32,
564                     rgb_width, job->height );
565
566     // Allocate the AVPicture frames and fill in
567
568     memset( filename, 0, 1024 );
569
570     hb_get_tempory_filename( h, filename, "%d_%d_%d",
571                              h->id, title->index, picture );
572
573     file = fopen( filename, "rb" );
574     if( !file )
575     {
576         hb_log( "hb_get_preview: fopen failed" );
577         return;
578     }
579
580     fread( buf1, avpicture_get_size( PIX_FMT_YUV420P, title->width, title->height), 1, file );
581     fclose( file );
582
583     if( job->deinterlace )
584     {
585         // Deinterlace and crop
586         avpicture_deinterlace( &pic_deint, &pic_in, PIX_FMT_YUV420P, title->width, title->height );
587         av_picture_crop( &pic_crop, &pic_deint, PIX_FMT_YUV420P, job->crop[0], job->crop[2] );
588     }
589     else
590     {
591         // Crop
592         av_picture_crop( &pic_crop, &pic_in, PIX_FMT_YUV420P, job->crop[0], job->crop[2] );
593     }
594
595     // Get scaling context
596     context = sws_getContext(title->width  - (job->crop[2] + job->crop[3]),
597                              title->height - (job->crop[0] + job->crop[1]),
598                              PIX_FMT_YUV420P,
599                              job->width, job->height, PIX_FMT_YUV420P,
600                              swsflags, NULL, NULL, NULL);
601
602     // Scale
603     sws_scale(context,
604               pic_crop.data, pic_crop.linesize,
605               0, title->height - (job->crop[0] + job->crop[1]),
606               pic_scale.data, pic_scale.linesize);
607
608     // Free context
609     sws_freeContext( context );
610
611     // Get preview context
612     context = sws_getContext(rgb_width, job->height, PIX_FMT_YUV420P,
613                               rgb_width, job->height, PIX_FMT_RGB32,
614                               swsflags, NULL, NULL, NULL);
615
616     // Create preview
617     sws_scale(context,
618               pic_scale.data, pic_scale.linesize,
619               0, job->height,
620               pic_preview.data, pic_preview.linesize);
621
622     // Free context
623     sws_freeContext( context );
624
625     preview_size = pic_preview.linesize[0];
626     pen = buffer;
627     for( i = 0; i < job->height; i++ )
628     {
629         memcpy( pen, buf4 + preview_size * i, 4 * job->width );
630         pen += 4 * job->width;
631     }
632
633     // Clean up
634     avpicture_free( &pic_preview );
635     avpicture_free( &pic_scale );
636     avpicture_free( &pic_deint );
637     avpicture_free( &pic_in );
638 }
639
640  /**
641  * Analyzes a frame to detect interlacing artifacts
642  * and returns true if interlacing (combing) is found.
643  *
644  * Code taken from Thomas Oestreich's 32detect filter
645  * in the Transcode project, with minor formatting changes.
646  *
647  * @param buf         An hb_buffer structure holding valid frame data
648  * @param width       The frame's width in pixels
649  * @param height      The frame's height in pixels
650  * @param color_equal Sensitivity for detecting similar colors
651  * @param color_diff  Sensitivity for detecting different colors
652  * @param threshold   Sensitivity for flagging planes as combed
653  * @param prog_equal  Sensitivity for detecting similar colors on progressive frames
654  * @param prog_diff   Sensitivity for detecting different colors on progressive frames
655  * @param prog_threshold Sensitivity for flagging progressive frames as combed
656  */
657 int hb_detect_comb( hb_buffer_t * buf, int width, int height, int color_equal, int color_diff, int threshold, int prog_equal, int prog_diff, int prog_threshold )
658 {
659     int j, k, n, off, cc_1, cc_2, cc[3];
660         // int flag[3] ; // debugging flag
661     uint16_t s1, s2, s3, s4;
662     cc_1 = 0; cc_2 = 0;
663
664     int offset = 0;
665     
666     if ( buf->flags & 16 )
667     {
668         /* Frame is progressive, be more discerning. */
669         color_diff = prog_diff;
670         color_equal = prog_equal;
671         threshold = prog_threshold;
672     }
673
674     /* One pas for Y, one pass for Cb, one pass for Cr */    
675     for( k = 0; k < 3; k++ )
676     {
677         if( k == 1 )
678         {
679             /* Y has already been checked, now offset by Y's dimensions
680                and divide all the other values by 2, since Cr and Cb
681                are half-size compared to Y.                               */
682             offset = width * height;
683             width >>= 1;
684             height >>= 1;
685         }
686         else if ( k == 2 )
687         {
688             /* Y and Cb are done, so the offset needs to be bumped
689                so it's width*height + (width / 2) * (height / 2)  */
690             offset *= 5/4;
691         }
692
693         for( j = 0; j < width; ++j )
694         {
695             off = 0;
696
697             for( n = 0; n < ( height - 4 ); n = n + 2 )
698             {
699                 /* Look at groups of 4 sequential horizontal lines */
700                 s1 = ( ( buf->data + offset )[ off + j             ] & 0xff );
701                 s2 = ( ( buf->data + offset )[ off + j + width     ] & 0xff );
702                 s3 = ( ( buf->data + offset )[ off + j + 2 * width ] & 0xff );
703                 s4 = ( ( buf->data + offset )[ off + j + 3 * width ] & 0xff );
704
705                 /* Note if the 1st and 2nd lines are more different in
706                    color than the 1st and 3rd lines are similar in color.*/
707                 if ( ( abs( s1 - s3 ) < color_equal ) &&
708                      ( abs( s1 - s2 ) > color_diff ) )
709                         ++cc_1;
710
711                 /* Note if the 2nd and 3rd lines are more different in
712                    color than the 2nd and 4th lines are similar in color.*/
713                 if ( ( abs( s2 - s4 ) < color_equal ) &&
714                      ( abs( s2 - s3 ) > color_diff) )
715                         ++cc_2;
716
717                 /* Now move down 2 horizontal lines before starting over.*/
718                 off += 2 * width;
719             }
720         }
721
722         // compare results
723         /*  The final cc score for a plane is the percentage of combed pixels it contains.
724             Because sensitivity goes down to hundreths of a percent, multiply by 1000
725             so it will be easy to compare against the threhold value which is an integer. */
726         cc[k] = (int)( ( cc_1 + cc_2 ) * 1000.0 / ( width * height ) );
727     }
728
729
730     /* HandBrake is all yuv420, so weight the average percentage of all 3 planes accordingly.*/
731     int average_cc = ( 2 * cc[0] + ( cc[1] / 2 ) + ( cc[2] / 2 ) ) / 3;
732     
733     /* Now see if that average percentage of combed pixels surpasses the threshold percentage given by the user.*/
734     if( average_cc > threshold )
735     {
736 #if 0
737             hb_log("Average %i combed (Threshold %i) %i/%i/%i | PTS: %"PRId64" (%fs) %s", average_cc, threshold, cc[0], cc[1], cc[2], buf->start, (float)buf->start / 90000, (buf->flags & 16) ? "Film" : "Video" );
738 #endif
739         return 1;
740     }
741
742 #if 0
743     hb_log("SKIPPED Average %i combed (Threshold %i) %i/%i/%i | PTS: %"PRId64" (%fs) %s", average_cc, threshold, cc[0], cc[1], cc[2], buf->start, (float)buf->start / 90000, (buf->flags & 16) ? "Film" : "Video" );
744 #endif
745
746     /* Reaching this point means no combing detected. */
747     return 0;
748
749 }
750
751 /**
752  * Calculates job width and height for anamorphic content,
753  *
754  * @param job Handle to hb_job_t
755  * @param output_width Pointer to returned storage width
756  * @param output_height Pointer to returned storage height
757  * @param output_par_width Pointer to returned pixel width
758  @ param output_par_height Pointer to returned pixel height
759  */
760 void hb_set_anamorphic_size( hb_job_t * job,
761         int *output_width, int *output_height,
762         int *output_par_width, int *output_par_height )
763 {
764     /* Set up some variables to make the math easier to follow. */
765     hb_title_t * title = job->title;
766     int cropped_width = title->width - job->crop[2] - job->crop[3] ;
767     int cropped_height = title->height - job->crop[0] - job->crop[1] ;
768     double storage_aspect = (double)cropped_width / (double)cropped_height;
769     int mod = job->modulus ? job->modulus : 16;
770     double aspect = title->aspect;
771     
772     int pixel_aspect_width  = job->anamorphic.par_width;
773     int pixel_aspect_height = job->anamorphic.par_height;
774
775     /* If a source was really NTSC or PAL and the user specified ITU PAR
776        values, replace the standard PAR values with the ITU broadcast ones. */
777     if( title->width == 720 && job->anamorphic.itu_par )
778     {
779         // convert aspect to a scaled integer so we can test for 16:9 & 4:3
780         // aspect ratios ignoring insignificant differences in the LSBs of
781         // the floating point representation.
782         int iaspect = aspect * 9.;
783
784         /* Handle ITU PARs */
785         if (title->height == 480)
786         {
787             /* It's NTSC */
788             if (iaspect == 16)
789             {
790                 /* It's widescreen */
791                 pixel_aspect_width = 40;
792                 pixel_aspect_height = 33;
793             }
794             else if (iaspect == 12)
795             {
796                 /* It's 4:3 */
797                 pixel_aspect_width = 10;
798                 pixel_aspect_height = 11;
799             }
800         }
801         else if (title->height == 576)
802         {
803             /* It's PAL */
804             if(iaspect == 16)
805             {
806                 /* It's widescreen */
807                 pixel_aspect_width = 16;
808                 pixel_aspect_height = 11;
809             }
810             else if (iaspect == 12)
811             {
812                 /* It's 4:3 */
813                 pixel_aspect_width = 12;
814                 pixel_aspect_height = 11;
815             }
816         }
817     }
818
819     /* Figure out what width the source would display at. */
820     int source_display_width = cropped_width * (double)pixel_aspect_width /
821                                (double)pixel_aspect_height ;
822
823     /*
824        3 different ways of deciding output dimensions:
825         - 1: Strict anamorphic, preserve source dimensions
826         - 2: Loose anamorphic, round to mod16 and preserve storage aspect ratio
827         - 3: Power user anamorphic, specify everything
828     */
829     int width, height;
830     switch( job->anamorphic.mode )
831     {
832         case 1:
833             /* Strict anamorphic */
834             *output_width = cropped_width;
835             *output_height = cropped_height;
836             *output_par_width = title->pixel_aspect_width;
837             *output_par_height = title->pixel_aspect_height;
838         break;
839
840         case 2:
841             /* "Loose" anamorphic.
842                 - Uses mod16-compliant dimensions,
843                 - Allows users to set the width
844             */
845             width = job->width;
846             // height: Gets set later, ignore user job->height value
847
848             /* Gotta handle bounding dimensions.
849                If the width is too big, just reset it with no rescaling.
850                Instead of using the aspect-scaled job height,
851                we need to see if the job width divided by the storage aspect
852                is bigger than the max. If so, set it to the max (this is sloppy).
853                If not, set job height to job width divided by storage aspect.
854             */
855
856             if ( job->maxWidth && (job->maxWidth < job->width) )
857                 width = job->maxWidth;
858
859             /* Time to get picture width that divide cleanly.*/
860             width  = MULTIPLE_MOD( width, mod);
861
862             /* Verify these new dimensions don't violate max height and width settings */
863             if ( job->maxWidth && (job->maxWidth < job->width) )
864                 width = job->maxWidth;
865
866             height = ((double)width / storage_aspect) + 0.5;
867             
868             if ( job->maxHeight && (job->maxHeight < height) )
869                 height = job->maxHeight;
870
871             /* Time to get picture height that divide cleanly.*/
872             height = MULTIPLE_MOD( height, mod);
873
874             /* Verify these new dimensions don't violate max height and width settings */
875             if ( job->maxHeight && (job->maxHeight < height) )
876                 height = job->maxHeight;
877
878             /* The film AR is the source's display width / cropped source height.
879                The output display width is the output height * film AR.
880                The output PAR is the output display width / output storage width. */
881             pixel_aspect_width = height * source_display_width / cropped_height;
882             pixel_aspect_height = width;
883
884             /* Pass the results back to the caller */
885             *output_width = width;
886             *output_height = height;
887         break;
888             
889         case 3:
890             /* Anamorphic 3: Power User Jamboree
891                - Set everything based on specified values */
892             
893             /* Use specified storage dimensions */
894             width = job->width;
895             height = job->height;
896             
897             /* Bind to max dimensions */
898             if( job->maxWidth && width > job->maxWidth )
899                 width = job->maxWidth;
900             if( job->maxHeight && height > job->maxHeight )
901                 height = job->maxHeight;
902             
903             /* Time to get picture dimensions that divide cleanly.*/
904             width  = MULTIPLE_MOD( width, mod);
905             height = MULTIPLE_MOD( height, mod);
906             
907             /* Verify we're still within max dimensions */
908             if( job->maxWidth && width > job->maxWidth )
909                 width = job->maxWidth - (mod/2);
910             if( job->maxHeight && height > job->maxHeight )
911                 height = job->maxHeight - (mod/2);
912                 
913             /* Re-ensure we have picture dimensions that divide cleanly. */
914             width  = MULTIPLE_MOD( width, mod );
915             height = MULTIPLE_MOD( height, mod );
916             
917             /* That finishes the storage dimensions. On to display. */            
918             if( job->anamorphic.dar_width && job->anamorphic.dar_height )
919             {
920                 /* We need to adjust the PAR to produce this aspect. */
921                 pixel_aspect_width = height * job->anamorphic.dar_width / job->anamorphic.dar_height;
922                 pixel_aspect_height = width;
923             }
924             else
925             {
926                 /* If we're doing ana 3 and not specifying a DAR, care needs to be taken.
927                    This indicates a PAR is potentially being set by the interface. But
928                    this is an output PAR, to correct a source, and it should not be assumed
929                    that it properly creates a display aspect ratio when applied to the source,
930                    which could easily be stored in a different resolution. */
931                 if( job->anamorphic.keep_display_aspect )
932                 {
933                     /* We can ignore the possibility of a PAR change */
934                     pixel_aspect_width = height * ( (double)source_display_width / (double)cropped_height );
935                     pixel_aspect_height = width;
936                 }
937                 else
938                 {
939                     int output_display_width = width * (double)pixel_aspect_width /
940                         (double)pixel_aspect_height;
941                     pixel_aspect_width = output_display_width;
942                     pixel_aspect_height = width;
943                 }
944             }
945             
946             /* Back to caller */
947             *output_width = width;
948             *output_height = height;
949         break;
950     }
951     
952     /* While x264 is smart enough to reduce fractions on its own, libavcodec
953        needs some help with the math, so lose superfluous factors.            */
954     hb_reduce( output_par_width, output_par_height,
955                pixel_aspect_width, pixel_aspect_height );
956 }
957
958 /**
959  * Calculates job width, height, and cropping parameters.
960  * @param job Handle to hb_job_t.
961  * @param aspect Desired aspect ratio. Value of -1 uses title aspect.
962  * @param pixels Maximum desired pixel count.
963  */
964 void hb_set_size( hb_job_t * job, double aspect, int pixels )
965 {
966     hb_title_t * title = job->title;
967
968     int croppedWidth  = title->width - title->crop[2] - title->crop[3];
969     int croppedHeight = title->height - title->crop[0] - title->crop[1];
970     double croppedAspect = title->aspect * title->height * croppedWidth /
971                            croppedHeight / title->width;
972     int addCrop;
973     int i, w, h;
974
975     if( aspect <= 0 )
976     {
977         /* Keep the best possible aspect ratio */
978         aspect = croppedAspect;
979     }
980
981     /* Crop if necessary to obtain the desired ratio */
982     memcpy( job->crop, title->crop, 4 * sizeof( int ) );
983     if( aspect < croppedAspect )
984     {
985         /* Need to crop on the left and right */
986         addCrop = croppedWidth - aspect * croppedHeight * title->width /
987                     title->aspect / title->height;
988         if( addCrop & 3 )
989         {
990             addCrop = ( addCrop + 1 ) / 2;
991             job->crop[2] += addCrop;
992             job->crop[3] += addCrop;
993         }
994         else if( addCrop & 2 )
995         {
996             addCrop /= 2;
997             job->crop[2] += addCrop - 1;
998             job->crop[3] += addCrop + 1;
999         }
1000         else
1001         {
1002             addCrop /= 2;
1003             job->crop[2] += addCrop;
1004             job->crop[3] += addCrop;
1005         }
1006     }
1007     else if( aspect > croppedAspect )
1008     {
1009         /* Need to crop on the top and bottom */
1010         addCrop = croppedHeight - croppedWidth * title->aspect *
1011             title->height / aspect / title->width;
1012         if( addCrop & 3 )
1013         {
1014             addCrop = ( addCrop + 1 ) / 2;
1015             job->crop[0] += addCrop;
1016             job->crop[1] += addCrop;
1017         }
1018         else if( addCrop & 2 )
1019         {
1020             addCrop /= 2;
1021             job->crop[0] += addCrop - 1;
1022             job->crop[1] += addCrop + 1;
1023         }
1024         else
1025         {
1026             addCrop /= 2;
1027             job->crop[0] += addCrop;
1028             job->crop[1] += addCrop;
1029         }
1030     }
1031
1032     /* Compute a resolution from the number of pixels and aspect */
1033     for( i = 0;; i++ )
1034     {
1035         w = 16 * i;
1036         h = MULTIPLE_16( (int)( (double)w / aspect ) );
1037         if( w * h > pixels )
1038         {
1039             break;
1040         }
1041     }
1042     i--;
1043     job->width  = 16 * i;
1044     job->height = MULTIPLE_16( (int)( (double)job->width / aspect ) );
1045 }
1046
1047 /**
1048  * Returns the number of jobs in the queue.
1049  * @param h Handle to hb_handle_t.
1050  * @return Number of jobs.
1051  */
1052 int hb_count( hb_handle_t * h )
1053 {
1054     return hb_list_count( h->jobs );
1055 }
1056
1057 /**
1058  * Returns handle to job at index i within the job list.
1059  * @param h Handle to hb_handle_t.
1060  * @param i Index of job.
1061  * @returns Handle to hb_job_t of desired job.
1062  */
1063 hb_job_t * hb_job( hb_handle_t * h, int i )
1064 {
1065     return hb_list_item( h->jobs, i );
1066 }
1067
1068 hb_job_t * hb_current_job( hb_handle_t * h )
1069 {
1070     return( h->current_job );
1071 }
1072
1073 /**
1074  * Adds a job to the job list.
1075  * @param h Handle to hb_handle_t.
1076  * @param job Handle to hb_job_t.
1077  */
1078 void hb_add( hb_handle_t * h, hb_job_t * job )
1079 {
1080     hb_job_t      * job_copy;
1081     hb_title_t    * title,    * title_copy;
1082     hb_chapter_t  * chapter,  * chapter_copy;
1083     hb_audio_t    * audio;
1084     hb_subtitle_t * subtitle, * subtitle_copy;
1085     int             i;
1086     char            audio_lang[4];
1087
1088     /* Copy the title */
1089     title      = job->title;
1090     title_copy = malloc( sizeof( hb_title_t ) );
1091     memcpy( title_copy, title, sizeof( hb_title_t ) );
1092
1093     title_copy->list_chapter = hb_list_init();
1094     for( i = 0; i < hb_list_count( title->list_chapter ); i++ )
1095     {
1096         chapter      = hb_list_item( title->list_chapter, i );
1097         chapter_copy = malloc( sizeof( hb_chapter_t ) );
1098         memcpy( chapter_copy, chapter, sizeof( hb_chapter_t ) );
1099         hb_list_add( title_copy->list_chapter, chapter_copy );
1100     }
1101
1102     /*
1103      * Copy the metadata
1104      */
1105     if( title->metadata )
1106     {
1107         title_copy->metadata = malloc( sizeof( hb_metadata_t ) );
1108         
1109         if( title_copy->metadata ) 
1110         {
1111             memcpy( title_copy->metadata, title->metadata, sizeof( hb_metadata_t ) );
1112
1113             /*
1114              * Need to copy the artwork seperatly (TODO).
1115              */
1116             if( title->metadata->coverart )
1117             {
1118                 title_copy->metadata->coverart = malloc( title->metadata->coverart_size );
1119                 if( title_copy->metadata->coverart )
1120                 {
1121                     memcpy( title_copy->metadata->coverart, title->metadata->coverart,
1122                             title->metadata->coverart_size );
1123                 } else {
1124                     title_copy->metadata->coverart_size = 0; 
1125                 }
1126             }
1127         }
1128     }
1129
1130     /* Copy the audio track(s) we want */
1131     title_copy->list_audio = hb_list_init();
1132
1133     for( i = 0; i < hb_list_count(job->list_audio); i++ )
1134     {
1135         if( ( audio = hb_list_item( job->list_audio, i ) ) )
1136         {
1137             hb_list_add( title_copy->list_audio, hb_audio_copy(audio) );
1138         }
1139     }
1140
1141     title_copy->list_subtitle = hb_list_init();
1142
1143     /*
1144      * The following code is confusing, there are two ways in which
1145      * we select subtitles and it depends on whether this is single or
1146      * two pass mode.
1147      *
1148      * subtitle_scan may be enabled, in which case the first pass
1149      * scans all subtitles of that language. The second pass does not
1150      * select any because they are set at the end of the first pass.
1151      *
1152      * We may have manually selected a subtitle, in which case that is
1153      * selected in the first pass of a single pass, or the second of a
1154      * two pass.
1155      */
1156     memset( audio_lang, 0, sizeof( audio_lang ) );
1157
1158     if ( job->indepth_scan ) {
1159
1160         /*
1161          * Find the first audio language that is being encoded
1162          */
1163         for( i = 0; i < hb_list_count(job->list_audio); i++ )
1164         {
1165             if( ( audio = hb_list_item( job->list_audio, i ) ) )
1166             {
1167                 strncpy(audio_lang, audio->config.lang.iso639_2, sizeof(audio_lang));
1168                 break;
1169             }
1170         }
1171     }
1172
1173     /*
1174      * If doing a subtitle scan then add all the matching subtitles for this
1175      * language.
1176      */
1177     if ( job->indepth_scan )
1178     {
1179         for( i=0; i < hb_list_count( title->list_subtitle ); i++ )
1180         {
1181             subtitle = hb_list_item( title->list_subtitle, i );
1182             if( strcmp( subtitle->iso639_2, audio_lang ) == 0 &&
1183                 subtitle->source == VOBSUB )
1184             {
1185                 /*
1186                  * Matched subtitle language with audio language, so
1187                  * add this to our list to scan.
1188                  *
1189                  * We will update the subtitle list on the second pass
1190                  * later after the first pass has completed.
1191                  */
1192                 subtitle_copy = malloc( sizeof( hb_subtitle_t ) );
1193                 memcpy( subtitle_copy, subtitle, sizeof( hb_subtitle_t ) );
1194                 hb_list_add( title_copy->list_subtitle, subtitle_copy );
1195             }
1196         }
1197     } else {
1198         /*
1199          * Not doing a subtitle scan in this pass, but maybe we are in the
1200          * first pass?
1201          */
1202         if( job->pass != 1 )
1203         {
1204             /*
1205              * Copy all of them from the input job, to the title_copy/job_copy.
1206              */
1207             for(  i = 0; i < hb_list_count(job->list_subtitle); i++ ) {
1208                 if( ( subtitle = hb_list_item( job->list_subtitle, i ) ) )
1209                 {
1210                     subtitle_copy = malloc( sizeof( hb_subtitle_t ) );
1211                     memcpy( subtitle_copy, subtitle, sizeof( hb_subtitle_t ) );
1212                     hb_list_add( title_copy->list_subtitle, subtitle_copy );
1213                 }
1214             }
1215         }
1216     }
1217
1218     /* Copy the job */
1219     job_copy        = calloc( sizeof( hb_job_t ), 1 );
1220     memcpy( job_copy, job, sizeof( hb_job_t ) );
1221     title_copy->job = job_copy;
1222     job_copy->title = title_copy;
1223     job_copy->list_audio = title_copy->list_audio;
1224     job_copy->list_subtitle = title_copy->list_subtitle;   // sharing list between title and job
1225     job_copy->file  = strdup( job->file );
1226     job_copy->h     = h;
1227     job_copy->pause = h->pause_lock;
1228
1229     /* Copy the job filter list */
1230     if( job->filters )
1231     {
1232         int i;
1233         int filter_count = hb_list_count( job->filters );
1234         job_copy->filters = hb_list_init();
1235         for( i = 0; i < filter_count; i++ )
1236         {
1237             /*
1238              * Copy the filters, since the MacGui reuses the global filter objects
1239              * meaning that queued up jobs overwrite the previous filter settings.
1240              * In reality, settings is probably the only field that needs duplicating
1241              * since it's the only value that is ever changed. But name is duplicated
1242              * as well for completeness. Not copying private_data since it gets
1243              * created for each job in renderInit.
1244              */
1245             hb_filter_object_t * filter = hb_list_item( job->filters, i );
1246             hb_filter_object_t * filter_copy = malloc( sizeof( hb_filter_object_t ) );
1247             memcpy( filter_copy, filter, sizeof( hb_filter_object_t ) );
1248             if( filter->name )
1249                 filter_copy->name = strdup( filter->name );
1250             if( filter->settings )
1251                 filter_copy->settings = strdup( filter->settings );
1252             hb_list_add( job_copy->filters, filter_copy );
1253         }
1254     }
1255
1256     /* Add the job to the list */
1257     hb_list_add( h->jobs, job_copy );
1258     h->job_count = hb_count(h);
1259     h->job_count_permanent++;
1260 }
1261
1262 /**
1263  * Removes a job from the job list.
1264  * @param h Handle to hb_handle_t.
1265  * @param job Handle to hb_job_t.
1266  */
1267 void hb_rem( hb_handle_t * h, hb_job_t * job )
1268 {
1269     hb_list_rem( h->jobs, job );
1270
1271     h->job_count = hb_count(h);
1272     if (h->job_count_permanent)
1273         h->job_count_permanent--;
1274
1275     /* XXX free everything XXX */
1276 }
1277
1278 /**
1279  * Starts the conversion process.
1280  * Sets state to HB_STATE_WORKING.
1281  * calls hb_work_init, to launch work thread. Stores handle to work thread.
1282  * @param h Handle to hb_handle_t.
1283  */
1284 void hb_start( hb_handle_t * h )
1285 {
1286     /* XXX Hack */
1287     h->job_count = hb_list_count( h->jobs );
1288     h->job_count_permanent = h->job_count;
1289
1290     hb_lock( h->state_lock );
1291     h->state.state = HB_STATE_WORKING;
1292 #define p h->state.param.working
1293     p.progress  = 0.0;
1294     p.job_cur   = 1;
1295     p.job_count = h->job_count;
1296     p.rate_cur  = 0.0;
1297     p.rate_avg  = 0.0;
1298     p.hours     = -1;
1299     p.minutes   = -1;
1300     p.seconds   = -1;
1301     p.sequence_id = 0;
1302 #undef p
1303     hb_unlock( h->state_lock );
1304
1305     h->paused = 0;
1306
1307     h->work_die    = 0;
1308     h->work_thread = hb_work_init( h->jobs, h->cpu_count,
1309                                    &h->work_die, &h->work_error, &h->current_job );
1310 }
1311
1312 /**
1313  * Pauses the conversion process.
1314  * @param h Handle to hb_handle_t.
1315  */
1316 void hb_pause( hb_handle_t * h )
1317 {
1318     if( !h->paused )
1319     {
1320         hb_lock( h->pause_lock );
1321         h->paused = 1;
1322
1323         hb_current_job( h )->st_pause_date = hb_get_date();
1324
1325         hb_lock( h->state_lock );
1326         h->state.state = HB_STATE_PAUSED;
1327         hb_unlock( h->state_lock );
1328     }
1329 }
1330
1331 /**
1332  * Resumes the conversion process.
1333  * @param h Handle to hb_handle_t.
1334  */
1335 void hb_resume( hb_handle_t * h )
1336 {
1337     if( h->paused )
1338     {
1339 #define job hb_current_job( h )
1340         if( job->st_pause_date != -1 )
1341         {
1342            job->st_paused += hb_get_date() - job->st_pause_date;
1343         }
1344 #undef job
1345
1346         hb_unlock( h->pause_lock );
1347         h->paused = 0;
1348     }
1349 }
1350
1351 /**
1352  * Stops the conversion process.
1353  * @param h Handle to hb_handle_t.
1354  */
1355 void hb_stop( hb_handle_t * h )
1356 {
1357     h->work_die = 1;
1358
1359     h->job_count = hb_count(h);
1360     h->job_count_permanent = 0;
1361
1362     hb_resume( h );
1363 }
1364
1365 /**
1366  * Stops the conversion process.
1367  * @param h Handle to hb_handle_t.
1368  */
1369 void hb_scan_stop( hb_handle_t * h )
1370 {
1371     h->scan_die = 1;
1372
1373     h->job_count = hb_count(h);
1374     h->job_count_permanent = 0;
1375
1376     hb_resume( h );
1377 }
1378
1379 /**
1380  * Returns the state of the conversion process.
1381  * @param h Handle to hb_handle_t.
1382  * @param s Handle to hb_state_t which to copy the state data.
1383  */
1384 void hb_get_state( hb_handle_t * h, hb_state_t * s )
1385 {
1386     hb_lock( h->state_lock );
1387
1388     memcpy( s, &h->state, sizeof( hb_state_t ) );
1389     if ( h->state.state == HB_STATE_SCANDONE || h->state.state == HB_STATE_WORKDONE )
1390         h->state.state = HB_STATE_IDLE;
1391
1392     hb_unlock( h->state_lock );
1393 }
1394
1395 void hb_get_state2( hb_handle_t * h, hb_state_t * s )
1396 {
1397     hb_lock( h->state_lock );
1398
1399     memcpy( s, &h->state, sizeof( hb_state_t ) );
1400
1401     hb_unlock( h->state_lock );
1402 }
1403
1404 /**
1405  * Called in MacGui in UpdateUI to check
1406  *  for a new scan being completed to set a new source
1407  */
1408 int hb_get_scancount( hb_handle_t * h)
1409  {
1410      return h->scanCount;
1411  }
1412
1413 /**
1414  * Closes access to libhb by freeing the hb_handle_t handle ontained in hb_init.
1415  * @param _h Pointer to handle to hb_handle_t.
1416  */
1417 void hb_close( hb_handle_t ** _h )
1418 {
1419     hb_handle_t * h = *_h;
1420     hb_title_t * title;
1421
1422     h->die = 1;
1423     
1424     hb_thread_close( &h->main_thread );
1425
1426     while( ( title = hb_list_item( h->list_title, 0 ) ) )
1427     {
1428         hb_list_rem( h->list_title, title );
1429         if( title->job && title->job->filters )
1430         {
1431             hb_list_close( &title->job->filters );
1432         }
1433         free( title->job );
1434         hb_title_close( &title );
1435     }
1436     hb_list_close( &h->list_title );
1437
1438     hb_list_close( &h->jobs );
1439     hb_lock_close( &h->state_lock );
1440     hb_lock_close( &h->pause_lock );
1441
1442     free( h );
1443     *_h = NULL;
1444 }
1445
1446 /**
1447  * Cleans up libhb at a process level. Call before the app closes. Removes preview directory.
1448  */
1449 void hb_global_close()
1450 {
1451     char dirname[1024];
1452     DIR * dir;
1453     struct dirent * entry;
1454     
1455     /* Find and remove temp folder */
1456     memset( dirname, 0, 1024 );
1457     hb_get_temporary_directory( dirname );
1458
1459     dir = opendir( dirname );
1460     if (dir)
1461     {
1462         while( ( entry = readdir( dir ) ) )
1463         {
1464             char filename[1024];
1465             if( entry->d_name[0] == '.' )
1466             {
1467                 continue;
1468             }
1469             memset( filename, 0, 1024 );
1470             snprintf( filename, 1023, "%s/%s", dirname, entry->d_name );
1471             unlink( filename );
1472         }
1473         closedir( dir );
1474         rmdir( dirname );
1475     }
1476 }
1477
1478 /**
1479  * Monitors the state of the update, scan, and work threads.
1480  * Sets scan done state when scan thread exits.
1481  * Sets work done state when work thread exits.
1482  * @param _h Handle to hb_handle_t
1483  */
1484 static void thread_func( void * _h )
1485 {
1486     hb_handle_t * h = (hb_handle_t *) _h;
1487     char dirname[1024];
1488
1489     h->pid = getpid();
1490
1491     /* Create folder for temporary files */
1492     memset( dirname, 0, 1024 );
1493     hb_get_temporary_directory( dirname );
1494
1495     hb_mkdir( dirname );
1496
1497     while( !h->die )
1498     {
1499         /* In case the check_update thread hangs, it'll die sooner or
1500            later. Then, we join it here */
1501         if( h->update_thread &&
1502             hb_thread_has_exited( h->update_thread ) )
1503         {
1504             hb_thread_close( &h->update_thread );
1505         }
1506
1507         /* Check if the scan thread is done */
1508         if( h->scan_thread &&
1509             hb_thread_has_exited( h->scan_thread ) )
1510         {
1511             hb_thread_close( &h->scan_thread );
1512
1513             if ( h->scan_die )
1514             {
1515                 hb_title_t * title;
1516
1517                 hb_remove_previews( h );
1518                 while( ( title = hb_list_item( h->list_title, 0 ) ) )
1519                 {
1520                     hb_list_rem( h->list_title, title );
1521                     hb_title_close( &title );
1522                 }
1523
1524                 hb_log( "hb_scan: canceled" );
1525             }
1526             else
1527             {
1528                 hb_log( "libhb: scan thread found %d valid title(s)",
1529                         hb_list_count( h->list_title ) );
1530             }
1531             hb_lock( h->state_lock );
1532             h->state.state = HB_STATE_SCANDONE; //originally state.state
1533                         hb_unlock( h->state_lock );
1534                         /*we increment this sessions scan count by one for the MacGui
1535                         to trigger a new source being set */
1536             h->scanCount++;
1537         }
1538
1539         /* Check if the work thread is done */
1540         if( h->work_thread &&
1541             hb_thread_has_exited( h->work_thread ) )
1542         {
1543             hb_thread_close( &h->work_thread );
1544
1545             hb_log( "libhb: work result = %d",
1546                     h->work_error );
1547             hb_lock( h->state_lock );
1548             h->state.state                = HB_STATE_WORKDONE;
1549             h->state.param.workdone.error = h->work_error;
1550
1551             h->job_count = hb_count(h);
1552             if (h->job_count < 1)
1553                 h->job_count_permanent = 0;
1554             hb_unlock( h->state_lock );
1555         }
1556
1557         hb_snooze( 50 );
1558     }
1559
1560     if( h->scan_thread )
1561     {
1562         hb_scan_stop( h );
1563         hb_thread_close( &h->scan_thread );
1564     }
1565     if( h->work_thread )
1566     {
1567         hb_stop( h );
1568         hb_thread_close( &h->work_thread );
1569     }
1570     hb_remove_previews( h );
1571 }
1572
1573 /**
1574  * Returns the PID.
1575  * @param h Handle to hb_handle_t
1576  */
1577 int hb_get_pid( hb_handle_t * h )
1578 {
1579     return h->pid;
1580 }
1581
1582 /**
1583  * Returns the id for the given instance.
1584  * @param h Handle to hb_handle_t
1585  */
1586 int hb_get_instance_id( hb_handle_t * h )
1587 {
1588     return h->id;
1589 }
1590
1591 /**
1592  * Sets the current state.
1593  * @param h Handle to hb_handle_t
1594  * @param s Handle to new hb_state_t
1595  */
1596 void hb_set_state( hb_handle_t * h, hb_state_t * s )
1597 {
1598     hb_lock( h->pause_lock );
1599     hb_lock( h->state_lock );
1600     memcpy( &h->state, s, sizeof( hb_state_t ) );
1601     if( h->state.state == HB_STATE_WORKING ||
1602         h->state.state == HB_STATE_SEARCHING )
1603     {
1604         /* XXX Hack */
1605         if (h->job_count < 1)
1606             h->job_count_permanent = 1;
1607
1608         h->state.param.working.job_cur =
1609             h->job_count_permanent - hb_list_count( h->jobs );
1610         h->state.param.working.job_count = h->job_count_permanent;
1611
1612         // Set which job is being worked on
1613         if (h->current_job)
1614             h->state.param.working.sequence_id = h->current_job->sequence_id;
1615         else
1616             h->state.param.working.sequence_id = 0;
1617     }
1618     hb_unlock( h->state_lock );
1619     hb_unlock( h->pause_lock );
1620 }
1621
1622 /* Passes a pointer to persistent data */
1623 hb_interjob_t * hb_interjob_get( hb_handle_t * h )
1624 {
1625     return h->interjob;
1626 }