OSDN Git Service

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