OSDN Git Service

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