8 #if defined( SYS_MINGW ) && defined( PTW32_STATIC_LIB )
16 /* The "Check for update" thread */
19 hb_thread_t * update_thread;
21 /* This thread's only purpose is to check other threads'
24 hb_thread_t * main_thread;
27 /* DVD/file scan thread */
28 hb_list_t * list_title;
29 hb_thread_t * scan_thread;
31 /* The thread which processes the jobs. Others threads are launched
32 from this one (see work.c) */
34 hb_job_t * current_job;
36 int job_count_permanent;
37 volatile int work_die;
39 hb_thread_t * work_thread;
43 hb_lock_t * state_lock;
47 hb_lock_t * pause_lock;
48 /* For MacGui active queue
49 increments each time the scan thread completes*/
51 volatile int scan_die;
53 /* Stash of persistent data between jobs, for stuff
54 like correcting frame count and framerate estimates
55 on multi-pass encodes where frames get dropped. */
56 hb_interjob_t * interjob;
60 hb_lock_t *hb_avcodec_lock;
61 hb_work_object_t * hb_objects = NULL;
62 int hb_instance_counter = 0;
63 int hb_process_initialized = 0;
65 static void thread_func( void * );
67 void hb_avcodec_init()
69 hb_avcodec_lock = hb_lock_init();
73 int hb_avcodec_open(AVCodecContext *avctx, AVCodec *codec)
76 hb_lock( hb_avcodec_lock );
77 ret = avcodec_open(avctx, codec);
78 hb_unlock( hb_avcodec_lock );
82 int hb_avcodec_close(AVCodecContext *avctx)
85 hb_lock( hb_avcodec_lock );
86 ret = avcodec_close(avctx);
87 hb_unlock( hb_avcodec_lock );
91 int hb_ff_layout_xlat(int64_t ff_channel_layout, int channels)
93 switch (ff_channel_layout)
96 return HB_INPUT_CH_LAYOUT_MONO;
97 case CH_LAYOUT_STEREO:
98 return HB_INPUT_CH_LAYOUT_STEREO;
99 case CH_LAYOUT_SURROUND:
100 return HB_INPUT_CH_LAYOUT_3F;
101 case CH_LAYOUT_4POINT0:
102 return HB_INPUT_CH_LAYOUT_3F1R;
104 return HB_INPUT_CH_LAYOUT_2F2R;
106 return HB_INPUT_CH_LAYOUT_2F2R;
107 case CH_LAYOUT_5POINT0:
108 // ffmpeg like to neglect to signal LFE
110 return HB_INPUT_CH_LAYOUT_3F2R|HB_INPUT_CH_LAYOUT_HAS_LFE;
111 return HB_INPUT_CH_LAYOUT_3F2R;
112 case CH_LAYOUT_5POINT1:
113 return HB_INPUT_CH_LAYOUT_3F2R|HB_INPUT_CH_LAYOUT_HAS_LFE;
114 case CH_LAYOUT_5POINT0_BACK:
115 // ffmpeg like to neglect to signal LFE
117 return HB_INPUT_CH_LAYOUT_3F2R|HB_INPUT_CH_LAYOUT_HAS_LFE;
118 return HB_INPUT_CH_LAYOUT_3F2R;
119 case CH_LAYOUT_5POINT1_BACK:
120 return HB_INPUT_CH_LAYOUT_3F2R|HB_INPUT_CH_LAYOUT_HAS_LFE;
121 case CH_LAYOUT_7POINT0:
122 // ffmpeg like to neglect to signal LFE
124 return HB_INPUT_CH_LAYOUT_3F4R|HB_INPUT_CH_LAYOUT_HAS_LFE;
125 return HB_INPUT_CH_LAYOUT_3F4R;
126 case CH_LAYOUT_7POINT1:
127 return HB_INPUT_CH_LAYOUT_3F4R|HB_INPUT_CH_LAYOUT_HAS_LFE;
128 case CH_LAYOUT_STEREO_DOWNMIX:
129 return HB_INPUT_CH_LAYOUT_STEREO;
131 return HB_INPUT_CH_LAYOUT_STEREO;
133 return HB_INPUT_CH_LAYOUT_STEREO;
137 * Registers work objects, by adding the work object to a liked list.
138 * @param w Handle to hb_work_object_t to register.
140 void hb_register( hb_work_object_t * w )
142 w->next = hb_objects;
147 * Ensures that the process has been initialized.
149 static void process_init()
151 if (!hb_process_initialized)
153 #if defined( SYS_MINGW ) && defined( PTW32_STATIC_LIB )
154 pthread_win32_process_attach_np();
157 #if defined( _WIN32 ) || defined( __MINGW32__ )
158 setvbuf( stdout, NULL, _IONBF, 0 );
159 setvbuf( stderr, NULL, _IONBF, 0 );
161 hb_process_initialized = 1;
166 void (*hb_log_callback)(const char* message);
167 static void redirect_thread_func(void *);
168 #define pipe(phandles) _pipe (phandles, 4096, _O_BINARY)
171 * Registers the given function as a logger. All logs will be passed to it.
172 * @param log_cb The function to register as a logger.
174 void hb_register_logger( void (*log_cb)(const char* message) )
178 hb_log_callback = log_cb;
179 hb_thread_init("ioredirect", redirect_thread_func, NULL, HB_NORMAL_PRIORITY);
183 * libhb initialization routine.
184 * @param verbose HB_DEBUG_NONE or HB_DEBUG_ALL.
185 * @param update_check signals libhb to check for updated version from HandBrake website.
186 * @return Handle to hb_handle_t for use on all subsequent calls to libhb.
188 hb_handle_t * hb_init( int verbose, int update_check )
192 hb_handle_t * h = calloc( sizeof( hb_handle_t ), 1 );
195 /* See hb_deep_log() and hb_log() in common.c */
196 global_verbosity_level = verbose;
198 putenv( "HB_DEBUG=1" );
200 h->id = hb_instance_counter++;
202 /* Check for an update on the website if asked to */
207 hb_log( "hb_init: checking for updates" );
208 date = hb_get_date();
209 h->update_thread = hb_update_init( &h->build, h->version );
213 if( hb_thread_has_exited( h->update_thread ) )
215 /* Immediate success or failure */
216 hb_thread_close( &h->update_thread );
219 if( hb_get_date() > date + 1000 )
221 /* Still nothing after one second. Connection problem,
222 let the thread die */
223 hb_log( "hb_init: connection problem, not waiting for "
232 * Initialise buffer pool
234 hb_buffer_pool_init();
236 /* CPU count detection */
237 hb_log( "hb_init: checking cpu count" );
238 h->cpu_count = hb_get_cpu_count();
240 h->list_title = hb_list_init();
241 h->jobs = hb_list_init();
243 h->state_lock = hb_lock_init();
244 h->state.state = HB_STATE_IDLE;
246 h->pause_lock = hb_lock_init();
248 h->interjob = calloc( sizeof( hb_interjob_t ), 1 );
253 /* Start library thread */
254 hb_log( "hb_init: starting libhb thread" );
256 h->main_thread = hb_thread_init( "libhb", thread_func, h,
257 HB_NORMAL_PRIORITY );
258 hb_register( &hb_sync_video );
259 hb_register( &hb_sync_audio );
260 hb_register( &hb_decmpeg2 );
261 hb_register( &hb_decvobsub );
262 hb_register( &hb_encvobsub );
263 hb_register( &hb_deccc608 );
264 hb_register( &hb_decsrtsub );
265 hb_register( &hb_render );
266 hb_register( &hb_encavcodec );
267 hb_register( &hb_encx264 );
268 hb_register( &hb_enctheora );
269 hb_register( &hb_deca52 );
270 hb_register( &hb_decdca );
271 hb_register( &hb_decavcodec );
272 hb_register( &hb_decavcodecv );
273 hb_register( &hb_decavcodecvi );
274 hb_register( &hb_decavcodecai );
275 hb_register( &hb_declpcm );
276 hb_register( &hb_encfaac );
277 hb_register( &hb_enclame );
278 hb_register( &hb_encvorbis );
279 hb_register( &hb_muxer );
281 hb_register( &hb_encca_aac );
288 * libhb initialization routine.
289 * This version is to use when calling the dylib, the macro hb_init isn't available from a dylib call!
290 * @param verbose HB_DEBUG_NONE or HB_DEBUG_ALL.
291 * @param update_check signals libhb to check for updated version from HandBrake website.
292 * @return Handle to hb_handle_t for use on all subsequent calls to libhb.
294 hb_handle_t * hb_init_dl( int verbose, int update_check )
296 hb_handle_t * h = calloc( sizeof( hb_handle_t ), 1 );
299 /* See hb_log() in common.c */
300 if( verbose > HB_DEBUG_NONE )
302 putenv( "HB_DEBUG=1" );
305 h->id = hb_instance_counter++;
307 /* Check for an update on the website if asked to */
312 hb_log( "hb_init: checking for updates" );
313 date = hb_get_date();
314 h->update_thread = hb_update_init( &h->build, h->version );
318 if( hb_thread_has_exited( h->update_thread ) )
320 /* Immediate success or failure */
321 hb_thread_close( &h->update_thread );
324 if( hb_get_date() > date + 1000 )
326 /* Still nothing after one second. Connection problem,
327 let the thread die */
328 hb_log( "hb_init: connection problem, not waiting for "
336 /* CPU count detection */
337 hb_log( "hb_init: checking cpu count" );
338 h->cpu_count = hb_get_cpu_count();
340 h->list_title = hb_list_init();
341 h->jobs = hb_list_init();
342 h->current_job = NULL;
344 h->state_lock = hb_lock_init();
345 h->state.state = HB_STATE_IDLE;
347 h->pause_lock = hb_lock_init();
351 avcodec_register_all();
353 /* Start library thread */
354 hb_log( "hb_init: starting libhb thread" );
356 h->main_thread = hb_thread_init( "libhb", thread_func, h,
357 HB_NORMAL_PRIORITY );
359 hb_register( &hb_sync_video );
360 hb_register( &hb_sync_audio );
361 hb_register( &hb_decmpeg2 );
362 hb_register( &hb_decvobsub );
363 hb_register( &hb_encvobsub );
364 hb_register( &hb_deccc608 );
365 hb_register( &hb_decsrtsub );
366 hb_register( &hb_render );
367 hb_register( &hb_encavcodec );
368 hb_register( &hb_encx264 );
369 hb_register( &hb_enctheora );
370 hb_register( &hb_deca52 );
371 hb_register( &hb_decdca );
372 hb_register( &hb_decavcodec );
373 hb_register( &hb_decavcodecv );
374 hb_register( &hb_decavcodecvi );
375 hb_register( &hb_decavcodecai );
376 hb_register( &hb_declpcm );
377 hb_register( &hb_encfaac );
378 hb_register( &hb_enclame );
379 hb_register( &hb_encvorbis );
380 hb_register( &hb_muxer );
382 hb_register( &hb_encca_aac );
390 * Returns current version of libhb.
391 * @param h Handle to hb_handle_t.
392 * @return character array of version number.
394 char * hb_get_version( hb_handle_t * h )
396 return HB_PROJECT_VERSION;
400 * Returns current build of libhb.
401 * @param h Handle to hb_handle_t.
402 * @return character array of build number.
404 int hb_get_build( hb_handle_t * h )
406 return HB_PROJECT_BUILD;
410 * Checks for needed update.
411 * @param h Handle to hb_handle_t.
412 * @param version Pointer to handle where version will be copied.
413 * @return update indicator.
415 int hb_check_update( hb_handle_t * h, char ** version )
417 *version = ( h->build < 0 ) ? NULL : h->version;
422 * Sets the cpu count to the desired value.
423 * @param h Handle to hb_handle_t
424 * @param cpu_count Number of CPUs to use.
426 void hb_set_cpu_count( hb_handle_t * h, int cpu_count )
428 cpu_count = MAX( 1, cpu_count );
429 cpu_count = MIN( cpu_count, 8 );
430 h->cpu_count = cpu_count;
434 * Deletes current previews associated with titles
435 * @param h Handle to hb_handle_t
437 void hb_remove_previews( hb_handle_t * h )
444 struct dirent * entry;
446 memset( dirname, 0, 1024 );
447 hb_get_temporary_directory( dirname );
448 dir = opendir( dirname );
449 if (dir == NULL) return;
451 count = hb_list_count( h->list_title );
452 while( ( entry = readdir( dir ) ) )
454 if( entry->d_name[0] == '.' )
458 for( i = 0; i < count; i++ )
460 title = hb_list_item( h->list_title, i );
461 len = snprintf( filename, 1024, "%d_%d", h->id, title->index );
462 if (strncmp(entry->d_name, filename, len) == 0)
464 snprintf( filename, 1024, "%s/%s", dirname, entry->d_name );
474 * Initializes a scan of the by calling hb_scan_init
475 * @param h Handle to hb_handle_t
476 * @param path location of VIDEO_TS folder.
477 * @param title_index Desired title to scan. 0 for all titles.
478 * @param preview_count Number of preview images to generate.
479 * @param store_previews Whether or not to write previews to disk.
481 void hb_scan( hb_handle_t * h, const char * path, int title_index,
482 int preview_count, int store_previews )
488 /* Clean up from previous scan */
489 hb_remove_previews( h );
490 while( ( title = hb_list_item( h->list_title, 0 ) ) )
492 hb_list_rem( h->list_title, title );
493 hb_title_close( &title );
496 hb_log( "hb_scan: path=%s, title_index=%d", path, title_index );
497 h->scan_thread = hb_scan_init( h, &h->scan_die, path, title_index,
498 h->list_title, preview_count,
503 * Returns the list of titles found.
504 * @param h Handle to hb_handle_t
505 * @return Handle to hb_list_t of the title list.
507 hb_list_t * hb_get_titles( hb_handle_t * h )
509 return h->list_title;
513 * Create preview image of desired title a index of picture.
514 * @param h Handle to hb_handle_t.
515 * @param title_index Index of the title to get the preview for (1-based).
516 * @param picture Index in title.
517 * @param buffer Handle to buffer were image will be drawn.
519 void hb_get_preview_by_index( hb_handle_t * h, int title_index, int picture, uint8_t * buffer )
523 title = hb_list_item( h->list_title, title_index - 1 );
526 hb_get_preview( h, title, picture, buffer );
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 buffer were image 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 h Instance handle
755 * @param title_index Index of the title/job to inspect (1-based).
756 * @param output_width Pointer to returned storage width
757 * @param output_height Pointer to returned storage height
758 * @param output_par_width Pointer to returned pixel width
759 * @param output_par_height Pointer to returned pixel height
761 void hb_set_anamorphic_size_by_index( hb_handle_t * h, int title_index,
762 int *output_width, int *output_height,
763 int *output_par_width, int *output_par_height )
766 title = hb_list_item( h->list_title, title_index - 1 );
768 hb_set_anamorphic_size( title->job, output_width, output_height, output_par_width, output_par_height );
772 * Calculates job width and height for anamorphic content,
774 * @param job Handle to hb_job_t
775 * @param output_width Pointer to returned storage width
776 * @param output_height Pointer to returned storage height
777 * @param output_par_width Pointer to returned pixel width
778 * @param output_par_height Pointer to returned pixel height
780 void hb_set_anamorphic_size( hb_job_t * job,
781 int *output_width, int *output_height,
782 int *output_par_width, int *output_par_height )
784 /* Set up some variables to make the math easier to follow. */
785 hb_title_t * title = job->title;
786 int cropped_width = title->width - job->crop[2] - job->crop[3] ;
787 int cropped_height = title->height - job->crop[0] - job->crop[1] ;
788 double storage_aspect = (double)cropped_width / (double)cropped_height;
789 int mod = job->modulus ? job->modulus : 16;
790 double aspect = title->aspect;
792 int pixel_aspect_width = job->anamorphic.par_width;
793 int pixel_aspect_height = job->anamorphic.par_height;
795 /* If a source was really NTSC or PAL and the user specified ITU PAR
796 values, replace the standard PAR values with the ITU broadcast ones. */
797 if( title->width == 720 && job->anamorphic.itu_par )
799 // convert aspect to a scaled integer so we can test for 16:9 & 4:3
800 // aspect ratios ignoring insignificant differences in the LSBs of
801 // the floating point representation.
802 int iaspect = aspect * 9.;
804 /* Handle ITU PARs */
805 if (title->height == 480)
810 /* It's widescreen */
811 pixel_aspect_width = 40;
812 pixel_aspect_height = 33;
814 else if (iaspect == 12)
817 pixel_aspect_width = 10;
818 pixel_aspect_height = 11;
821 else if (title->height == 576)
826 /* It's widescreen */
827 pixel_aspect_width = 16;
828 pixel_aspect_height = 11;
830 else if (iaspect == 12)
833 pixel_aspect_width = 12;
834 pixel_aspect_height = 11;
839 /* Figure out what width the source would display at. */
840 int source_display_width = cropped_width * (double)pixel_aspect_width /
841 (double)pixel_aspect_height ;
844 3 different ways of deciding output dimensions:
845 - 1: Strict anamorphic, preserve source dimensions
846 - 2: Loose anamorphic, round to mod16 and preserve storage aspect ratio
847 - 3: Power user anamorphic, specify everything
850 switch( job->anamorphic.mode )
853 /* Strict anamorphic */
854 *output_width = cropped_width;
855 *output_height = cropped_height;
856 *output_par_width = title->pixel_aspect_width;
857 *output_par_height = title->pixel_aspect_height;
861 /* "Loose" anamorphic.
862 - Uses mod16-compliant dimensions,
863 - Allows users to set the width
866 // height: Gets set later, ignore user job->height value
868 /* Gotta handle bounding dimensions.
869 If the width is too big, just reset it with no rescaling.
870 Instead of using the aspect-scaled job height,
871 we need to see if the job width divided by the storage aspect
872 is bigger than the max. If so, set it to the max (this is sloppy).
873 If not, set job height to job width divided by storage aspect.
876 if ( job->maxWidth && (job->maxWidth < job->width) )
877 width = job->maxWidth;
879 /* Time to get picture width that divide cleanly.*/
880 width = MULTIPLE_MOD( width, mod);
882 /* Verify these new dimensions don't violate max height and width settings */
883 if ( job->maxWidth && (job->maxWidth < job->width) )
884 width = job->maxWidth;
886 height = ((double)width / storage_aspect) + 0.5;
888 if ( job->maxHeight && (job->maxHeight < height) )
889 height = job->maxHeight;
891 /* Time to get picture height that divide cleanly.*/
892 height = MULTIPLE_MOD( height, mod);
894 /* Verify these new dimensions don't violate max height and width settings */
895 if ( job->maxHeight && (job->maxHeight < height) )
896 height = job->maxHeight;
898 /* The film AR is the source's display width / cropped source height.
899 The output display width is the output height * film AR.
900 The output PAR is the output display width / output storage width. */
901 pixel_aspect_width = height * source_display_width / cropped_height;
902 pixel_aspect_height = width;
904 /* Pass the results back to the caller */
905 *output_width = width;
906 *output_height = height;
910 /* Anamorphic 3: Power User Jamboree
911 - Set everything based on specified values */
913 /* Use specified storage dimensions */
915 height = job->height;
917 /* Bind to max dimensions */
918 if( job->maxWidth && width > job->maxWidth )
919 width = job->maxWidth;
920 if( job->maxHeight && height > job->maxHeight )
921 height = job->maxHeight;
923 /* Time to get picture dimensions that divide cleanly.*/
924 width = MULTIPLE_MOD( width, mod);
925 height = MULTIPLE_MOD( height, mod);
927 /* Verify we're still within max dimensions */
928 if( job->maxWidth && width > job->maxWidth )
929 width = job->maxWidth - (mod/2);
930 if( job->maxHeight && height > job->maxHeight )
931 height = job->maxHeight - (mod/2);
933 /* Re-ensure we have picture dimensions that divide cleanly. */
934 width = MULTIPLE_MOD( width, mod );
935 height = MULTIPLE_MOD( height, mod );
937 /* That finishes the storage dimensions. On to display. */
938 if( job->anamorphic.dar_width && job->anamorphic.dar_height )
940 /* We need to adjust the PAR to produce this aspect. */
941 pixel_aspect_width = height * job->anamorphic.dar_width / job->anamorphic.dar_height;
942 pixel_aspect_height = width;
946 /* If we're doing ana 3 and not specifying a DAR, care needs to be taken.
947 This indicates a PAR is potentially being set by the interface. But
948 this is an output PAR, to correct a source, and it should not be assumed
949 that it properly creates a display aspect ratio when applied to the source,
950 which could easily be stored in a different resolution. */
951 if( job->anamorphic.keep_display_aspect )
953 /* We can ignore the possibility of a PAR change */
954 pixel_aspect_width = height * ( (double)source_display_width / (double)cropped_height );
955 pixel_aspect_height = width;
959 int output_display_width = width * (double)pixel_aspect_width /
960 (double)pixel_aspect_height;
961 pixel_aspect_width = output_display_width;
962 pixel_aspect_height = width;
967 *output_width = width;
968 *output_height = height;
972 /* While x264 is smart enough to reduce fractions on its own, libavcodec
973 needs some help with the math, so lose superfluous factors. */
974 hb_reduce( output_par_width, output_par_height,
975 pixel_aspect_width, pixel_aspect_height );
979 * Calculates job width, height, and cropping parameters.
980 * @param job Handle to hb_job_t.
981 * @param aspect Desired aspect ratio. Value of -1 uses title aspect.
982 * @param pixels Maximum desired pixel count.
984 void hb_set_size( hb_job_t * job, double aspect, int pixels )
986 hb_title_t * title = job->title;
988 int croppedWidth = title->width - title->crop[2] - title->crop[3];
989 int croppedHeight = title->height - title->crop[0] - title->crop[1];
990 double croppedAspect = title->aspect * title->height * croppedWidth /
991 croppedHeight / title->width;
997 /* Keep the best possible aspect ratio */
998 aspect = croppedAspect;
1001 /* Crop if necessary to obtain the desired ratio */
1002 memcpy( job->crop, title->crop, 4 * sizeof( int ) );
1003 if( aspect < croppedAspect )
1005 /* Need to crop on the left and right */
1006 addCrop = croppedWidth - aspect * croppedHeight * title->width /
1007 title->aspect / title->height;
1010 addCrop = ( addCrop + 1 ) / 2;
1011 job->crop[2] += addCrop;
1012 job->crop[3] += addCrop;
1014 else if( addCrop & 2 )
1017 job->crop[2] += addCrop - 1;
1018 job->crop[3] += addCrop + 1;
1023 job->crop[2] += addCrop;
1024 job->crop[3] += addCrop;
1027 else if( aspect > croppedAspect )
1029 /* Need to crop on the top and bottom */
1030 addCrop = croppedHeight - croppedWidth * title->aspect *
1031 title->height / aspect / title->width;
1034 addCrop = ( addCrop + 1 ) / 2;
1035 job->crop[0] += addCrop;
1036 job->crop[1] += addCrop;
1038 else if( addCrop & 2 )
1041 job->crop[0] += addCrop - 1;
1042 job->crop[1] += addCrop + 1;
1047 job->crop[0] += addCrop;
1048 job->crop[1] += addCrop;
1052 /* Compute a resolution from the number of pixels and aspect */
1056 h = MULTIPLE_16( (int)( (double)w / aspect ) );
1057 if( w * h > pixels )
1063 job->width = 16 * i;
1064 job->height = MULTIPLE_16( (int)( (double)job->width / aspect ) );
1068 * Returns the number of jobs in the queue.
1069 * @param h Handle to hb_handle_t.
1070 * @return Number of jobs.
1072 int hb_count( hb_handle_t * h )
1074 return hb_list_count( h->jobs );
1078 * Returns handle to job at index i within the job list.
1079 * @param h Handle to hb_handle_t.
1080 * @param i Index of job.
1081 * @returns Handle to hb_job_t of desired job.
1083 hb_job_t * hb_job( hb_handle_t * h, int i )
1085 return hb_list_item( h->jobs, i );
1088 hb_job_t * hb_current_job( hb_handle_t * h )
1090 return( h->current_job );
1094 * Applies information from the given job to the official job instance.
1095 * @param h Handle to hb_handle_t.
1096 * @param title_index Index of the title to apply the chapter name to (1-based).
1097 * @param chapter The chapter to apply the name to (1-based).
1098 * @param job Job information to apply.
1100 void hb_set_chapter_name( hb_handle_t * h, int title_index, int chapter_index, const char * chapter_name )
1103 title = hb_list_item( h->list_title, title_index - 1 );
1105 hb_chapter_t * chapter = hb_list_item( title->list_chapter, chapter_index - 1 );
1107 strncpy(chapter->title, chapter_name, 1023);
1108 chapter->title[1023] = '\0';
1112 * Applies information from the given job to the official job instance.
1113 * Currently only applies information needed for anamorphic size calculation and previews.
1114 * @param h Handle to hb_handle_t.
1115 * @param title_index Index of the title to apply the job information to (1-based).
1116 * @param job Job information to apply.
1118 void hb_set_job( hb_handle_t * h, int title_index, hb_job_t * job )
1123 title = hb_list_item( h->list_title, title_index - 1 );
1125 hb_job_t * job_target = title->job;
1127 job_target->deinterlace = job->deinterlace;
1128 job_target->width = job->width;
1129 job_target->height = job->height;
1130 job_target->maxWidth = job->maxWidth;
1131 job_target->maxHeight = job->maxHeight;
1132 for (i = 0; i < 4; i++)
1134 job_target->crop[i] = job->crop[i];
1137 job_target->anamorphic = job->anamorphic;
1141 * Adds a job to the job list.
1142 * @param h Handle to hb_handle_t.
1143 * @param job Handle to hb_job_t.
1145 void hb_add( hb_handle_t * h, hb_job_t * job )
1147 hb_job_t * job_copy;
1148 hb_title_t * title, * title_copy;
1149 hb_chapter_t * chapter, * chapter_copy;
1151 hb_subtitle_t * subtitle, * subtitle_copy;
1155 /* Copy the title */
1157 title_copy = malloc( sizeof( hb_title_t ) );
1158 memcpy( title_copy, title, sizeof( hb_title_t ) );
1160 title_copy->list_chapter = hb_list_init();
1161 for( i = 0; i < hb_list_count( title->list_chapter ); i++ )
1163 chapter = hb_list_item( title->list_chapter, i );
1164 chapter_copy = malloc( sizeof( hb_chapter_t ) );
1165 memcpy( chapter_copy, chapter, sizeof( hb_chapter_t ) );
1166 hb_list_add( title_copy->list_chapter, chapter_copy );
1172 if( title->metadata )
1174 title_copy->metadata = malloc( sizeof( hb_metadata_t ) );
1176 if( title_copy->metadata )
1178 memcpy( title_copy->metadata, title->metadata, sizeof( hb_metadata_t ) );
1181 * Need to copy the artwork seperatly (TODO).
1183 if( title->metadata->coverart )
1185 title_copy->metadata->coverart = malloc( title->metadata->coverart_size );
1186 if( title_copy->metadata->coverart )
1188 memcpy( title_copy->metadata->coverart, title->metadata->coverart,
1189 title->metadata->coverart_size );
1191 title_copy->metadata->coverart_size = 0;
1197 /* Copy the audio track(s) we want */
1198 title_copy->list_audio = hb_list_init();
1200 for( i = 0; i < hb_list_count(job->list_audio); i++ )
1202 if( ( audio = hb_list_item( job->list_audio, i ) ) )
1204 hb_list_add( title_copy->list_audio, hb_audio_copy(audio) );
1208 title_copy->list_subtitle = hb_list_init();
1211 * The following code is confusing, there are two ways in which
1212 * we select subtitles and it depends on whether this is single or
1215 * subtitle_scan may be enabled, in which case the first pass
1216 * scans all subtitles of that language. The second pass does not
1217 * select any because they are set at the end of the first pass.
1219 * We may have manually selected a subtitle, in which case that is
1220 * selected in the first pass of a single pass, or the second of a
1223 memset( audio_lang, 0, sizeof( audio_lang ) );
1225 if ( job->indepth_scan ) {
1228 * Find the first audio language that is being encoded
1230 for( i = 0; i < hb_list_count(job->list_audio); i++ )
1232 if( ( audio = hb_list_item( job->list_audio, i ) ) )
1234 strncpy(audio_lang, audio->config.lang.iso639_2, sizeof(audio_lang));
1241 * If doing a subtitle scan then add all the matching subtitles for this
1244 if ( job->indepth_scan )
1246 for( i=0; i < hb_list_count( title->list_subtitle ); i++ )
1248 subtitle = hb_list_item( title->list_subtitle, i );
1249 if( strcmp( subtitle->iso639_2, audio_lang ) == 0 &&
1250 subtitle->source == VOBSUB )
1253 * Matched subtitle language with audio language, so
1254 * add this to our list to scan.
1256 * We will update the subtitle list on the second pass
1257 * later after the first pass has completed.
1259 subtitle_copy = malloc( sizeof( hb_subtitle_t ) );
1260 memcpy( subtitle_copy, subtitle, sizeof( hb_subtitle_t ) );
1261 hb_list_add( title_copy->list_subtitle, subtitle_copy );
1266 * Not doing a subtitle scan in this pass, but maybe we are in the
1269 if( job->pass != 1 )
1272 * Copy all of them from the input job, to the title_copy/job_copy.
1274 for( i = 0; i < hb_list_count(job->list_subtitle); i++ ) {
1275 if( ( subtitle = hb_list_item( job->list_subtitle, i ) ) )
1277 subtitle_copy = malloc( sizeof( hb_subtitle_t ) );
1278 memcpy( subtitle_copy, subtitle, sizeof( hb_subtitle_t ) );
1279 hb_list_add( title_copy->list_subtitle, subtitle_copy );
1286 job_copy = calloc( sizeof( hb_job_t ), 1 );
1287 memcpy( job_copy, job, sizeof( hb_job_t ) );
1288 title_copy->job = job_copy;
1289 job_copy->title = title_copy;
1290 job_copy->list_audio = title_copy->list_audio;
1291 job_copy->list_subtitle = title_copy->list_subtitle; // sharing list between title and job
1292 job_copy->file = strdup( job->file );
1294 job_copy->pause = h->pause_lock;
1296 /* Copy the job filter list */
1300 int filter_count = hb_list_count( job->filters );
1301 job_copy->filters = hb_list_init();
1302 for( i = 0; i < filter_count; i++ )
1305 * Copy the filters, since the MacGui reuses the global filter objects
1306 * meaning that queued up jobs overwrite the previous filter settings.
1307 * In reality, settings is probably the only field that needs duplicating
1308 * since it's the only value that is ever changed. But name is duplicated
1309 * as well for completeness. Not copying private_data since it gets
1310 * created for each job in renderInit.
1312 hb_filter_object_t * filter = hb_list_item( job->filters, i );
1313 hb_filter_object_t * filter_copy = malloc( sizeof( hb_filter_object_t ) );
1314 memcpy( filter_copy, filter, sizeof( hb_filter_object_t ) );
1316 filter_copy->name = strdup( filter->name );
1317 if( filter->settings )
1318 filter_copy->settings = strdup( filter->settings );
1319 hb_list_add( job_copy->filters, filter_copy );
1323 /* Add the job to the list */
1324 hb_list_add( h->jobs, job_copy );
1325 h->job_count = hb_count(h);
1326 h->job_count_permanent++;
1330 * Removes a job from the job list.
1331 * @param h Handle to hb_handle_t.
1332 * @param job Handle to hb_job_t.
1334 void hb_rem( hb_handle_t * h, hb_job_t * job )
1336 hb_list_rem( h->jobs, job );
1338 h->job_count = hb_count(h);
1339 if (h->job_count_permanent)
1340 h->job_count_permanent--;
1342 /* XXX free everything XXX */
1346 * Starts the conversion process.
1347 * Sets state to HB_STATE_WORKING.
1348 * calls hb_work_init, to launch work thread. Stores handle to work thread.
1349 * @param h Handle to hb_handle_t.
1351 void hb_start( hb_handle_t * h )
1354 h->job_count = hb_list_count( h->jobs );
1355 h->job_count_permanent = h->job_count;
1357 hb_lock( h->state_lock );
1358 h->state.state = HB_STATE_WORKING;
1359 #define p h->state.param.working
1362 p.job_count = h->job_count;
1370 hb_unlock( h->state_lock );
1375 h->work_thread = hb_work_init( h->jobs, h->cpu_count,
1376 &h->work_die, &h->work_error, &h->current_job );
1380 * Pauses the conversion process.
1381 * @param h Handle to hb_handle_t.
1383 void hb_pause( hb_handle_t * h )
1387 hb_lock( h->pause_lock );
1390 hb_current_job( h )->st_pause_date = hb_get_date();
1392 hb_lock( h->state_lock );
1393 h->state.state = HB_STATE_PAUSED;
1394 hb_unlock( h->state_lock );
1399 * Resumes the conversion process.
1400 * @param h Handle to hb_handle_t.
1402 void hb_resume( hb_handle_t * h )
1406 #define job hb_current_job( h )
1407 if( job->st_pause_date != -1 )
1409 job->st_paused += hb_get_date() - job->st_pause_date;
1413 hb_unlock( h->pause_lock );
1419 * Stops the conversion process.
1420 * @param h Handle to hb_handle_t.
1422 void hb_stop( hb_handle_t * h )
1426 h->job_count = hb_count(h);
1427 h->job_count_permanent = 0;
1433 * Stops the conversion process.
1434 * @param h Handle to hb_handle_t.
1436 void hb_scan_stop( hb_handle_t * h )
1440 h->job_count = hb_count(h);
1441 h->job_count_permanent = 0;
1447 * Gets a filter object with the given type and settings.
1448 * @param filter_id The type of filter to get.
1449 * @param settings The filter settings to use.
1450 * @returns The requested filter object.
1452 hb_filter_object_t * hb_get_filter_object(int filter_id, const char * settings)
1454 if (filter_id == HB_FILTER_ROTATE)
1456 hb_filter_rotate.settings = strdup(settings);
1457 return &hb_filter_rotate;
1460 if (filter_id == HB_FILTER_DETELECINE)
1462 hb_filter_detelecine.settings = strdup(settings);
1463 return &hb_filter_detelecine;
1466 if (filter_id == HB_FILTER_DECOMB)
1468 hb_filter_decomb.settings = strdup(settings);
1469 return &hb_filter_decomb;
1472 if (filter_id == HB_FILTER_DEINTERLACE)
1474 hb_filter_deinterlace.settings = strdup(settings);
1475 return &hb_filter_deinterlace;
1478 if (filter_id == HB_FILTER_DEBLOCK)
1480 hb_filter_deblock.settings = strdup(settings);
1481 return &hb_filter_deblock;
1484 if (filter_id == HB_FILTER_DENOISE)
1486 hb_filter_denoise.settings = strdup(settings);
1487 return &hb_filter_denoise;
1492 * Returns the state of the conversion process.
1493 * @param h Handle to hb_handle_t.
1494 * @param s Handle to hb_state_t which to copy the state data.
1496 void hb_get_state( hb_handle_t * h, hb_state_t * s )
1498 hb_lock( h->state_lock );
1500 memcpy( s, &h->state, sizeof( hb_state_t ) );
1501 if ( h->state.state == HB_STATE_SCANDONE || h->state.state == HB_STATE_WORKDONE )
1502 h->state.state = HB_STATE_IDLE;
1504 hb_unlock( h->state_lock );
1507 void hb_get_state2( hb_handle_t * h, hb_state_t * s )
1509 hb_lock( h->state_lock );
1511 memcpy( s, &h->state, sizeof( hb_state_t ) );
1513 hb_unlock( h->state_lock );
1517 * Called in MacGui in UpdateUI to check
1518 * for a new scan being completed to set a new source
1520 int hb_get_scancount( hb_handle_t * h)
1522 return h->scanCount;
1526 * Closes access to libhb by freeing the hb_handle_t handle ontained in hb_init.
1527 * @param _h Pointer to handle to hb_handle_t.
1529 void hb_close( hb_handle_t ** _h )
1531 hb_handle_t * h = *_h;
1536 hb_thread_close( &h->main_thread );
1538 while( ( title = hb_list_item( h->list_title, 0 ) ) )
1540 hb_list_rem( h->list_title, title );
1541 if( title->job && title->job->filters )
1543 hb_list_close( &title->job->filters );
1546 hb_title_close( &title );
1548 hb_list_close( &h->list_title );
1550 hb_list_close( &h->jobs );
1551 hb_lock_close( &h->state_lock );
1552 hb_lock_close( &h->pause_lock );
1559 * Cleans up libhb at a process level. Call before the app closes. Removes preview directory.
1561 void hb_global_close()
1565 struct dirent * entry;
1567 /* Find and remove temp folder */
1568 memset( dirname, 0, 1024 );
1569 hb_get_temporary_directory( dirname );
1571 dir = opendir( dirname );
1574 while( ( entry = readdir( dir ) ) )
1576 char filename[1024];
1577 if( entry->d_name[0] == '.' )
1581 memset( filename, 0, 1024 );
1582 snprintf( filename, 1023, "%s/%s", dirname, entry->d_name );
1591 * Monitors the state of the update, scan, and work threads.
1592 * Sets scan done state when scan thread exits.
1593 * Sets work done state when work thread exits.
1594 * @param _h Handle to hb_handle_t
1596 static void thread_func( void * _h )
1598 hb_handle_t * h = (hb_handle_t *) _h;
1603 /* Create folder for temporary files */
1604 memset( dirname, 0, 1024 );
1605 hb_get_temporary_directory( dirname );
1607 hb_mkdir( dirname );
1611 /* In case the check_update thread hangs, it'll die sooner or
1612 later. Then, we join it here */
1613 if( h->update_thread &&
1614 hb_thread_has_exited( h->update_thread ) )
1616 hb_thread_close( &h->update_thread );
1619 /* Check if the scan thread is done */
1620 if( h->scan_thread &&
1621 hb_thread_has_exited( h->scan_thread ) )
1623 hb_thread_close( &h->scan_thread );
1629 hb_remove_previews( h );
1630 while( ( title = hb_list_item( h->list_title, 0 ) ) )
1632 hb_list_rem( h->list_title, title );
1633 hb_title_close( &title );
1636 hb_log( "hb_scan: canceled" );
1640 hb_log( "libhb: scan thread found %d valid title(s)",
1641 hb_list_count( h->list_title ) );
1643 hb_lock( h->state_lock );
1644 h->state.state = HB_STATE_SCANDONE; //originally state.state
1645 hb_unlock( h->state_lock );
1646 /*we increment this sessions scan count by one for the MacGui
1647 to trigger a new source being set */
1651 /* Check if the work thread is done */
1652 if( h->work_thread &&
1653 hb_thread_has_exited( h->work_thread ) )
1655 hb_thread_close( &h->work_thread );
1657 hb_log( "libhb: work result = %d",
1659 hb_lock( h->state_lock );
1660 h->state.state = HB_STATE_WORKDONE;
1661 h->state.param.workdone.error = h->work_error;
1663 h->job_count = hb_count(h);
1664 if (h->job_count < 1)
1665 h->job_count_permanent = 0;
1666 hb_unlock( h->state_lock );
1672 if( h->scan_thread )
1675 hb_thread_close( &h->scan_thread );
1677 if( h->work_thread )
1680 hb_thread_close( &h->work_thread );
1682 hb_remove_previews( h );
1686 * Redirects stderr to the registered callback
1688 * @param _data Unused.
1690 static void redirect_thread_func(void * _data)
1694 stderr->_file = pfd[1];
1695 FILE * log_f = fdopen(pfd[0], "rb");
1697 char line_buffer[500];
1698 while(fgets(line_buffer, 500, log_f) != NULL)
1700 hb_log_callback(line_buffer);
1706 * @param h Handle to hb_handle_t
1708 int hb_get_pid( hb_handle_t * h )
1714 * Returns the id for the given instance.
1715 * @param h Handle to hb_handle_t
1716 * @returns The ID for the given instance
1718 int hb_get_instance_id( hb_handle_t * h )
1724 * Sets the current state.
1725 * @param h Handle to hb_handle_t
1726 * @param s Handle to new hb_state_t
1728 void hb_set_state( hb_handle_t * h, hb_state_t * s )
1730 hb_lock( h->pause_lock );
1731 hb_lock( h->state_lock );
1732 memcpy( &h->state, s, sizeof( hb_state_t ) );
1733 if( h->state.state == HB_STATE_WORKING ||
1734 h->state.state == HB_STATE_SEARCHING )
1737 if (h->job_count < 1)
1738 h->job_count_permanent = 1;
1740 h->state.param.working.job_cur =
1741 h->job_count_permanent - hb_list_count( h->jobs );
1742 h->state.param.working.job_count = h->job_count_permanent;
1744 // Set which job is being worked on
1746 h->state.param.working.sequence_id = h->current_job->sequence_id;
1748 h->state.param.working.sequence_id = 0;
1750 hb_unlock( h->state_lock );
1751 hb_unlock( h->pause_lock );
1754 /* Passes a pointer to persistent data */
1755 hb_interjob_t * hb_interjob_get( hb_handle_t * h )