OSDN Git Service

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