OSDN Git Service

MacGui: Fixed the warning in ChapterTitles for real this time.
[handbrake-jp/handbrake-jp-git.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_log() in common.c */
73     if( verbose > HB_DEBUG_NONE )
74     {
75         putenv( "HB_DEBUG=1" );
76                 av_log_set_level(AV_LOG_DEBUG);
77     }
78
79     /* Check for an update on the website if asked to */
80     h->build = -1;
81
82     if( update_check )
83     {
84         hb_log( "hb_init: checking for updates" );
85         date             = hb_get_date();
86         h->update_thread = hb_update_init( &h->build, h->version );
87
88         for( ;; )
89         {
90             if( hb_thread_has_exited( h->update_thread ) )
91             {
92                 /* Immediate success or failure */
93                 hb_thread_close( &h->update_thread );
94                 break;
95             }
96             if( hb_get_date() > date + 1000 )
97             {
98                 /* Still nothing after one second. Connection problem,
99                    let the thread die */
100                 hb_log( "hb_init: connection problem, not waiting for "
101                         "update_thread" );
102                 break;
103             }
104             hb_snooze( 500 );
105         }
106     }
107
108     /*
109      * Initialise buffer pool
110      */
111     hb_buffer_pool_init();
112
113     /* CPU count detection */
114     hb_log( "hb_init: checking cpu count" );
115     h->cpu_count = hb_get_cpu_count();
116
117     h->list_title = hb_list_init();
118     h->jobs       = hb_list_init();
119
120     h->state_lock  = hb_lock_init();
121     h->state.state = HB_STATE_IDLE;
122
123     h->pause_lock = hb_lock_init();
124
125     /* libavcodec */
126     av_register_all();
127
128     /* Start library thread */
129     hb_log( "hb_init: starting libhb thread" );
130     h->die         = 0;
131     h->main_thread = hb_thread_init( "libhb", thread_func, h,
132                                      HB_NORMAL_PRIORITY );
133
134     return h;
135
136         /* Set the scan count to start at 0 */
137         //scan_count = 0;
138 }
139
140 /**
141  * libhb initialization routine.
142  * This version is to use when calling the dylib, the macro hb_init isn't available from a dylib call!
143  * @param verbose HB_DEBUG_NONE or HB_DEBUG_ALL.
144  * @param update_check signals libhb to check for updated version from HandBrake website.
145  * @return Handle to hb_handle_t for use on all subsequent calls to libhb.
146  */
147 hb_handle_t * hb_init_dl( int verbose, int update_check )
148 {
149     hb_handle_t * h = calloc( sizeof( hb_handle_t ), 1 );
150     uint64_t      date;
151
152     /* See hb_log() in common.c */
153     if( verbose > HB_DEBUG_NONE )
154     {
155         putenv( "HB_DEBUG=1" );
156                 av_log_set_level(AV_LOG_DEBUG);
157     }
158
159     /* Check for an update on the website if asked to */
160     h->build = -1;
161
162     if( update_check )
163     {
164         hb_log( "hb_init: checking for updates" );
165         date             = hb_get_date();
166         h->update_thread = hb_update_init( &h->build, h->version );
167
168         for( ;; )
169         {
170             if( hb_thread_has_exited( h->update_thread ) )
171             {
172                 /* Immediate success or failure */
173                 hb_thread_close( &h->update_thread );
174                 break;
175             }
176             if( hb_get_date() > date + 1000 )
177             {
178                 /* Still nothing after one second. Connection problem,
179                    let the thread die */
180                 hb_log( "hb_init: connection problem, not waiting for "
181                         "update_thread" );
182                 break;
183             }
184             hb_snooze( 500 );
185         }
186     }
187
188     /* CPU count detection */
189     hb_log( "hb_init: checking cpu count" );
190     h->cpu_count = hb_get_cpu_count();
191
192     h->list_title = hb_list_init();
193     h->jobs       = hb_list_init();
194     h->current_job = NULL;
195
196     h->state_lock  = hb_lock_init();
197     h->state.state = HB_STATE_IDLE;
198
199     h->pause_lock = hb_lock_init();
200
201     /* libavcodec */
202     avcodec_init();
203     avcodec_register_all();
204
205     /* Start library thread */
206     hb_log( "hb_init: starting libhb thread" );
207     h->die         = 0;
208     h->main_thread = hb_thread_init( "libhb", thread_func, h,
209                                      HB_NORMAL_PRIORITY );
210
211     hb_register( &hb_sync );
212         hb_register( &hb_decmpeg2 );
213         hb_register( &hb_decsub );
214         hb_register( &hb_render );
215         hb_register( &hb_encavcodec );
216         hb_register( &hb_encxvid );
217         hb_register( &hb_encx264 );
218     hb_register( &hb_enctheora );
219         hb_register( &hb_deca52 );
220         hb_register( &hb_decdca );
221         hb_register( &hb_decavcodec );
222         hb_register( &hb_decavcodecv );
223         hb_register( &hb_decavcodecvi );
224         hb_register( &hb_decavcodecai );
225         hb_register( &hb_declpcm );
226         hb_register( &hb_encfaac );
227         hb_register( &hb_enclame );
228         hb_register( &hb_encvorbis );
229
230         return h;
231 }
232
233
234 /**
235  * Returns current version of libhb.
236  * @param h Handle to hb_handle_t.
237  * @return character array of version number.
238  */
239 char * hb_get_version( hb_handle_t * h )
240 {
241     return HB_VERSION;
242 }
243
244 /**
245  * Returns current build of libhb.
246  * @param h Handle to hb_handle_t.
247  * @return character array of build number.
248  */
249 int hb_get_build( hb_handle_t * h )
250 {
251     return HB_BUILD;
252 }
253
254 /**
255  * Checks for needed update.
256  * @param h Handle to hb_handle_t.
257  * @param version Pointer to handle where version will be copied.
258  * @return update indicator.
259  */
260 int hb_check_update( hb_handle_t * h, char ** version )
261 {
262     *version = ( h->build < 0 ) ? NULL : h->version;
263     return h->build;
264 }
265
266 /**
267  * Sets the cpu count to the desired value.
268  * @param h Handle to hb_handle_t
269  * @param cpu_count Number of CPUs to use.
270  */
271 void hb_set_cpu_count( hb_handle_t * h, int cpu_count )
272 {
273     cpu_count    = MAX( 1, cpu_count );
274     cpu_count    = MIN( cpu_count, 8 );
275     h->cpu_count = cpu_count;
276 }
277
278 /**
279  * Initializes a scan of the by calling hb_scan_init
280  * @param h Handle to hb_handle_t
281  * @param path location of VIDEO_TS folder.
282  * @param title_index Desired title to scan.  0 for all titles.
283  */
284 void hb_scan( hb_handle_t * h, const char * path, int title_index )
285 {
286     hb_title_t * title;
287
288     /* Clean up from previous scan */
289     while( ( title = hb_list_item( h->list_title, 0 ) ) )
290     {
291         hb_list_rem( h->list_title, title );
292         hb_title_close( &title );
293     }
294
295     hb_log( "hb_scan: path=%s, title_index=%d", path, title_index );
296     h->scan_thread = hb_scan_init( h, path, title_index, h->list_title );
297 }
298
299 /**
300  * Returns the list of titles found.
301  * @param h Handle to hb_handle_t
302  * @return Handle to hb_list_t of the title list.
303  */
304 hb_list_t * hb_get_titles( hb_handle_t * h )
305 {
306     return h->list_title;
307 }
308
309 /**
310  * Create preview image of desired title a index of picture.
311  * @param h Handle to hb_handle_t.
312  * @param title Handle to hb_title_t of desired title.
313  * @param picture Index in title.
314  * @param buffer Handle to buufer were inage will be drawn.
315  */
316 void hb_get_preview( hb_handle_t * h, hb_title_t * title, int picture,
317                      uint8_t * buffer )
318 {
319     hb_job_t           * job = title->job;
320     char                 filename[1024];
321     FILE               * file;
322     uint8_t            * buf1, * buf2, * buf3, * buf4, * pen;
323     uint32_t           * p32, swsflags;
324     AVPicture            pic_in, pic_preview, pic_deint, pic_crop, pic_scale;
325     struct SwsContext  * context;
326     int                  i;
327
328     swsflags = SWS_LANCZOS;
329 #ifndef __x86_64__
330     swsflags |= SWS_ACCURATE_RND;
331 #endif  /* __x86_64__ */
332
333     buf1 = malloc( title->width * title->height * 3 / 2 );
334     buf2 = malloc( title->width * title->height * 3 / 2 );
335     buf3 = malloc( title->width * title->height * 3 / 2 );
336     buf4 = malloc( title->width * title->height * 4 );
337     avpicture_fill( &pic_in, buf1, PIX_FMT_YUV420P,
338                     title->width, title->height );
339     avpicture_fill( &pic_deint, buf2, PIX_FMT_YUV420P,
340                     title->width, title->height );
341     avpicture_fill( &pic_scale, buf3, PIX_FMT_YUV420P,
342                     job->width, job->height );
343     avpicture_fill( &pic_preview, buf4, PIX_FMT_RGBA32,
344                     job->width, job->height );
345
346     // Allocate the AVPicture frames and fill in
347
348     memset( filename, 0, 1024 );
349
350     hb_get_tempory_filename( h, filename, "%x%d",
351                              (intptr_t) title, picture );
352
353     file = fopen( filename, "r" );
354     if( !file )
355     {
356         hb_log( "hb_get_preview: fopen failed" );
357         return;
358     }
359
360     fread( buf1, title->width * title->height * 3 / 2, 1, file );
361     fclose( file );
362
363     if( job->deinterlace )
364     {
365         // Deinterlace and crop
366         avpicture_deinterlace( &pic_deint, &pic_in, PIX_FMT_YUV420P, title->width, title->height );
367         av_picture_crop( &pic_crop, &pic_deint, PIX_FMT_YUV420P, job->crop[0], job->crop[2] );
368     }
369     else
370     {
371         // Crop
372         av_picture_crop( &pic_crop, &pic_in, PIX_FMT_YUV420P, job->crop[0], job->crop[2] );
373     }
374
375     // Get scaling context
376     context = sws_getContext(title->width  - (job->crop[2] + job->crop[3]),
377                              title->height - (job->crop[0] + job->crop[1]),
378                              PIX_FMT_YUV420P,
379                              job->width, job->height, PIX_FMT_YUV420P,
380                              swsflags, NULL, NULL, NULL);
381
382     // Scale
383     sws_scale(context,
384               pic_crop.data, pic_crop.linesize,
385               0, title->height - (job->crop[0] + job->crop[1]),
386               pic_scale.data, pic_scale.linesize);
387
388     // Free context
389     sws_freeContext( context );
390
391     // Get preview context
392     context = sws_getContext(job->width, job->height, PIX_FMT_YUV420P,
393                               job->width, job->height, PIX_FMT_RGBA32,
394                               swsflags, NULL, NULL, NULL);
395
396     // Create preview
397     sws_scale(context,
398               pic_scale.data, pic_scale.linesize,
399               0, job->height,
400               pic_preview.data, pic_preview.linesize);
401
402     // Free context
403     sws_freeContext( context );
404
405     /* Gray background */
406     p32 = (uint32_t *) buffer;
407     for( i = 0; i < ( title->width + 2 ) * ( title->height + 2 ); i++ )
408     {
409         p32[i] = 0xFF808080;
410     }
411
412     /* Draw the picture, centered, and draw the cropping zone */
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 + 4 * job->width * 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 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     {
591         height = job->maxHeight;
592     }
593     else
594     {
595         height = (double)width / storage_aspect;
596     }
597
598
599     /* Time to get picture dimensions that divide cleanly.
600        These variables will store temporary dimensions as we iterate. */
601     int i, w, h;
602
603     /* In case the user specified a modulus, use it */
604     if (job->modulus)
605         mod = job->modulus;
606     else
607         mod = 16;
608
609     /* Iterate through multiples of mod to find one close to job->width. */
610     for( i = 1;; i++ )
611     {
612         w = mod * i;
613
614         if (w < width)
615         {
616             if ( ( width - w ) <= ( mod / 2 ) )
617                 /* We'll take a width that's
618                    smaller, but close enough. */
619                 break;
620         }
621         if (w == width)
622             /* Mod 16 dimensions, how nice! */
623             break;
624         if( w > width )
625         {
626             if ( ( w - width ) < (mod/2) )
627                 /* We'll take a width that's bigger, if we have to. */
628                 break;
629         }
630     }
631     width  = mod * (i);
632
633     /* Now do the same for a mod-friendly value near job->height. */
634     for( i = 1;; i++)
635     {
636         h = i * mod;
637
638         if (h < height)
639             {
640                 if ( ( height - h ) <= ( mod / 2 ))
641                     /* Go with a smaller height,
642                        if it's close enough.    */
643                     break;
644             }
645         if (h == height)
646             /* Mod 16 dimensions, how nice! */
647             break;
648
649         if ( h > height)
650         {
651             if ( ( h - height ) < ( mod / 2 ))
652                 /* Use a taller height if necessary */
653                 break;
654         }
655     }
656     height = mod  * (i);
657
658     int pixel_aspect_width = job->pixel_aspect_width;
659     int pixel_aspect_height = job->pixel_aspect_height;
660     
661     /* If a source was really 704*480 and hard matted with cropping
662        to 720*480, replace the PAR values with the ITU broadcast ones. */
663     if (title->width == 720 && cropped_width <= 706)
664     {
665         // convert aspect to a scaled integer so we can test for 16:9 & 4:3
666         // aspect ratios ignoring insignificant differences in the LSBs of
667         // the floating point representation.
668         int iaspect = aspect * 9.;
669
670         /* Handle ITU PARs */
671         if (title->height == 480)
672         {
673             /* It's NTSC */
674             if (iaspect == 16)
675             {
676                 /* It's widescreen */
677                 pixel_aspect_width = 40;
678                 pixel_aspect_height = 33;
679             }
680             else if (iaspect == 12)
681             {
682                 /* It's 4:3 */
683                 pixel_aspect_width = 10;
684                 pixel_aspect_height = 11;
685             }
686         }
687         else if (title->height == 576)
688         {
689             /* It's PAL */
690             if(iaspect == 16)
691             {
692                 /* It's widescreen */
693                 pixel_aspect_width = 16;
694                 pixel_aspect_height = 11;
695             }
696             else if (iaspect == 12)
697             {
698                 /* It's 4:3 */
699                 pixel_aspect_width = 12;
700                 pixel_aspect_height = 11;
701             }
702         }
703     }
704
705     /* Figure out what dimensions the source would display at. */
706     int source_display_width = cropped_width * (double)pixel_aspect_width /
707                                (double)pixel_aspect_height ;
708
709     /* The film AR is the source's display width / cropped source height.
710        The output display width is the output height * film AR.
711        The output PAR is the output display width / output storage width. */
712     pixel_aspect_width = height * source_display_width / cropped_height;
713     pixel_aspect_height = width;
714
715     /* Pass the results back to the caller */
716     *output_width = width;
717     *output_height = height;
718
719     /* While x264 is smart enough to reduce fractions on its own, libavcodec
720        needs some help with the math, so lose superfluous factors.            */
721     hb_reduce( output_par_width, output_par_height,
722                pixel_aspect_width, pixel_aspect_height );
723 }
724
725 /**
726  * Calculates job width, height, and cropping parameters.
727  * @param job Handle to hb_job_t.
728  * @param aspect Desired aspect ratio. Value of -1 uses title aspect.
729  * @param pixels Maximum desired pixel count.
730  */
731 void hb_set_size( hb_job_t * job, double aspect, int pixels )
732 {
733     hb_title_t * title = job->title;
734
735     int croppedWidth  = title->width - title->crop[2] - title->crop[3];
736     int croppedHeight = title->height - title->crop[0] - title->crop[1];
737     double croppedAspect = title->aspect * title->height * croppedWidth /
738                            croppedHeight / title->width;
739     int addCrop;
740     int i, w, h;
741
742     if( aspect <= 0 )
743     {
744         /* Keep the best possible aspect ratio */
745         aspect = croppedAspect;
746     }
747
748     /* Crop if necessary to obtain the desired ratio */
749     memcpy( job->crop, title->crop, 4 * sizeof( int ) );
750     if( aspect < croppedAspect )
751     {
752         /* Need to crop on the left and right */
753         addCrop = croppedWidth - aspect * croppedHeight * title->width /
754                     title->aspect / title->height;
755         if( addCrop & 3 )
756         {
757             addCrop = ( addCrop + 1 ) / 2;
758             job->crop[2] += addCrop;
759             job->crop[3] += addCrop;
760         }
761         else if( addCrop & 2 )
762         {
763             addCrop /= 2;
764             job->crop[2] += addCrop - 1;
765             job->crop[3] += addCrop + 1;
766         }
767         else
768         {
769             addCrop /= 2;
770             job->crop[2] += addCrop;
771             job->crop[3] += addCrop;
772         }
773     }
774     else if( aspect > croppedAspect )
775     {
776         /* Need to crop on the top and bottom */
777         addCrop = croppedHeight - croppedWidth * title->aspect *
778             title->height / aspect / title->width;
779         if( addCrop & 3 )
780         {
781             addCrop = ( addCrop + 1 ) / 2;
782             job->crop[0] += addCrop;
783             job->crop[1] += addCrop;
784         }
785         else if( addCrop & 2 )
786         {
787             addCrop /= 2;
788             job->crop[0] += addCrop - 1;
789             job->crop[1] += addCrop + 1;
790         }
791         else
792         {
793             addCrop /= 2;
794             job->crop[0] += addCrop;
795             job->crop[1] += addCrop;
796         }
797     }
798
799     /* Compute a resolution from the number of pixels and aspect */
800     for( i = 0;; i++ )
801     {
802         w = 16 * i;
803         h = MULTIPLE_16( (int)( (double)w / aspect ) );
804         if( w * h > pixels )
805         {
806             break;
807         }
808     }
809     i--;
810     job->width  = 16 * i;
811     job->height = MULTIPLE_16( (int)( (double)job->width / aspect ) );
812 }
813
814 /**
815  * Returns the number of jobs in the queue.
816  * @param h Handle to hb_handle_t.
817  * @return Number of jobs.
818  */
819 int hb_count( hb_handle_t * h )
820 {
821     return hb_list_count( h->jobs );
822 }
823
824 /**
825  * Returns handle to job at index i within the job list.
826  * @param h Handle to hb_handle_t.
827  * @param i Index of job.
828  * @returns Handle to hb_job_t of desired job.
829  */
830 hb_job_t * hb_job( hb_handle_t * h, int i )
831 {
832     return hb_list_item( h->jobs, i );
833 }
834
835 hb_job_t * hb_current_job( hb_handle_t * h )
836 {
837     return( h->current_job );
838 }
839
840 /**
841  * Adds a job to the job list.
842  * @param h Handle to hb_handle_t.
843  * @param job Handle to hb_job_t.
844  */
845 void hb_add( hb_handle_t * h, hb_job_t * job )
846 {
847     hb_job_t      * job_copy;
848     hb_title_t    * title,    * title_copy;
849     hb_chapter_t  * chapter,  * chapter_copy;
850     hb_audio_t    * audio;
851     hb_subtitle_t * subtitle, * subtitle_copy;
852     int             i;
853     char            audio_lang[4];
854
855     /* Copy the title */
856     title      = job->title;
857     title_copy = malloc( sizeof( hb_title_t ) );
858     memcpy( title_copy, title, sizeof( hb_title_t ) );
859
860     title_copy->list_chapter = hb_list_init();
861     for( i = 0; i < hb_list_count( title->list_chapter ); i++ )
862     {
863         chapter      = hb_list_item( title->list_chapter, i );
864         chapter_copy = malloc( sizeof( hb_chapter_t ) );
865         memcpy( chapter_copy, chapter, sizeof( hb_chapter_t ) );
866         hb_list_add( title_copy->list_chapter, chapter_copy );
867     }
868
869     /* Copy the audio track(s) we want */
870     title_copy->list_audio = hb_list_init();
871
872     /* Do nothing about audio during first pass */
873     if( job->pass == 0 || job->pass == 2 )
874     {
875         for( i = 0; i < hb_list_count(job->list_audio); i++ )
876         {
877             if( ( audio = hb_list_item( job->list_audio, i ) ) )
878             {
879                 hb_list_add( title_copy->list_audio, hb_audio_copy(audio) );
880             }
881         }
882     }
883
884     title_copy->list_subtitle = hb_list_init();
885
886     /*
887      * The following code is confusing, there are three ways in which
888      * we select subtitles and it depends on whether this is single or
889      * two pass mode.
890      *
891      * subtitle_scan may be enabled, in which case the first pass
892      * scans all subtitles of that language. The second pass does not
893      * select any because they are set at the end of the first pass.
894      *
895      * native_language may have a preferred language, in which case we
896      * may be switching the language we want for the subtitles in the
897      * first pass of a single pass, or the second pass of a two pass.
898      *
899      * We may have manually selected a subtitle, in which case that is
900      * selected in the first pass of a single pass, or the second of a
901      * two pass.
902      */
903     memset( audio_lang, 0, sizeof( audio_lang ) );
904
905     if ( job->indepth_scan || job->native_language ) {
906
907         /*
908          * Find the first audio language that is being encoded
909          */
910         for( i = 0; i < hb_list_count(job->list_audio); i++ )
911         {
912             if( ( audio = hb_list_item( job->list_audio, i ) ) )
913             {
914                 strncpy(audio_lang, audio->config.lang.iso639_2, sizeof(audio_lang));
915                 break;
916             }
917         }
918
919         /*
920          * In all cases switch the language if we need to to our native
921          * language.
922          */
923         if( job->native_language )
924         {
925             if( strncasecmp( job->native_language, audio_lang,
926                              sizeof( audio_lang ) ) != 0 )
927             {
928
929                 if( job->pass != 2 )
930                 {
931                     hb_log( "Enabled subtitles in native language '%s', audio is in '%s'",
932                             job->native_language, audio_lang);
933                 }
934                 /*
935                  * The main audio track is not in our native language, so switch
936                  * the subtitles to use our native language instead.
937                  */
938                 strncpy( audio_lang, job->native_language, sizeof( audio_lang ) );
939             } else {
940                 /*
941                  * native language is irrelevent, free it.
942                  */
943                 free( job->native_language );
944                 job->native_language = NULL;
945             }
946         }
947     }
948
949     /*
950      * If doing a subtitle scan then add all the matching subtitles for this
951      * language.
952      */
953     if ( job->indepth_scan )
954     {
955         for( i=0; i < hb_list_count( title->list_subtitle ); i++ )
956         {
957             subtitle = hb_list_item( title->list_subtitle, i );
958             if( strcmp( subtitle->iso639_2, audio_lang ) == 0 )
959             {
960                 /*
961                  * Matched subtitle language with audio language, so
962                  * add this to our list to scan.
963                  *
964                  * We will update the subtitle list on the second pass
965                  * later after the first pass has completed.
966                  */
967                 subtitle_copy = malloc( sizeof( hb_subtitle_t ) );
968                 memcpy( subtitle_copy, subtitle, sizeof( hb_subtitle_t ) );
969                 hb_list_add( title_copy->list_subtitle, subtitle_copy );
970                 if ( job->native_language ) {
971                     /*
972                      * With native language just select the
973                      * first match in our langiage, not all of
974                      * them. Subsequent ones are likely to be commentary
975                      */
976                     break;
977                 }
978             }
979         }
980     } else {
981         /*
982          * Not doing a subtitle scan in this pass, but maybe we are in the
983          * first pass?
984          */
985         if( job->select_subtitle )
986         {
987             /*
988              * Don't add subtitles here, we'll add them via select_subtitle
989              * at the end of the subtitle_scan.
990              */
991         } else {
992             /*
993              * Definitely not doing a subtitle scan.
994              */
995             if( job->pass != 1 && job->native_language )
996             {
997                 /*
998                  * We are not doing a subtitle scan but do want the
999                  * native langauge subtitle selected, so select it
1000                  * for pass 0 or pass 2 of a two pass.
1001                  */
1002                 for( i=0; i < hb_list_count( title->list_subtitle ); i++ )
1003                 {
1004                     subtitle = hb_list_item( title->list_subtitle, i );
1005                     if( strcmp( subtitle->iso639_2, audio_lang ) == 0 )
1006                     {
1007                         /*
1008                          * Matched subtitle language with audio language, so
1009                          * add this to our list to scan.
1010                          */
1011                         subtitle_copy = malloc( sizeof( hb_subtitle_t ) );
1012                         memcpy( subtitle_copy, subtitle, sizeof( hb_subtitle_t ) );
1013                         hb_list_add( title_copy->list_subtitle, subtitle_copy );
1014                         break;
1015                     }
1016                 }
1017             } else {
1018                 /*
1019                  * Manually selected subtitle, in which case only
1020                  * bother adding them for pass 0 or pass 2 of a two
1021                  * pass.
1022                  */
1023                 if( job->pass != 1 )
1024                 {
1025                     if( ( subtitle = hb_list_item( title->list_subtitle, job->subtitle ) ) )
1026                     {
1027                         subtitle_copy = malloc( sizeof( hb_subtitle_t ) );
1028                         memcpy( subtitle_copy, subtitle, sizeof( hb_subtitle_t ) );
1029                         hb_list_add( title_copy->list_subtitle, subtitle_copy );
1030                     }
1031                 }
1032             }
1033         }
1034     }
1035
1036     /* Copy the job */
1037     job_copy        = calloc( sizeof( hb_job_t ), 1 );
1038     memcpy( job_copy, job, sizeof( hb_job_t ) );
1039     title_copy->job = job_copy;
1040     job_copy->title = title_copy;
1041     job_copy->list_audio = title_copy->list_audio;
1042     job_copy->file  = strdup( job->file );
1043     job_copy->h     = h;
1044     job_copy->pause = h->pause_lock;
1045
1046     /* Copy the job filter list */
1047     if( job->filters )
1048     {
1049         int i;
1050         int filter_count = hb_list_count( job->filters );
1051         job_copy->filters = hb_list_init();
1052         for( i = 0; i < filter_count; i++ )
1053         {
1054             /*
1055              * Copy the filters, since the MacGui reuses the global filter objects
1056              * meaning that queued up jobs overwrite the previous filter settings.
1057              * In reality, settings is probably the only field that needs duplicating
1058              * since it's the only value that is ever changed. But name is duplicated
1059              * as well for completeness. Not copying private_data since it gets
1060              * created for each job in renderInit.
1061              */
1062             hb_filter_object_t * filter = hb_list_item( job->filters, i );
1063             hb_filter_object_t * filter_copy = malloc( sizeof( hb_filter_object_t ) );
1064             memcpy( filter_copy, filter, sizeof( hb_filter_object_t ) );
1065             if( filter->name )
1066                 filter_copy->name = strdup( filter->name );
1067             if( filter->settings )
1068                 filter_copy->settings = strdup( filter->settings );
1069             hb_list_add( job_copy->filters, filter_copy );
1070         }
1071     }
1072
1073     /* Add the job to the list */
1074     hb_list_add( h->jobs, job_copy );
1075     h->job_count = hb_count(h);
1076     h->job_count_permanent++;
1077 }
1078
1079 /**
1080  * Removes a job from the job list.
1081  * @param h Handle to hb_handle_t.
1082  * @param job Handle to hb_job_t.
1083  */
1084 void hb_rem( hb_handle_t * h, hb_job_t * job )
1085 {
1086     hb_list_rem( h->jobs, job );
1087
1088     h->job_count = hb_count(h);
1089     if (h->job_count_permanent)
1090         h->job_count_permanent--;
1091
1092     /* XXX free everything XXX */
1093 }
1094
1095 /**
1096  * Starts the conversion process.
1097  * Sets state to HB_STATE_WORKING.
1098  * calls hb_work_init, to launch work thread. Stores handle to work thread.
1099  * @param h Handle to hb_handle_t.
1100  */
1101 void hb_start( hb_handle_t * h )
1102 {
1103     /* XXX Hack */
1104     h->job_count = hb_list_count( h->jobs );
1105     h->job_count_permanent = h->job_count;
1106
1107     hb_lock( h->state_lock );
1108     h->state.state = HB_STATE_WORKING;
1109 #define p h->state.param.working
1110     p.progress  = 0.0;
1111     p.job_cur   = 1;
1112     p.job_count = h->job_count;
1113     p.rate_cur  = 0.0;
1114     p.rate_avg  = 0.0;
1115     p.hours     = -1;
1116     p.minutes   = -1;
1117     p.seconds   = -1;
1118     p.sequence_id = 0;
1119 #undef p
1120     hb_unlock( h->state_lock );
1121
1122     h->paused = 0;
1123
1124     h->work_die    = 0;
1125     h->work_thread = hb_work_init( h->jobs, h->cpu_count,
1126                                    &h->work_die, &h->work_error, &h->current_job );
1127 }
1128
1129 /**
1130  * Pauses the conversion process.
1131  * @param h Handle to hb_handle_t.
1132  */
1133 void hb_pause( hb_handle_t * h )
1134 {
1135     if( !h->paused )
1136     {
1137         hb_lock( h->pause_lock );
1138         h->paused = 1;
1139
1140         hb_lock( h->state_lock );
1141         h->state.state = HB_STATE_PAUSED;
1142         hb_unlock( h->state_lock );
1143     }
1144 }
1145
1146 /**
1147  * Resumes the conversion process.
1148  * @param h Handle to hb_handle_t.
1149  */
1150 void hb_resume( hb_handle_t * h )
1151 {
1152     if( h->paused )
1153     {
1154         hb_unlock( h->pause_lock );
1155         h->paused = 0;
1156     }
1157 }
1158
1159 /**
1160  * Stops the conversion process.
1161  * @param h Handle to hb_handle_t.
1162  */
1163 void hb_stop( hb_handle_t * h )
1164 {
1165     h->work_die = 1;
1166
1167     h->job_count = hb_count(h);
1168     h->job_count_permanent = 0;
1169
1170     hb_resume( h );
1171 }
1172
1173 /**
1174  * Returns the state of the conversion process.
1175  * @param h Handle to hb_handle_t.
1176  * @param s Handle to hb_state_t which to copy the state data.
1177  */
1178 void hb_get_state( hb_handle_t * h, hb_state_t * s )
1179 {
1180     hb_lock( h->state_lock );
1181
1182     memcpy( s, &h->state, sizeof( hb_state_t ) );
1183     if ( h->state.state == HB_STATE_SCANDONE || h->state.state == HB_STATE_WORKDONE )
1184         h->state.state = HB_STATE_IDLE;
1185
1186     hb_unlock( h->state_lock );
1187 }
1188
1189 void hb_get_state2( hb_handle_t * h, hb_state_t * s )
1190 {
1191     hb_lock( h->state_lock );
1192
1193     memcpy( s, &h->state, sizeof( hb_state_t ) );
1194
1195     hb_unlock( h->state_lock );
1196 }
1197
1198 /**
1199  * Called in MacGui in UpdateUI to check
1200  *  for a new scan being completed to set a new source
1201  */
1202 int hb_get_scancount( hb_handle_t * h)
1203  {
1204      return h->scanCount;
1205  }
1206
1207 /**
1208  * Closes access to libhb by freeing the hb_handle_t handle ontained in hb_init_real.
1209  * @param _h Pointer to handle to hb_handle_t.
1210  */
1211 void hb_close( hb_handle_t ** _h )
1212 {
1213     hb_handle_t * h = *_h;
1214     hb_title_t * title;
1215
1216     h->die = 1;
1217     hb_thread_close( &h->main_thread );
1218
1219     while( ( title = hb_list_item( h->list_title, 0 ) ) )
1220     {
1221         hb_list_rem( h->list_title, title );
1222         if( title->job && title->job->filters )
1223         {
1224             hb_list_close( &title->job->filters );
1225         }
1226         free( title->job );
1227         hb_title_close( &title );
1228     }
1229     hb_list_close( &h->list_title );
1230
1231     hb_list_close( &h->jobs );
1232     hb_lock_close( &h->state_lock );
1233     hb_lock_close( &h->pause_lock );
1234     free( h );
1235     *_h = NULL;
1236
1237 }
1238
1239 /**
1240  * Monitors the state of the update, scan, and work threads.
1241  * Sets scan done state when scan thread exits.
1242  * Sets work done state when work thread exits.
1243  * @param _h Handle to hb_handle_t
1244  */
1245 static void thread_func( void * _h )
1246 {
1247     hb_handle_t * h = (hb_handle_t *) _h;
1248     char dirname[1024];
1249     DIR * dir;
1250     struct dirent * entry;
1251
1252     h->pid = getpid();
1253
1254     /* Create folder for temporary files */
1255     memset( dirname, 0, 1024 );
1256     hb_get_tempory_directory( h, dirname );
1257
1258     hb_mkdir( dirname );
1259
1260     while( !h->die )
1261     {
1262         /* In case the check_update thread hangs, it'll die sooner or
1263            later. Then, we join it here */
1264         if( h->update_thread &&
1265             hb_thread_has_exited( h->update_thread ) )
1266         {
1267             hb_thread_close( &h->update_thread );
1268         }
1269
1270         /* Check if the scan thread is done */
1271         if( h->scan_thread &&
1272             hb_thread_has_exited( h->scan_thread ) )
1273         {
1274             hb_thread_close( &h->scan_thread );
1275
1276             hb_log( "libhb: scan thread found %d valid title(s)",
1277                     hb_list_count( h->list_title ) );
1278             hb_lock( h->state_lock );
1279             h->state.state = HB_STATE_SCANDONE; //originally state.state
1280                         hb_unlock( h->state_lock );
1281                         /*we increment this sessions scan count by one for the MacGui
1282                         to trigger a new source being set */
1283             h->scanCount++;
1284         }
1285
1286         /* Check if the work thread is done */
1287         if( h->work_thread &&
1288             hb_thread_has_exited( h->work_thread ) )
1289         {
1290             hb_thread_close( &h->work_thread );
1291
1292             hb_log( "libhb: work result = %d",
1293                     h->work_error );
1294             hb_lock( h->state_lock );
1295             h->state.state                = HB_STATE_WORKDONE;
1296             h->state.param.workdone.error = h->work_error;
1297
1298             h->job_count = hb_count(h);
1299             if (h->job_count < 1)
1300                 h->job_count_permanent = 0;
1301             hb_unlock( h->state_lock );
1302         }
1303
1304         hb_snooze( 50 );
1305     }
1306
1307     if( h->work_thread )
1308     {
1309         hb_stop( h );
1310         hb_thread_close( &h->work_thread );
1311     }
1312
1313     /* Remove temp folder */
1314     dir = opendir( dirname );
1315     while( ( entry = readdir( dir ) ) )
1316     {
1317         char filename[1024];
1318         if( entry->d_name[0] == '.' )
1319         {
1320             continue;
1321         }
1322         memset( filename, 0, 1024 );
1323         snprintf( filename, 1023, "%s/%s", dirname, entry->d_name );
1324         unlink( filename );
1325     }
1326     closedir( dir );
1327     rmdir( dirname );
1328 }
1329
1330 /**
1331  * Returns the PID.
1332  * @param h Handle to hb_handle_t
1333  */
1334 int hb_get_pid( hb_handle_t * h )
1335 {
1336     return h->pid;
1337 }
1338
1339 /**
1340  * Sets the current state.
1341  * @param h Handle to hb_handle_t
1342  * @param s Handle to new hb_state_t
1343  */
1344 void hb_set_state( hb_handle_t * h, hb_state_t * s )
1345 {
1346     hb_lock( h->pause_lock );
1347     hb_lock( h->state_lock );
1348     memcpy( &h->state, s, sizeof( hb_state_t ) );
1349     if( h->state.state == HB_STATE_WORKING )
1350     {
1351         /* XXX Hack */
1352         if (h->job_count < 1)
1353             h->job_count_permanent = 1;
1354
1355         h->state.param.working.job_cur =
1356             h->job_count_permanent - hb_list_count( h->jobs );
1357         h->state.param.working.job_count = h->job_count_permanent;
1358
1359         // Set which job is being worked on
1360         if (h->current_job)
1361             h->state.param.working.sequence_id = h->current_job->sequence_id;
1362         else
1363             h->state.param.working.sequence_id = 0;
1364     }
1365     hb_unlock( h->state_lock );
1366     hb_unlock( h->pause_lock );
1367 }