OSDN Git Service

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