OSDN Git Service

import 0.9.3
[handbrake-jp/handbrake-jp.git] / libhb / hb.c
1 #include "hb.h"
2
3 #include "libavcodec/avcodec.h"
4 #include "libavformat/avformat.h"
5 #include "libswscale/swscale.h"
6
7 struct hb_handle_s
8 {
9     /* The "Check for update" thread */
10     int            build;
11     char           version[16];
12     hb_thread_t  * update_thread;
13
14     /* This thread's only purpose is to check other threads'
15        states */
16     volatile int   die;
17     hb_thread_t  * main_thread;
18     int            pid;
19
20     /* DVD/file scan thread */
21     hb_list_t    * list_title;
22     hb_thread_t  * scan_thread;
23
24     /* The thread which processes the jobs. Others threads are launched
25        from this one (see work.c) */
26     hb_list_t    * jobs;
27     hb_job_t     * current_job;
28     int            job_count;
29     int            job_count_permanent;
30     volatile int   work_die;
31     int            work_error;
32     hb_thread_t  * work_thread;
33
34     int            cpu_count;
35
36     hb_lock_t    * state_lock;
37     hb_state_t     state;
38
39     int            paused;
40     hb_lock_t    * pause_lock;
41     /* For MacGui active queue
42        increments each time the scan thread completes*/
43     int            scanCount;
44
45 };
46
47 hb_work_object_t * hb_objects = NULL;
48
49 static void thread_func( void * );
50
51 /**
52  * Registers work objects, by adding the work object to a liked list.
53  * @param w Handle to hb_work_object_t to register.
54  */
55 void hb_register( hb_work_object_t * w )
56 {
57     w->next    = hb_objects;
58     hb_objects = w;
59 }
60
61 /**
62  * libhb initialization routine.
63  * @param verbose HB_DEBUG_NONE or HB_DEBUG_ALL.
64  * @param update_check signals libhb to check for updated version from HandBrake website.
65  * @return Handle to hb_handle_t for use on all subsequent calls to libhb.
66  */
67 hb_handle_t * hb_init_real( int verbose, int update_check )
68 {
69     hb_handle_t * h = calloc( sizeof( hb_handle_t ), 1 );
70     uint64_t      date;
71
72     /* See hb_deep_log() and hb_log() in common.c */
73     global_verbosity_level = verbose;
74     if( verbose )
75         putenv( "HB_DEBUG=1" );
76
77     /* Check for an update on the website if asked to */
78     h->build = -1;
79
80     if( update_check )
81     {
82         hb_log( "hb_init: checking for updates" );
83         date             = hb_get_date();
84         h->update_thread = hb_update_init( &h->build, h->version );
85
86         for( ;; )
87         {
88             if( hb_thread_has_exited( h->update_thread ) )
89             {
90                 /* Immediate success or failure */
91                 hb_thread_close( &h->update_thread );
92                 break;
93             }
94             if( hb_get_date() > date + 1000 )
95             {
96                 /* Still nothing after one second. Connection problem,
97                    let the thread die */
98                 hb_log( "hb_init: connection problem, not waiting for "
99                         "update_thread" );
100                 break;
101             }
102             hb_snooze( 500 );
103         }
104     }
105
106     /*
107      * Initialise buffer pool
108      */
109     hb_buffer_pool_init();
110
111     /* CPU count detection */
112     hb_log( "hb_init: checking cpu count" );
113     h->cpu_count = hb_get_cpu_count();
114
115     h->list_title = hb_list_init();
116     h->jobs       = hb_list_init();
117
118     h->state_lock  = hb_lock_init();
119     h->state.state = HB_STATE_IDLE;
120
121     h->pause_lock = hb_lock_init();
122
123     /* libavcodec */
124     av_register_all();
125
126     /* Start library thread */
127     hb_log( "hb_init: starting libhb thread" );
128     h->die         = 0;
129     h->main_thread = hb_thread_init( "libhb", thread_func, h,
130                                      HB_NORMAL_PRIORITY );
131
132     return h;
133
134         /* Set the scan count to start at 0 */
135         //scan_count = 0;
136 }
137
138 /**
139  * libhb initialization routine.
140  * This version is to use when calling the dylib, the macro hb_init isn't available from a dylib call!
141  * @param verbose HB_DEBUG_NONE or HB_DEBUG_ALL.
142  * @param update_check signals libhb to check for updated version from HandBrake website.
143  * @return Handle to hb_handle_t for use on all subsequent calls to libhb.
144  */
145 hb_handle_t * hb_init_dl( int verbose, int update_check )
146 {
147     hb_handle_t * h = calloc( sizeof( hb_handle_t ), 1 );
148     uint64_t      date;
149
150     /* See hb_log() in common.c */
151     if( verbose > HB_DEBUG_NONE )
152     {
153         putenv( "HB_DEBUG=1" );
154     }
155
156     /* Check for an update on the website if asked to */
157     h->build = -1;
158
159     if( update_check )
160     {
161         hb_log( "hb_init: checking for updates" );
162         date             = hb_get_date();
163         h->update_thread = hb_update_init( &h->build, h->version );
164
165         for( ;; )
166         {
167             if( hb_thread_has_exited( h->update_thread ) )
168             {
169                 /* Immediate success or failure */
170                 hb_thread_close( &h->update_thread );
171                 break;
172             }
173             if( hb_get_date() > date + 1000 )
174             {
175                 /* Still nothing after one second. Connection problem,
176                    let the thread die */
177                 hb_log( "hb_init: connection problem, not waiting for "
178                         "update_thread" );
179                 break;
180             }
181             hb_snooze( 500 );
182         }
183     }
184
185     /* CPU count detection */
186     hb_log( "hb_init: checking cpu count" );
187     h->cpu_count = hb_get_cpu_count();
188
189     h->list_title = hb_list_init();
190     h->jobs       = hb_list_init();
191     h->current_job = NULL;
192
193     h->state_lock  = hb_lock_init();
194     h->state.state = HB_STATE_IDLE;
195
196     h->pause_lock = hb_lock_init();
197
198     /* libavcodec */
199     avcodec_init();
200     avcodec_register_all();
201
202     /* Start library thread */
203     hb_log( "hb_init: starting libhb thread" );
204     h->die         = 0;
205     h->main_thread = hb_thread_init( "libhb", thread_func, h,
206                                      HB_NORMAL_PRIORITY );
207
208     hb_register( &hb_sync );
209         hb_register( &hb_decmpeg2 );
210         hb_register( &hb_decsub );
211         hb_register( &hb_render );
212         hb_register( &hb_encavcodec );
213         hb_register( &hb_encxvid );
214         hb_register( &hb_encx264 );
215     hb_register( &hb_enctheora );
216         hb_register( &hb_deca52 );
217         hb_register( &hb_decdca );
218         hb_register( &hb_decavcodec );
219         hb_register( &hb_decavcodecv );
220         hb_register( &hb_decavcodecvi );
221         hb_register( &hb_decavcodecai );
222         hb_register( &hb_declpcm );
223         hb_register( &hb_encfaac );
224         hb_register( &hb_enclame );
225         hb_register( &hb_encvorbis );
226
227         return h;
228 }
229
230
231 /**
232  * Returns current version of libhb.
233  * @param h Handle to hb_handle_t.
234  * @return character array of version number.
235  */
236 char * hb_get_version( hb_handle_t * h )
237 {
238     return HB_VERSION;
239 }
240
241 /**
242  * Returns current build of libhb.
243  * @param h Handle to hb_handle_t.
244  * @return character array of build number.
245  */
246 int hb_get_build( hb_handle_t * h )
247 {
248     return HB_BUILD;
249 }
250
251 /**
252  * Checks for needed update.
253  * @param h Handle to hb_handle_t.
254  * @param version Pointer to handle where version will be copied.
255  * @return update indicator.
256  */
257 int hb_check_update( hb_handle_t * h, char ** version )
258 {
259     *version = ( h->build < 0 ) ? NULL : h->version;
260     return h->build;
261 }
262
263 /**
264  * Sets the cpu count to the desired value.
265  * @param h Handle to hb_handle_t
266  * @param cpu_count Number of CPUs to use.
267  */
268 void hb_set_cpu_count( hb_handle_t * h, int cpu_count )
269 {
270     cpu_count    = MAX( 1, cpu_count );
271     cpu_count    = MIN( cpu_count, 8 );
272     h->cpu_count = cpu_count;
273 }
274
275 /**
276  * Initializes a scan of the by calling hb_scan_init
277  * @param h Handle to hb_handle_t
278  * @param path location of VIDEO_TS folder.
279  * @param title_index Desired title to scan.  0 for all titles.
280  */
281 void hb_scan( hb_handle_t * h, const char * path, int title_index )
282 {
283     hb_title_t * title;
284
285     /* Clean up from previous scan */
286     while( ( title = hb_list_item( h->list_title, 0 ) ) )
287     {
288         hb_list_rem( h->list_title, title );
289         hb_title_close( &title );
290     }
291
292     hb_log( "hb_scan: path=%s, title_index=%d", path, title_index );
293     h->scan_thread = hb_scan_init( h, path, title_index, h->list_title );
294 }
295
296 /**
297  * Returns the list of titles found.
298  * @param h Handle to hb_handle_t
299  * @return Handle to hb_list_t of the title list.
300  */
301 hb_list_t * hb_get_titles( hb_handle_t * h )
302 {
303     return h->list_title;
304 }
305
306 /**
307  * Create preview image of desired title a index of picture.
308  * @param h Handle to hb_handle_t.
309  * @param title Handle to hb_title_t of desired title.
310  * @param picture Index in title.
311  * @param buffer Handle to buufer were inage will be drawn.
312  */
313 void hb_get_preview( hb_handle_t * h, hb_title_t * title, int picture,
314                      uint8_t * buffer )
315 {
316     hb_job_t           * job = title->job;
317     char                 filename[1024];
318     FILE               * file;
319     uint8_t            * buf1, * buf2, * buf3, * buf4, * pen;
320     uint32_t           * p32, swsflags;
321     AVPicture            pic_in, pic_preview, pic_deint, pic_crop, pic_scale;
322     struct SwsContext  * context;
323     int                  i;
324     int                  rgb_width = ((job->width + 7) >> 3) << 3;
325     int                  preview_size;
326
327     swsflags = SWS_LANCZOS;
328 #ifndef __x86_64__
329     swsflags |= SWS_ACCURATE_RND;
330 #endif  /* __x86_64__ */
331
332     buf1 = av_malloc( avpicture_get_size( PIX_FMT_YUV420P, title->width, title->height ) );
333     buf2 = av_malloc( avpicture_get_size( PIX_FMT_YUV420P, title->width, title->height ) );
334     buf3 = av_malloc( avpicture_get_size( PIX_FMT_YUV420P, job->width, job->height ) );
335     buf4 = av_malloc( avpicture_get_size( PIX_FMT_RGBA32, rgb_width, job->height ) );
336     avpicture_fill( &pic_in, buf1, PIX_FMT_YUV420P,
337                     title->width, title->height );
338     avpicture_fill( &pic_deint, buf2, PIX_FMT_YUV420P,
339                     title->width, title->height );
340     avpicture_fill( &pic_scale, buf3, PIX_FMT_YUV420P,
341                     job->width, job->height );
342     avpicture_fill( &pic_preview, buf4, PIX_FMT_RGBA32,
343                     rgb_width, job->height );
344
345     // Allocate the AVPicture frames and fill in
346
347     memset( filename, 0, 1024 );
348
349     hb_get_tempory_filename( h, filename, "%x%d",
350                              (intptr_t) title, picture );
351
352     file = fopen( filename, "r" );
353     if( !file )
354     {
355         hb_log( "hb_get_preview: fopen failed" );
356         return;
357     }
358
359     fread( buf1, avpicture_get_size( PIX_FMT_YUV420P, title->width, title->height), 1, file );
360     fclose( file );
361
362     if( job->deinterlace )
363     {
364         // Deinterlace and crop
365         avpicture_deinterlace( &pic_deint, &pic_in, PIX_FMT_YUV420P, title->width, title->height );
366         av_picture_crop( &pic_crop, &pic_deint, PIX_FMT_YUV420P, job->crop[0], job->crop[2] );
367     }
368     else
369     {
370         // Crop
371         av_picture_crop( &pic_crop, &pic_in, PIX_FMT_YUV420P, job->crop[0], job->crop[2] );
372     }
373
374     // Get scaling context
375     context = sws_getContext(title->width  - (job->crop[2] + job->crop[3]),
376                              title->height - (job->crop[0] + job->crop[1]),
377                              PIX_FMT_YUV420P,
378                              job->width, job->height, PIX_FMT_YUV420P,
379                              swsflags, NULL, NULL, NULL);
380
381     // Scale
382     sws_scale(context,
383               pic_crop.data, pic_crop.linesize,
384               0, title->height - (job->crop[0] + job->crop[1]),
385               pic_scale.data, pic_scale.linesize);
386
387     // Free context
388     sws_freeContext( context );
389
390     // Get preview context
391     context = sws_getContext(rgb_width, job->height, PIX_FMT_YUV420P,
392                               rgb_width, job->height, PIX_FMT_RGBA32,
393                               swsflags, NULL, NULL, NULL);
394
395     // Create preview
396     sws_scale(context,
397               pic_scale.data, pic_scale.linesize,
398               0, job->height,
399               pic_preview.data, pic_preview.linesize);
400
401     // Free context
402     sws_freeContext( context );
403
404     /* Gray background */
405     p32 = (uint32_t *) buffer;
406     for( i = 0; i < ( title->width + 2 ) * ( title->height + 2 ); i++ )
407     {
408         p32[i] = 0xFF808080;
409     }
410
411     /* Draw the picture, centered, and draw the cropping zone */
412     preview_size = pic_preview.linesize[0];
413     pen = buffer + ( title->height - job->height ) *
414         ( title->width + 2 ) * 2 + ( title->width - job->width ) * 2;
415     memset( pen, 0xFF, 4 * ( job->width + 2 ) );
416     pen += 4 * ( title->width + 2 );
417     for( i = 0; i < job->height; i++ )
418     {
419         uint8_t * nextLine;
420         nextLine = pen + 4 * ( title->width + 2 );
421         memset( pen, 0xFF, 4 );
422         pen += 4;
423         memcpy( pen, buf4 + preview_size * i, 4 * job->width );
424         pen += 4 * job->width;
425         memset( pen, 0xFF, 4 );
426         pen = nextLine;
427     }
428     memset( pen, 0xFF, 4 * ( job->width + 2 ) );
429
430     // Clean up
431     avpicture_free( &pic_preview );
432     avpicture_free( &pic_scale );
433     avpicture_free( &pic_deint );
434     avpicture_free( &pic_in );
435 }
436
437  /**
438  * Analyzes a frame to detect interlacing artifacts
439  * and returns true if interlacing (combing) is found.
440  *
441  * Code taken from Thomas Oestreich's 32detect filter
442  * in the Transcode project, with minor formatting changes.
443  *
444  * @param buf         An hb_buffer structure holding valid frame data
445  * @param width       The frame's width in pixels
446  * @param height      The frame's height in pixels
447  * @param color_equal Sensitivity for detecting similar colors
448  * @param color_diff  Sensitivity for detecting different colors
449  * @param threshold   Sensitivity for flagging planes as combed
450  * @param prog_equal  Sensitivity for detecting similar colors on progressive frames
451  * @param prog_diff   Sensitivity for detecting different colors on progressive frames
452  * @param prog_threshold Sensitivity for flagging progressive frames as combed
453  */
454 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 )
455 {
456     int j, k, n, off, cc_1, cc_2, cc[3], flag[3] ;
457     uint16_t s1, s2, s3, s4;
458     cc_1 = 0; cc_2 = 0;
459
460     int offset = 0;
461     
462     if ( buf->flags & 16 )
463     {
464         /* Frame is progressive, be more discerning. */
465         color_diff = prog_diff;
466         color_equal = prog_equal;
467         threshold = prog_threshold;
468     }
469
470     /* One pas for Y, one pass for Cb, one pass for Cr */    
471     for( k = 0; k < 3; k++ )
472     {
473         if( k == 1 )
474         {
475             /* Y has already been checked, now offset by Y's dimensions
476                and divide all the other values by 2, since Cr and Cb
477                are half-size compared to Y.                               */
478             offset = width * height;
479             width >>= 1;
480             height >>= 1;
481         }
482         else if ( k == 2 )
483         {
484             /* Y and Cb are done, so the offset needs to be bumped
485                so it's width*height + (width / 2) * (height / 2)  */
486             offset *= 5/4;
487         }
488
489         for( j = 0; j < width; ++j )
490         {
491             off = 0;
492
493             for( n = 0; n < ( height - 4 ); n = n + 2 )
494             {
495                 /* Look at groups of 4 sequential horizontal lines */
496                 s1 = ( ( buf->data + offset )[ off + j             ] & 0xff );
497                 s2 = ( ( buf->data + offset )[ off + j + width     ] & 0xff );
498                 s3 = ( ( buf->data + offset )[ off + j + 2 * width ] & 0xff );
499                 s4 = ( ( buf->data + offset )[ off + j + 3 * width ] & 0xff );
500
501                 /* Note if the 1st and 2nd lines are more different in
502                    color than the 1st and 3rd lines are similar in color.*/
503                 if ( ( abs( s1 - s3 ) < color_equal ) &&
504                      ( abs( s1 - s2 ) > color_diff ) )
505                         ++cc_1;
506
507                 /* Note if the 2nd and 3rd lines are more different in
508                    color than the 2nd and 4th lines are similar in color.*/
509                 if ( ( abs( s2 - s4 ) < color_equal ) &&
510                      ( abs( s2 - s3 ) > color_diff) )
511                         ++cc_2;
512
513                 /* Now move down 2 horizontal lines before starting over.*/
514                 off += 2 * width;
515             }
516         }
517
518         // compare results
519         /*  The final cc score for a plane is the percentage of combed pixels it contains.
520             Because sensitivity goes down to hundreths of a percent, multiply by 1000
521             so it will be easy to compare against the threhold value which is an integer. */
522         cc[k] = (int)( ( cc_1 + cc_2 ) * 1000.0 / ( width * height ) );
523     }
524
525
526     /* HandBrake is all yuv420, so weight the average percentage of all 3 planes accordingly.*/
527     int average_cc = ( 2 * cc[0] + ( cc[1] / 2 ) + ( cc[2] / 2 ) ) / 3;
528     
529     /* Now see if that average percentage of combed pixels surpasses the threshold percentage given by the user.*/
530     if( average_cc > threshold )
531     {
532 #if 0
533             hb_log("Average %i combed (Threshold %i) %i/%i/%i | PTS: %lld (%fs) %s", average_cc, threshold, cc[0], cc[1], cc[2], buf->start, (float)buf->start / 90000, (buf->flags & 16) ? "Film" : "Video" );
534 #endif
535         return 1;
536     }
537
538 #if 0
539     hb_log("SKIPPED Average %i combed (Threshold %i) %i/%i/%i | PTS: %lld (%fs) %s", average_cc, threshold, cc[0], cc[1], cc[2], buf->start, (float)buf->start / 90000, (buf->flags & 16) ? "Film" : "Video" );
540 #endif
541
542     /* Reaching this point means no combing detected. */
543     return 0;
544
545 }
546
547 /**
548  * Calculates job width and height for anamorphic content,
549  *
550  * @param job Handle to hb_job_t
551  * @param output_width Pointer to returned storage width
552  * @param output_height Pointer to returned storage height
553  * @param output_par_width Pointer to returned pixel width
554  @ param output_par_height Pointer to returned pixel height
555  */
556 void hb_set_anamorphic_size( hb_job_t * job,
557         int *output_width, int *output_height,
558         int *output_par_width, int *output_par_height )
559 {
560     /* "Loose" anamorphic.
561         - Uses mod16-compliant dimensions,
562         - Allows users to set the width
563         - Handles ITU pixel aspects
564     */
565
566     /* Set up some variables to make the math easier to follow. */
567     hb_title_t * title = job->title;
568     int cropped_width = title->width - job->crop[2] - job->crop[3] ;
569     int cropped_height = title->height - job->crop[0] - job->crop[1] ;
570     double storage_aspect = (double)cropped_width / (double)cropped_height;
571     int width = job->width;
572     int height; // Gets set later, ignore user job->height value
573     int mod = job->modulus;
574     double aspect = title->aspect;
575
576     /* Gotta handle bounding dimensions differently
577        than for non-anamorphic encodes:
578        If the width is too big, just reset it with no rescaling.
579        Instead of using the aspect-scaled job height,
580        we need to see if the job width divided by the storage aspect
581        is bigger than the max. If so, set it to the max (this is sloppy).
582        If not, set job height to job width divided by storage aspect.
583     */
584
585     if ( job->maxWidth && (job->maxWidth < job->width) )
586         width = job->maxWidth;
587
588     height = (double)width / storage_aspect;
589     if ( job->maxHeight && (job->maxHeight < height) )
590         height = job->maxHeight;
591
592     /* In case the user specified a modulus, use it */
593     if (job->modulus)
594         mod = job->modulus;
595     else
596         mod = 16;
597
598     /* Time to get picture dimensions that divide cleanly.*/
599     width  = MULTIPLE_MOD( width, mod);
600     height = MULTIPLE_MOD( height, mod);
601
602     /* Verify these new dimensions don't violate max height and width settings */
603     if ( job->maxWidth && (job->maxWidth < job->width) )
604         width = job->maxWidth;
605     if ( job->maxHeight && (job->maxHeight < height) )
606         height = job->maxHeight;
607     
608     int pixel_aspect_width = job->pixel_aspect_width;
609     int pixel_aspect_height = job->pixel_aspect_height;
610     
611     /* If a source was really 704*480 and hard matted with cropping
612        to 720*480, replace the PAR values with the ITU broadcast ones. */
613     if (title->width == 720 && cropped_width <= 706)
614     {
615         // convert aspect to a scaled integer so we can test for 16:9 & 4:3
616         // aspect ratios ignoring insignificant differences in the LSBs of
617         // the floating point representation.
618         int iaspect = aspect * 9.;
619
620         /* Handle ITU PARs */
621         if (title->height == 480)
622         {
623             /* It's NTSC */
624             if (iaspect == 16)
625             {
626                 /* It's widescreen */
627                 pixel_aspect_width = 40;
628                 pixel_aspect_height = 33;
629             }
630             else if (iaspect == 12)
631             {
632                 /* It's 4:3 */
633                 pixel_aspect_width = 10;
634                 pixel_aspect_height = 11;
635             }
636         }
637         else if (title->height == 576)
638         {
639             /* It's PAL */
640             if(iaspect == 16)
641             {
642                 /* It's widescreen */
643                 pixel_aspect_width = 16;
644                 pixel_aspect_height = 11;
645             }
646             else if (iaspect == 12)
647             {
648                 /* It's 4:3 */
649                 pixel_aspect_width = 12;
650                 pixel_aspect_height = 11;
651             }
652         }
653     }
654
655     /* Figure out what dimensions the source would display at. */
656     int source_display_width = cropped_width * (double)pixel_aspect_width /
657                                (double)pixel_aspect_height ;
658
659     /* The film AR is the source's display width / cropped source height.
660        The output display width is the output height * film AR.
661        The output PAR is the output display width / output storage width. */
662     pixel_aspect_width = height * source_display_width / cropped_height;
663     pixel_aspect_height = width;
664
665     /* Pass the results back to the caller */
666     *output_width = width;
667     *output_height = height;
668
669     /* While x264 is smart enough to reduce fractions on its own, libavcodec
670        needs some help with the math, so lose superfluous factors.            */
671     hb_reduce( output_par_width, output_par_height,
672                pixel_aspect_width, pixel_aspect_height );
673 }
674
675 /**
676  * Calculates job width, height, and cropping parameters.
677  * @param job Handle to hb_job_t.
678  * @param aspect Desired aspect ratio. Value of -1 uses title aspect.
679  * @param pixels Maximum desired pixel count.
680  */
681 void hb_set_size( hb_job_t * job, double aspect, int pixels )
682 {
683     hb_title_t * title = job->title;
684
685     int croppedWidth  = title->width - title->crop[2] - title->crop[3];
686     int croppedHeight = title->height - title->crop[0] - title->crop[1];
687     double croppedAspect = title->aspect * title->height * croppedWidth /
688                            croppedHeight / title->width;
689     int addCrop;
690     int i, w, h;
691
692     if( aspect <= 0 )
693     {
694         /* Keep the best possible aspect ratio */
695         aspect = croppedAspect;
696     }
697
698     /* Crop if necessary to obtain the desired ratio */
699     memcpy( job->crop, title->crop, 4 * sizeof( int ) );
700     if( aspect < croppedAspect )
701     {
702         /* Need to crop on the left and right */
703         addCrop = croppedWidth - aspect * croppedHeight * title->width /
704                     title->aspect / title->height;
705         if( addCrop & 3 )
706         {
707             addCrop = ( addCrop + 1 ) / 2;
708             job->crop[2] += addCrop;
709             job->crop[3] += addCrop;
710         }
711         else if( addCrop & 2 )
712         {
713             addCrop /= 2;
714             job->crop[2] += addCrop - 1;
715             job->crop[3] += addCrop + 1;
716         }
717         else
718         {
719             addCrop /= 2;
720             job->crop[2] += addCrop;
721             job->crop[3] += addCrop;
722         }
723     }
724     else if( aspect > croppedAspect )
725     {
726         /* Need to crop on the top and bottom */
727         addCrop = croppedHeight - croppedWidth * title->aspect *
728             title->height / aspect / title->width;
729         if( addCrop & 3 )
730         {
731             addCrop = ( addCrop + 1 ) / 2;
732             job->crop[0] += addCrop;
733             job->crop[1] += addCrop;
734         }
735         else if( addCrop & 2 )
736         {
737             addCrop /= 2;
738             job->crop[0] += addCrop - 1;
739             job->crop[1] += addCrop + 1;
740         }
741         else
742         {
743             addCrop /= 2;
744             job->crop[0] += addCrop;
745             job->crop[1] += addCrop;
746         }
747     }
748
749     /* Compute a resolution from the number of pixels and aspect */
750     for( i = 0;; i++ )
751     {
752         w = 16 * i;
753         h = MULTIPLE_16( (int)( (double)w / aspect ) );
754         if( w * h > pixels )
755         {
756             break;
757         }
758     }
759     i--;
760     job->width  = 16 * i;
761     job->height = MULTIPLE_16( (int)( (double)job->width / aspect ) );
762 }
763
764 /**
765  * Returns the number of jobs in the queue.
766  * @param h Handle to hb_handle_t.
767  * @return Number of jobs.
768  */
769 int hb_count( hb_handle_t * h )
770 {
771     return hb_list_count( h->jobs );
772 }
773
774 /**
775  * Returns handle to job at index i within the job list.
776  * @param h Handle to hb_handle_t.
777  * @param i Index of job.
778  * @returns Handle to hb_job_t of desired job.
779  */
780 hb_job_t * hb_job( hb_handle_t * h, int i )
781 {
782     return hb_list_item( h->jobs, i );
783 }
784
785 hb_job_t * hb_current_job( hb_handle_t * h )
786 {
787     return( h->current_job );
788 }
789
790 /**
791  * Adds a job to the job list.
792  * @param h Handle to hb_handle_t.
793  * @param job Handle to hb_job_t.
794  */
795 void hb_add( hb_handle_t * h, hb_job_t * job )
796 {
797     hb_job_t      * job_copy;
798     hb_title_t    * title,    * title_copy;
799     hb_chapter_t  * chapter,  * chapter_copy;
800     hb_audio_t    * audio;
801     hb_subtitle_t * subtitle, * subtitle_copy;
802     int             i;
803     char            audio_lang[4];
804
805     /* Copy the title */
806     title      = job->title;
807     title_copy = malloc( sizeof( hb_title_t ) );
808     memcpy( title_copy, title, sizeof( hb_title_t ) );
809
810     title_copy->list_chapter = hb_list_init();
811     for( i = 0; i < hb_list_count( title->list_chapter ); i++ )
812     {
813         chapter      = hb_list_item( title->list_chapter, i );
814         chapter_copy = malloc( sizeof( hb_chapter_t ) );
815         memcpy( chapter_copy, chapter, sizeof( hb_chapter_t ) );
816         hb_list_add( title_copy->list_chapter, chapter_copy );
817     }
818
819     /* Copy the audio track(s) we want */
820     title_copy->list_audio = hb_list_init();
821
822     for( i = 0; i < hb_list_count(job->list_audio); i++ )
823     {
824         if( ( audio = hb_list_item( job->list_audio, i ) ) )
825         {
826             hb_list_add( title_copy->list_audio, hb_audio_copy(audio) );
827         }
828     }
829
830     title_copy->list_subtitle = hb_list_init();
831
832     /*
833      * The following code is confusing, there are three ways in which
834      * we select subtitles and it depends on whether this is single or
835      * two pass mode.
836      *
837      * subtitle_scan may be enabled, in which case the first pass
838      * scans all subtitles of that language. The second pass does not
839      * select any because they are set at the end of the first pass.
840      *
841      * native_language may have a preferred language, in which case we
842      * may be switching the language we want for the subtitles in the
843      * first pass of a single pass, or the second pass of a two pass.
844      *
845      * We may have manually selected a subtitle, in which case that is
846      * selected in the first pass of a single pass, or the second of a
847      * two pass.
848      */
849     memset( audio_lang, 0, sizeof( audio_lang ) );
850
851     if ( job->indepth_scan || job->native_language ) {
852
853         /*
854          * Find the first audio language that is being encoded
855          */
856         for( i = 0; i < hb_list_count(job->list_audio); i++ )
857         {
858             if( ( audio = hb_list_item( job->list_audio, i ) ) )
859             {
860                 strncpy(audio_lang, audio->config.lang.iso639_2, sizeof(audio_lang));
861                 break;
862             }
863         }
864
865         /*
866          * In all cases switch the language if we need to to our native
867          * language.
868          */
869         if( job->native_language )
870         {
871             if( strncasecmp( job->native_language, audio_lang,
872                              sizeof( audio_lang ) ) != 0 )
873             {
874
875                 if( job->pass != 2 )
876                 {
877                     hb_log( "Enabled subtitles in native language '%s', audio is in '%s'",
878                             job->native_language, audio_lang);
879                 }
880                 /*
881                  * The main audio track is not in our native language, so switch
882                  * the subtitles to use our native language instead.
883                  */
884                 strncpy( audio_lang, job->native_language, sizeof( audio_lang ) );
885             } else {
886                 /*
887                  * native language is irrelevent, free it.
888                  */
889                 free( job->native_language );
890                 job->native_language = NULL;
891             }
892         }
893     }
894
895     /*
896      * If doing a subtitle scan then add all the matching subtitles for this
897      * language.
898      */
899     if ( job->indepth_scan )
900     {
901         for( i=0; i < hb_list_count( title->list_subtitle ); i++ )
902         {
903             subtitle = hb_list_item( title->list_subtitle, i );
904             if( strcmp( subtitle->iso639_2, audio_lang ) == 0 )
905             {
906                 /*
907                  * Matched subtitle language with audio language, so
908                  * add this to our list to scan.
909                  *
910                  * We will update the subtitle list on the second pass
911                  * later after the first pass has completed.
912                  */
913                 subtitle_copy = malloc( sizeof( hb_subtitle_t ) );
914                 memcpy( subtitle_copy, subtitle, sizeof( hb_subtitle_t ) );
915                 hb_list_add( title_copy->list_subtitle, subtitle_copy );
916                 if ( job->native_language ) {
917                     /*
918                      * With native language just select the
919                      * first match in our langiage, not all of
920                      * them. Subsequent ones are likely to be commentary
921                      */
922                     break;
923                 }
924             }
925         }
926     } else {
927         /*
928          * Not doing a subtitle scan in this pass, but maybe we are in the
929          * first pass?
930          */
931         if( job->select_subtitle )
932         {
933             /*
934              * Don't add subtitles here, we'll add them via select_subtitle
935              * at the end of the subtitle_scan.
936              */
937         } else {
938             /*
939              * Definitely not doing a subtitle scan.
940              */
941             if( job->pass != 1 && job->native_language )
942             {
943                 /*
944                  * We are not doing a subtitle scan but do want the
945                  * native langauge subtitle selected, so select it
946                  * for pass 0 or pass 2 of a two pass.
947                  */
948                 for( i=0; i < hb_list_count( title->list_subtitle ); i++ )
949                 {
950                     subtitle = hb_list_item( title->list_subtitle, i );
951                     if( strcmp( subtitle->iso639_2, audio_lang ) == 0 )
952                     {
953                         /*
954                          * Matched subtitle language with audio language, so
955                          * add this to our list to scan.
956                          */
957                         subtitle_copy = malloc( sizeof( hb_subtitle_t ) );
958                         memcpy( subtitle_copy, subtitle, sizeof( hb_subtitle_t ) );
959                         hb_list_add( title_copy->list_subtitle, subtitle_copy );
960                         break;
961                     }
962                 }
963             } else {
964                 /*
965                  * Manually selected subtitle, in which case only
966                  * bother adding them for pass 0 or pass 2 of a two
967                  * pass.
968                  */
969                 if( job->pass != 1 )
970                 {
971                     if( ( subtitle = hb_list_item( title->list_subtitle, job->subtitle ) ) )
972                     {
973                         subtitle_copy = malloc( sizeof( hb_subtitle_t ) );
974                         memcpy( subtitle_copy, subtitle, sizeof( hb_subtitle_t ) );
975                         hb_list_add( title_copy->list_subtitle, subtitle_copy );
976                     }
977                 }
978             }
979         }
980     }
981
982     /* Copy the job */
983     job_copy        = calloc( sizeof( hb_job_t ), 1 );
984     memcpy( job_copy, job, sizeof( hb_job_t ) );
985     title_copy->job = job_copy;
986     job_copy->title = title_copy;
987     job_copy->list_audio = title_copy->list_audio;
988     job_copy->file  = strdup( job->file );
989     job_copy->h     = h;
990     job_copy->pause = h->pause_lock;
991
992     /* Copy the job filter list */
993     if( job->filters )
994     {
995         int i;
996         int filter_count = hb_list_count( job->filters );
997         job_copy->filters = hb_list_init();
998         for( i = 0; i < filter_count; i++ )
999         {
1000             /*
1001              * Copy the filters, since the MacGui reuses the global filter objects
1002              * meaning that queued up jobs overwrite the previous filter settings.
1003              * In reality, settings is probably the only field that needs duplicating
1004              * since it's the only value that is ever changed. But name is duplicated
1005              * as well for completeness. Not copying private_data since it gets
1006              * created for each job in renderInit.
1007              */
1008             hb_filter_object_t * filter = hb_list_item( job->filters, i );
1009             hb_filter_object_t * filter_copy = malloc( sizeof( hb_filter_object_t ) );
1010             memcpy( filter_copy, filter, sizeof( hb_filter_object_t ) );
1011             if( filter->name )
1012                 filter_copy->name = strdup( filter->name );
1013             if( filter->settings )
1014                 filter_copy->settings = strdup( filter->settings );
1015             hb_list_add( job_copy->filters, filter_copy );
1016         }
1017     }
1018
1019     /* Add the job to the list */
1020     hb_list_add( h->jobs, job_copy );
1021     h->job_count = hb_count(h);
1022     h->job_count_permanent++;
1023 }
1024
1025 /**
1026  * Removes a job from the job list.
1027  * @param h Handle to hb_handle_t.
1028  * @param job Handle to hb_job_t.
1029  */
1030 void hb_rem( hb_handle_t * h, hb_job_t * job )
1031 {
1032     hb_list_rem( h->jobs, job );
1033
1034     h->job_count = hb_count(h);
1035     if (h->job_count_permanent)
1036         h->job_count_permanent--;
1037
1038     /* XXX free everything XXX */
1039 }
1040
1041 /**
1042  * Starts the conversion process.
1043  * Sets state to HB_STATE_WORKING.
1044  * calls hb_work_init, to launch work thread. Stores handle to work thread.
1045  * @param h Handle to hb_handle_t.
1046  */
1047 void hb_start( hb_handle_t * h )
1048 {
1049     /* XXX Hack */
1050     h->job_count = hb_list_count( h->jobs );
1051     h->job_count_permanent = h->job_count;
1052
1053     hb_lock( h->state_lock );
1054     h->state.state = HB_STATE_WORKING;
1055 #define p h->state.param.working
1056     p.progress  = 0.0;
1057     p.job_cur   = 1;
1058     p.job_count = h->job_count;
1059     p.rate_cur  = 0.0;
1060     p.rate_avg  = 0.0;
1061     p.hours     = -1;
1062     p.minutes   = -1;
1063     p.seconds   = -1;
1064     p.sequence_id = 0;
1065 #undef p
1066     hb_unlock( h->state_lock );
1067
1068     h->paused = 0;
1069
1070     h->work_die    = 0;
1071     h->work_thread = hb_work_init( h->jobs, h->cpu_count,
1072                                    &h->work_die, &h->work_error, &h->current_job );
1073 }
1074
1075 /**
1076  * Pauses the conversion process.
1077  * @param h Handle to hb_handle_t.
1078  */
1079 void hb_pause( hb_handle_t * h )
1080 {
1081     if( !h->paused )
1082     {
1083         hb_lock( h->pause_lock );
1084         h->paused = 1;
1085
1086         hb_lock( h->state_lock );
1087         h->state.state = HB_STATE_PAUSED;
1088         hb_unlock( h->state_lock );
1089     }
1090 }
1091
1092 /**
1093  * Resumes the conversion process.
1094  * @param h Handle to hb_handle_t.
1095  */
1096 void hb_resume( hb_handle_t * h )
1097 {
1098     if( h->paused )
1099     {
1100         hb_unlock( h->pause_lock );
1101         h->paused = 0;
1102     }
1103 }
1104
1105 /**
1106  * Stops the conversion process.
1107  * @param h Handle to hb_handle_t.
1108  */
1109 void hb_stop( hb_handle_t * h )
1110 {
1111     h->work_die = 1;
1112
1113     h->job_count = hb_count(h);
1114     h->job_count_permanent = 0;
1115
1116     hb_resume( h );
1117 }
1118
1119 /**
1120  * Returns the state of the conversion process.
1121  * @param h Handle to hb_handle_t.
1122  * @param s Handle to hb_state_t which to copy the state data.
1123  */
1124 void hb_get_state( hb_handle_t * h, hb_state_t * s )
1125 {
1126     hb_lock( h->state_lock );
1127
1128     memcpy( s, &h->state, sizeof( hb_state_t ) );
1129     if ( h->state.state == HB_STATE_SCANDONE || h->state.state == HB_STATE_WORKDONE )
1130         h->state.state = HB_STATE_IDLE;
1131
1132     hb_unlock( h->state_lock );
1133 }
1134
1135 void hb_get_state2( hb_handle_t * h, hb_state_t * s )
1136 {
1137     hb_lock( h->state_lock );
1138
1139     memcpy( s, &h->state, sizeof( hb_state_t ) );
1140
1141     hb_unlock( h->state_lock );
1142 }
1143
1144 /**
1145  * Called in MacGui in UpdateUI to check
1146  *  for a new scan being completed to set a new source
1147  */
1148 int hb_get_scancount( hb_handle_t * h)
1149  {
1150      return h->scanCount;
1151  }
1152
1153 /**
1154  * Closes access to libhb by freeing the hb_handle_t handle ontained in hb_init_real.
1155  * @param _h Pointer to handle to hb_handle_t.
1156  */
1157 void hb_close( hb_handle_t ** _h )
1158 {
1159     hb_handle_t * h = *_h;
1160     hb_title_t * title;
1161
1162     h->die = 1;
1163     hb_thread_close( &h->main_thread );
1164
1165     while( ( title = hb_list_item( h->list_title, 0 ) ) )
1166     {
1167         hb_list_rem( h->list_title, title );
1168         if( title->job && title->job->filters )
1169         {
1170             hb_list_close( &title->job->filters );
1171         }
1172         free( title->job );
1173         hb_title_close( &title );
1174     }
1175     hb_list_close( &h->list_title );
1176
1177     hb_list_close( &h->jobs );
1178     hb_lock_close( &h->state_lock );
1179     hb_lock_close( &h->pause_lock );
1180     free( h );
1181     *_h = NULL;
1182
1183 }
1184
1185 /**
1186  * Monitors the state of the update, scan, and work threads.
1187  * Sets scan done state when scan thread exits.
1188  * Sets work done state when work thread exits.
1189  * @param _h Handle to hb_handle_t
1190  */
1191 static void thread_func( void * _h )
1192 {
1193     hb_handle_t * h = (hb_handle_t *) _h;
1194     char dirname[1024];
1195     DIR * dir;
1196     struct dirent * entry;
1197
1198     h->pid = getpid();
1199
1200     /* Create folder for temporary files */
1201     memset( dirname, 0, 1024 );
1202     hb_get_tempory_directory( h, dirname );
1203
1204     hb_mkdir( dirname );
1205
1206     while( !h->die )
1207     {
1208         /* In case the check_update thread hangs, it'll die sooner or
1209            later. Then, we join it here */
1210         if( h->update_thread &&
1211             hb_thread_has_exited( h->update_thread ) )
1212         {
1213             hb_thread_close( &h->update_thread );
1214         }
1215
1216         /* Check if the scan thread is done */
1217         if( h->scan_thread &&
1218             hb_thread_has_exited( h->scan_thread ) )
1219         {
1220             hb_thread_close( &h->scan_thread );
1221
1222             hb_log( "libhb: scan thread found %d valid title(s)",
1223                     hb_list_count( h->list_title ) );
1224             hb_lock( h->state_lock );
1225             h->state.state = HB_STATE_SCANDONE; //originally state.state
1226                         hb_unlock( h->state_lock );
1227                         /*we increment this sessions scan count by one for the MacGui
1228                         to trigger a new source being set */
1229             h->scanCount++;
1230         }
1231
1232         /* Check if the work thread is done */
1233         if( h->work_thread &&
1234             hb_thread_has_exited( h->work_thread ) )
1235         {
1236             hb_thread_close( &h->work_thread );
1237
1238             hb_log( "libhb: work result = %d",
1239                     h->work_error );
1240             hb_lock( h->state_lock );
1241             h->state.state                = HB_STATE_WORKDONE;
1242             h->state.param.workdone.error = h->work_error;
1243
1244             h->job_count = hb_count(h);
1245             if (h->job_count < 1)
1246                 h->job_count_permanent = 0;
1247             hb_unlock( h->state_lock );
1248         }
1249
1250         hb_snooze( 50 );
1251     }
1252
1253     if( h->work_thread )
1254     {
1255         hb_stop( h );
1256         hb_thread_close( &h->work_thread );
1257     }
1258
1259     /* Remove temp folder */
1260     dir = opendir( dirname );
1261     if (dir)
1262     {
1263         while( ( entry = readdir( dir ) ) )
1264         {
1265             char filename[1024];
1266             if( entry->d_name[0] == '.' )
1267             {
1268                 continue;
1269             }
1270             memset( filename, 0, 1024 );
1271             snprintf( filename, 1023, "%s/%s", dirname, entry->d_name );
1272             unlink( filename );
1273         }
1274         closedir( dir );
1275         rmdir( dirname );
1276     }
1277 }
1278
1279 /**
1280  * Returns the PID.
1281  * @param h Handle to hb_handle_t
1282  */
1283 int hb_get_pid( hb_handle_t * h )
1284 {
1285     return h->pid;
1286 }
1287
1288 /**
1289  * Sets the current state.
1290  * @param h Handle to hb_handle_t
1291  * @param s Handle to new hb_state_t
1292  */
1293 void hb_set_state( hb_handle_t * h, hb_state_t * s )
1294 {
1295     hb_lock( h->pause_lock );
1296     hb_lock( h->state_lock );
1297     memcpy( &h->state, s, sizeof( hb_state_t ) );
1298     if( h->state.state == HB_STATE_WORKING )
1299     {
1300         /* XXX Hack */
1301         if (h->job_count < 1)
1302             h->job_count_permanent = 1;
1303
1304         h->state.param.working.job_cur =
1305             h->job_count_permanent - hb_list_count( h->jobs );
1306         h->state.param.working.job_count = h->job_count_permanent;
1307
1308         // Set which job is being worked on
1309         if (h->current_job)
1310             h->state.param.working.sequence_id = h->current_job->sequence_id;
1311         else
1312             h->state.param.working.sequence_id = 0;
1313     }
1314     hb_unlock( h->state_lock );
1315     hb_unlock( h->pause_lock );
1316 }