OSDN Git Service

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