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*/
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;
49 hb_lock_t *hb_avcodec_lock;
50 hb_work_object_t * hb_objects = NULL;
52 static void thread_func( void * );
54 void hb_avcodec_init()
56 hb_avcodec_lock = hb_lock_init();
60 int hb_avcodec_open(AVCodecContext *avctx, AVCodec *codec)
63 hb_lock( hb_avcodec_lock );
64 ret = avcodec_open(avctx, codec);
65 hb_unlock( hb_avcodec_lock );
69 int hb_avcodec_close(AVCodecContext *avctx)
72 hb_lock( hb_avcodec_lock );
73 ret = avcodec_close(avctx);
74 hb_unlock( hb_avcodec_lock );
79 * Registers work objects, by adding the work object to a liked list.
80 * @param w Handle to hb_work_object_t to register.
82 void hb_register( hb_work_object_t * w )
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.
94 hb_handle_t * hb_init( int verbose, int update_check )
96 hb_handle_t * h = calloc( sizeof( hb_handle_t ), 1 );
99 /* See hb_deep_log() and hb_log() in common.c */
100 global_verbosity_level = verbose;
102 putenv( "HB_DEBUG=1" );
104 /* Check for an update on the website if asked to */
109 hb_log( "hb_init: checking for updates" );
110 date = hb_get_date();
111 h->update_thread = hb_update_init( &h->build, h->version );
115 if( hb_thread_has_exited( h->update_thread ) )
117 /* Immediate success or failure */
118 hb_thread_close( &h->update_thread );
121 if( hb_get_date() > date + 1000 )
123 /* Still nothing after one second. Connection problem,
124 let the thread die */
125 hb_log( "hb_init: connection problem, not waiting for "
134 * Initialise buffer pool
136 hb_buffer_pool_init();
138 /* CPU count detection */
139 hb_log( "hb_init: checking cpu count" );
140 h->cpu_count = hb_get_cpu_count();
142 h->list_title = hb_list_init();
143 h->jobs = hb_list_init();
145 h->state_lock = hb_lock_init();
146 h->state.state = HB_STATE_IDLE;
148 h->pause_lock = hb_lock_init();
150 h->interjob = calloc( sizeof( hb_interjob_t ), 1 );
155 /* Start library thread */
156 hb_log( "hb_init: starting libhb thread" );
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_decsrtsub );
166 hb_register( &hb_render );
167 hb_register( &hb_encavcodec );
168 hb_register( &hb_encx264 );
169 hb_register( &hb_enctheora );
170 hb_register( &hb_deca52 );
171 hb_register( &hb_decdca );
172 hb_register( &hb_decavcodec );
173 hb_register( &hb_decavcodecv );
174 hb_register( &hb_decavcodecvi );
175 hb_register( &hb_decavcodecai );
176 hb_register( &hb_declpcm );
177 hb_register( &hb_encfaac );
178 hb_register( &hb_enclame );
179 hb_register( &hb_encvorbis );
181 hb_register( &hb_encca_aac );
188 * libhb initialization routine.
189 * This version is to use when calling the dylib, the macro hb_init isn't available from a dylib call!
190 * @param verbose HB_DEBUG_NONE or HB_DEBUG_ALL.
191 * @param update_check signals libhb to check for updated version from HandBrake website.
192 * @return Handle to hb_handle_t for use on all subsequent calls to libhb.
194 hb_handle_t * hb_init_dl( int verbose, int update_check )
196 hb_handle_t * h = calloc( sizeof( hb_handle_t ), 1 );
199 /* See hb_log() in common.c */
200 if( verbose > HB_DEBUG_NONE )
202 putenv( "HB_DEBUG=1" );
205 /* Check for an update on the website if asked to */
210 hb_log( "hb_init: checking for updates" );
211 date = hb_get_date();
212 h->update_thread = hb_update_init( &h->build, h->version );
216 if( hb_thread_has_exited( h->update_thread ) )
218 /* Immediate success or failure */
219 hb_thread_close( &h->update_thread );
222 if( hb_get_date() > date + 1000 )
224 /* Still nothing after one second. Connection problem,
225 let the thread die */
226 hb_log( "hb_init: connection problem, not waiting for "
234 /* CPU count detection */
235 hb_log( "hb_init: checking cpu count" );
236 h->cpu_count = hb_get_cpu_count();
238 h->list_title = hb_list_init();
239 h->jobs = hb_list_init();
240 h->current_job = NULL;
242 h->state_lock = hb_lock_init();
243 h->state.state = HB_STATE_IDLE;
245 h->pause_lock = hb_lock_init();
249 avcodec_register_all();
251 /* Start library thread */
252 hb_log( "hb_init: starting libhb thread" );
254 h->main_thread = hb_thread_init( "libhb", thread_func, h,
255 HB_NORMAL_PRIORITY );
257 hb_register( &hb_sync );
258 hb_register( &hb_decmpeg2 );
259 hb_register( &hb_decvobsub );
260 hb_register( &hb_encvobsub );
261 hb_register( &hb_deccc608 );
262 hb_register( &hb_decsrtsub );
263 hb_register( &hb_render );
264 hb_register( &hb_encavcodec );
265 hb_register( &hb_encx264 );
266 hb_register( &hb_enctheora );
267 hb_register( &hb_deca52 );
268 hb_register( &hb_decdca );
269 hb_register( &hb_decavcodec );
270 hb_register( &hb_decavcodecv );
271 hb_register( &hb_decavcodecvi );
272 hb_register( &hb_decavcodecai );
273 hb_register( &hb_declpcm );
274 hb_register( &hb_encfaac );
275 hb_register( &hb_enclame );
276 hb_register( &hb_encvorbis );
278 hb_register( &hb_encca_aac );
286 * Returns current version of libhb.
287 * @param h Handle to hb_handle_t.
288 * @return character array of version number.
290 char * hb_get_version( hb_handle_t * h )
292 return HB_PROJECT_VERSION;
296 * Returns current build of libhb.
297 * @param h Handle to hb_handle_t.
298 * @return character array of build number.
300 int hb_get_build( hb_handle_t * h )
302 return HB_PROJECT_BUILD;
306 * Checks for needed update.
307 * @param h Handle to hb_handle_t.
308 * @param version Pointer to handle where version will be copied.
309 * @return update indicator.
311 int hb_check_update( hb_handle_t * h, char ** version )
313 *version = ( h->build < 0 ) ? NULL : h->version;
318 * Sets the cpu count to the desired value.
319 * @param h Handle to hb_handle_t
320 * @param cpu_count Number of CPUs to use.
322 void hb_set_cpu_count( hb_handle_t * h, int cpu_count )
324 cpu_count = MAX( 1, cpu_count );
325 cpu_count = MIN( cpu_count, 8 );
326 h->cpu_count = cpu_count;
330 * Deletes current previews associated with titles
331 * @param h Handle to hb_handle_t
333 void hb_remove_previews( hb_handle_t * h )
340 struct dirent * entry;
342 memset( dirname, 0, 1024 );
343 hb_get_tempory_directory( h, dirname );
344 dir = opendir( dirname );
345 if (dir == NULL) return;
347 count = hb_list_count( h->list_title );
348 while( ( entry = readdir( dir ) ) )
350 if( entry->d_name[0] == '.' )
354 for( i = 0; i < count; i++ )
356 title = hb_list_item( h->list_title, i );
357 len = snprintf( filename, 1024, "%" PRIxPTR, (intptr_t) title );
358 if (strncmp(entry->d_name, filename, len) == 0)
360 snprintf( filename, 1024, "%s/%s", dirname, entry->d_name );
370 * Initializes a scan of the by calling hb_scan_init
371 * @param h Handle to hb_handle_t
372 * @param path location of VIDEO_TS folder.
373 * @param title_index Desired title to scan. 0 for all titles.
374 * @param preview_count Number of preview images to generate.
375 * @param store_previews Whether or not to write previews to disk.
377 void hb_scan( hb_handle_t * h, const char * path, int title_index,
378 int preview_count, int store_previews )
382 /* Clean up from previous scan */
383 hb_remove_previews( h );
384 while( ( title = hb_list_item( h->list_title, 0 ) ) )
386 hb_list_rem( h->list_title, title );
387 hb_title_close( &title );
390 hb_log( "hb_scan: path=%s, title_index=%d", path, title_index );
391 h->scan_thread = hb_scan_init( h, path, title_index, h->list_title,
392 preview_count, store_previews );
396 * Returns the list of titles found.
397 * @param h Handle to hb_handle_t
398 * @return Handle to hb_list_t of the title list.
400 hb_list_t * hb_get_titles( hb_handle_t * h )
402 return h->list_title;
406 * Create preview image of desired title a index of picture.
407 * @param h Handle to hb_handle_t.
408 * @param title Handle to hb_title_t of desired title.
409 * @param picture Index in title.
410 * @param buffer Handle to buufer were inage will be drawn.
412 void hb_get_preview( hb_handle_t * h, hb_title_t * title, int picture,
415 hb_job_t * job = title->job;
418 uint8_t * buf1, * buf2, * buf3, * buf4, * pen;
420 AVPicture pic_in, pic_preview, pic_deint, pic_crop, pic_scale;
421 struct SwsContext * context;
423 int rgb_width = ((job->width + 7) >> 3) << 3;
426 swsflags = SWS_LANCZOS | SWS_ACCURATE_RND;
428 buf1 = av_malloc( avpicture_get_size( PIX_FMT_YUV420P, title->width, title->height ) );
429 buf2 = av_malloc( avpicture_get_size( PIX_FMT_YUV420P, title->width, title->height ) );
430 buf3 = av_malloc( avpicture_get_size( PIX_FMT_YUV420P, rgb_width, job->height ) );
431 buf4 = av_malloc( avpicture_get_size( PIX_FMT_RGB32, rgb_width, job->height ) );
432 avpicture_fill( &pic_in, buf1, PIX_FMT_YUV420P,
433 title->width, title->height );
434 avpicture_fill( &pic_deint, buf2, PIX_FMT_YUV420P,
435 title->width, title->height );
436 avpicture_fill( &pic_scale, buf3, PIX_FMT_YUV420P,
437 rgb_width, job->height );
438 avpicture_fill( &pic_preview, buf4, PIX_FMT_RGB32,
439 rgb_width, job->height );
441 // Allocate the AVPicture frames and fill in
443 memset( filename, 0, 1024 );
445 hb_get_tempory_filename( h, filename, "%" PRIxPTR "%d",
446 (intptr_t) title, picture );
448 file = fopen( filename, "rb" );
451 hb_log( "hb_get_preview: fopen failed" );
455 fread( buf1, avpicture_get_size( PIX_FMT_YUV420P, title->width, title->height), 1, file );
458 if( job->deinterlace )
460 // Deinterlace and crop
461 avpicture_deinterlace( &pic_deint, &pic_in, PIX_FMT_YUV420P, title->width, title->height );
462 av_picture_crop( &pic_crop, &pic_deint, PIX_FMT_YUV420P, job->crop[0], job->crop[2] );
467 av_picture_crop( &pic_crop, &pic_in, PIX_FMT_YUV420P, job->crop[0], job->crop[2] );
470 // Get scaling context
471 context = sws_getContext(title->width - (job->crop[2] + job->crop[3]),
472 title->height - (job->crop[0] + job->crop[1]),
474 job->width, job->height, PIX_FMT_YUV420P,
475 swsflags, NULL, NULL, NULL);
479 pic_crop.data, pic_crop.linesize,
480 0, title->height - (job->crop[0] + job->crop[1]),
481 pic_scale.data, pic_scale.linesize);
484 sws_freeContext( context );
486 // Get preview context
487 context = sws_getContext(rgb_width, job->height, PIX_FMT_YUV420P,
488 rgb_width, job->height, PIX_FMT_RGB32,
489 swsflags, NULL, NULL, NULL);
493 pic_scale.data, pic_scale.linesize,
495 pic_preview.data, pic_preview.linesize);
498 sws_freeContext( context );
500 preview_size = pic_preview.linesize[0];
502 for( i = 0; i < job->height; i++ )
504 memcpy( pen, buf4 + preview_size * i, 4 * job->width );
505 pen += 4 * job->width;
509 avpicture_free( &pic_preview );
510 avpicture_free( &pic_scale );
511 avpicture_free( &pic_deint );
512 avpicture_free( &pic_in );
516 * Analyzes a frame to detect interlacing artifacts
517 * and returns true if interlacing (combing) is found.
519 * Code taken from Thomas Oestreich's 32detect filter
520 * in the Transcode project, with minor formatting changes.
522 * @param buf An hb_buffer structure holding valid frame data
523 * @param width The frame's width in pixels
524 * @param height The frame's height in pixels
525 * @param color_equal Sensitivity for detecting similar colors
526 * @param color_diff Sensitivity for detecting different colors
527 * @param threshold Sensitivity for flagging planes as combed
528 * @param prog_equal Sensitivity for detecting similar colors on progressive frames
529 * @param prog_diff Sensitivity for detecting different colors on progressive frames
530 * @param prog_threshold Sensitivity for flagging progressive frames as combed
532 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 )
534 int j, k, n, off, cc_1, cc_2, cc[3];
535 // int flag[3] ; // debugging flag
536 uint16_t s1, s2, s3, s4;
541 if ( buf->flags & 16 )
543 /* Frame is progressive, be more discerning. */
544 color_diff = prog_diff;
545 color_equal = prog_equal;
546 threshold = prog_threshold;
549 /* One pas for Y, one pass for Cb, one pass for Cr */
550 for( k = 0; k < 3; k++ )
554 /* Y has already been checked, now offset by Y's dimensions
555 and divide all the other values by 2, since Cr and Cb
556 are half-size compared to Y. */
557 offset = width * height;
563 /* Y and Cb are done, so the offset needs to be bumped
564 so it's width*height + (width / 2) * (height / 2) */
568 for( j = 0; j < width; ++j )
572 for( n = 0; n < ( height - 4 ); n = n + 2 )
574 /* Look at groups of 4 sequential horizontal lines */
575 s1 = ( ( buf->data + offset )[ off + j ] & 0xff );
576 s2 = ( ( buf->data + offset )[ off + j + width ] & 0xff );
577 s3 = ( ( buf->data + offset )[ off + j + 2 * width ] & 0xff );
578 s4 = ( ( buf->data + offset )[ off + j + 3 * width ] & 0xff );
580 /* Note if the 1st and 2nd lines are more different in
581 color than the 1st and 3rd lines are similar in color.*/
582 if ( ( abs( s1 - s3 ) < color_equal ) &&
583 ( abs( s1 - s2 ) > color_diff ) )
586 /* Note if the 2nd and 3rd lines are more different in
587 color than the 2nd and 4th lines are similar in color.*/
588 if ( ( abs( s2 - s4 ) < color_equal ) &&
589 ( abs( s2 - s3 ) > color_diff) )
592 /* Now move down 2 horizontal lines before starting over.*/
598 /* The final cc score for a plane is the percentage of combed pixels it contains.
599 Because sensitivity goes down to hundreths of a percent, multiply by 1000
600 so it will be easy to compare against the threhold value which is an integer. */
601 cc[k] = (int)( ( cc_1 + cc_2 ) * 1000.0 / ( width * height ) );
605 /* HandBrake is all yuv420, so weight the average percentage of all 3 planes accordingly.*/
606 int average_cc = ( 2 * cc[0] + ( cc[1] / 2 ) + ( cc[2] / 2 ) ) / 3;
608 /* Now see if that average percentage of combed pixels surpasses the threshold percentage given by the user.*/
609 if( average_cc > threshold )
612 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" );
618 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" );
621 /* Reaching this point means no combing detected. */
627 * Calculates job width and height for anamorphic content,
629 * @param job Handle to hb_job_t
630 * @param output_width Pointer to returned storage width
631 * @param output_height Pointer to returned storage height
632 * @param output_par_width Pointer to returned pixel width
633 @ param output_par_height Pointer to returned pixel height
635 void hb_set_anamorphic_size( hb_job_t * job,
636 int *output_width, int *output_height,
637 int *output_par_width, int *output_par_height )
639 /* Set up some variables to make the math easier to follow. */
640 hb_title_t * title = job->title;
641 int cropped_width = title->width - job->crop[2] - job->crop[3] ;
642 int cropped_height = title->height - job->crop[0] - job->crop[1] ;
643 double storage_aspect = (double)cropped_width / (double)cropped_height;
644 int mod = job->anamorphic.modulus ? job->anamorphic.modulus : 16;
645 double aspect = title->aspect;
647 int pixel_aspect_width = job->anamorphic.par_width;
648 int pixel_aspect_height = job->anamorphic.par_height;
650 /* If a source was really NTSC or PAL and the user specified ITU PAR
651 values, replace the standard PAR values with the ITU broadcast ones. */
652 if( title->width == 720 && job->anamorphic.itu_par )
654 // convert aspect to a scaled integer so we can test for 16:9 & 4:3
655 // aspect ratios ignoring insignificant differences in the LSBs of
656 // the floating point representation.
657 int iaspect = aspect * 9.;
659 /* Handle ITU PARs */
660 if (title->height == 480)
665 /* It's widescreen */
666 pixel_aspect_width = 40;
667 pixel_aspect_height = 33;
669 else if (iaspect == 12)
672 pixel_aspect_width = 10;
673 pixel_aspect_height = 11;
676 else if (title->height == 576)
681 /* It's widescreen */
682 pixel_aspect_width = 16;
683 pixel_aspect_height = 11;
685 else if (iaspect == 12)
688 pixel_aspect_width = 12;
689 pixel_aspect_height = 11;
694 /* Figure out what width the source would display at. */
695 int source_display_width = cropped_width * (double)pixel_aspect_width /
696 (double)pixel_aspect_height ;
699 3 different ways of deciding output dimensions:
700 - 1: Strict anamorphic, preserve source dimensions
701 - 2: Loose anamorphic, round to mod16 and preserve storage aspect ratio
702 - 3: Power user anamorphic, specify everything
705 switch( job->anamorphic.mode )
708 /* Strict anamorphic */
709 *output_width = cropped_width;
710 *output_height = cropped_height;
711 *output_par_width = title->pixel_aspect_width;
712 *output_par_height = title->pixel_aspect_height;
716 /* "Loose" anamorphic.
717 - Uses mod16-compliant dimensions,
718 - Allows users to set the width
721 // height: Gets set later, ignore user job->height value
723 /* Gotta handle bounding dimensions.
724 If the width is too big, just reset it with no rescaling.
725 Instead of using the aspect-scaled job height,
726 we need to see if the job width divided by the storage aspect
727 is bigger than the max. If so, set it to the max (this is sloppy).
728 If not, set job height to job width divided by storage aspect.
731 if ( job->maxWidth && (job->maxWidth < job->width) )
732 width = job->maxWidth;
734 /* Time to get picture width that divide cleanly.*/
735 width = MULTIPLE_MOD( width, mod);
737 /* Verify these new dimensions don't violate max height and width settings */
738 if ( job->maxWidth && (job->maxWidth < job->width) )
739 width = job->maxWidth;
741 height = ((double)width / storage_aspect) + 0.5;
743 if ( job->maxHeight && (job->maxHeight < height) )
744 height = job->maxHeight;
746 /* Time to get picture height that divide cleanly.*/
747 height = MULTIPLE_MOD( height, mod);
749 /* Verify these new dimensions don't violate max height and width settings */
750 if ( job->maxHeight && (job->maxHeight < height) )
751 height = job->maxHeight;
753 /* The film AR is the source's display width / cropped source height.
754 The output display width is the output height * film AR.
755 The output PAR is the output display width / output storage width. */
756 pixel_aspect_width = height * source_display_width / cropped_height;
757 pixel_aspect_height = width;
759 /* Pass the results back to the caller */
760 *output_width = width;
761 *output_height = height;
765 /* Anamorphic 3: Power User Jamboree
766 - Set everything based on specified values */
768 /* Use specified storage dimensions */
770 height = job->height;
772 /* Bind to max dimensions */
773 if( job->maxWidth && width > job->maxWidth )
774 width = job->maxWidth;
775 if( job->maxHeight && height > job->maxHeight )
776 height = job->maxHeight;
778 /* Time to get picture dimensions that divide cleanly.*/
779 width = MULTIPLE_MOD( width, mod);
780 height = MULTIPLE_MOD( height, mod);
782 /* Verify we're still within max dimensions */
783 if( job->maxWidth && width > job->maxWidth )
784 width = job->maxWidth - (mod/2);
785 if( job->maxHeight && height > job->maxHeight )
786 height = job->maxHeight - (mod/2);
788 /* Re-ensure we have picture dimensions that divide cleanly. */
789 width = MULTIPLE_MOD( width, mod );
790 height = MULTIPLE_MOD( height, mod );
792 /* That finishes the storage dimensions. On to display. */
793 if( job->anamorphic.dar_width && job->anamorphic.dar_height )
795 /* We need to adjust the PAR to produce this aspect. */
796 pixel_aspect_width = height * job->anamorphic.dar_width / job->anamorphic.dar_height;
797 pixel_aspect_height = width;
801 /* If we're doing ana 3 and not specifying a DAR, care needs to be taken.
802 This indicates a PAR is potentially being set by the interface. But
803 this is an output PAR, to correct a source, and it should not be assumed
804 that it properly creates a display aspect ratio when applied to the source,
805 which could easily be stored in a different resolution. */
806 if( job->anamorphic.keep_display_aspect )
808 /* We can ignore the possibility of a PAR change */
809 pixel_aspect_width = height * ( (double)source_display_width / (double)cropped_height );
810 pixel_aspect_height = width;
814 int output_display_width = width * (double)pixel_aspect_width /
815 (double)pixel_aspect_height;
816 pixel_aspect_width = output_display_width;
817 pixel_aspect_height = width;
822 *output_width = width;
823 *output_height = height;
827 /* While x264 is smart enough to reduce fractions on its own, libavcodec
828 needs some help with the math, so lose superfluous factors. */
829 hb_reduce( output_par_width, output_par_height,
830 pixel_aspect_width, pixel_aspect_height );
834 * Calculates job width, height, and cropping parameters.
835 * @param job Handle to hb_job_t.
836 * @param aspect Desired aspect ratio. Value of -1 uses title aspect.
837 * @param pixels Maximum desired pixel count.
839 void hb_set_size( hb_job_t * job, double aspect, int pixels )
841 hb_title_t * title = job->title;
843 int croppedWidth = title->width - title->crop[2] - title->crop[3];
844 int croppedHeight = title->height - title->crop[0] - title->crop[1];
845 double croppedAspect = title->aspect * title->height * croppedWidth /
846 croppedHeight / title->width;
852 /* Keep the best possible aspect ratio */
853 aspect = croppedAspect;
856 /* Crop if necessary to obtain the desired ratio */
857 memcpy( job->crop, title->crop, 4 * sizeof( int ) );
858 if( aspect < croppedAspect )
860 /* Need to crop on the left and right */
861 addCrop = croppedWidth - aspect * croppedHeight * title->width /
862 title->aspect / title->height;
865 addCrop = ( addCrop + 1 ) / 2;
866 job->crop[2] += addCrop;
867 job->crop[3] += addCrop;
869 else if( addCrop & 2 )
872 job->crop[2] += addCrop - 1;
873 job->crop[3] += addCrop + 1;
878 job->crop[2] += addCrop;
879 job->crop[3] += addCrop;
882 else if( aspect > croppedAspect )
884 /* Need to crop on the top and bottom */
885 addCrop = croppedHeight - croppedWidth * title->aspect *
886 title->height / aspect / title->width;
889 addCrop = ( addCrop + 1 ) / 2;
890 job->crop[0] += addCrop;
891 job->crop[1] += addCrop;
893 else if( addCrop & 2 )
896 job->crop[0] += addCrop - 1;
897 job->crop[1] += addCrop + 1;
902 job->crop[0] += addCrop;
903 job->crop[1] += addCrop;
907 /* Compute a resolution from the number of pixels and aspect */
911 h = MULTIPLE_16( (int)( (double)w / aspect ) );
919 job->height = MULTIPLE_16( (int)( (double)job->width / aspect ) );
923 * Returns the number of jobs in the queue.
924 * @param h Handle to hb_handle_t.
925 * @return Number of jobs.
927 int hb_count( hb_handle_t * h )
929 return hb_list_count( h->jobs );
933 * Returns handle to job at index i within the job list.
934 * @param h Handle to hb_handle_t.
935 * @param i Index of job.
936 * @returns Handle to hb_job_t of desired job.
938 hb_job_t * hb_job( hb_handle_t * h, int i )
940 return hb_list_item( h->jobs, i );
943 hb_job_t * hb_current_job( hb_handle_t * h )
945 return( h->current_job );
949 * Adds a job to the job list.
950 * @param h Handle to hb_handle_t.
951 * @param job Handle to hb_job_t.
953 void hb_add( hb_handle_t * h, hb_job_t * job )
956 hb_title_t * title, * title_copy;
957 hb_chapter_t * chapter, * chapter_copy;
959 hb_subtitle_t * subtitle, * subtitle_copy;
965 title_copy = malloc( sizeof( hb_title_t ) );
966 memcpy( title_copy, title, sizeof( hb_title_t ) );
968 title_copy->list_chapter = hb_list_init();
969 for( i = 0; i < hb_list_count( title->list_chapter ); i++ )
971 chapter = hb_list_item( title->list_chapter, i );
972 chapter_copy = malloc( sizeof( hb_chapter_t ) );
973 memcpy( chapter_copy, chapter, sizeof( hb_chapter_t ) );
974 hb_list_add( title_copy->list_chapter, chapter_copy );
980 if( title->metadata )
982 title_copy->metadata = malloc( sizeof( hb_metadata_t ) );
984 if( title_copy->metadata )
986 memcpy( title_copy->metadata, title->metadata, sizeof( hb_metadata_t ) );
989 * Need to copy the artwork seperatly (TODO).
991 if( title->metadata->coverart )
993 title_copy->metadata->coverart = malloc( title->metadata->coverart_size );
994 if( title_copy->metadata->coverart )
996 memcpy( title_copy->metadata->coverart, title->metadata->coverart,
997 title->metadata->coverart_size );
999 title_copy->metadata->coverart_size = 0;
1005 /* Copy the audio track(s) we want */
1006 title_copy->list_audio = hb_list_init();
1008 for( i = 0; i < hb_list_count(job->list_audio); i++ )
1010 if( ( audio = hb_list_item( job->list_audio, i ) ) )
1012 hb_list_add( title_copy->list_audio, hb_audio_copy(audio) );
1016 title_copy->list_subtitle = hb_list_init();
1019 * The following code is confusing, there are two ways in which
1020 * we select subtitles and it depends on whether this is single or
1023 * subtitle_scan may be enabled, in which case the first pass
1024 * scans all subtitles of that language. The second pass does not
1025 * select any because they are set at the end of the first pass.
1027 * We may have manually selected a subtitle, in which case that is
1028 * selected in the first pass of a single pass, or the second of a
1031 memset( audio_lang, 0, sizeof( audio_lang ) );
1033 if ( job->indepth_scan ) {
1036 * Find the first audio language that is being encoded
1038 for( i = 0; i < hb_list_count(job->list_audio); i++ )
1040 if( ( audio = hb_list_item( job->list_audio, i ) ) )
1042 strncpy(audio_lang, audio->config.lang.iso639_2, sizeof(audio_lang));
1049 * If doing a subtitle scan then add all the matching subtitles for this
1052 if ( job->indepth_scan )
1054 for( i=0; i < hb_list_count( title->list_subtitle ); i++ )
1056 subtitle = hb_list_item( title->list_subtitle, i );
1057 if( strcmp( subtitle->iso639_2, audio_lang ) == 0 &&
1058 subtitle->source == VOBSUB )
1061 * Matched subtitle language with audio language, so
1062 * add this to our list to scan.
1064 * We will update the subtitle list on the second pass
1065 * later after the first pass has completed.
1067 subtitle_copy = malloc( sizeof( hb_subtitle_t ) );
1068 memcpy( subtitle_copy, subtitle, sizeof( hb_subtitle_t ) );
1069 hb_list_add( title_copy->list_subtitle, subtitle_copy );
1074 * Not doing a subtitle scan in this pass, but maybe we are in the
1077 if( job->pass != 1 )
1080 * Copy all of them from the input job, to the title_copy/job_copy.
1082 for( i = 0; i < hb_list_count(job->list_subtitle); i++ ) {
1083 if( ( subtitle = hb_list_item( job->list_subtitle, i ) ) )
1085 subtitle_copy = malloc( sizeof( hb_subtitle_t ) );
1086 memcpy( subtitle_copy, subtitle, sizeof( hb_subtitle_t ) );
1087 hb_list_add( title_copy->list_subtitle, subtitle_copy );
1094 job_copy = calloc( sizeof( hb_job_t ), 1 );
1095 memcpy( job_copy, job, sizeof( hb_job_t ) );
1096 title_copy->job = job_copy;
1097 job_copy->title = title_copy;
1098 job_copy->list_audio = title_copy->list_audio;
1099 job_copy->list_subtitle = title_copy->list_subtitle; // sharing list between title and job
1100 job_copy->file = strdup( job->file );
1102 job_copy->pause = h->pause_lock;
1104 /* Copy the job filter list */
1108 int filter_count = hb_list_count( job->filters );
1109 job_copy->filters = hb_list_init();
1110 for( i = 0; i < filter_count; i++ )
1113 * Copy the filters, since the MacGui reuses the global filter objects
1114 * meaning that queued up jobs overwrite the previous filter settings.
1115 * In reality, settings is probably the only field that needs duplicating
1116 * since it's the only value that is ever changed. But name is duplicated
1117 * as well for completeness. Not copying private_data since it gets
1118 * created for each job in renderInit.
1120 hb_filter_object_t * filter = hb_list_item( job->filters, i );
1121 hb_filter_object_t * filter_copy = malloc( sizeof( hb_filter_object_t ) );
1122 memcpy( filter_copy, filter, sizeof( hb_filter_object_t ) );
1124 filter_copy->name = strdup( filter->name );
1125 if( filter->settings )
1126 filter_copy->settings = strdup( filter->settings );
1127 hb_list_add( job_copy->filters, filter_copy );
1131 /* Add the job to the list */
1132 hb_list_add( h->jobs, job_copy );
1133 h->job_count = hb_count(h);
1134 h->job_count_permanent++;
1138 * Removes a job from the job list.
1139 * @param h Handle to hb_handle_t.
1140 * @param job Handle to hb_job_t.
1142 void hb_rem( hb_handle_t * h, hb_job_t * job )
1144 hb_list_rem( h->jobs, job );
1146 h->job_count = hb_count(h);
1147 if (h->job_count_permanent)
1148 h->job_count_permanent--;
1150 /* XXX free everything XXX */
1154 * Starts the conversion process.
1155 * Sets state to HB_STATE_WORKING.
1156 * calls hb_work_init, to launch work thread. Stores handle to work thread.
1157 * @param h Handle to hb_handle_t.
1159 void hb_start( hb_handle_t * h )
1162 h->job_count = hb_list_count( h->jobs );
1163 h->job_count_permanent = h->job_count;
1165 hb_lock( h->state_lock );
1166 h->state.state = HB_STATE_WORKING;
1167 #define p h->state.param.working
1170 p.job_count = h->job_count;
1178 hb_unlock( h->state_lock );
1183 h->work_thread = hb_work_init( h->jobs, h->cpu_count,
1184 &h->work_die, &h->work_error, &h->current_job );
1188 * Pauses the conversion process.
1189 * @param h Handle to hb_handle_t.
1191 void hb_pause( hb_handle_t * h )
1195 hb_lock( h->pause_lock );
1198 hb_lock( h->state_lock );
1199 h->state.state = HB_STATE_PAUSED;
1200 hb_unlock( h->state_lock );
1205 * Resumes the conversion process.
1206 * @param h Handle to hb_handle_t.
1208 void hb_resume( hb_handle_t * h )
1212 hb_unlock( h->pause_lock );
1218 * Stops the conversion process.
1219 * @param h Handle to hb_handle_t.
1221 void hb_stop( hb_handle_t * h )
1225 h->job_count = hb_count(h);
1226 h->job_count_permanent = 0;
1232 * Returns the state of the conversion process.
1233 * @param h Handle to hb_handle_t.
1234 * @param s Handle to hb_state_t which to copy the state data.
1236 void hb_get_state( hb_handle_t * h, hb_state_t * s )
1238 hb_lock( h->state_lock );
1240 memcpy( s, &h->state, sizeof( hb_state_t ) );
1241 if ( h->state.state == HB_STATE_SCANDONE || h->state.state == HB_STATE_WORKDONE )
1242 h->state.state = HB_STATE_IDLE;
1244 hb_unlock( h->state_lock );
1247 void hb_get_state2( hb_handle_t * h, hb_state_t * s )
1249 hb_lock( h->state_lock );
1251 memcpy( s, &h->state, sizeof( hb_state_t ) );
1253 hb_unlock( h->state_lock );
1257 * Called in MacGui in UpdateUI to check
1258 * for a new scan being completed to set a new source
1260 int hb_get_scancount( hb_handle_t * h)
1262 return h->scanCount;
1266 * Closes access to libhb by freeing the hb_handle_t handle ontained in hb_init.
1267 * @param _h Pointer to handle to hb_handle_t.
1269 void hb_close( hb_handle_t ** _h )
1271 hb_handle_t * h = *_h;
1275 hb_thread_close( &h->main_thread );
1277 while( ( title = hb_list_item( h->list_title, 0 ) ) )
1279 hb_list_rem( h->list_title, title );
1280 if( title->job && title->job->filters )
1282 hb_list_close( &title->job->filters );
1285 hb_title_close( &title );
1287 hb_list_close( &h->list_title );
1289 hb_list_close( &h->jobs );
1290 hb_lock_close( &h->state_lock );
1291 hb_lock_close( &h->pause_lock );
1298 * Monitors the state of the update, scan, and work threads.
1299 * Sets scan done state when scan thread exits.
1300 * Sets work done state when work thread exits.
1301 * @param _h Handle to hb_handle_t
1303 static void thread_func( void * _h )
1305 hb_handle_t * h = (hb_handle_t *) _h;
1308 struct dirent * entry;
1312 /* Create folder for temporary files */
1313 memset( dirname, 0, 1024 );
1314 hb_get_tempory_directory( h, dirname );
1316 hb_mkdir( dirname );
1320 /* In case the check_update thread hangs, it'll die sooner or
1321 later. Then, we join it here */
1322 if( h->update_thread &&
1323 hb_thread_has_exited( h->update_thread ) )
1325 hb_thread_close( &h->update_thread );
1328 /* Check if the scan thread is done */
1329 if( h->scan_thread &&
1330 hb_thread_has_exited( h->scan_thread ) )
1332 hb_thread_close( &h->scan_thread );
1334 hb_log( "libhb: scan thread found %d valid title(s)",
1335 hb_list_count( h->list_title ) );
1336 hb_lock( h->state_lock );
1337 h->state.state = HB_STATE_SCANDONE; //originally state.state
1338 hb_unlock( h->state_lock );
1339 /*we increment this sessions scan count by one for the MacGui
1340 to trigger a new source being set */
1344 /* Check if the work thread is done */
1345 if( h->work_thread &&
1346 hb_thread_has_exited( h->work_thread ) )
1348 hb_thread_close( &h->work_thread );
1350 hb_log( "libhb: work result = %d",
1352 hb_lock( h->state_lock );
1353 h->state.state = HB_STATE_WORKDONE;
1354 h->state.param.workdone.error = h->work_error;
1356 h->job_count = hb_count(h);
1357 if (h->job_count < 1)
1358 h->job_count_permanent = 0;
1359 hb_unlock( h->state_lock );
1365 if( h->work_thread )
1368 hb_thread_close( &h->work_thread );
1371 /* Remove temp folder */
1372 dir = opendir( dirname );
1375 while( ( entry = readdir( dir ) ) )
1377 char filename[1024];
1378 if( entry->d_name[0] == '.' )
1382 memset( filename, 0, 1024 );
1383 snprintf( filename, 1023, "%s/%s", dirname, entry->d_name );
1393 * @param h Handle to hb_handle_t
1395 int hb_get_pid( hb_handle_t * h )
1401 * Sets the current state.
1402 * @param h Handle to hb_handle_t
1403 * @param s Handle to new hb_state_t
1405 void hb_set_state( hb_handle_t * h, hb_state_t * s )
1407 hb_lock( h->pause_lock );
1408 hb_lock( h->state_lock );
1409 memcpy( &h->state, s, sizeof( hb_state_t ) );
1410 if( h->state.state == HB_STATE_WORKING )
1413 if (h->job_count < 1)
1414 h->job_count_permanent = 1;
1416 h->state.param.working.job_cur =
1417 h->job_count_permanent - hb_list_count( h->jobs );
1418 h->state.param.working.job_count = h->job_count_permanent;
1420 // Set which job is being worked on
1422 h->state.param.working.sequence_id = h->current_job->sequence_id;
1424 h->state.param.working.sequence_id = 0;
1426 hb_unlock( h->state_lock );
1427 hb_unlock( h->pause_lock );
1430 /* Passes a pointer to persistent data */
1431 hb_interjob_t * hb_interjob_get( hb_handle_t * h )