4 #if defined( SYS_MINGW ) && defined( PTW32_STATIC_LIB )
12 /* The "Check for update" thread */
15 hb_thread_t * update_thread;
17 /* This thread's only purpose is to check other threads'
20 hb_thread_t * main_thread;
23 /* DVD/file scan thread */
24 hb_list_t * list_title;
25 hb_thread_t * scan_thread;
27 /* The thread which processes the jobs. Others threads are launched
28 from this one (see work.c) */
30 hb_job_t * current_job;
32 int job_count_permanent;
33 volatile int work_die;
35 hb_thread_t * work_thread;
39 hb_lock_t * state_lock;
43 hb_lock_t * pause_lock;
44 /* For MacGui active queue
45 increments each time the scan thread completes*/
47 volatile int scan_die;
49 /* Stash of persistent data between jobs, for stuff
50 like correcting frame count and framerate estimates
51 on multi-pass encodes where frames get dropped. */
52 hb_interjob_t * interjob;
56 hb_lock_t *hb_avcodec_lock;
57 hb_work_object_t * hb_objects = NULL;
58 int hb_instance_counter = 0;
59 int hb_process_initialized = 0;
61 static void thread_func( void * );
63 void hb_avcodec_init()
65 hb_avcodec_lock = hb_lock_init();
69 int hb_avcodec_open(AVCodecContext *avctx, AVCodec *codec)
72 hb_lock( hb_avcodec_lock );
73 ret = avcodec_open(avctx, codec);
74 hb_unlock( hb_avcodec_lock );
78 int hb_avcodec_close(AVCodecContext *avctx)
81 hb_lock( hb_avcodec_lock );
82 ret = avcodec_close(avctx);
83 hb_unlock( hb_avcodec_lock );
87 int hb_ff_layout_xlat(int64_t ff_channel_layout, int channels)
91 switch (ff_channel_layout)
94 hb_layout = HB_INPUT_CH_LAYOUT_MONO;
96 case CH_LAYOUT_STEREO:
97 hb_layout = HB_INPUT_CH_LAYOUT_STEREO;
99 case CH_LAYOUT_SURROUND:
100 hb_layout = HB_INPUT_CH_LAYOUT_3F;
102 case CH_LAYOUT_4POINT0:
103 hb_layout = HB_INPUT_CH_LAYOUT_3F1R;
106 hb_layout = HB_INPUT_CH_LAYOUT_2F2R;
109 hb_layout = HB_INPUT_CH_LAYOUT_2F2R;
111 case CH_LAYOUT_5POINT0:
112 hb_layout = HB_INPUT_CH_LAYOUT_3F2R;
114 case CH_LAYOUT_5POINT1:
115 hb_layout = HB_INPUT_CH_LAYOUT_3F2R|HB_INPUT_CH_LAYOUT_HAS_LFE;
117 case CH_LAYOUT_5POINT0_BACK:
118 hb_layout = HB_INPUT_CH_LAYOUT_3F2R;
120 case CH_LAYOUT_5POINT1_BACK:
121 hb_layout = HB_INPUT_CH_LAYOUT_3F2R|HB_INPUT_CH_LAYOUT_HAS_LFE;
123 case CH_LAYOUT_7POINT0:
124 hb_layout = HB_INPUT_CH_LAYOUT_3F4R;
126 case CH_LAYOUT_7POINT1:
127 hb_layout = HB_INPUT_CH_LAYOUT_3F4R|HB_INPUT_CH_LAYOUT_HAS_LFE;
129 case CH_LAYOUT_STEREO_DOWNMIX:
130 hb_layout = HB_INPUT_CH_LAYOUT_STEREO;
133 hb_layout = HB_INPUT_CH_LAYOUT_STEREO;
136 // Now make sure the chosen layout agrees with the number of channels
137 // ffmpeg tells us there are. It seems ffmpeg is sometimes confused
138 // about this. So we will make a best guess based on the number
140 int chans = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT( hb_layout );
141 if ( chans == channels )
145 hb_log( "Channels reported by ffmpeg (%d) != computed layout channels (%d).", channels, chans );
149 hb_layout = HB_INPUT_CH_LAYOUT_MONO;
152 hb_layout = HB_INPUT_CH_LAYOUT_STEREO;
155 hb_layout = HB_INPUT_CH_LAYOUT_3F;
158 hb_layout = HB_INPUT_CH_LAYOUT_3F1R;
161 hb_layout = HB_INPUT_CH_LAYOUT_3F2R;
164 hb_layout = HB_INPUT_CH_LAYOUT_3F2R|HB_INPUT_CH_LAYOUT_HAS_LFE;
167 hb_layout = HB_INPUT_CH_LAYOUT_3F4R;
170 hb_layout = HB_INPUT_CH_LAYOUT_3F4R|HB_INPUT_CH_LAYOUT_HAS_LFE;
173 hb_log("Unsupported number of audio channels (%d).\n", channels);
181 * Registers work objects, by adding the work object to a liked list.
182 * @param w Handle to hb_work_object_t to register.
184 void hb_register( hb_work_object_t * w )
186 w->next = hb_objects;
191 * libhb initialization routine.
192 * @param verbose HB_DEBUG_NONE or HB_DEBUG_ALL.
193 * @param update_check signals libhb to check for updated version from HandBrake website.
194 * @return Handle to hb_handle_t for use on all subsequent calls to libhb.
196 hb_handle_t * hb_init( int verbose, int update_check )
198 if (!hb_process_initialized)
200 #if defined( SYS_MINGW ) && defined( PTW32_STATIC_LIB )
201 pthread_win32_process_attach_np();
203 hb_process_initialized =1;
206 hb_handle_t * h = calloc( sizeof( hb_handle_t ), 1 );
209 /* See hb_deep_log() and hb_log() in common.c */
210 global_verbosity_level = verbose;
212 putenv( "HB_DEBUG=1" );
214 h->id = hb_instance_counter++;
216 /* Check for an update on the website if asked to */
221 hb_log( "hb_init: checking for updates" );
222 date = hb_get_date();
223 h->update_thread = hb_update_init( &h->build, h->version );
227 if( hb_thread_has_exited( h->update_thread ) )
229 /* Immediate success or failure */
230 hb_thread_close( &h->update_thread );
233 if( hb_get_date() > date + 1000 )
235 /* Still nothing after one second. Connection problem,
236 let the thread die */
237 hb_log( "hb_init: connection problem, not waiting for "
246 * Initialise buffer pool
248 hb_buffer_pool_init();
250 /* CPU count detection */
251 hb_log( "hb_init: checking cpu count" );
252 h->cpu_count = hb_get_cpu_count();
254 h->list_title = hb_list_init();
255 h->jobs = hb_list_init();
257 h->state_lock = hb_lock_init();
258 h->state.state = HB_STATE_IDLE;
260 h->pause_lock = hb_lock_init();
262 h->interjob = calloc( sizeof( hb_interjob_t ), 1 );
267 /* Start library thread */
268 hb_log( "hb_init: starting libhb thread" );
270 h->main_thread = hb_thread_init( "libhb", thread_func, h,
271 HB_NORMAL_PRIORITY );
272 hb_register( &hb_sync_video );
273 hb_register( &hb_sync_audio );
274 hb_register( &hb_decmpeg2 );
275 hb_register( &hb_decvobsub );
276 hb_register( &hb_encvobsub );
277 hb_register( &hb_deccc608 );
278 hb_register( &hb_decsrtsub );
279 hb_register( &hb_decutf8sub );
280 hb_register( &hb_dectx3gsub );
281 hb_register( &hb_render );
282 hb_register( &hb_encavcodec );
283 hb_register( &hb_encx264 );
284 hb_register( &hb_enctheora );
285 hb_register( &hb_deca52 );
286 hb_register( &hb_decdca );
287 hb_register( &hb_decavcodec );
288 hb_register( &hb_decavcodecv );
289 hb_register( &hb_decavcodecvi );
290 hb_register( &hb_decavcodecai );
291 hb_register( &hb_declpcm );
292 hb_register( &hb_encfaac );
293 hb_register( &hb_enclame );
294 hb_register( &hb_encvorbis );
295 hb_register( &hb_muxer );
297 hb_register( &hb_encca_aac );
304 * libhb initialization routine.
305 * This version is to use when calling the dylib, the macro hb_init isn't available from a dylib call!
306 * @param verbose HB_DEBUG_NONE or HB_DEBUG_ALL.
307 * @param update_check signals libhb to check for updated version from HandBrake website.
308 * @return Handle to hb_handle_t for use on all subsequent calls to libhb.
310 hb_handle_t * hb_init_dl( int verbose, int update_check )
312 hb_handle_t * h = calloc( sizeof( hb_handle_t ), 1 );
315 /* See hb_log() in common.c */
316 if( verbose > HB_DEBUG_NONE )
318 putenv( "HB_DEBUG=1" );
321 h->id = hb_instance_counter++;
323 /* Check for an update on the website if asked to */
328 hb_log( "hb_init: checking for updates" );
329 date = hb_get_date();
330 h->update_thread = hb_update_init( &h->build, h->version );
334 if( hb_thread_has_exited( h->update_thread ) )
336 /* Immediate success or failure */
337 hb_thread_close( &h->update_thread );
340 if( hb_get_date() > date + 1000 )
342 /* Still nothing after one second. Connection problem,
343 let the thread die */
344 hb_log( "hb_init: connection problem, not waiting for "
352 /* CPU count detection */
353 hb_log( "hb_init: checking cpu count" );
354 h->cpu_count = hb_get_cpu_count();
356 h->list_title = hb_list_init();
357 h->jobs = hb_list_init();
358 h->current_job = NULL;
360 h->state_lock = hb_lock_init();
361 h->state.state = HB_STATE_IDLE;
363 h->pause_lock = hb_lock_init();
367 avcodec_register_all();
369 /* Start library thread */
370 hb_log( "hb_init: starting libhb thread" );
372 h->main_thread = hb_thread_init( "libhb", thread_func, h,
373 HB_NORMAL_PRIORITY );
375 hb_register( &hb_sync_video );
376 hb_register( &hb_sync_audio );
377 hb_register( &hb_decmpeg2 );
378 hb_register( &hb_decvobsub );
379 hb_register( &hb_encvobsub );
380 hb_register( &hb_deccc608 );
381 hb_register( &hb_decsrtsub );
382 hb_register( &hb_decutf8sub );
383 hb_register( &hb_dectx3gsub );
384 hb_register( &hb_render );
385 hb_register( &hb_encavcodec );
386 hb_register( &hb_encx264 );
387 hb_register( &hb_enctheora );
388 hb_register( &hb_deca52 );
389 hb_register( &hb_decdca );
390 hb_register( &hb_decavcodec );
391 hb_register( &hb_decavcodecv );
392 hb_register( &hb_decavcodecvi );
393 hb_register( &hb_decavcodecai );
394 hb_register( &hb_declpcm );
395 hb_register( &hb_encfaac );
396 hb_register( &hb_enclame );
397 hb_register( &hb_encvorbis );
398 hb_register( &hb_muxer );
400 hb_register( &hb_encca_aac );
408 * Returns current version of libhb.
409 * @param h Handle to hb_handle_t.
410 * @return character array of version number.
412 char * hb_get_version( hb_handle_t * h )
414 return HB_PROJECT_VERSION;
418 * Returns current build of libhb.
419 * @param h Handle to hb_handle_t.
420 * @return character array of build number.
422 int hb_get_build( hb_handle_t * h )
424 return HB_PROJECT_BUILD;
428 * Checks for needed update.
429 * @param h Handle to hb_handle_t.
430 * @param version Pointer to handle where version will be copied.
431 * @return update indicator.
433 int hb_check_update( hb_handle_t * h, char ** version )
435 *version = ( h->build < 0 ) ? NULL : h->version;
440 * Sets the cpu count to the desired value.
441 * @param h Handle to hb_handle_t
442 * @param cpu_count Number of CPUs to use.
444 void hb_set_cpu_count( hb_handle_t * h, int cpu_count )
446 cpu_count = MAX( 1, cpu_count );
447 cpu_count = MIN( cpu_count, 8 );
448 h->cpu_count = cpu_count;
452 * Deletes current previews associated with titles
453 * @param h Handle to hb_handle_t
455 void hb_remove_previews( hb_handle_t * h )
462 struct dirent * entry;
464 memset( dirname, 0, 1024 );
465 hb_get_temporary_directory( dirname );
466 dir = opendir( dirname );
467 if (dir == NULL) return;
469 count = hb_list_count( h->list_title );
470 while( ( entry = readdir( dir ) ) )
472 if( entry->d_name[0] == '.' )
476 for( i = 0; i < count; i++ )
478 title = hb_list_item( h->list_title, i );
479 len = snprintf( filename, 1024, "%d_%d", h->id, title->index );
480 if (strncmp(entry->d_name, filename, len) == 0)
482 snprintf( filename, 1024, "%s/%s", dirname, entry->d_name );
492 * Initializes a scan of the by calling hb_scan_init
493 * @param h Handle to hb_handle_t
494 * @param path location of VIDEO_TS folder.
495 * @param title_index Desired title to scan. 0 for all titles.
496 * @param preview_count Number of preview images to generate.
497 * @param store_previews Whether or not to write previews to disk.
499 void hb_scan( hb_handle_t * h, const char * path, int title_index,
500 int preview_count, int store_previews )
506 /* Clean up from previous scan */
507 hb_remove_previews( h );
508 while( ( title = hb_list_item( h->list_title, 0 ) ) )
510 hb_list_rem( h->list_title, title );
511 hb_title_close( &title );
514 hb_log( "hb_scan: path=%s, title_index=%d", path, title_index );
515 h->scan_thread = hb_scan_init( h, &h->scan_die, path, title_index,
516 h->list_title, preview_count,
521 * Returns the list of titles found.
522 * @param h Handle to hb_handle_t
523 * @return Handle to hb_list_t of the title list.
525 hb_list_t * hb_get_titles( hb_handle_t * h )
527 return h->list_title;
531 * Create preview image of desired title a index of picture.
532 * @param h Handle to hb_handle_t.
533 * @param title Handle to hb_title_t of desired title.
534 * @param picture Index in title.
535 * @param buffer Handle to buufer were inage will be drawn.
537 void hb_get_preview( hb_handle_t * h, hb_title_t * title, int picture,
540 hb_job_t * job = title->job;
543 uint8_t * buf1, * buf2, * buf3, * buf4, * pen;
545 AVPicture pic_in, pic_preview, pic_deint, pic_crop, pic_scale;
546 struct SwsContext * context;
548 int rgb_width = ((job->width + 7) >> 3) << 3;
551 swsflags = SWS_LANCZOS | SWS_ACCURATE_RND;
553 buf1 = av_malloc( avpicture_get_size( PIX_FMT_YUV420P, title->width, title->height ) );
554 buf2 = av_malloc( avpicture_get_size( PIX_FMT_YUV420P, title->width, title->height ) );
555 buf3 = av_malloc( avpicture_get_size( PIX_FMT_YUV420P, rgb_width, job->height ) );
556 buf4 = av_malloc( avpicture_get_size( PIX_FMT_RGB32, rgb_width, job->height ) );
557 avpicture_fill( &pic_in, buf1, PIX_FMT_YUV420P,
558 title->width, title->height );
559 avpicture_fill( &pic_deint, buf2, PIX_FMT_YUV420P,
560 title->width, title->height );
561 avpicture_fill( &pic_scale, buf3, PIX_FMT_YUV420P,
562 rgb_width, job->height );
563 avpicture_fill( &pic_preview, buf4, PIX_FMT_RGB32,
564 rgb_width, job->height );
566 // Allocate the AVPicture frames and fill in
568 memset( filename, 0, 1024 );
570 hb_get_tempory_filename( h, filename, "%d_%d_%d",
571 h->id, title->index, picture );
573 file = fopen( filename, "rb" );
576 hb_log( "hb_get_preview: fopen failed" );
580 fread( buf1, avpicture_get_size( PIX_FMT_YUV420P, title->width, title->height), 1, file );
583 if( job->deinterlace )
585 // Deinterlace and crop
586 avpicture_deinterlace( &pic_deint, &pic_in, PIX_FMT_YUV420P, title->width, title->height );
587 av_picture_crop( &pic_crop, &pic_deint, PIX_FMT_YUV420P, job->crop[0], job->crop[2] );
592 av_picture_crop( &pic_crop, &pic_in, PIX_FMT_YUV420P, job->crop[0], job->crop[2] );
595 // Get scaling context
596 context = sws_getContext(title->width - (job->crop[2] + job->crop[3]),
597 title->height - (job->crop[0] + job->crop[1]),
599 job->width, job->height, PIX_FMT_YUV420P,
600 swsflags, NULL, NULL, NULL);
604 pic_crop.data, pic_crop.linesize,
605 0, title->height - (job->crop[0] + job->crop[1]),
606 pic_scale.data, pic_scale.linesize);
609 sws_freeContext( context );
611 // Get preview context
612 context = sws_getContext(rgb_width, job->height, PIX_FMT_YUV420P,
613 rgb_width, job->height, PIX_FMT_RGB32,
614 swsflags, NULL, NULL, NULL);
618 pic_scale.data, pic_scale.linesize,
620 pic_preview.data, pic_preview.linesize);
623 sws_freeContext( context );
625 preview_size = pic_preview.linesize[0];
627 for( i = 0; i < job->height; i++ )
629 memcpy( pen, buf4 + preview_size * i, 4 * job->width );
630 pen += 4 * job->width;
634 avpicture_free( &pic_preview );
635 avpicture_free( &pic_scale );
636 avpicture_free( &pic_deint );
637 avpicture_free( &pic_in );
641 * Analyzes a frame to detect interlacing artifacts
642 * and returns true if interlacing (combing) is found.
644 * Code taken from Thomas Oestreich's 32detect filter
645 * in the Transcode project, with minor formatting changes.
647 * @param buf An hb_buffer structure holding valid frame data
648 * @param width The frame's width in pixels
649 * @param height The frame's height in pixels
650 * @param color_equal Sensitivity for detecting similar colors
651 * @param color_diff Sensitivity for detecting different colors
652 * @param threshold Sensitivity for flagging planes as combed
653 * @param prog_equal Sensitivity for detecting similar colors on progressive frames
654 * @param prog_diff Sensitivity for detecting different colors on progressive frames
655 * @param prog_threshold Sensitivity for flagging progressive frames as combed
657 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 )
659 int j, k, n, off, cc_1, cc_2, cc[3];
660 // int flag[3] ; // debugging flag
661 uint16_t s1, s2, s3, s4;
666 if ( buf->flags & 16 )
668 /* Frame is progressive, be more discerning. */
669 color_diff = prog_diff;
670 color_equal = prog_equal;
671 threshold = prog_threshold;
674 /* One pas for Y, one pass for Cb, one pass for Cr */
675 for( k = 0; k < 3; k++ )
679 /* Y has already been checked, now offset by Y's dimensions
680 and divide all the other values by 2, since Cr and Cb
681 are half-size compared to Y. */
682 offset = width * height;
688 /* Y and Cb are done, so the offset needs to be bumped
689 so it's width*height + (width / 2) * (height / 2) */
693 for( j = 0; j < width; ++j )
697 for( n = 0; n < ( height - 4 ); n = n + 2 )
699 /* Look at groups of 4 sequential horizontal lines */
700 s1 = ( ( buf->data + offset )[ off + j ] & 0xff );
701 s2 = ( ( buf->data + offset )[ off + j + width ] & 0xff );
702 s3 = ( ( buf->data + offset )[ off + j + 2 * width ] & 0xff );
703 s4 = ( ( buf->data + offset )[ off + j + 3 * width ] & 0xff );
705 /* Note if the 1st and 2nd lines are more different in
706 color than the 1st and 3rd lines are similar in color.*/
707 if ( ( abs( s1 - s3 ) < color_equal ) &&
708 ( abs( s1 - s2 ) > color_diff ) )
711 /* Note if the 2nd and 3rd lines are more different in
712 color than the 2nd and 4th lines are similar in color.*/
713 if ( ( abs( s2 - s4 ) < color_equal ) &&
714 ( abs( s2 - s3 ) > color_diff) )
717 /* Now move down 2 horizontal lines before starting over.*/
723 /* The final cc score for a plane is the percentage of combed pixels it contains.
724 Because sensitivity goes down to hundreths of a percent, multiply by 1000
725 so it will be easy to compare against the threhold value which is an integer. */
726 cc[k] = (int)( ( cc_1 + cc_2 ) * 1000.0 / ( width * height ) );
730 /* HandBrake is all yuv420, so weight the average percentage of all 3 planes accordingly.*/
731 int average_cc = ( 2 * cc[0] + ( cc[1] / 2 ) + ( cc[2] / 2 ) ) / 3;
733 /* Now see if that average percentage of combed pixels surpasses the threshold percentage given by the user.*/
734 if( average_cc > threshold )
737 hb_log("Average %i combed (Threshold %i) %i/%i/%i | PTS: %"PRId64" (%fs) %s", average_cc, threshold, cc[0], cc[1], cc[2], buf->start, (float)buf->start / 90000, (buf->flags & 16) ? "Film" : "Video" );
743 hb_log("SKIPPED Average %i combed (Threshold %i) %i/%i/%i | PTS: %"PRId64" (%fs) %s", average_cc, threshold, cc[0], cc[1], cc[2], buf->start, (float)buf->start / 90000, (buf->flags & 16) ? "Film" : "Video" );
746 /* Reaching this point means no combing detected. */
752 * Calculates job width and height for anamorphic content,
754 * @param job Handle to hb_job_t
755 * @param output_width Pointer to returned storage width
756 * @param output_height Pointer to returned storage height
757 * @param output_par_width Pointer to returned pixel width
758 @ param output_par_height Pointer to returned pixel height
760 void hb_set_anamorphic_size( hb_job_t * job,
761 int *output_width, int *output_height,
762 int *output_par_width, int *output_par_height )
764 /* Set up some variables to make the math easier to follow. */
765 hb_title_t * title = job->title;
766 int cropped_width = title->width - job->crop[2] - job->crop[3] ;
767 int cropped_height = title->height - job->crop[0] - job->crop[1] ;
768 double storage_aspect = (double)cropped_width / (double)cropped_height;
769 int mod = job->modulus ? job->modulus : 16;
770 double aspect = title->aspect;
772 int pixel_aspect_width = job->anamorphic.par_width;
773 int pixel_aspect_height = job->anamorphic.par_height;
775 /* If a source was really NTSC or PAL and the user specified ITU PAR
776 values, replace the standard PAR values with the ITU broadcast ones. */
777 if( title->width == 720 && job->anamorphic.itu_par )
779 // convert aspect to a scaled integer so we can test for 16:9 & 4:3
780 // aspect ratios ignoring insignificant differences in the LSBs of
781 // the floating point representation.
782 int iaspect = aspect * 9.;
784 /* Handle ITU PARs */
785 if (title->height == 480)
790 /* It's widescreen */
791 pixel_aspect_width = 40;
792 pixel_aspect_height = 33;
794 else if (iaspect == 12)
797 pixel_aspect_width = 10;
798 pixel_aspect_height = 11;
801 else if (title->height == 576)
806 /* It's widescreen */
807 pixel_aspect_width = 16;
808 pixel_aspect_height = 11;
810 else if (iaspect == 12)
813 pixel_aspect_width = 12;
814 pixel_aspect_height = 11;
819 /* Figure out what width the source would display at. */
820 int source_display_width = cropped_width * (double)pixel_aspect_width /
821 (double)pixel_aspect_height ;
824 3 different ways of deciding output dimensions:
825 - 1: Strict anamorphic, preserve source dimensions
826 - 2: Loose anamorphic, round to mod16 and preserve storage aspect ratio
827 - 3: Power user anamorphic, specify everything
830 switch( job->anamorphic.mode )
833 /* Strict anamorphic */
834 *output_width = cropped_width;
835 *output_height = cropped_height;
836 *output_par_width = title->pixel_aspect_width;
837 *output_par_height = title->pixel_aspect_height;
841 /* "Loose" anamorphic.
842 - Uses mod16-compliant dimensions,
843 - Allows users to set the width
846 // height: Gets set later, ignore user job->height value
848 /* Gotta handle bounding dimensions.
849 If the width is too big, just reset it with no rescaling.
850 Instead of using the aspect-scaled job height,
851 we need to see if the job width divided by the storage aspect
852 is bigger than the max. If so, set it to the max (this is sloppy).
853 If not, set job height to job width divided by storage aspect.
856 if ( job->maxWidth && (job->maxWidth < job->width) )
857 width = job->maxWidth;
859 /* Time to get picture width that divide cleanly.*/
860 width = MULTIPLE_MOD( width, mod);
862 /* Verify these new dimensions don't violate max height and width settings */
863 if ( job->maxWidth && (job->maxWidth < job->width) )
864 width = job->maxWidth;
866 height = ((double)width / storage_aspect) + 0.5;
868 if ( job->maxHeight && (job->maxHeight < height) )
869 height = job->maxHeight;
871 /* Time to get picture height that divide cleanly.*/
872 height = MULTIPLE_MOD( height, mod);
874 /* Verify these new dimensions don't violate max height and width settings */
875 if ( job->maxHeight && (job->maxHeight < height) )
876 height = job->maxHeight;
878 /* The film AR is the source's display width / cropped source height.
879 The output display width is the output height * film AR.
880 The output PAR is the output display width / output storage width. */
881 pixel_aspect_width = height * source_display_width / cropped_height;
882 pixel_aspect_height = width;
884 /* Pass the results back to the caller */
885 *output_width = width;
886 *output_height = height;
890 /* Anamorphic 3: Power User Jamboree
891 - Set everything based on specified values */
893 /* Use specified storage dimensions */
895 height = job->height;
897 /* Bind to max dimensions */
898 if( job->maxWidth && width > job->maxWidth )
899 width = job->maxWidth;
900 if( job->maxHeight && height > job->maxHeight )
901 height = job->maxHeight;
903 /* Time to get picture dimensions that divide cleanly.*/
904 width = MULTIPLE_MOD( width, mod);
905 height = MULTIPLE_MOD( height, mod);
907 /* Verify we're still within max dimensions */
908 if( job->maxWidth && width > job->maxWidth )
909 width = job->maxWidth - (mod/2);
910 if( job->maxHeight && height > job->maxHeight )
911 height = job->maxHeight - (mod/2);
913 /* Re-ensure we have picture dimensions that divide cleanly. */
914 width = MULTIPLE_MOD( width, mod );
915 height = MULTIPLE_MOD( height, mod );
917 /* That finishes the storage dimensions. On to display. */
918 if( job->anamorphic.dar_width && job->anamorphic.dar_height )
920 /* We need to adjust the PAR to produce this aspect. */
921 pixel_aspect_width = height * job->anamorphic.dar_width / job->anamorphic.dar_height;
922 pixel_aspect_height = width;
926 /* If we're doing ana 3 and not specifying a DAR, care needs to be taken.
927 This indicates a PAR is potentially being set by the interface. But
928 this is an output PAR, to correct a source, and it should not be assumed
929 that it properly creates a display aspect ratio when applied to the source,
930 which could easily be stored in a different resolution. */
931 if( job->anamorphic.keep_display_aspect )
933 /* We can ignore the possibility of a PAR change */
934 pixel_aspect_width = height * ( (double)source_display_width / (double)cropped_height );
935 pixel_aspect_height = width;
939 int output_display_width = width * (double)pixel_aspect_width /
940 (double)pixel_aspect_height;
941 pixel_aspect_width = output_display_width;
942 pixel_aspect_height = width;
947 *output_width = width;
948 *output_height = height;
952 /* While x264 is smart enough to reduce fractions on its own, libavcodec
953 needs some help with the math, so lose superfluous factors. */
954 hb_reduce( output_par_width, output_par_height,
955 pixel_aspect_width, pixel_aspect_height );
959 * Calculates job width, height, and cropping parameters.
960 * @param job Handle to hb_job_t.
961 * @param aspect Desired aspect ratio. Value of -1 uses title aspect.
962 * @param pixels Maximum desired pixel count.
964 void hb_set_size( hb_job_t * job, double aspect, int pixels )
966 hb_title_t * title = job->title;
968 int croppedWidth = title->width - title->crop[2] - title->crop[3];
969 int croppedHeight = title->height - title->crop[0] - title->crop[1];
970 double croppedAspect = title->aspect * title->height * croppedWidth /
971 croppedHeight / title->width;
977 /* Keep the best possible aspect ratio */
978 aspect = croppedAspect;
981 /* Crop if necessary to obtain the desired ratio */
982 memcpy( job->crop, title->crop, 4 * sizeof( int ) );
983 if( aspect < croppedAspect )
985 /* Need to crop on the left and right */
986 addCrop = croppedWidth - aspect * croppedHeight * title->width /
987 title->aspect / title->height;
990 addCrop = ( addCrop + 1 ) / 2;
991 job->crop[2] += addCrop;
992 job->crop[3] += addCrop;
994 else if( addCrop & 2 )
997 job->crop[2] += addCrop - 1;
998 job->crop[3] += addCrop + 1;
1003 job->crop[2] += addCrop;
1004 job->crop[3] += addCrop;
1007 else if( aspect > croppedAspect )
1009 /* Need to crop on the top and bottom */
1010 addCrop = croppedHeight - croppedWidth * title->aspect *
1011 title->height / aspect / title->width;
1014 addCrop = ( addCrop + 1 ) / 2;
1015 job->crop[0] += addCrop;
1016 job->crop[1] += addCrop;
1018 else if( addCrop & 2 )
1021 job->crop[0] += addCrop - 1;
1022 job->crop[1] += addCrop + 1;
1027 job->crop[0] += addCrop;
1028 job->crop[1] += addCrop;
1032 /* Compute a resolution from the number of pixels and aspect */
1036 h = MULTIPLE_16( (int)( (double)w / aspect ) );
1037 if( w * h > pixels )
1043 job->width = 16 * i;
1044 job->height = MULTIPLE_16( (int)( (double)job->width / aspect ) );
1048 * Returns the number of jobs in the queue.
1049 * @param h Handle to hb_handle_t.
1050 * @return Number of jobs.
1052 int hb_count( hb_handle_t * h )
1054 return hb_list_count( h->jobs );
1058 * Returns handle to job at index i within the job list.
1059 * @param h Handle to hb_handle_t.
1060 * @param i Index of job.
1061 * @returns Handle to hb_job_t of desired job.
1063 hb_job_t * hb_job( hb_handle_t * h, int i )
1065 return hb_list_item( h->jobs, i );
1068 hb_job_t * hb_current_job( hb_handle_t * h )
1070 return( h->current_job );
1074 * Adds a job to the job list.
1075 * @param h Handle to hb_handle_t.
1076 * @param job Handle to hb_job_t.
1078 void hb_add( hb_handle_t * h, hb_job_t * job )
1080 hb_job_t * job_copy;
1081 hb_title_t * title, * title_copy;
1082 hb_chapter_t * chapter, * chapter_copy;
1084 hb_subtitle_t * subtitle, * subtitle_copy;
1088 /* Copy the title */
1090 title_copy = malloc( sizeof( hb_title_t ) );
1091 memcpy( title_copy, title, sizeof( hb_title_t ) );
1093 title_copy->list_chapter = hb_list_init();
1094 for( i = 0; i < hb_list_count( title->list_chapter ); i++ )
1096 chapter = hb_list_item( title->list_chapter, i );
1097 chapter_copy = malloc( sizeof( hb_chapter_t ) );
1098 memcpy( chapter_copy, chapter, sizeof( hb_chapter_t ) );
1099 hb_list_add( title_copy->list_chapter, chapter_copy );
1105 if( title->metadata )
1107 title_copy->metadata = malloc( sizeof( hb_metadata_t ) );
1109 if( title_copy->metadata )
1111 memcpy( title_copy->metadata, title->metadata, sizeof( hb_metadata_t ) );
1114 * Need to copy the artwork seperatly (TODO).
1116 if( title->metadata->coverart )
1118 title_copy->metadata->coverart = malloc( title->metadata->coverart_size );
1119 if( title_copy->metadata->coverart )
1121 memcpy( title_copy->metadata->coverart, title->metadata->coverart,
1122 title->metadata->coverart_size );
1124 title_copy->metadata->coverart_size = 0;
1130 /* Copy the audio track(s) we want */
1131 title_copy->list_audio = hb_list_init();
1133 for( i = 0; i < hb_list_count(job->list_audio); i++ )
1135 if( ( audio = hb_list_item( job->list_audio, i ) ) )
1137 hb_list_add( title_copy->list_audio, hb_audio_copy(audio) );
1141 title_copy->list_subtitle = hb_list_init();
1144 * The following code is confusing, there are two ways in which
1145 * we select subtitles and it depends on whether this is single or
1148 * subtitle_scan may be enabled, in which case the first pass
1149 * scans all subtitles of that language. The second pass does not
1150 * select any because they are set at the end of the first pass.
1152 * We may have manually selected a subtitle, in which case that is
1153 * selected in the first pass of a single pass, or the second of a
1156 memset( audio_lang, 0, sizeof( audio_lang ) );
1158 if ( job->indepth_scan ) {
1161 * Find the first audio language that is being encoded
1163 for( i = 0; i < hb_list_count(job->list_audio); i++ )
1165 if( ( audio = hb_list_item( job->list_audio, i ) ) )
1167 strncpy(audio_lang, audio->config.lang.iso639_2, sizeof(audio_lang));
1174 * If doing a subtitle scan then add all the matching subtitles for this
1177 if ( job->indepth_scan )
1179 for( i=0; i < hb_list_count( title->list_subtitle ); i++ )
1181 subtitle = hb_list_item( title->list_subtitle, i );
1182 if( strcmp( subtitle->iso639_2, audio_lang ) == 0 &&
1183 subtitle->source == VOBSUB )
1186 * Matched subtitle language with audio language, so
1187 * add this to our list to scan.
1189 * We will update the subtitle list on the second pass
1190 * later after the first pass has completed.
1192 subtitle_copy = malloc( sizeof( hb_subtitle_t ) );
1193 memcpy( subtitle_copy, subtitle, sizeof( hb_subtitle_t ) );
1194 hb_list_add( title_copy->list_subtitle, subtitle_copy );
1199 * Not doing a subtitle scan in this pass, but maybe we are in the
1202 if( job->pass != 1 )
1205 * Copy all of them from the input job, to the title_copy/job_copy.
1207 for( i = 0; i < hb_list_count(job->list_subtitle); i++ ) {
1208 if( ( subtitle = hb_list_item( job->list_subtitle, i ) ) )
1210 subtitle_copy = malloc( sizeof( hb_subtitle_t ) );
1211 memcpy( subtitle_copy, subtitle, sizeof( hb_subtitle_t ) );
1212 hb_list_add( title_copy->list_subtitle, subtitle_copy );
1219 job_copy = calloc( sizeof( hb_job_t ), 1 );
1220 memcpy( job_copy, job, sizeof( hb_job_t ) );
1221 title_copy->job = job_copy;
1222 job_copy->title = title_copy;
1223 job_copy->list_audio = title_copy->list_audio;
1224 job_copy->list_subtitle = title_copy->list_subtitle; // sharing list between title and job
1225 job_copy->file = strdup( job->file );
1227 job_copy->pause = h->pause_lock;
1229 /* Copy the job filter list */
1233 int filter_count = hb_list_count( job->filters );
1234 job_copy->filters = hb_list_init();
1235 for( i = 0; i < filter_count; i++ )
1238 * Copy the filters, since the MacGui reuses the global filter objects
1239 * meaning that queued up jobs overwrite the previous filter settings.
1240 * In reality, settings is probably the only field that needs duplicating
1241 * since it's the only value that is ever changed. But name is duplicated
1242 * as well for completeness. Not copying private_data since it gets
1243 * created for each job in renderInit.
1245 hb_filter_object_t * filter = hb_list_item( job->filters, i );
1246 hb_filter_object_t * filter_copy = malloc( sizeof( hb_filter_object_t ) );
1247 memcpy( filter_copy, filter, sizeof( hb_filter_object_t ) );
1249 filter_copy->name = strdup( filter->name );
1250 if( filter->settings )
1251 filter_copy->settings = strdup( filter->settings );
1252 hb_list_add( job_copy->filters, filter_copy );
1256 /* Add the job to the list */
1257 hb_list_add( h->jobs, job_copy );
1258 h->job_count = hb_count(h);
1259 h->job_count_permanent++;
1263 * Removes a job from the job list.
1264 * @param h Handle to hb_handle_t.
1265 * @param job Handle to hb_job_t.
1267 void hb_rem( hb_handle_t * h, hb_job_t * job )
1269 hb_list_rem( h->jobs, job );
1271 h->job_count = hb_count(h);
1272 if (h->job_count_permanent)
1273 h->job_count_permanent--;
1275 /* XXX free everything XXX */
1279 * Starts the conversion process.
1280 * Sets state to HB_STATE_WORKING.
1281 * calls hb_work_init, to launch work thread. Stores handle to work thread.
1282 * @param h Handle to hb_handle_t.
1284 void hb_start( hb_handle_t * h )
1287 h->job_count = hb_list_count( h->jobs );
1288 h->job_count_permanent = h->job_count;
1290 hb_lock( h->state_lock );
1291 h->state.state = HB_STATE_WORKING;
1292 #define p h->state.param.working
1295 p.job_count = h->job_count;
1303 hb_unlock( h->state_lock );
1308 h->work_thread = hb_work_init( h->jobs, h->cpu_count,
1309 &h->work_die, &h->work_error, &h->current_job );
1313 * Pauses the conversion process.
1314 * @param h Handle to hb_handle_t.
1316 void hb_pause( hb_handle_t * h )
1320 hb_lock( h->pause_lock );
1323 hb_current_job( h )->st_pause_date = hb_get_date();
1325 hb_lock( h->state_lock );
1326 h->state.state = HB_STATE_PAUSED;
1327 hb_unlock( h->state_lock );
1332 * Resumes the conversion process.
1333 * @param h Handle to hb_handle_t.
1335 void hb_resume( hb_handle_t * h )
1339 #define job hb_current_job( h )
1340 if( job->st_pause_date != -1 )
1342 job->st_paused += hb_get_date() - job->st_pause_date;
1346 hb_unlock( h->pause_lock );
1352 * Stops the conversion process.
1353 * @param h Handle to hb_handle_t.
1355 void hb_stop( hb_handle_t * h )
1359 h->job_count = hb_count(h);
1360 h->job_count_permanent = 0;
1366 * Stops the conversion process.
1367 * @param h Handle to hb_handle_t.
1369 void hb_scan_stop( hb_handle_t * h )
1373 h->job_count = hb_count(h);
1374 h->job_count_permanent = 0;
1380 * Returns the state of the conversion process.
1381 * @param h Handle to hb_handle_t.
1382 * @param s Handle to hb_state_t which to copy the state data.
1384 void hb_get_state( hb_handle_t * h, hb_state_t * s )
1386 hb_lock( h->state_lock );
1388 memcpy( s, &h->state, sizeof( hb_state_t ) );
1389 if ( h->state.state == HB_STATE_SCANDONE || h->state.state == HB_STATE_WORKDONE )
1390 h->state.state = HB_STATE_IDLE;
1392 hb_unlock( h->state_lock );
1395 void hb_get_state2( hb_handle_t * h, hb_state_t * s )
1397 hb_lock( h->state_lock );
1399 memcpy( s, &h->state, sizeof( hb_state_t ) );
1401 hb_unlock( h->state_lock );
1405 * Called in MacGui in UpdateUI to check
1406 * for a new scan being completed to set a new source
1408 int hb_get_scancount( hb_handle_t * h)
1410 return h->scanCount;
1414 * Closes access to libhb by freeing the hb_handle_t handle ontained in hb_init.
1415 * @param _h Pointer to handle to hb_handle_t.
1417 void hb_close( hb_handle_t ** _h )
1419 hb_handle_t * h = *_h;
1424 hb_thread_close( &h->main_thread );
1426 while( ( title = hb_list_item( h->list_title, 0 ) ) )
1428 hb_list_rem( h->list_title, title );
1429 if( title->job && title->job->filters )
1431 hb_list_close( &title->job->filters );
1434 hb_title_close( &title );
1436 hb_list_close( &h->list_title );
1438 hb_list_close( &h->jobs );
1439 hb_lock_close( &h->state_lock );
1440 hb_lock_close( &h->pause_lock );
1447 * Cleans up libhb at a process level. Call before the app closes. Removes preview directory.
1449 void hb_global_close()
1453 struct dirent * entry;
1455 /* Find and remove temp folder */
1456 memset( dirname, 0, 1024 );
1457 hb_get_temporary_directory( dirname );
1459 dir = opendir( dirname );
1462 while( ( entry = readdir( dir ) ) )
1464 char filename[1024];
1465 if( entry->d_name[0] == '.' )
1469 memset( filename, 0, 1024 );
1470 snprintf( filename, 1023, "%s/%s", dirname, entry->d_name );
1479 * Monitors the state of the update, scan, and work threads.
1480 * Sets scan done state when scan thread exits.
1481 * Sets work done state when work thread exits.
1482 * @param _h Handle to hb_handle_t
1484 static void thread_func( void * _h )
1486 hb_handle_t * h = (hb_handle_t *) _h;
1491 /* Create folder for temporary files */
1492 memset( dirname, 0, 1024 );
1493 hb_get_temporary_directory( dirname );
1495 hb_mkdir( dirname );
1499 /* In case the check_update thread hangs, it'll die sooner or
1500 later. Then, we join it here */
1501 if( h->update_thread &&
1502 hb_thread_has_exited( h->update_thread ) )
1504 hb_thread_close( &h->update_thread );
1507 /* Check if the scan thread is done */
1508 if( h->scan_thread &&
1509 hb_thread_has_exited( h->scan_thread ) )
1511 hb_thread_close( &h->scan_thread );
1517 hb_remove_previews( h );
1518 while( ( title = hb_list_item( h->list_title, 0 ) ) )
1520 hb_list_rem( h->list_title, title );
1521 hb_title_close( &title );
1524 hb_log( "hb_scan: canceled" );
1528 hb_log( "libhb: scan thread found %d valid title(s)",
1529 hb_list_count( h->list_title ) );
1531 hb_lock( h->state_lock );
1532 h->state.state = HB_STATE_SCANDONE; //originally state.state
1533 hb_unlock( h->state_lock );
1534 /*we increment this sessions scan count by one for the MacGui
1535 to trigger a new source being set */
1539 /* Check if the work thread is done */
1540 if( h->work_thread &&
1541 hb_thread_has_exited( h->work_thread ) )
1543 hb_thread_close( &h->work_thread );
1545 hb_log( "libhb: work result = %d",
1547 hb_lock( h->state_lock );
1548 h->state.state = HB_STATE_WORKDONE;
1549 h->state.param.workdone.error = h->work_error;
1551 h->job_count = hb_count(h);
1552 if (h->job_count < 1)
1553 h->job_count_permanent = 0;
1554 hb_unlock( h->state_lock );
1560 if( h->scan_thread )
1563 hb_thread_close( &h->scan_thread );
1565 if( h->work_thread )
1568 hb_thread_close( &h->work_thread );
1570 hb_remove_previews( h );
1575 * @param h Handle to hb_handle_t
1577 int hb_get_pid( hb_handle_t * h )
1583 * Returns the id for the given instance.
1584 * @param h Handle to hb_handle_t
1586 int hb_get_instance_id( hb_handle_t * h )
1592 * Sets the current state.
1593 * @param h Handle to hb_handle_t
1594 * @param s Handle to new hb_state_t
1596 void hb_set_state( hb_handle_t * h, hb_state_t * s )
1598 hb_lock( h->pause_lock );
1599 hb_lock( h->state_lock );
1600 memcpy( &h->state, s, sizeof( hb_state_t ) );
1601 if( h->state.state == HB_STATE_WORKING ||
1602 h->state.state == HB_STATE_SEARCHING )
1605 if (h->job_count < 1)
1606 h->job_count_permanent = 1;
1608 h->state.param.working.job_cur =
1609 h->job_count_permanent - hb_list_count( h->jobs );
1610 h->state.param.working.job_count = h->job_count_permanent;
1612 // Set which job is being worked on
1614 h->state.param.working.sequence_id = h->current_job->sequence_id;
1616 h->state.param.working.sequence_id = 0;
1618 hb_unlock( h->state_lock );
1619 hb_unlock( h->pause_lock );
1622 /* Passes a pointer to persistent data */
1623 hb_interjob_t * hb_interjob_get( hb_handle_t * h )