OSDN Git Service

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