6 /* The "Check for update" thread */
9 hb_thread_t * update_thread;
11 /* This thread's only purpose is to check other threads'
14 hb_thread_t * main_thread;
17 /* DVD/file scan thread */
18 hb_list_t * list_title;
19 hb_thread_t * scan_thread;
21 /* The thread which processes the jobs. Others threads are launched
22 from this one (see work.c) */
24 hb_job_t * current_job;
26 int job_count_permanent;
27 volatile int work_die;
29 hb_thread_t * work_thread;
33 hb_lock_t * state_lock;
37 hb_lock_t * pause_lock;
38 /* For MacGui active queue
39 increments each time the scan thread completes*/
44 hb_lock_t *hb_avcodec_lock;
45 hb_work_object_t * hb_objects = NULL;
47 static void thread_func( void * );
49 void hb_avcodec_init()
51 hb_avcodec_lock = hb_lock_init();
55 int hb_avcodec_open(AVCodecContext *avctx, AVCodec *codec)
58 hb_lock( hb_avcodec_lock );
59 ret = avcodec_open(avctx, codec);
60 hb_unlock( hb_avcodec_lock );
64 int hb_avcodec_close(AVCodecContext *avctx)
67 hb_lock( hb_avcodec_lock );
68 ret = avcodec_close(avctx);
69 hb_unlock( hb_avcodec_lock );
74 * Registers work objects, by adding the work object to a liked list.
75 * @param w Handle to hb_work_object_t to register.
77 void hb_register( hb_work_object_t * w )
84 * libhb initialization routine.
85 * @param verbose HB_DEBUG_NONE or HB_DEBUG_ALL.
86 * @param update_check signals libhb to check for updated version from HandBrake website.
87 * @return Handle to hb_handle_t for use on all subsequent calls to libhb.
89 hb_handle_t * hb_init( int verbose, int update_check )
91 hb_handle_t * h = calloc( sizeof( hb_handle_t ), 1 );
94 /* See hb_deep_log() and hb_log() in common.c */
95 global_verbosity_level = verbose;
97 putenv( "HB_DEBUG=1" );
99 /* Check for an update on the website if asked to */
104 hb_log( "hb_init: checking for updates" );
105 date = hb_get_date();
106 h->update_thread = hb_update_init( &h->build, h->version );
110 if( hb_thread_has_exited( h->update_thread ) )
112 /* Immediate success or failure */
113 hb_thread_close( &h->update_thread );
116 if( hb_get_date() > date + 1000 )
118 /* Still nothing after one second. Connection problem,
119 let the thread die */
120 hb_log( "hb_init: connection problem, not waiting for "
129 * Initialise buffer pool
131 hb_buffer_pool_init();
133 /* CPU count detection */
134 hb_log( "hb_init: checking cpu count" );
135 h->cpu_count = hb_get_cpu_count();
137 h->list_title = hb_list_init();
138 h->jobs = hb_list_init();
140 h->state_lock = hb_lock_init();
141 h->state.state = HB_STATE_IDLE;
143 h->pause_lock = hb_lock_init();
148 /* Start library thread */
149 hb_log( "hb_init: starting libhb thread" );
151 h->main_thread = hb_thread_init( "libhb", thread_func, h,
152 HB_NORMAL_PRIORITY );
153 hb_register( &hb_sync );
154 hb_register( &hb_decmpeg2 );
155 hb_register( &hb_decvobsub );
156 hb_register( &hb_encvobsub );
157 hb_register( &hb_deccc608 );
158 hb_register( &hb_render );
159 hb_register( &hb_encavcodec );
160 hb_register( &hb_encx264 );
161 hb_register( &hb_enctheora );
162 hb_register( &hb_deca52 );
163 hb_register( &hb_decdca );
164 hb_register( &hb_decavcodec );
165 hb_register( &hb_decavcodecv );
166 hb_register( &hb_decavcodecvi );
167 hb_register( &hb_decavcodecai );
168 hb_register( &hb_declpcm );
169 hb_register( &hb_encfaac );
170 hb_register( &hb_enclame );
171 hb_register( &hb_encvorbis );
173 hb_register( &hb_encca_aac );
180 * libhb initialization routine.
181 * This version is to use when calling the dylib, the macro hb_init isn't available from a dylib call!
182 * @param verbose HB_DEBUG_NONE or HB_DEBUG_ALL.
183 * @param update_check signals libhb to check for updated version from HandBrake website.
184 * @return Handle to hb_handle_t for use on all subsequent calls to libhb.
186 hb_handle_t * hb_init_dl( int verbose, int update_check )
188 hb_handle_t * h = calloc( sizeof( hb_handle_t ), 1 );
191 /* See hb_log() in common.c */
192 if( verbose > HB_DEBUG_NONE )
194 putenv( "HB_DEBUG=1" );
197 /* Check for an update on the website if asked to */
202 hb_log( "hb_init: checking for updates" );
203 date = hb_get_date();
204 h->update_thread = hb_update_init( &h->build, h->version );
208 if( hb_thread_has_exited( h->update_thread ) )
210 /* Immediate success or failure */
211 hb_thread_close( &h->update_thread );
214 if( hb_get_date() > date + 1000 )
216 /* Still nothing after one second. Connection problem,
217 let the thread die */
218 hb_log( "hb_init: connection problem, not waiting for "
226 /* CPU count detection */
227 hb_log( "hb_init: checking cpu count" );
228 h->cpu_count = hb_get_cpu_count();
230 h->list_title = hb_list_init();
231 h->jobs = hb_list_init();
232 h->current_job = NULL;
234 h->state_lock = hb_lock_init();
235 h->state.state = HB_STATE_IDLE;
237 h->pause_lock = hb_lock_init();
241 avcodec_register_all();
243 /* Start library thread */
244 hb_log( "hb_init: starting libhb thread" );
246 h->main_thread = hb_thread_init( "libhb", thread_func, h,
247 HB_NORMAL_PRIORITY );
249 hb_register( &hb_sync );
250 hb_register( &hb_decmpeg2 );
251 hb_register( &hb_decvobsub );
252 hb_register( &hb_encvobsub );
253 hb_register( &hb_deccc608 );
254 hb_register( &hb_render );
255 hb_register( &hb_encavcodec );
256 hb_register( &hb_encx264 );
257 hb_register( &hb_enctheora );
258 hb_register( &hb_deca52 );
259 hb_register( &hb_decdca );
260 hb_register( &hb_decavcodec );
261 hb_register( &hb_decavcodecv );
262 hb_register( &hb_decavcodecvi );
263 hb_register( &hb_decavcodecai );
264 hb_register( &hb_declpcm );
265 hb_register( &hb_encfaac );
266 hb_register( &hb_enclame );
267 hb_register( &hb_encvorbis );
269 hb_register( &hb_encca_aac );
277 * Returns current version of libhb.
278 * @param h Handle to hb_handle_t.
279 * @return character array of version number.
281 char * hb_get_version( hb_handle_t * h )
283 return HB_PROJECT_VERSION;
287 * Returns current build of libhb.
288 * @param h Handle to hb_handle_t.
289 * @return character array of build number.
291 int hb_get_build( hb_handle_t * h )
293 return HB_PROJECT_BUILD;
297 * Checks for needed update.
298 * @param h Handle to hb_handle_t.
299 * @param version Pointer to handle where version will be copied.
300 * @return update indicator.
302 int hb_check_update( hb_handle_t * h, char ** version )
304 *version = ( h->build < 0 ) ? NULL : h->version;
309 * Sets the cpu count to the desired value.
310 * @param h Handle to hb_handle_t
311 * @param cpu_count Number of CPUs to use.
313 void hb_set_cpu_count( hb_handle_t * h, int cpu_count )
315 cpu_count = MAX( 1, cpu_count );
316 cpu_count = MIN( cpu_count, 8 );
317 h->cpu_count = cpu_count;
321 * Deletes current previews associated with titles
322 * @param h Handle to hb_handle_t
324 void hb_remove_previews( hb_handle_t * h )
331 struct dirent * entry;
333 memset( dirname, 0, 1024 );
334 hb_get_tempory_directory( h, dirname );
335 dir = opendir( dirname );
336 if (dir == NULL) return;
338 count = hb_list_count( h->list_title );
339 while( ( entry = readdir( dir ) ) )
341 if( entry->d_name[0] == '.' )
345 for( i = 0; i < count; i++ )
347 title = hb_list_item( h->list_title, i );
348 len = snprintf( filename, 1024, "%" PRIxPTR, (intptr_t) title );
349 if (strncmp(entry->d_name, filename, len) == 0)
351 snprintf( filename, 1024, "%s/%s", dirname, entry->d_name );
361 * Initializes a scan of the by calling hb_scan_init
362 * @param h Handle to hb_handle_t
363 * @param path location of VIDEO_TS folder.
364 * @param title_index Desired title to scan. 0 for all titles.
365 * @param preview_count Number of preview images to generate.
366 * @param store_previews Whether or not to write previews to disk.
368 void hb_scan( hb_handle_t * h, const char * path, int title_index,
369 int preview_count, int store_previews )
373 /* Clean up from previous scan */
374 hb_remove_previews( h );
375 while( ( title = hb_list_item( h->list_title, 0 ) ) )
377 hb_list_rem( h->list_title, title );
378 hb_title_close( &title );
381 hb_log( "hb_scan: path=%s, title_index=%d", path, title_index );
382 h->scan_thread = hb_scan_init( h, path, title_index, h->list_title,
383 preview_count, store_previews );
387 * Returns the list of titles found.
388 * @param h Handle to hb_handle_t
389 * @return Handle to hb_list_t of the title list.
391 hb_list_t * hb_get_titles( hb_handle_t * h )
393 return h->list_title;
397 * Create preview image of desired title a index of picture.
398 * @param h Handle to hb_handle_t.
399 * @param title Handle to hb_title_t of desired title.
400 * @param picture Index in title.
401 * @param buffer Handle to buufer were inage will be drawn.
403 void hb_get_preview( hb_handle_t * h, hb_title_t * title, int picture,
406 hb_job_t * job = title->job;
409 uint8_t * buf1, * buf2, * buf3, * buf4, * pen;
411 AVPicture pic_in, pic_preview, pic_deint, pic_crop, pic_scale;
412 struct SwsContext * context;
414 int rgb_width = ((job->width + 7) >> 3) << 3;
417 swsflags = SWS_LANCZOS | SWS_ACCURATE_RND;
419 buf1 = av_malloc( avpicture_get_size( PIX_FMT_YUV420P, title->width, title->height ) );
420 buf2 = av_malloc( avpicture_get_size( PIX_FMT_YUV420P, title->width, title->height ) );
421 buf3 = av_malloc( avpicture_get_size( PIX_FMT_YUV420P, rgb_width, job->height ) );
422 buf4 = av_malloc( avpicture_get_size( PIX_FMT_RGB32, rgb_width, job->height ) );
423 avpicture_fill( &pic_in, buf1, PIX_FMT_YUV420P,
424 title->width, title->height );
425 avpicture_fill( &pic_deint, buf2, PIX_FMT_YUV420P,
426 title->width, title->height );
427 avpicture_fill( &pic_scale, buf3, PIX_FMT_YUV420P,
428 rgb_width, job->height );
429 avpicture_fill( &pic_preview, buf4, PIX_FMT_RGB32,
430 rgb_width, job->height );
432 // Allocate the AVPicture frames and fill in
434 memset( filename, 0, 1024 );
436 hb_get_tempory_filename( h, filename, "%" PRIxPTR "%d",
437 (intptr_t) title, picture );
439 file = fopen( filename, "r" );
442 hb_log( "hb_get_preview: fopen failed" );
446 fread( buf1, avpicture_get_size( PIX_FMT_YUV420P, title->width, title->height), 1, file );
449 if( job->deinterlace )
451 // Deinterlace and crop
452 avpicture_deinterlace( &pic_deint, &pic_in, PIX_FMT_YUV420P, title->width, title->height );
453 av_picture_crop( &pic_crop, &pic_deint, PIX_FMT_YUV420P, job->crop[0], job->crop[2] );
458 av_picture_crop( &pic_crop, &pic_in, PIX_FMT_YUV420P, job->crop[0], job->crop[2] );
461 // Get scaling context
462 context = sws_getContext(title->width - (job->crop[2] + job->crop[3]),
463 title->height - (job->crop[0] + job->crop[1]),
465 rgb_width, job->height, PIX_FMT_YUV420P,
466 swsflags, NULL, NULL, NULL);
470 pic_crop.data, pic_crop.linesize,
471 0, title->height - (job->crop[0] + job->crop[1]),
472 pic_scale.data, pic_scale.linesize);
475 sws_freeContext( context );
477 // Get preview context
478 context = sws_getContext(rgb_width, job->height, PIX_FMT_YUV420P,
479 rgb_width, job->height, PIX_FMT_RGB32,
480 swsflags, NULL, NULL, NULL);
484 pic_scale.data, pic_scale.linesize,
486 pic_preview.data, pic_preview.linesize);
489 sws_freeContext( context );
491 preview_size = pic_preview.linesize[0];
493 for( i = 0; i < job->height; i++ )
495 memcpy( pen, buf4 + preview_size * i, 4 * job->width );
496 pen += 4 * job->width;
500 avpicture_free( &pic_preview );
501 avpicture_free( &pic_scale );
502 avpicture_free( &pic_deint );
503 avpicture_free( &pic_in );
507 * Analyzes a frame to detect interlacing artifacts
508 * and returns true if interlacing (combing) is found.
510 * Code taken from Thomas Oestreich's 32detect filter
511 * in the Transcode project, with minor formatting changes.
513 * @param buf An hb_buffer structure holding valid frame data
514 * @param width The frame's width in pixels
515 * @param height The frame's height in pixels
516 * @param color_equal Sensitivity for detecting similar colors
517 * @param color_diff Sensitivity for detecting different colors
518 * @param threshold Sensitivity for flagging planes as combed
519 * @param prog_equal Sensitivity for detecting similar colors on progressive frames
520 * @param prog_diff Sensitivity for detecting different colors on progressive frames
521 * @param prog_threshold Sensitivity for flagging progressive frames as combed
523 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 )
525 int j, k, n, off, cc_1, cc_2, cc[3];
526 // int flag[3] ; // debugging flag
527 uint16_t s1, s2, s3, s4;
532 if ( buf->flags & 16 )
534 /* Frame is progressive, be more discerning. */
535 color_diff = prog_diff;
536 color_equal = prog_equal;
537 threshold = prog_threshold;
540 /* One pas for Y, one pass for Cb, one pass for Cr */
541 for( k = 0; k < 3; k++ )
545 /* Y has already been checked, now offset by Y's dimensions
546 and divide all the other values by 2, since Cr and Cb
547 are half-size compared to Y. */
548 offset = width * height;
554 /* Y and Cb are done, so the offset needs to be bumped
555 so it's width*height + (width / 2) * (height / 2) */
559 for( j = 0; j < width; ++j )
563 for( n = 0; n < ( height - 4 ); n = n + 2 )
565 /* Look at groups of 4 sequential horizontal lines */
566 s1 = ( ( buf->data + offset )[ off + j ] & 0xff );
567 s2 = ( ( buf->data + offset )[ off + j + width ] & 0xff );
568 s3 = ( ( buf->data + offset )[ off + j + 2 * width ] & 0xff );
569 s4 = ( ( buf->data + offset )[ off + j + 3 * width ] & 0xff );
571 /* Note if the 1st and 2nd lines are more different in
572 color than the 1st and 3rd lines are similar in color.*/
573 if ( ( abs( s1 - s3 ) < color_equal ) &&
574 ( abs( s1 - s2 ) > color_diff ) )
577 /* Note if the 2nd and 3rd lines are more different in
578 color than the 2nd and 4th lines are similar in color.*/
579 if ( ( abs( s2 - s4 ) < color_equal ) &&
580 ( abs( s2 - s3 ) > color_diff) )
583 /* Now move down 2 horizontal lines before starting over.*/
589 /* The final cc score for a plane is the percentage of combed pixels it contains.
590 Because sensitivity goes down to hundreths of a percent, multiply by 1000
591 so it will be easy to compare against the threhold value which is an integer. */
592 cc[k] = (int)( ( cc_1 + cc_2 ) * 1000.0 / ( width * height ) );
596 /* HandBrake is all yuv420, so weight the average percentage of all 3 planes accordingly.*/
597 int average_cc = ( 2 * cc[0] + ( cc[1] / 2 ) + ( cc[2] / 2 ) ) / 3;
599 /* Now see if that average percentage of combed pixels surpasses the threshold percentage given by the user.*/
600 if( average_cc > threshold )
603 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" );
609 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" );
612 /* Reaching this point means no combing detected. */
618 * Calculates job width and height for anamorphic content,
620 * @param job Handle to hb_job_t
621 * @param output_width Pointer to returned storage width
622 * @param output_height Pointer to returned storage height
623 * @param output_par_width Pointer to returned pixel width
624 @ param output_par_height Pointer to returned pixel height
626 void hb_set_anamorphic_size( hb_job_t * job,
627 int *output_width, int *output_height,
628 int *output_par_width, int *output_par_height )
630 /* Set up some variables to make the math easier to follow. */
631 hb_title_t * title = job->title;
632 int cropped_width = title->width - job->crop[2] - job->crop[3] ;
633 int cropped_height = title->height - job->crop[0] - job->crop[1] ;
634 double storage_aspect = (double)cropped_width / (double)cropped_height;
635 int mod = job->anamorphic.modulus ? job->anamorphic.modulus : 16;
636 double aspect = title->aspect;
638 int pixel_aspect_width = job->anamorphic.par_width;
639 int pixel_aspect_height = job->anamorphic.par_height;
641 /* If a source was really NTSC or PAL and the user specified ITU PAR
642 values, replace the standard PAR values with the ITU broadcast ones. */
643 if( title->width == 720 && job->anamorphic.itu_par )
645 // convert aspect to a scaled integer so we can test for 16:9 & 4:3
646 // aspect ratios ignoring insignificant differences in the LSBs of
647 // the floating point representation.
648 int iaspect = aspect * 9.;
650 /* Handle ITU PARs */
651 if (title->height == 480)
656 /* It's widescreen */
657 pixel_aspect_width = 40;
658 pixel_aspect_height = 33;
660 else if (iaspect == 12)
663 pixel_aspect_width = 10;
664 pixel_aspect_height = 11;
667 else if (title->height == 576)
672 /* It's widescreen */
673 pixel_aspect_width = 16;
674 pixel_aspect_height = 11;
676 else if (iaspect == 12)
679 pixel_aspect_width = 12;
680 pixel_aspect_height = 11;
685 /* Figure out what width the source would display at. */
686 int source_display_width = cropped_width * (double)pixel_aspect_width /
687 (double)pixel_aspect_height ;
690 3 different ways of deciding output dimensions:
691 - 1: Strict anamorphic, preserve source dimensions
692 - 2: Loose anamorphic, round to mod16 and preserve storage aspect ratio
693 - 3: Power user anamorphic, specify everything
696 switch( job->anamorphic.mode )
699 /* Strict anamorphic */
700 *output_width = cropped_width;
701 *output_height = cropped_height;
702 *output_par_width = title->pixel_aspect_width;
703 *output_par_height = title->pixel_aspect_height;
707 /* "Loose" anamorphic.
708 - Uses mod16-compliant dimensions,
709 - Allows users to set the width
712 // height: Gets set later, ignore user job->height value
714 /* Gotta handle bounding dimensions.
715 If the width is too big, just reset it with no rescaling.
716 Instead of using the aspect-scaled job height,
717 we need to see if the job width divided by the storage aspect
718 is bigger than the max. If so, set it to the max (this is sloppy).
719 If not, set job height to job width divided by storage aspect.
722 if ( job->maxWidth && (job->maxWidth < job->width) )
723 width = job->maxWidth;
725 /* Time to get picture width that divide cleanly.*/
726 width = MULTIPLE_MOD( width, mod);
728 /* Verify these new dimensions don't violate max height and width settings */
729 if ( job->maxWidth && (job->maxWidth < job->width) )
730 width = job->maxWidth;
732 height = ((double)width / storage_aspect) + 0.5;
734 if ( job->maxHeight && (job->maxHeight < height) )
735 height = job->maxHeight;
737 /* Time to get picture height that divide cleanly.*/
738 height = MULTIPLE_MOD( height, mod);
740 /* Verify these new dimensions don't violate max height and width settings */
741 if ( job->maxHeight && (job->maxHeight < height) )
742 height = job->maxHeight;
744 /* The film AR is the source's display width / cropped source height.
745 The output display width is the output height * film AR.
746 The output PAR is the output display width / output storage width. */
747 pixel_aspect_width = height * source_display_width / cropped_height;
748 pixel_aspect_height = width;
750 /* Pass the results back to the caller */
751 *output_width = width;
752 *output_height = height;
756 /* Anamorphic 3: Power User Jamboree
757 - Set everything based on specified values */
759 /* Use specified storage dimensions */
761 height = job->height;
763 /* Bind to max dimensions */
764 if( job->maxWidth && width > job->maxWidth )
765 width = job->maxWidth;
766 if( job->maxHeight && height > job->maxHeight )
767 height = job->maxHeight;
769 /* Time to get picture dimensions that divide cleanly.*/
770 width = MULTIPLE_MOD( width, mod);
771 height = MULTIPLE_MOD( height, mod);
773 /* Verify we're still within max dimensions */
774 if( job->maxWidth && width > job->maxWidth )
775 width = job->maxWidth - (mod/2);
776 if( job->maxHeight && height > job->maxHeight )
777 height = job->maxHeight - (mod/2);
779 /* Re-ensure we have picture dimensions that divide cleanly. */
780 width = MULTIPLE_MOD( width, mod );
781 height = MULTIPLE_MOD( height, mod );
783 /* That finishes the storage dimensions. On to display. */
784 if( job->anamorphic.dar_width && job->anamorphic.dar_height )
786 /* We need to adjust the PAR to produce this aspect. */
787 pixel_aspect_width = height * job->anamorphic.dar_width / job->anamorphic.dar_height;
788 pixel_aspect_height = width;
792 /* We first need the display ar.
793 That's the source display width divided by the source height after cropping.
794 Then we multiple the output height by that to get the pixel aspect width,
795 and the pixel aspect height is the storage width.*/
796 pixel_aspect_width = height * source_display_width / cropped_height;
797 pixel_aspect_height = width;
801 *output_width = width;
802 *output_height = height;
806 /* While x264 is smart enough to reduce fractions on its own, libavcodec
807 needs some help with the math, so lose superfluous factors. */
808 hb_reduce( output_par_width, output_par_height,
809 pixel_aspect_width, pixel_aspect_height );
813 * Calculates job width, height, and cropping parameters.
814 * @param job Handle to hb_job_t.
815 * @param aspect Desired aspect ratio. Value of -1 uses title aspect.
816 * @param pixels Maximum desired pixel count.
818 void hb_set_size( hb_job_t * job, double aspect, int pixels )
820 hb_title_t * title = job->title;
822 int croppedWidth = title->width - title->crop[2] - title->crop[3];
823 int croppedHeight = title->height - title->crop[0] - title->crop[1];
824 double croppedAspect = title->aspect * title->height * croppedWidth /
825 croppedHeight / title->width;
831 /* Keep the best possible aspect ratio */
832 aspect = croppedAspect;
835 /* Crop if necessary to obtain the desired ratio */
836 memcpy( job->crop, title->crop, 4 * sizeof( int ) );
837 if( aspect < croppedAspect )
839 /* Need to crop on the left and right */
840 addCrop = croppedWidth - aspect * croppedHeight * title->width /
841 title->aspect / title->height;
844 addCrop = ( addCrop + 1 ) / 2;
845 job->crop[2] += addCrop;
846 job->crop[3] += addCrop;
848 else if( addCrop & 2 )
851 job->crop[2] += addCrop - 1;
852 job->crop[3] += addCrop + 1;
857 job->crop[2] += addCrop;
858 job->crop[3] += addCrop;
861 else if( aspect > croppedAspect )
863 /* Need to crop on the top and bottom */
864 addCrop = croppedHeight - croppedWidth * title->aspect *
865 title->height / aspect / title->width;
868 addCrop = ( addCrop + 1 ) / 2;
869 job->crop[0] += addCrop;
870 job->crop[1] += addCrop;
872 else if( addCrop & 2 )
875 job->crop[0] += addCrop - 1;
876 job->crop[1] += addCrop + 1;
881 job->crop[0] += addCrop;
882 job->crop[1] += addCrop;
886 /* Compute a resolution from the number of pixels and aspect */
890 h = MULTIPLE_16( (int)( (double)w / aspect ) );
898 job->height = MULTIPLE_16( (int)( (double)job->width / aspect ) );
902 * Returns the number of jobs in the queue.
903 * @param h Handle to hb_handle_t.
904 * @return Number of jobs.
906 int hb_count( hb_handle_t * h )
908 return hb_list_count( h->jobs );
912 * Returns handle to job at index i within the job list.
913 * @param h Handle to hb_handle_t.
914 * @param i Index of job.
915 * @returns Handle to hb_job_t of desired job.
917 hb_job_t * hb_job( hb_handle_t * h, int i )
919 return hb_list_item( h->jobs, i );
922 hb_job_t * hb_current_job( hb_handle_t * h )
924 return( h->current_job );
928 * Adds a job to the job list.
929 * @param h Handle to hb_handle_t.
930 * @param job Handle to hb_job_t.
932 void hb_add( hb_handle_t * h, hb_job_t * job )
935 hb_title_t * title, * title_copy;
936 hb_chapter_t * chapter, * chapter_copy;
938 hb_subtitle_t * subtitle, * subtitle_copy;
944 title_copy = malloc( sizeof( hb_title_t ) );
945 memcpy( title_copy, title, sizeof( hb_title_t ) );
947 title_copy->list_chapter = hb_list_init();
948 for( i = 0; i < hb_list_count( title->list_chapter ); i++ )
950 chapter = hb_list_item( title->list_chapter, i );
951 chapter_copy = malloc( sizeof( hb_chapter_t ) );
952 memcpy( chapter_copy, chapter, sizeof( hb_chapter_t ) );
953 hb_list_add( title_copy->list_chapter, chapter_copy );
959 if( title->metadata )
961 title_copy->metadata = malloc( sizeof( hb_metadata_t ) );
963 if( title_copy->metadata )
965 memcpy( title_copy->metadata, title->metadata, sizeof( hb_metadata_t ) );
968 * Need to copy the artwork seperatly (TODO).
970 if( title->metadata->coverart )
972 title_copy->metadata->coverart = malloc( title->metadata->coverart_size );
973 if( title_copy->metadata->coverart )
975 memcpy( title_copy->metadata->coverart, title->metadata->coverart,
976 title->metadata->coverart_size );
978 title_copy->metadata->coverart_size = 0;
984 /* Copy the audio track(s) we want */
985 title_copy->list_audio = hb_list_init();
987 for( i = 0; i < hb_list_count(job->list_audio); i++ )
989 if( ( audio = hb_list_item( job->list_audio, i ) ) )
991 hb_list_add( title_copy->list_audio, hb_audio_copy(audio) );
995 title_copy->list_subtitle = hb_list_init();
998 * The following code is confusing, there are three ways in which
999 * we select subtitles and it depends on whether this is single or
1002 * subtitle_scan may be enabled, in which case the first pass
1003 * scans all subtitles of that language. The second pass does not
1004 * select any because they are set at the end of the first pass.
1006 * native_language may have a preferred language, in which case we
1007 * may be switching the language we want for the subtitles in the
1008 * first pass of a single pass, or the second pass of a two pass.
1010 * We may have manually selected a subtitle, in which case that is
1011 * selected in the first pass of a single pass, or the second of a
1014 memset( audio_lang, 0, sizeof( audio_lang ) );
1016 if ( job->indepth_scan || job->native_language ) {
1019 * Find the first audio language that is being encoded
1021 for( i = 0; i < hb_list_count(job->list_audio); i++ )
1023 if( ( audio = hb_list_item( job->list_audio, i ) ) )
1025 strncpy(audio_lang, audio->config.lang.iso639_2, sizeof(audio_lang));
1031 * In all cases switch the language if we need to to our native
1034 if( job->native_language )
1036 if( strncasecmp( job->native_language, audio_lang,
1037 sizeof( audio_lang ) ) != 0 )
1040 if( job->pass != 2 )
1042 hb_log( "Enabled subtitles in native language '%s', audio is in '%s'",
1043 job->native_language, audio_lang);
1046 * The main audio track is not in our native language, so switch
1047 * the subtitles to use our native language instead.
1049 strncpy( audio_lang, job->native_language, sizeof( audio_lang ) );
1052 * native language is irrelevent, free it.
1054 free( job->native_language );
1055 job->native_language = NULL;
1061 * If doing a subtitle scan then add all the matching subtitles for this
1064 if ( job->indepth_scan )
1066 for( i=0; i < hb_list_count( title->list_subtitle ); i++ )
1068 subtitle = hb_list_item( title->list_subtitle, i );
1069 if( strcmp( subtitle->iso639_2, audio_lang ) == 0 &&
1070 subtitle->source == VOBSUB )
1073 * Matched subtitle language with audio language, so
1074 * add this to our list to scan.
1076 * We will update the subtitle list on the second pass
1077 * later after the first pass has completed.
1079 subtitle_copy = malloc( sizeof( hb_subtitle_t ) );
1080 memcpy( subtitle_copy, subtitle, sizeof( hb_subtitle_t ) );
1081 hb_list_add( title_copy->list_subtitle, subtitle_copy );
1082 if ( job->native_language ) {
1084 * With native language just select the
1085 * first match in our langiage, not all of
1086 * them. Subsequent ones are likely to be commentary
1094 * Not doing a subtitle scan in this pass, but maybe we are in the
1097 if( job->pass != 1 && job->native_language )
1100 * We are not doing a subtitle scan but do want the
1101 * native langauge subtitle selected, so select it
1102 * for pass 0 or pass 2 of a two pass.
1104 for( i=0; i < hb_list_count( title->list_subtitle ); i++ )
1106 subtitle = hb_list_item( title->list_subtitle, i );
1107 if( strcmp( subtitle->iso639_2, audio_lang ) == 0 )
1110 * Matched subtitle language with audio language, so
1111 * add this to our list to scan.
1113 subtitle_copy = malloc( sizeof( hb_subtitle_t ) );
1114 memcpy( subtitle_copy, subtitle, sizeof( hb_subtitle_t ) );
1115 hb_list_add( title_copy->list_subtitle, subtitle_copy );
1121 * Manually selected subtitles, in which case only
1122 * bother adding them for pass 0 or pass 2 of a two
1125 if( job->pass != 1 )
1128 * Copy all of them from the input job, to the title_copy/job_copy.
1130 for( i = 0; i < hb_list_count(job->list_subtitle); i++ ) {
1131 if( ( subtitle = hb_list_item( job->list_subtitle, i ) ) )
1133 subtitle_copy = malloc( sizeof( hb_subtitle_t ) );
1134 memcpy( subtitle_copy, subtitle, sizeof( hb_subtitle_t ) );
1135 hb_list_add( title_copy->list_subtitle, subtitle_copy );
1143 job_copy = calloc( sizeof( hb_job_t ), 1 );
1144 memcpy( job_copy, job, sizeof( hb_job_t ) );
1145 title_copy->job = job_copy;
1146 job_copy->title = title_copy;
1147 job_copy->list_audio = title_copy->list_audio;
1148 job_copy->list_subtitle = title_copy->list_subtitle; // sharing list between title and job
1149 job_copy->file = strdup( job->file );
1151 job_copy->pause = h->pause_lock;
1153 /* Copy the job filter list */
1157 int filter_count = hb_list_count( job->filters );
1158 job_copy->filters = hb_list_init();
1159 for( i = 0; i < filter_count; i++ )
1162 * Copy the filters, since the MacGui reuses the global filter objects
1163 * meaning that queued up jobs overwrite the previous filter settings.
1164 * In reality, settings is probably the only field that needs duplicating
1165 * since it's the only value that is ever changed. But name is duplicated
1166 * as well for completeness. Not copying private_data since it gets
1167 * created for each job in renderInit.
1169 hb_filter_object_t * filter = hb_list_item( job->filters, i );
1170 hb_filter_object_t * filter_copy = malloc( sizeof( hb_filter_object_t ) );
1171 memcpy( filter_copy, filter, sizeof( hb_filter_object_t ) );
1173 filter_copy->name = strdup( filter->name );
1174 if( filter->settings )
1175 filter_copy->settings = strdup( filter->settings );
1176 hb_list_add( job_copy->filters, filter_copy );
1180 /* Add the job to the list */
1181 hb_list_add( h->jobs, job_copy );
1182 h->job_count = hb_count(h);
1183 h->job_count_permanent++;
1187 * Removes a job from the job list.
1188 * @param h Handle to hb_handle_t.
1189 * @param job Handle to hb_job_t.
1191 void hb_rem( hb_handle_t * h, hb_job_t * job )
1193 hb_list_rem( h->jobs, job );
1195 h->job_count = hb_count(h);
1196 if (h->job_count_permanent)
1197 h->job_count_permanent--;
1199 /* XXX free everything XXX */
1203 * Starts the conversion process.
1204 * Sets state to HB_STATE_WORKING.
1205 * calls hb_work_init, to launch work thread. Stores handle to work thread.
1206 * @param h Handle to hb_handle_t.
1208 void hb_start( hb_handle_t * h )
1211 h->job_count = hb_list_count( h->jobs );
1212 h->job_count_permanent = h->job_count;
1214 hb_lock( h->state_lock );
1215 h->state.state = HB_STATE_WORKING;
1216 #define p h->state.param.working
1219 p.job_count = h->job_count;
1227 hb_unlock( h->state_lock );
1232 h->work_thread = hb_work_init( h->jobs, h->cpu_count,
1233 &h->work_die, &h->work_error, &h->current_job );
1237 * Pauses the conversion process.
1238 * @param h Handle to hb_handle_t.
1240 void hb_pause( hb_handle_t * h )
1244 hb_lock( h->pause_lock );
1247 hb_lock( h->state_lock );
1248 h->state.state = HB_STATE_PAUSED;
1249 hb_unlock( h->state_lock );
1254 * Resumes the conversion process.
1255 * @param h Handle to hb_handle_t.
1257 void hb_resume( hb_handle_t * h )
1261 hb_unlock( h->pause_lock );
1267 * Stops the conversion process.
1268 * @param h Handle to hb_handle_t.
1270 void hb_stop( hb_handle_t * h )
1274 h->job_count = hb_count(h);
1275 h->job_count_permanent = 0;
1281 * Returns the state of the conversion process.
1282 * @param h Handle to hb_handle_t.
1283 * @param s Handle to hb_state_t which to copy the state data.
1285 void hb_get_state( hb_handle_t * h, hb_state_t * s )
1287 hb_lock( h->state_lock );
1289 memcpy( s, &h->state, sizeof( hb_state_t ) );
1290 if ( h->state.state == HB_STATE_SCANDONE || h->state.state == HB_STATE_WORKDONE )
1291 h->state.state = HB_STATE_IDLE;
1293 hb_unlock( h->state_lock );
1296 void hb_get_state2( hb_handle_t * h, hb_state_t * s )
1298 hb_lock( h->state_lock );
1300 memcpy( s, &h->state, sizeof( hb_state_t ) );
1302 hb_unlock( h->state_lock );
1306 * Called in MacGui in UpdateUI to check
1307 * for a new scan being completed to set a new source
1309 int hb_get_scancount( hb_handle_t * h)
1311 return h->scanCount;
1315 * Closes access to libhb by freeing the hb_handle_t handle ontained in hb_init.
1316 * @param _h Pointer to handle to hb_handle_t.
1318 void hb_close( hb_handle_t ** _h )
1320 hb_handle_t * h = *_h;
1324 hb_thread_close( &h->main_thread );
1326 while( ( title = hb_list_item( h->list_title, 0 ) ) )
1328 hb_list_rem( h->list_title, title );
1329 if( title->job && title->job->filters )
1331 hb_list_close( &title->job->filters );
1334 hb_title_close( &title );
1336 hb_list_close( &h->list_title );
1338 hb_list_close( &h->jobs );
1339 hb_lock_close( &h->state_lock );
1340 hb_lock_close( &h->pause_lock );
1347 * Monitors the state of the update, scan, and work threads.
1348 * Sets scan done state when scan thread exits.
1349 * Sets work done state when work thread exits.
1350 * @param _h Handle to hb_handle_t
1352 static void thread_func( void * _h )
1354 hb_handle_t * h = (hb_handle_t *) _h;
1357 struct dirent * entry;
1361 /* Create folder for temporary files */
1362 memset( dirname, 0, 1024 );
1363 hb_get_tempory_directory( h, dirname );
1365 hb_mkdir( dirname );
1369 /* In case the check_update thread hangs, it'll die sooner or
1370 later. Then, we join it here */
1371 if( h->update_thread &&
1372 hb_thread_has_exited( h->update_thread ) )
1374 hb_thread_close( &h->update_thread );
1377 /* Check if the scan thread is done */
1378 if( h->scan_thread &&
1379 hb_thread_has_exited( h->scan_thread ) )
1381 hb_thread_close( &h->scan_thread );
1383 hb_log( "libhb: scan thread found %d valid title(s)",
1384 hb_list_count( h->list_title ) );
1385 hb_lock( h->state_lock );
1386 h->state.state = HB_STATE_SCANDONE; //originally state.state
1387 hb_unlock( h->state_lock );
1388 /*we increment this sessions scan count by one for the MacGui
1389 to trigger a new source being set */
1393 /* Check if the work thread is done */
1394 if( h->work_thread &&
1395 hb_thread_has_exited( h->work_thread ) )
1397 hb_thread_close( &h->work_thread );
1399 hb_log( "libhb: work result = %d",
1401 hb_lock( h->state_lock );
1402 h->state.state = HB_STATE_WORKDONE;
1403 h->state.param.workdone.error = h->work_error;
1405 h->job_count = hb_count(h);
1406 if (h->job_count < 1)
1407 h->job_count_permanent = 0;
1408 hb_unlock( h->state_lock );
1414 if( h->work_thread )
1417 hb_thread_close( &h->work_thread );
1420 /* Remove temp folder */
1421 dir = opendir( dirname );
1424 while( ( entry = readdir( dir ) ) )
1426 char filename[1024];
1427 if( entry->d_name[0] == '.' )
1431 memset( filename, 0, 1024 );
1432 snprintf( filename, 1023, "%s/%s", dirname, entry->d_name );
1442 * @param h Handle to hb_handle_t
1444 int hb_get_pid( hb_handle_t * h )
1450 * Sets the current state.
1451 * @param h Handle to hb_handle_t
1452 * @param s Handle to new hb_state_t
1454 void hb_set_state( hb_handle_t * h, hb_state_t * s )
1456 hb_lock( h->pause_lock );
1457 hb_lock( h->state_lock );
1458 memcpy( &h->state, s, sizeof( hb_state_t ) );
1459 if( h->state.state == HB_STATE_WORKING )
1462 if (h->job_count < 1)
1463 h->job_count_permanent = 1;
1465 h->state.param.working.job_cur =
1466 h->job_count_permanent - hb_list_count( h->jobs );
1467 h->state.param.working.job_count = h->job_count_permanent;
1469 // Set which job is being worked on
1471 h->state.param.working.sequence_id = h->current_job->sequence_id;
1473 h->state.param.working.sequence_id = 0;
1475 hb_unlock( h->state_lock );
1476 hb_unlock( h->pause_lock );