OSDN Git Service

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