8 /* The "Check for update" thread */
11 hb_thread_t * update_thread;
13 /* This thread's only purpose is to check other threads'
16 hb_thread_t * main_thread;
19 /* DVD/file scan thread */
20 hb_list_t * list_title;
21 hb_thread_t * scan_thread;
23 /* The thread which processes the jobs. Others threads are launched
24 from this one (see work.c) */
26 hb_job_t * current_job;
28 int job_count_permanent;
29 volatile int work_die;
31 hb_thread_t * work_thread;
35 hb_lock_t * state_lock;
39 hb_lock_t * pause_lock;
40 /* For MacGui active queue
41 increments each time the scan thread completes*/
43 volatile int scan_die;
45 /* Stash of persistent data between jobs, for stuff
46 like correcting frame count and framerate estimates
47 on multi-pass encodes where frames get dropped. */
48 hb_interjob_t * interjob;
52 hb_lock_t *hb_avcodec_lock;
53 hb_work_object_t * hb_objects = NULL;
54 int hb_instance_counter = 0;
55 int hb_process_initialized = 0;
57 static void thread_func( void * );
59 void hb_avcodec_init()
61 hb_avcodec_lock = hb_lock_init();
65 int hb_avcodec_open(AVCodecContext *avctx, AVCodec *codec)
68 hb_lock( hb_avcodec_lock );
69 ret = avcodec_open(avctx, codec);
70 hb_unlock( hb_avcodec_lock );
74 int hb_avcodec_close(AVCodecContext *avctx)
77 hb_lock( hb_avcodec_lock );
78 ret = avcodec_close(avctx);
79 hb_unlock( hb_avcodec_lock );
83 int hb_ff_layout_xlat(int64_t ff_channel_layout, int channels)
85 switch (ff_channel_layout)
88 return HB_INPUT_CH_LAYOUT_MONO;
89 case CH_LAYOUT_STEREO:
90 return HB_INPUT_CH_LAYOUT_STEREO;
91 case CH_LAYOUT_SURROUND:
92 return HB_INPUT_CH_LAYOUT_3F;
93 case CH_LAYOUT_4POINT0:
94 return HB_INPUT_CH_LAYOUT_3F1R;
96 return HB_INPUT_CH_LAYOUT_2F2R;
98 return HB_INPUT_CH_LAYOUT_2F2R;
99 case CH_LAYOUT_5POINT0:
100 // ffmpeg like to neglect to signal LFE
102 return HB_INPUT_CH_LAYOUT_3F2R|HB_INPUT_CH_LAYOUT_HAS_LFE;
103 return HB_INPUT_CH_LAYOUT_3F2R;
104 case CH_LAYOUT_5POINT1:
105 return HB_INPUT_CH_LAYOUT_3F2R|HB_INPUT_CH_LAYOUT_HAS_LFE;
106 case CH_LAYOUT_5POINT0_BACK:
107 // ffmpeg like to neglect to signal LFE
109 return HB_INPUT_CH_LAYOUT_3F2R|HB_INPUT_CH_LAYOUT_HAS_LFE;
110 return HB_INPUT_CH_LAYOUT_3F2R;
111 case CH_LAYOUT_5POINT1_BACK:
112 return HB_INPUT_CH_LAYOUT_3F2R|HB_INPUT_CH_LAYOUT_HAS_LFE;
113 case CH_LAYOUT_7POINT0:
114 // ffmpeg like to neglect to signal LFE
116 return HB_INPUT_CH_LAYOUT_3F4R|HB_INPUT_CH_LAYOUT_HAS_LFE;
117 return HB_INPUT_CH_LAYOUT_3F4R;
118 case CH_LAYOUT_7POINT1:
119 return HB_INPUT_CH_LAYOUT_3F4R|HB_INPUT_CH_LAYOUT_HAS_LFE;
120 case CH_LAYOUT_STEREO_DOWNMIX:
121 return HB_INPUT_CH_LAYOUT_STEREO;
123 return HB_INPUT_CH_LAYOUT_STEREO;
125 return HB_INPUT_CH_LAYOUT_STEREO;
129 * Registers work objects, by adding the work object to a liked list.
130 * @param w Handle to hb_work_object_t to register.
132 void hb_register( hb_work_object_t * w )
134 w->next = hb_objects;
139 * libhb initialization routine.
140 * @param verbose HB_DEBUG_NONE or HB_DEBUG_ALL.
141 * @param update_check signals libhb to check for updated version from HandBrake website.
142 * @return Handle to hb_handle_t for use on all subsequent calls to libhb.
144 hb_handle_t * hb_init( int verbose, int update_check )
146 if (!hb_process_initialized)
149 #if defined( _WIN32 ) || defined( __MINGW32__ )
150 pthread_win32_process_attach_np();
153 hb_process_initialized =1;
156 hb_handle_t * h = calloc( sizeof( hb_handle_t ), 1 );
159 /* See hb_deep_log() and hb_log() in common.c */
160 global_verbosity_level = verbose;
162 putenv( "HB_DEBUG=1" );
164 h->id = hb_instance_counter++;
166 /* Check for an update on the website if asked to */
171 hb_log( "hb_init: checking for updates" );
172 date = hb_get_date();
173 h->update_thread = hb_update_init( &h->build, h->version );
177 if( hb_thread_has_exited( h->update_thread ) )
179 /* Immediate success or failure */
180 hb_thread_close( &h->update_thread );
183 if( hb_get_date() > date + 1000 )
185 /* Still nothing after one second. Connection problem,
186 let the thread die */
187 hb_log( "hb_init: connection problem, not waiting for "
196 * Initialise buffer pool
198 hb_buffer_pool_init();
200 /* CPU count detection */
201 hb_log( "hb_init: checking cpu count" );
202 h->cpu_count = hb_get_cpu_count();
204 h->list_title = hb_list_init();
205 h->jobs = hb_list_init();
207 h->state_lock = hb_lock_init();
208 h->state.state = HB_STATE_IDLE;
210 h->pause_lock = hb_lock_init();
212 h->interjob = calloc( sizeof( hb_interjob_t ), 1 );
217 /* Start library thread */
218 hb_log( "hb_init: starting libhb thread" );
220 h->main_thread = hb_thread_init( "libhb", thread_func, h,
221 HB_NORMAL_PRIORITY );
222 hb_register( &hb_sync_video );
223 hb_register( &hb_sync_audio );
224 hb_register( &hb_decmpeg2 );
225 hb_register( &hb_decvobsub );
226 hb_register( &hb_encvobsub );
227 hb_register( &hb_deccc608 );
228 hb_register( &hb_decsrtsub );
229 hb_register( &hb_render );
230 hb_register( &hb_encavcodec );
231 hb_register( &hb_encx264 );
232 hb_register( &hb_enctheora );
233 hb_register( &hb_deca52 );
234 hb_register( &hb_decdca );
235 hb_register( &hb_decavcodec );
236 hb_register( &hb_decavcodecv );
237 hb_register( &hb_decavcodecvi );
238 hb_register( &hb_decavcodecai );
239 hb_register( &hb_declpcm );
240 hb_register( &hb_encfaac );
241 hb_register( &hb_enclame );
242 hb_register( &hb_encvorbis );
243 hb_register( &hb_muxer );
245 hb_register( &hb_encca_aac );
252 * libhb initialization routine.
253 * This version is to use when calling the dylib, the macro hb_init isn't available from a dylib call!
254 * @param verbose HB_DEBUG_NONE or HB_DEBUG_ALL.
255 * @param update_check signals libhb to check for updated version from HandBrake website.
256 * @return Handle to hb_handle_t for use on all subsequent calls to libhb.
258 hb_handle_t * hb_init_dl( int verbose, int update_check )
260 hb_handle_t * h = calloc( sizeof( hb_handle_t ), 1 );
263 /* See hb_log() in common.c */
264 if( verbose > HB_DEBUG_NONE )
266 putenv( "HB_DEBUG=1" );
269 h->id = hb_instance_counter++;
271 /* Check for an update on the website if asked to */
276 hb_log( "hb_init: checking for updates" );
277 date = hb_get_date();
278 h->update_thread = hb_update_init( &h->build, h->version );
282 if( hb_thread_has_exited( h->update_thread ) )
284 /* Immediate success or failure */
285 hb_thread_close( &h->update_thread );
288 if( hb_get_date() > date + 1000 )
290 /* Still nothing after one second. Connection problem,
291 let the thread die */
292 hb_log( "hb_init: connection problem, not waiting for "
300 /* CPU count detection */
301 hb_log( "hb_init: checking cpu count" );
302 h->cpu_count = hb_get_cpu_count();
304 h->list_title = hb_list_init();
305 h->jobs = hb_list_init();
306 h->current_job = NULL;
308 h->state_lock = hb_lock_init();
309 h->state.state = HB_STATE_IDLE;
311 h->pause_lock = hb_lock_init();
315 avcodec_register_all();
317 /* Start library thread */
318 hb_log( "hb_init: starting libhb thread" );
320 h->main_thread = hb_thread_init( "libhb", thread_func, h,
321 HB_NORMAL_PRIORITY );
323 hb_register( &hb_sync_video );
324 hb_register( &hb_sync_audio );
325 hb_register( &hb_decmpeg2 );
326 hb_register( &hb_decvobsub );
327 hb_register( &hb_encvobsub );
328 hb_register( &hb_deccc608 );
329 hb_register( &hb_decsrtsub );
330 hb_register( &hb_render );
331 hb_register( &hb_encavcodec );
332 hb_register( &hb_encx264 );
333 hb_register( &hb_enctheora );
334 hb_register( &hb_deca52 );
335 hb_register( &hb_decdca );
336 hb_register( &hb_decavcodec );
337 hb_register( &hb_decavcodecv );
338 hb_register( &hb_decavcodecvi );
339 hb_register( &hb_decavcodecai );
340 hb_register( &hb_declpcm );
341 hb_register( &hb_encfaac );
342 hb_register( &hb_enclame );
343 hb_register( &hb_encvorbis );
344 hb_register( &hb_muxer );
346 hb_register( &hb_encca_aac );
354 * Returns current version of libhb.
355 * @param h Handle to hb_handle_t.
356 * @return character array of version number.
358 char * hb_get_version( hb_handle_t * h )
360 return HB_PROJECT_VERSION;
364 * Returns current build of libhb.
365 * @param h Handle to hb_handle_t.
366 * @return character array of build number.
368 int hb_get_build( hb_handle_t * h )
370 return HB_PROJECT_BUILD;
374 * Checks for needed update.
375 * @param h Handle to hb_handle_t.
376 * @param version Pointer to handle where version will be copied.
377 * @return update indicator.
379 int hb_check_update( hb_handle_t * h, char ** version )
381 *version = ( h->build < 0 ) ? NULL : h->version;
386 * Sets the cpu count to the desired value.
387 * @param h Handle to hb_handle_t
388 * @param cpu_count Number of CPUs to use.
390 void hb_set_cpu_count( hb_handle_t * h, int cpu_count )
392 cpu_count = MAX( 1, cpu_count );
393 cpu_count = MIN( cpu_count, 8 );
394 h->cpu_count = cpu_count;
398 * Deletes current previews associated with titles
399 * @param h Handle to hb_handle_t
401 void hb_remove_previews( hb_handle_t * h )
408 struct dirent * entry;
410 memset( dirname, 0, 1024 );
411 hb_get_temporary_directory( dirname );
412 dir = opendir( dirname );
413 if (dir == NULL) return;
415 count = hb_list_count( h->list_title );
416 while( ( entry = readdir( dir ) ) )
418 if( entry->d_name[0] == '.' )
422 for( i = 0; i < count; i++ )
424 title = hb_list_item( h->list_title, i );
425 len = snprintf( filename, 1024, "%d_%d", h->id, title->index );
426 if (strncmp(entry->d_name, filename, len) == 0)
428 snprintf( filename, 1024, "%s/%s", dirname, entry->d_name );
438 * Initializes a scan of the by calling hb_scan_init
439 * @param h Handle to hb_handle_t
440 * @param path location of VIDEO_TS folder.
441 * @param title_index Desired title to scan. 0 for all titles.
442 * @param preview_count Number of preview images to generate.
443 * @param store_previews Whether or not to write previews to disk.
445 void hb_scan( hb_handle_t * h, const char * path, int title_index,
446 int preview_count, int store_previews )
452 /* Clean up from previous scan */
453 hb_remove_previews( h );
454 while( ( title = hb_list_item( h->list_title, 0 ) ) )
456 hb_list_rem( h->list_title, title );
457 hb_title_close( &title );
460 hb_log( "hb_scan: path=%s, title_index=%d", path, title_index );
461 h->scan_thread = hb_scan_init( h, &h->scan_die, path, title_index,
462 h->list_title, preview_count,
467 * Returns the list of titles found.
468 * @param h Handle to hb_handle_t
469 * @return Handle to hb_list_t of the title list.
471 hb_list_t * hb_get_titles( hb_handle_t * h )
473 return h->list_title;
477 * Create preview image of desired title a index of picture.
478 * @param h Handle to hb_handle_t.
479 * @param title Handle to hb_title_t of desired title.
480 * @param picture Index in title.
481 * @param buffer Handle to buufer were inage will be drawn.
483 void hb_get_preview( hb_handle_t * h, hb_title_t * title, int picture,
486 hb_job_t * job = title->job;
489 uint8_t * buf1, * buf2, * buf3, * buf4, * pen;
491 AVPicture pic_in, pic_preview, pic_deint, pic_crop, pic_scale;
492 struct SwsContext * context;
494 int rgb_width = ((job->width + 7) >> 3) << 3;
497 swsflags = SWS_LANCZOS | SWS_ACCURATE_RND;
499 buf1 = av_malloc( avpicture_get_size( PIX_FMT_YUV420P, title->width, title->height ) );
500 buf2 = av_malloc( avpicture_get_size( PIX_FMT_YUV420P, title->width, title->height ) );
501 buf3 = av_malloc( avpicture_get_size( PIX_FMT_YUV420P, rgb_width, job->height ) );
502 buf4 = av_malloc( avpicture_get_size( PIX_FMT_RGB32, rgb_width, job->height ) );
503 avpicture_fill( &pic_in, buf1, PIX_FMT_YUV420P,
504 title->width, title->height );
505 avpicture_fill( &pic_deint, buf2, PIX_FMT_YUV420P,
506 title->width, title->height );
507 avpicture_fill( &pic_scale, buf3, PIX_FMT_YUV420P,
508 rgb_width, job->height );
509 avpicture_fill( &pic_preview, buf4, PIX_FMT_RGB32,
510 rgb_width, job->height );
512 // Allocate the AVPicture frames and fill in
514 memset( filename, 0, 1024 );
516 hb_get_tempory_filename( h, filename, "%d_%d_%d",
517 h->id, title->index, picture );
519 file = fopen( filename, "rb" );
522 hb_log( "hb_get_preview: fopen failed" );
526 fread( buf1, avpicture_get_size( PIX_FMT_YUV420P, title->width, title->height), 1, file );
529 if( job->deinterlace )
531 // Deinterlace and crop
532 avpicture_deinterlace( &pic_deint, &pic_in, PIX_FMT_YUV420P, title->width, title->height );
533 av_picture_crop( &pic_crop, &pic_deint, PIX_FMT_YUV420P, job->crop[0], job->crop[2] );
538 av_picture_crop( &pic_crop, &pic_in, PIX_FMT_YUV420P, job->crop[0], job->crop[2] );
541 // Get scaling context
542 context = sws_getContext(title->width - (job->crop[2] + job->crop[3]),
543 title->height - (job->crop[0] + job->crop[1]),
545 job->width, job->height, PIX_FMT_YUV420P,
546 swsflags, NULL, NULL, NULL);
550 pic_crop.data, pic_crop.linesize,
551 0, title->height - (job->crop[0] + job->crop[1]),
552 pic_scale.data, pic_scale.linesize);
555 sws_freeContext( context );
557 // Get preview context
558 context = sws_getContext(rgb_width, job->height, PIX_FMT_YUV420P,
559 rgb_width, job->height, PIX_FMT_RGB32,
560 swsflags, NULL, NULL, NULL);
564 pic_scale.data, pic_scale.linesize,
566 pic_preview.data, pic_preview.linesize);
569 sws_freeContext( context );
571 preview_size = pic_preview.linesize[0];
573 for( i = 0; i < job->height; i++ )
575 memcpy( pen, buf4 + preview_size * i, 4 * job->width );
576 pen += 4 * job->width;
580 avpicture_free( &pic_preview );
581 avpicture_free( &pic_scale );
582 avpicture_free( &pic_deint );
583 avpicture_free( &pic_in );
587 * Analyzes a frame to detect interlacing artifacts
588 * and returns true if interlacing (combing) is found.
590 * Code taken from Thomas Oestreich's 32detect filter
591 * in the Transcode project, with minor formatting changes.
593 * @param buf An hb_buffer structure holding valid frame data
594 * @param width The frame's width in pixels
595 * @param height The frame's height in pixels
596 * @param color_equal Sensitivity for detecting similar colors
597 * @param color_diff Sensitivity for detecting different colors
598 * @param threshold Sensitivity for flagging planes as combed
599 * @param prog_equal Sensitivity for detecting similar colors on progressive frames
600 * @param prog_diff Sensitivity for detecting different colors on progressive frames
601 * @param prog_threshold Sensitivity for flagging progressive frames as combed
603 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 )
605 int j, k, n, off, cc_1, cc_2, cc[3];
606 // int flag[3] ; // debugging flag
607 uint16_t s1, s2, s3, s4;
612 if ( buf->flags & 16 )
614 /* Frame is progressive, be more discerning. */
615 color_diff = prog_diff;
616 color_equal = prog_equal;
617 threshold = prog_threshold;
620 /* One pas for Y, one pass for Cb, one pass for Cr */
621 for( k = 0; k < 3; k++ )
625 /* Y has already been checked, now offset by Y's dimensions
626 and divide all the other values by 2, since Cr and Cb
627 are half-size compared to Y. */
628 offset = width * height;
634 /* Y and Cb are done, so the offset needs to be bumped
635 so it's width*height + (width / 2) * (height / 2) */
639 for( j = 0; j < width; ++j )
643 for( n = 0; n < ( height - 4 ); n = n + 2 )
645 /* Look at groups of 4 sequential horizontal lines */
646 s1 = ( ( buf->data + offset )[ off + j ] & 0xff );
647 s2 = ( ( buf->data + offset )[ off + j + width ] & 0xff );
648 s3 = ( ( buf->data + offset )[ off + j + 2 * width ] & 0xff );
649 s4 = ( ( buf->data + offset )[ off + j + 3 * width ] & 0xff );
651 /* Note if the 1st and 2nd lines are more different in
652 color than the 1st and 3rd lines are similar in color.*/
653 if ( ( abs( s1 - s3 ) < color_equal ) &&
654 ( abs( s1 - s2 ) > color_diff ) )
657 /* Note if the 2nd and 3rd lines are more different in
658 color than the 2nd and 4th lines are similar in color.*/
659 if ( ( abs( s2 - s4 ) < color_equal ) &&
660 ( abs( s2 - s3 ) > color_diff) )
663 /* Now move down 2 horizontal lines before starting over.*/
669 /* The final cc score for a plane is the percentage of combed pixels it contains.
670 Because sensitivity goes down to hundreths of a percent, multiply by 1000
671 so it will be easy to compare against the threhold value which is an integer. */
672 cc[k] = (int)( ( cc_1 + cc_2 ) * 1000.0 / ( width * height ) );
676 /* HandBrake is all yuv420, so weight the average percentage of all 3 planes accordingly.*/
677 int average_cc = ( 2 * cc[0] + ( cc[1] / 2 ) + ( cc[2] / 2 ) ) / 3;
679 /* Now see if that average percentage of combed pixels surpasses the threshold percentage given by the user.*/
680 if( average_cc > threshold )
683 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" );
689 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" );
692 /* Reaching this point means no combing detected. */
698 * Calculates job width and height for anamorphic content,
700 * @param job Handle to hb_job_t
701 * @param output_width Pointer to returned storage width
702 * @param output_height Pointer to returned storage height
703 * @param output_par_width Pointer to returned pixel width
704 @ param output_par_height Pointer to returned pixel height
706 void hb_set_anamorphic_size( hb_job_t * job,
707 int *output_width, int *output_height,
708 int *output_par_width, int *output_par_height )
710 /* Set up some variables to make the math easier to follow. */
711 hb_title_t * title = job->title;
712 int cropped_width = title->width - job->crop[2] - job->crop[3] ;
713 int cropped_height = title->height - job->crop[0] - job->crop[1] ;
714 double storage_aspect = (double)cropped_width / (double)cropped_height;
715 int mod = job->modulus ? job->modulus : 16;
716 double aspect = title->aspect;
718 int pixel_aspect_width = job->anamorphic.par_width;
719 int pixel_aspect_height = job->anamorphic.par_height;
721 /* If a source was really NTSC or PAL and the user specified ITU PAR
722 values, replace the standard PAR values with the ITU broadcast ones. */
723 if( title->width == 720 && job->anamorphic.itu_par )
725 // convert aspect to a scaled integer so we can test for 16:9 & 4:3
726 // aspect ratios ignoring insignificant differences in the LSBs of
727 // the floating point representation.
728 int iaspect = aspect * 9.;
730 /* Handle ITU PARs */
731 if (title->height == 480)
736 /* It's widescreen */
737 pixel_aspect_width = 40;
738 pixel_aspect_height = 33;
740 else if (iaspect == 12)
743 pixel_aspect_width = 10;
744 pixel_aspect_height = 11;
747 else if (title->height == 576)
752 /* It's widescreen */
753 pixel_aspect_width = 16;
754 pixel_aspect_height = 11;
756 else if (iaspect == 12)
759 pixel_aspect_width = 12;
760 pixel_aspect_height = 11;
765 /* Figure out what width the source would display at. */
766 int source_display_width = cropped_width * (double)pixel_aspect_width /
767 (double)pixel_aspect_height ;
770 3 different ways of deciding output dimensions:
771 - 1: Strict anamorphic, preserve source dimensions
772 - 2: Loose anamorphic, round to mod16 and preserve storage aspect ratio
773 - 3: Power user anamorphic, specify everything
776 switch( job->anamorphic.mode )
779 /* Strict anamorphic */
780 *output_width = cropped_width;
781 *output_height = cropped_height;
782 *output_par_width = title->pixel_aspect_width;
783 *output_par_height = title->pixel_aspect_height;
787 /* "Loose" anamorphic.
788 - Uses mod16-compliant dimensions,
789 - Allows users to set the width
792 // height: Gets set later, ignore user job->height value
794 /* Gotta handle bounding dimensions.
795 If the width is too big, just reset it with no rescaling.
796 Instead of using the aspect-scaled job height,
797 we need to see if the job width divided by the storage aspect
798 is bigger than the max. If so, set it to the max (this is sloppy).
799 If not, set job height to job width divided by storage aspect.
802 if ( job->maxWidth && (job->maxWidth < job->width) )
803 width = job->maxWidth;
805 /* Time to get picture width that divide cleanly.*/
806 width = MULTIPLE_MOD( width, mod);
808 /* Verify these new dimensions don't violate max height and width settings */
809 if ( job->maxWidth && (job->maxWidth < job->width) )
810 width = job->maxWidth;
812 height = ((double)width / storage_aspect) + 0.5;
814 if ( job->maxHeight && (job->maxHeight < height) )
815 height = job->maxHeight;
817 /* Time to get picture height that divide cleanly.*/
818 height = MULTIPLE_MOD( height, mod);
820 /* Verify these new dimensions don't violate max height and width settings */
821 if ( job->maxHeight && (job->maxHeight < height) )
822 height = job->maxHeight;
824 /* The film AR is the source's display width / cropped source height.
825 The output display width is the output height * film AR.
826 The output PAR is the output display width / output storage width. */
827 pixel_aspect_width = height * source_display_width / cropped_height;
828 pixel_aspect_height = width;
830 /* Pass the results back to the caller */
831 *output_width = width;
832 *output_height = height;
836 /* Anamorphic 3: Power User Jamboree
837 - Set everything based on specified values */
839 /* Use specified storage dimensions */
841 height = job->height;
843 /* Bind to max dimensions */
844 if( job->maxWidth && width > job->maxWidth )
845 width = job->maxWidth;
846 if( job->maxHeight && height > job->maxHeight )
847 height = job->maxHeight;
849 /* Time to get picture dimensions that divide cleanly.*/
850 width = MULTIPLE_MOD( width, mod);
851 height = MULTIPLE_MOD( height, mod);
853 /* Verify we're still within max dimensions */
854 if( job->maxWidth && width > job->maxWidth )
855 width = job->maxWidth - (mod/2);
856 if( job->maxHeight && height > job->maxHeight )
857 height = job->maxHeight - (mod/2);
859 /* Re-ensure we have picture dimensions that divide cleanly. */
860 width = MULTIPLE_MOD( width, mod );
861 height = MULTIPLE_MOD( height, mod );
863 /* That finishes the storage dimensions. On to display. */
864 if( job->anamorphic.dar_width && job->anamorphic.dar_height )
866 /* We need to adjust the PAR to produce this aspect. */
867 pixel_aspect_width = height * job->anamorphic.dar_width / job->anamorphic.dar_height;
868 pixel_aspect_height = width;
872 /* If we're doing ana 3 and not specifying a DAR, care needs to be taken.
873 This indicates a PAR is potentially being set by the interface. But
874 this is an output PAR, to correct a source, and it should not be assumed
875 that it properly creates a display aspect ratio when applied to the source,
876 which could easily be stored in a different resolution. */
877 if( job->anamorphic.keep_display_aspect )
879 /* We can ignore the possibility of a PAR change */
880 pixel_aspect_width = height * ( (double)source_display_width / (double)cropped_height );
881 pixel_aspect_height = width;
885 int output_display_width = width * (double)pixel_aspect_width /
886 (double)pixel_aspect_height;
887 pixel_aspect_width = output_display_width;
888 pixel_aspect_height = width;
893 *output_width = width;
894 *output_height = height;
898 /* While x264 is smart enough to reduce fractions on its own, libavcodec
899 needs some help with the math, so lose superfluous factors. */
900 hb_reduce( output_par_width, output_par_height,
901 pixel_aspect_width, pixel_aspect_height );
905 * Calculates job width, height, and cropping parameters.
906 * @param job Handle to hb_job_t.
907 * @param aspect Desired aspect ratio. Value of -1 uses title aspect.
908 * @param pixels Maximum desired pixel count.
910 void hb_set_size( hb_job_t * job, double aspect, int pixels )
912 hb_title_t * title = job->title;
914 int croppedWidth = title->width - title->crop[2] - title->crop[3];
915 int croppedHeight = title->height - title->crop[0] - title->crop[1];
916 double croppedAspect = title->aspect * title->height * croppedWidth /
917 croppedHeight / title->width;
923 /* Keep the best possible aspect ratio */
924 aspect = croppedAspect;
927 /* Crop if necessary to obtain the desired ratio */
928 memcpy( job->crop, title->crop, 4 * sizeof( int ) );
929 if( aspect < croppedAspect )
931 /* Need to crop on the left and right */
932 addCrop = croppedWidth - aspect * croppedHeight * title->width /
933 title->aspect / title->height;
936 addCrop = ( addCrop + 1 ) / 2;
937 job->crop[2] += addCrop;
938 job->crop[3] += addCrop;
940 else if( addCrop & 2 )
943 job->crop[2] += addCrop - 1;
944 job->crop[3] += addCrop + 1;
949 job->crop[2] += addCrop;
950 job->crop[3] += addCrop;
953 else if( aspect > croppedAspect )
955 /* Need to crop on the top and bottom */
956 addCrop = croppedHeight - croppedWidth * title->aspect *
957 title->height / aspect / title->width;
960 addCrop = ( addCrop + 1 ) / 2;
961 job->crop[0] += addCrop;
962 job->crop[1] += addCrop;
964 else if( addCrop & 2 )
967 job->crop[0] += addCrop - 1;
968 job->crop[1] += addCrop + 1;
973 job->crop[0] += addCrop;
974 job->crop[1] += addCrop;
978 /* Compute a resolution from the number of pixels and aspect */
982 h = MULTIPLE_16( (int)( (double)w / aspect ) );
990 job->height = MULTIPLE_16( (int)( (double)job->width / aspect ) );
994 * Returns the number of jobs in the queue.
995 * @param h Handle to hb_handle_t.
996 * @return Number of jobs.
998 int hb_count( hb_handle_t * h )
1000 return hb_list_count( h->jobs );
1004 * Returns handle to job at index i within the job list.
1005 * @param h Handle to hb_handle_t.
1006 * @param i Index of job.
1007 * @returns Handle to hb_job_t of desired job.
1009 hb_job_t * hb_job( hb_handle_t * h, int i )
1011 return hb_list_item( h->jobs, i );
1014 hb_job_t * hb_current_job( hb_handle_t * h )
1016 return( h->current_job );
1020 * Adds a job to the job list.
1021 * @param h Handle to hb_handle_t.
1022 * @param job Handle to hb_job_t.
1024 void hb_add( hb_handle_t * h, hb_job_t * job )
1026 hb_job_t * job_copy;
1027 hb_title_t * title, * title_copy;
1028 hb_chapter_t * chapter, * chapter_copy;
1030 hb_subtitle_t * subtitle, * subtitle_copy;
1034 /* Copy the title */
1036 title_copy = malloc( sizeof( hb_title_t ) );
1037 memcpy( title_copy, title, sizeof( hb_title_t ) );
1039 title_copy->list_chapter = hb_list_init();
1040 for( i = 0; i < hb_list_count( title->list_chapter ); i++ )
1042 chapter = hb_list_item( title->list_chapter, i );
1043 chapter_copy = malloc( sizeof( hb_chapter_t ) );
1044 memcpy( chapter_copy, chapter, sizeof( hb_chapter_t ) );
1045 hb_list_add( title_copy->list_chapter, chapter_copy );
1051 if( title->metadata )
1053 title_copy->metadata = malloc( sizeof( hb_metadata_t ) );
1055 if( title_copy->metadata )
1057 memcpy( title_copy->metadata, title->metadata, sizeof( hb_metadata_t ) );
1060 * Need to copy the artwork seperatly (TODO).
1062 if( title->metadata->coverart )
1064 title_copy->metadata->coverart = malloc( title->metadata->coverart_size );
1065 if( title_copy->metadata->coverart )
1067 memcpy( title_copy->metadata->coverart, title->metadata->coverart,
1068 title->metadata->coverart_size );
1070 title_copy->metadata->coverart_size = 0;
1076 /* Copy the audio track(s) we want */
1077 title_copy->list_audio = hb_list_init();
1079 for( i = 0; i < hb_list_count(job->list_audio); i++ )
1081 if( ( audio = hb_list_item( job->list_audio, i ) ) )
1083 hb_list_add( title_copy->list_audio, hb_audio_copy(audio) );
1087 title_copy->list_subtitle = hb_list_init();
1090 * The following code is confusing, there are two ways in which
1091 * we select subtitles and it depends on whether this is single or
1094 * subtitle_scan may be enabled, in which case the first pass
1095 * scans all subtitles of that language. The second pass does not
1096 * select any because they are set at the end of the first pass.
1098 * We may have manually selected a subtitle, in which case that is
1099 * selected in the first pass of a single pass, or the second of a
1102 memset( audio_lang, 0, sizeof( audio_lang ) );
1104 if ( job->indepth_scan ) {
1107 * Find the first audio language that is being encoded
1109 for( i = 0; i < hb_list_count(job->list_audio); i++ )
1111 if( ( audio = hb_list_item( job->list_audio, i ) ) )
1113 strncpy(audio_lang, audio->config.lang.iso639_2, sizeof(audio_lang));
1120 * If doing a subtitle scan then add all the matching subtitles for this
1123 if ( job->indepth_scan )
1125 for( i=0; i < hb_list_count( title->list_subtitle ); i++ )
1127 subtitle = hb_list_item( title->list_subtitle, i );
1128 if( strcmp( subtitle->iso639_2, audio_lang ) == 0 &&
1129 subtitle->source == VOBSUB )
1132 * Matched subtitle language with audio language, so
1133 * add this to our list to scan.
1135 * We will update the subtitle list on the second pass
1136 * later after the first pass has completed.
1138 subtitle_copy = malloc( sizeof( hb_subtitle_t ) );
1139 memcpy( subtitle_copy, subtitle, sizeof( hb_subtitle_t ) );
1140 hb_list_add( title_copy->list_subtitle, subtitle_copy );
1145 * Not doing a subtitle scan in this pass, but maybe we are in the
1148 if( job->pass != 1 )
1151 * Copy all of them from the input job, to the title_copy/job_copy.
1153 for( i = 0; i < hb_list_count(job->list_subtitle); i++ ) {
1154 if( ( subtitle = hb_list_item( job->list_subtitle, i ) ) )
1156 subtitle_copy = malloc( sizeof( hb_subtitle_t ) );
1157 memcpy( subtitle_copy, subtitle, sizeof( hb_subtitle_t ) );
1158 hb_list_add( title_copy->list_subtitle, subtitle_copy );
1165 job_copy = calloc( sizeof( hb_job_t ), 1 );
1166 memcpy( job_copy, job, sizeof( hb_job_t ) );
1167 title_copy->job = job_copy;
1168 job_copy->title = title_copy;
1169 job_copy->list_audio = title_copy->list_audio;
1170 job_copy->list_subtitle = title_copy->list_subtitle; // sharing list between title and job
1171 job_copy->file = strdup( job->file );
1173 job_copy->pause = h->pause_lock;
1175 /* Copy the job filter list */
1179 int filter_count = hb_list_count( job->filters );
1180 job_copy->filters = hb_list_init();
1181 for( i = 0; i < filter_count; i++ )
1184 * Copy the filters, since the MacGui reuses the global filter objects
1185 * meaning that queued up jobs overwrite the previous filter settings.
1186 * In reality, settings is probably the only field that needs duplicating
1187 * since it's the only value that is ever changed. But name is duplicated
1188 * as well for completeness. Not copying private_data since it gets
1189 * created for each job in renderInit.
1191 hb_filter_object_t * filter = hb_list_item( job->filters, i );
1192 hb_filter_object_t * filter_copy = malloc( sizeof( hb_filter_object_t ) );
1193 memcpy( filter_copy, filter, sizeof( hb_filter_object_t ) );
1195 filter_copy->name = strdup( filter->name );
1196 if( filter->settings )
1197 filter_copy->settings = strdup( filter->settings );
1198 hb_list_add( job_copy->filters, filter_copy );
1202 /* Add the job to the list */
1203 hb_list_add( h->jobs, job_copy );
1204 h->job_count = hb_count(h);
1205 h->job_count_permanent++;
1209 * Removes a job from the job list.
1210 * @param h Handle to hb_handle_t.
1211 * @param job Handle to hb_job_t.
1213 void hb_rem( hb_handle_t * h, hb_job_t * job )
1215 hb_list_rem( h->jobs, job );
1217 h->job_count = hb_count(h);
1218 if (h->job_count_permanent)
1219 h->job_count_permanent--;
1221 /* XXX free everything XXX */
1225 * Starts the conversion process.
1226 * Sets state to HB_STATE_WORKING.
1227 * calls hb_work_init, to launch work thread. Stores handle to work thread.
1228 * @param h Handle to hb_handle_t.
1230 void hb_start( hb_handle_t * h )
1233 h->job_count = hb_list_count( h->jobs );
1234 h->job_count_permanent = h->job_count;
1236 hb_lock( h->state_lock );
1237 h->state.state = HB_STATE_WORKING;
1238 #define p h->state.param.working
1241 p.job_count = h->job_count;
1249 hb_unlock( h->state_lock );
1254 h->work_thread = hb_work_init( h->jobs, h->cpu_count,
1255 &h->work_die, &h->work_error, &h->current_job );
1259 * Pauses the conversion process.
1260 * @param h Handle to hb_handle_t.
1262 void hb_pause( hb_handle_t * h )
1266 hb_lock( h->pause_lock );
1269 hb_current_job( h )->st_pause_date = hb_get_date();
1271 hb_lock( h->state_lock );
1272 h->state.state = HB_STATE_PAUSED;
1273 hb_unlock( h->state_lock );
1278 * Resumes the conversion process.
1279 * @param h Handle to hb_handle_t.
1281 void hb_resume( hb_handle_t * h )
1285 #define job hb_current_job( h )
1286 if( job->st_pause_date != -1 )
1288 job->st_paused += hb_get_date() - job->st_pause_date;
1292 hb_unlock( h->pause_lock );
1298 * Stops the conversion process.
1299 * @param h Handle to hb_handle_t.
1301 void hb_stop( hb_handle_t * h )
1305 h->job_count = hb_count(h);
1306 h->job_count_permanent = 0;
1312 * Stops the conversion process.
1313 * @param h Handle to hb_handle_t.
1315 void hb_scan_stop( hb_handle_t * h )
1319 h->job_count = hb_count(h);
1320 h->job_count_permanent = 0;
1326 * Returns the state of the conversion process.
1327 * @param h Handle to hb_handle_t.
1328 * @param s Handle to hb_state_t which to copy the state data.
1330 void hb_get_state( hb_handle_t * h, hb_state_t * s )
1332 hb_lock( h->state_lock );
1334 memcpy( s, &h->state, sizeof( hb_state_t ) );
1335 if ( h->state.state == HB_STATE_SCANDONE || h->state.state == HB_STATE_WORKDONE )
1336 h->state.state = HB_STATE_IDLE;
1338 hb_unlock( h->state_lock );
1341 void hb_get_state2( hb_handle_t * h, hb_state_t * s )
1343 hb_lock( h->state_lock );
1345 memcpy( s, &h->state, sizeof( hb_state_t ) );
1347 hb_unlock( h->state_lock );
1351 * Called in MacGui in UpdateUI to check
1352 * for a new scan being completed to set a new source
1354 int hb_get_scancount( hb_handle_t * h)
1356 return h->scanCount;
1360 * Closes access to libhb by freeing the hb_handle_t handle ontained in hb_init.
1361 * @param _h Pointer to handle to hb_handle_t.
1363 void hb_close( hb_handle_t ** _h )
1365 hb_handle_t * h = *_h;
1370 hb_thread_close( &h->main_thread );
1372 while( ( title = hb_list_item( h->list_title, 0 ) ) )
1374 hb_list_rem( h->list_title, title );
1375 if( title->job && title->job->filters )
1377 hb_list_close( &title->job->filters );
1380 hb_title_close( &title );
1382 hb_list_close( &h->list_title );
1384 hb_list_close( &h->jobs );
1385 hb_lock_close( &h->state_lock );
1386 hb_lock_close( &h->pause_lock );
1393 * Cleans up libhb at a process level. Call before the app closes. Removes preview directory.
1395 void hb_global_close()
1399 struct dirent * entry;
1401 /* Find and remove temp folder */
1402 memset( dirname, 0, 1024 );
1403 hb_get_temporary_directory( dirname );
1405 dir = opendir( dirname );
1408 while( ( entry = readdir( dir ) ) )
1410 char filename[1024];
1411 if( entry->d_name[0] == '.' )
1415 memset( filename, 0, 1024 );
1416 snprintf( filename, 1023, "%s/%s", dirname, entry->d_name );
1425 * Monitors the state of the update, scan, and work threads.
1426 * Sets scan done state when scan thread exits.
1427 * Sets work done state when work thread exits.
1428 * @param _h Handle to hb_handle_t
1430 static void thread_func( void * _h )
1432 hb_handle_t * h = (hb_handle_t *) _h;
1437 /* Create folder for temporary files */
1438 memset( dirname, 0, 1024 );
1439 hb_get_temporary_directory( dirname );
1441 hb_mkdir( dirname );
1445 /* In case the check_update thread hangs, it'll die sooner or
1446 later. Then, we join it here */
1447 if( h->update_thread &&
1448 hb_thread_has_exited( h->update_thread ) )
1450 hb_thread_close( &h->update_thread );
1453 /* Check if the scan thread is done */
1454 if( h->scan_thread &&
1455 hb_thread_has_exited( h->scan_thread ) )
1457 hb_thread_close( &h->scan_thread );
1463 hb_remove_previews( h );
1464 while( ( title = hb_list_item( h->list_title, 0 ) ) )
1466 hb_list_rem( h->list_title, title );
1467 hb_title_close( &title );
1470 hb_log( "hb_scan: canceled" );
1474 hb_log( "libhb: scan thread found %d valid title(s)",
1475 hb_list_count( h->list_title ) );
1477 hb_lock( h->state_lock );
1478 h->state.state = HB_STATE_SCANDONE; //originally state.state
1479 hb_unlock( h->state_lock );
1480 /*we increment this sessions scan count by one for the MacGui
1481 to trigger a new source being set */
1485 /* Check if the work thread is done */
1486 if( h->work_thread &&
1487 hb_thread_has_exited( h->work_thread ) )
1489 hb_thread_close( &h->work_thread );
1491 hb_log( "libhb: work result = %d",
1493 hb_lock( h->state_lock );
1494 h->state.state = HB_STATE_WORKDONE;
1495 h->state.param.workdone.error = h->work_error;
1497 h->job_count = hb_count(h);
1498 if (h->job_count < 1)
1499 h->job_count_permanent = 0;
1500 hb_unlock( h->state_lock );
1506 if( h->scan_thread )
1509 hb_thread_close( &h->scan_thread );
1511 if( h->work_thread )
1514 hb_thread_close( &h->work_thread );
1516 hb_remove_previews( h );
1521 * @param h Handle to hb_handle_t
1523 int hb_get_pid( hb_handle_t * h )
1529 * Returns the id for the given instance.
1530 * @param h Handle to hb_handle_t
1532 int hb_get_instance_id( hb_handle_t * h )
1538 * Sets the current state.
1539 * @param h Handle to hb_handle_t
1540 * @param s Handle to new hb_state_t
1542 void hb_set_state( hb_handle_t * h, hb_state_t * s )
1544 hb_lock( h->pause_lock );
1545 hb_lock( h->state_lock );
1546 memcpy( &h->state, s, sizeof( hb_state_t ) );
1547 if( h->state.state == HB_STATE_WORKING ||
1548 h->state.state == HB_STATE_SEARCHING )
1551 if (h->job_count < 1)
1552 h->job_count_permanent = 1;
1554 h->state.param.working.job_cur =
1555 h->job_count_permanent - hb_list_count( h->jobs );
1556 h->state.param.working.job_count = h->job_count_permanent;
1558 // Set which job is being worked on
1560 h->state.param.working.sequence_id = h->current_job->sequence_id;
1562 h->state.param.working.sequence_id = 0;
1564 hb_unlock( h->state_lock );
1565 hb_unlock( h->pause_lock );
1568 /* Passes a pointer to persistent data */
1569 hb_interjob_t * hb_interjob_get( hb_handle_t * h )