OSDN Git Service

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