OSDN Git Service

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