OSDN Git Service

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