6 /* The "Check for update" thread */
9 hb_thread_t * update_thread;
11 /* This thread's only purpose is to check other threads'
14 hb_thread_t * main_thread;
17 /* DVD/file scan thread */
18 hb_list_t * list_title;
19 hb_thread_t * scan_thread;
21 /* The thread which processes the jobs. Others threads are launched
22 from this one (see work.c) */
24 hb_job_t * current_job;
26 int job_count_permanent;
27 volatile int work_die;
29 hb_thread_t * work_thread;
33 hb_lock_t * state_lock;
37 hb_lock_t * pause_lock;
38 /* For MacGui active queue
39 increments each time the scan thread completes*/
41 volatile int scan_die;
43 /* Stash of persistent data between jobs, for stuff
44 like correcting frame count and framerate estimates
45 on multi-pass encodes where frames get dropped. */
46 hb_interjob_t * interjob;
50 hb_lock_t *hb_avcodec_lock;
51 hb_work_object_t * hb_objects = NULL;
52 hb_process_initialized = 0;
54 static void thread_func( void * );
62 void hb_avcodec_init()
64 hb_avcodec_lock = hb_lock_init();
68 int hb_avcodec_open(AVCodecContext *avctx, AVCodec *codec)
71 hb_lock( hb_avcodec_lock );
72 ret = avcodec_open(avctx, codec);
73 hb_unlock( hb_avcodec_lock );
77 int hb_avcodec_close(AVCodecContext *avctx)
80 hb_lock( hb_avcodec_lock );
81 ret = avcodec_close(avctx);
82 hb_unlock( hb_avcodec_lock );
87 * Registers work objects, by adding the work object to a liked list.
88 * @param w Handle to hb_work_object_t to register.
90 void hb_register( hb_work_object_t * w )
97 * libhb initialization routine.
98 * @param verbose HB_DEBUG_NONE or HB_DEBUG_ALL.
99 * @param update_check signals libhb to check for updated version from HandBrake website.
100 * @return Handle to hb_handle_t for use on all subsequent calls to libhb.
102 hb_handle_t * hb_init( int verbose, int update_check )
104 if (!hb_process_initialized)
107 #if defined( _WIN32 ) || defined( __MINGW32__ )
108 pthread_win32_process_attach_np();
111 hb_process_initialized =1;
114 hb_handle_t * h = calloc( sizeof( hb_handle_t ), 1 );
117 /* See hb_deep_log() and hb_log() in common.c */
118 global_verbosity_level = verbose;
120 putenv( "HB_DEBUG=1" );
122 /* Check for an update on the website if asked to */
127 hb_log( "hb_init: checking for updates" );
128 date = hb_get_date();
129 h->update_thread = hb_update_init( &h->build, h->version );
133 if( hb_thread_has_exited( h->update_thread ) )
135 /* Immediate success or failure */
136 hb_thread_close( &h->update_thread );
139 if( hb_get_date() > date + 1000 )
141 /* Still nothing after one second. Connection problem,
142 let the thread die */
143 hb_log( "hb_init: connection problem, not waiting for "
152 * Initialise buffer pool
154 hb_buffer_pool_init();
156 /* CPU count detection */
157 hb_log( "hb_init: checking cpu count" );
158 h->cpu_count = hb_get_cpu_count();
160 h->list_title = hb_list_init();
161 h->jobs = hb_list_init();
163 h->state_lock = hb_lock_init();
164 h->state.state = HB_STATE_IDLE;
166 h->pause_lock = hb_lock_init();
168 h->interjob = calloc( sizeof( hb_interjob_t ), 1 );
173 /* Start library thread */
174 hb_log( "hb_init: starting libhb thread" );
176 h->main_thread = hb_thread_init( "libhb", thread_func, h,
177 HB_NORMAL_PRIORITY );
178 hb_register( &hb_sync_video );
179 hb_register( &hb_sync_audio );
180 hb_register( &hb_decmpeg2 );
181 hb_register( &hb_decvobsub );
182 hb_register( &hb_encvobsub );
183 hb_register( &hb_deccc608 );
184 hb_register( &hb_decsrtsub );
185 hb_register( &hb_render );
186 hb_register( &hb_encavcodec );
187 hb_register( &hb_encx264 );
188 hb_register( &hb_enctheora );
189 hb_register( &hb_deca52 );
190 hb_register( &hb_decdca );
191 hb_register( &hb_decavcodec );
192 hb_register( &hb_decavcodecv );
193 hb_register( &hb_decavcodecvi );
194 hb_register( &hb_decavcodecai );
195 hb_register( &hb_declpcm );
196 hb_register( &hb_encfaac );
197 hb_register( &hb_enclame );
198 hb_register( &hb_encvorbis );
199 hb_register( &hb_muxer );
201 hb_register( &hb_encca_aac );
208 * libhb initialization routine.
209 * This version is to use when calling the dylib, the macro hb_init isn't available from a dylib call!
210 * @param verbose HB_DEBUG_NONE or HB_DEBUG_ALL.
211 * @param update_check signals libhb to check for updated version from HandBrake website.
212 * @return Handle to hb_handle_t for use on all subsequent calls to libhb.
214 hb_handle_t * hb_init_dl( int verbose, int update_check )
216 hb_handle_t * h = calloc( sizeof( hb_handle_t ), 1 );
219 /* See hb_log() in common.c */
220 if( verbose > HB_DEBUG_NONE )
222 putenv( "HB_DEBUG=1" );
225 /* Check for an update on the website if asked to */
230 hb_log( "hb_init: checking for updates" );
231 date = hb_get_date();
232 h->update_thread = hb_update_init( &h->build, h->version );
236 if( hb_thread_has_exited( h->update_thread ) )
238 /* Immediate success or failure */
239 hb_thread_close( &h->update_thread );
242 if( hb_get_date() > date + 1000 )
244 /* Still nothing after one second. Connection problem,
245 let the thread die */
246 hb_log( "hb_init: connection problem, not waiting for "
254 /* CPU count detection */
255 hb_log( "hb_init: checking cpu count" );
256 h->cpu_count = hb_get_cpu_count();
258 h->list_title = hb_list_init();
259 h->jobs = hb_list_init();
260 h->current_job = NULL;
262 h->state_lock = hb_lock_init();
263 h->state.state = HB_STATE_IDLE;
265 h->pause_lock = hb_lock_init();
269 avcodec_register_all();
271 /* Start library thread */
272 hb_log( "hb_init: starting libhb thread" );
274 h->main_thread = hb_thread_init( "libhb", thread_func, h,
275 HB_NORMAL_PRIORITY );
277 hb_register( &hb_sync_video );
278 hb_register( &hb_sync_audio );
279 hb_register( &hb_decmpeg2 );
280 hb_register( &hb_decvobsub );
281 hb_register( &hb_encvobsub );
282 hb_register( &hb_deccc608 );
283 hb_register( &hb_decsrtsub );
284 hb_register( &hb_render );
285 hb_register( &hb_encavcodec );
286 hb_register( &hb_encx264 );
287 hb_register( &hb_enctheora );
288 hb_register( &hb_deca52 );
289 hb_register( &hb_decdca );
290 hb_register( &hb_decavcodec );
291 hb_register( &hb_decavcodecv );
292 hb_register( &hb_decavcodecvi );
293 hb_register( &hb_decavcodecai );
294 hb_register( &hb_declpcm );
295 hb_register( &hb_encfaac );
296 hb_register( &hb_enclame );
297 hb_register( &hb_encvorbis );
298 hb_register( &hb_muxer );
300 hb_register( &hb_encca_aac );
308 * Returns current version of libhb.
309 * @param h Handle to hb_handle_t.
310 * @return character array of version number.
312 char * hb_get_version( hb_handle_t * h )
314 return HB_PROJECT_VERSION;
318 * Returns current build of libhb.
319 * @param h Handle to hb_handle_t.
320 * @return character array of build number.
322 int hb_get_build( hb_handle_t * h )
324 return HB_PROJECT_BUILD;
328 * Checks for needed update.
329 * @param h Handle to hb_handle_t.
330 * @param version Pointer to handle where version will be copied.
331 * @return update indicator.
333 int hb_check_update( hb_handle_t * h, char ** version )
335 *version = ( h->build < 0 ) ? NULL : h->version;
340 * Sets the cpu count to the desired value.
341 * @param h Handle to hb_handle_t
342 * @param cpu_count Number of CPUs to use.
344 void hb_set_cpu_count( hb_handle_t * h, int cpu_count )
346 cpu_count = MAX( 1, cpu_count );
347 cpu_count = MIN( cpu_count, 8 );
348 h->cpu_count = cpu_count;
352 * Deletes current previews associated with titles
353 * @param h Handle to hb_handle_t
355 void hb_remove_previews( hb_handle_t * h )
362 struct dirent * entry;
364 memset( dirname, 0, 1024 );
365 hb_get_tempory_directory( h, dirname );
366 dir = opendir( dirname );
367 if (dir == NULL) return;
369 count = hb_list_count( h->list_title );
370 while( ( entry = readdir( dir ) ) )
372 if( entry->d_name[0] == '.' )
376 for( i = 0; i < count; i++ )
378 title = hb_list_item( h->list_title, i );
379 len = snprintf( filename, 1024, "%" PRIxPTR, (intptr_t) title );
380 if (strncmp(entry->d_name, filename, len) == 0)
382 snprintf( filename, 1024, "%s/%s", dirname, entry->d_name );
392 * Initializes a scan of the by calling hb_scan_init
393 * @param h Handle to hb_handle_t
394 * @param path location of VIDEO_TS folder.
395 * @param title_index Desired title to scan. 0 for all titles.
396 * @param preview_count Number of preview images to generate.
397 * @param store_previews Whether or not to write previews to disk.
399 void hb_scan( hb_handle_t * h, const char * path, int title_index,
400 int preview_count, int store_previews )
406 /* Clean up from previous scan */
407 hb_remove_previews( h );
408 while( ( title = hb_list_item( h->list_title, 0 ) ) )
410 hb_list_rem( h->list_title, title );
411 hb_title_close( &title );
414 hb_log( "hb_scan: path=%s, title_index=%d", path, title_index );
415 h->scan_thread = hb_scan_init( h, &h->scan_die, path, title_index,
416 h->list_title, preview_count,
421 * Returns the list of titles found.
422 * @param h Handle to hb_handle_t
423 * @return Handle to hb_list_t of the title list.
425 hb_list_t * hb_get_titles( hb_handle_t * h )
427 return h->list_title;
431 * Create preview image of desired title a index of picture.
432 * @param h Handle to hb_handle_t.
433 * @param title Handle to hb_title_t of desired title.
434 * @param picture Index in title.
435 * @param buffer Handle to buufer were inage will be drawn.
437 void hb_get_preview( hb_handle_t * h, hb_title_t * title, int picture,
440 hb_job_t * job = title->job;
443 uint8_t * buf1, * buf2, * buf3, * buf4, * pen;
445 AVPicture pic_in, pic_preview, pic_deint, pic_crop, pic_scale;
446 struct SwsContext * context;
448 int rgb_width = ((job->width + 7) >> 3) << 3;
451 swsflags = SWS_LANCZOS | SWS_ACCURATE_RND;
453 buf1 = av_malloc( avpicture_get_size( PIX_FMT_YUV420P, title->width, title->height ) );
454 buf2 = av_malloc( avpicture_get_size( PIX_FMT_YUV420P, title->width, title->height ) );
455 buf3 = av_malloc( avpicture_get_size( PIX_FMT_YUV420P, rgb_width, job->height ) );
456 buf4 = av_malloc( avpicture_get_size( PIX_FMT_RGB32, rgb_width, job->height ) );
457 avpicture_fill( &pic_in, buf1, PIX_FMT_YUV420P,
458 title->width, title->height );
459 avpicture_fill( &pic_deint, buf2, PIX_FMT_YUV420P,
460 title->width, title->height );
461 avpicture_fill( &pic_scale, buf3, PIX_FMT_YUV420P,
462 rgb_width, job->height );
463 avpicture_fill( &pic_preview, buf4, PIX_FMT_RGB32,
464 rgb_width, job->height );
466 // Allocate the AVPicture frames and fill in
468 memset( filename, 0, 1024 );
470 hb_get_tempory_filename( h, filename, "%" PRIxPTR "%d",
471 (intptr_t) title, picture );
473 file = fopen( filename, "rb" );
476 hb_log( "hb_get_preview: fopen failed" );
480 fread( buf1, avpicture_get_size( PIX_FMT_YUV420P, title->width, title->height), 1, file );
483 if( job->deinterlace )
485 // Deinterlace and crop
486 avpicture_deinterlace( &pic_deint, &pic_in, PIX_FMT_YUV420P, title->width, title->height );
487 av_picture_crop( &pic_crop, &pic_deint, PIX_FMT_YUV420P, job->crop[0], job->crop[2] );
492 av_picture_crop( &pic_crop, &pic_in, PIX_FMT_YUV420P, job->crop[0], job->crop[2] );
495 // Get scaling context
496 context = sws_getContext(title->width - (job->crop[2] + job->crop[3]),
497 title->height - (job->crop[0] + job->crop[1]),
499 job->width, job->height, PIX_FMT_YUV420P,
500 swsflags, NULL, NULL, NULL);
504 pic_crop.data, pic_crop.linesize,
505 0, title->height - (job->crop[0] + job->crop[1]),
506 pic_scale.data, pic_scale.linesize);
509 sws_freeContext( context );
511 // Get preview context
512 context = sws_getContext(rgb_width, job->height, PIX_FMT_YUV420P,
513 rgb_width, job->height, PIX_FMT_RGB32,
514 swsflags, NULL, NULL, NULL);
518 pic_scale.data, pic_scale.linesize,
520 pic_preview.data, pic_preview.linesize);
523 sws_freeContext( context );
525 preview_size = pic_preview.linesize[0];
527 for( i = 0; i < job->height; i++ )
529 memcpy( pen, buf4 + preview_size * i, 4 * job->width );
530 pen += 4 * job->width;
534 avpicture_free( &pic_preview );
535 avpicture_free( &pic_scale );
536 avpicture_free( &pic_deint );
537 avpicture_free( &pic_in );
541 * Analyzes a frame to detect interlacing artifacts
542 * and returns true if interlacing (combing) is found.
544 * Code taken from Thomas Oestreich's 32detect filter
545 * in the Transcode project, with minor formatting changes.
547 * @param buf An hb_buffer structure holding valid frame data
548 * @param width The frame's width in pixels
549 * @param height The frame's height in pixels
550 * @param color_equal Sensitivity for detecting similar colors
551 * @param color_diff Sensitivity for detecting different colors
552 * @param threshold Sensitivity for flagging planes as combed
553 * @param prog_equal Sensitivity for detecting similar colors on progressive frames
554 * @param prog_diff Sensitivity for detecting different colors on progressive frames
555 * @param prog_threshold Sensitivity for flagging progressive frames as combed
557 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 )
559 int j, k, n, off, cc_1, cc_2, cc[3];
560 // int flag[3] ; // debugging flag
561 uint16_t s1, s2, s3, s4;
566 if ( buf->flags & 16 )
568 /* Frame is progressive, be more discerning. */
569 color_diff = prog_diff;
570 color_equal = prog_equal;
571 threshold = prog_threshold;
574 /* One pas for Y, one pass for Cb, one pass for Cr */
575 for( k = 0; k < 3; k++ )
579 /* Y has already been checked, now offset by Y's dimensions
580 and divide all the other values by 2, since Cr and Cb
581 are half-size compared to Y. */
582 offset = width * height;
588 /* Y and Cb are done, so the offset needs to be bumped
589 so it's width*height + (width / 2) * (height / 2) */
593 for( j = 0; j < width; ++j )
597 for( n = 0; n < ( height - 4 ); n = n + 2 )
599 /* Look at groups of 4 sequential horizontal lines */
600 s1 = ( ( buf->data + offset )[ off + j ] & 0xff );
601 s2 = ( ( buf->data + offset )[ off + j + width ] & 0xff );
602 s3 = ( ( buf->data + offset )[ off + j + 2 * width ] & 0xff );
603 s4 = ( ( buf->data + offset )[ off + j + 3 * width ] & 0xff );
605 /* Note if the 1st and 2nd lines are more different in
606 color than the 1st and 3rd lines are similar in color.*/
607 if ( ( abs( s1 - s3 ) < color_equal ) &&
608 ( abs( s1 - s2 ) > color_diff ) )
611 /* Note if the 2nd and 3rd lines are more different in
612 color than the 2nd and 4th lines are similar in color.*/
613 if ( ( abs( s2 - s4 ) < color_equal ) &&
614 ( abs( s2 - s3 ) > color_diff) )
617 /* Now move down 2 horizontal lines before starting over.*/
623 /* The final cc score for a plane is the percentage of combed pixels it contains.
624 Because sensitivity goes down to hundreths of a percent, multiply by 1000
625 so it will be easy to compare against the threhold value which is an integer. */
626 cc[k] = (int)( ( cc_1 + cc_2 ) * 1000.0 / ( width * height ) );
630 /* HandBrake is all yuv420, so weight the average percentage of all 3 planes accordingly.*/
631 int average_cc = ( 2 * cc[0] + ( cc[1] / 2 ) + ( cc[2] / 2 ) ) / 3;
633 /* Now see if that average percentage of combed pixels surpasses the threshold percentage given by the user.*/
634 if( average_cc > threshold )
637 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" );
643 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" );
646 /* Reaching this point means no combing detected. */
652 * Calculates job width and height for anamorphic content,
654 * @param job Handle to hb_job_t
655 * @param output_width Pointer to returned storage width
656 * @param output_height Pointer to returned storage height
657 * @param output_par_width Pointer to returned pixel width
658 @ param output_par_height Pointer to returned pixel height
660 void hb_set_anamorphic_size( hb_job_t * job,
661 int *output_width, int *output_height,
662 int *output_par_width, int *output_par_height )
664 /* Set up some variables to make the math easier to follow. */
665 hb_title_t * title = job->title;
666 int cropped_width = title->width - job->crop[2] - job->crop[3] ;
667 int cropped_height = title->height - job->crop[0] - job->crop[1] ;
668 double storage_aspect = (double)cropped_width / (double)cropped_height;
669 int mod = job->anamorphic.modulus ? job->anamorphic.modulus : 16;
670 double aspect = title->aspect;
672 int pixel_aspect_width = job->anamorphic.par_width;
673 int pixel_aspect_height = job->anamorphic.par_height;
675 /* If a source was really NTSC or PAL and the user specified ITU PAR
676 values, replace the standard PAR values with the ITU broadcast ones. */
677 if( title->width == 720 && job->anamorphic.itu_par )
679 // convert aspect to a scaled integer so we can test for 16:9 & 4:3
680 // aspect ratios ignoring insignificant differences in the LSBs of
681 // the floating point representation.
682 int iaspect = aspect * 9.;
684 /* Handle ITU PARs */
685 if (title->height == 480)
690 /* It's widescreen */
691 pixel_aspect_width = 40;
692 pixel_aspect_height = 33;
694 else if (iaspect == 12)
697 pixel_aspect_width = 10;
698 pixel_aspect_height = 11;
701 else if (title->height == 576)
706 /* It's widescreen */
707 pixel_aspect_width = 16;
708 pixel_aspect_height = 11;
710 else if (iaspect == 12)
713 pixel_aspect_width = 12;
714 pixel_aspect_height = 11;
719 /* Figure out what width the source would display at. */
720 int source_display_width = cropped_width * (double)pixel_aspect_width /
721 (double)pixel_aspect_height ;
724 3 different ways of deciding output dimensions:
725 - 1: Strict anamorphic, preserve source dimensions
726 - 2: Loose anamorphic, round to mod16 and preserve storage aspect ratio
727 - 3: Power user anamorphic, specify everything
730 switch( job->anamorphic.mode )
733 /* Strict anamorphic */
734 *output_width = cropped_width;
735 *output_height = cropped_height;
736 *output_par_width = title->pixel_aspect_width;
737 *output_par_height = title->pixel_aspect_height;
741 /* "Loose" anamorphic.
742 - Uses mod16-compliant dimensions,
743 - Allows users to set the width
746 // height: Gets set later, ignore user job->height value
748 /* Gotta handle bounding dimensions.
749 If the width is too big, just reset it with no rescaling.
750 Instead of using the aspect-scaled job height,
751 we need to see if the job width divided by the storage aspect
752 is bigger than the max. If so, set it to the max (this is sloppy).
753 If not, set job height to job width divided by storage aspect.
756 if ( job->maxWidth && (job->maxWidth < job->width) )
757 width = job->maxWidth;
759 /* Time to get picture width that divide cleanly.*/
760 width = MULTIPLE_MOD( width, mod);
762 /* Verify these new dimensions don't violate max height and width settings */
763 if ( job->maxWidth && (job->maxWidth < job->width) )
764 width = job->maxWidth;
766 height = ((double)width / storage_aspect) + 0.5;
768 if ( job->maxHeight && (job->maxHeight < height) )
769 height = job->maxHeight;
771 /* Time to get picture height that divide cleanly.*/
772 height = MULTIPLE_MOD( height, mod);
774 /* Verify these new dimensions don't violate max height and width settings */
775 if ( job->maxHeight && (job->maxHeight < height) )
776 height = job->maxHeight;
778 /* The film AR is the source's display width / cropped source height.
779 The output display width is the output height * film AR.
780 The output PAR is the output display width / output storage width. */
781 pixel_aspect_width = height * source_display_width / cropped_height;
782 pixel_aspect_height = width;
784 /* Pass the results back to the caller */
785 *output_width = width;
786 *output_height = height;
790 /* Anamorphic 3: Power User Jamboree
791 - Set everything based on specified values */
793 /* Use specified storage dimensions */
795 height = job->height;
797 /* Bind to max dimensions */
798 if( job->maxWidth && width > job->maxWidth )
799 width = job->maxWidth;
800 if( job->maxHeight && height > job->maxHeight )
801 height = job->maxHeight;
803 /* Time to get picture dimensions that divide cleanly.*/
804 width = MULTIPLE_MOD( width, mod);
805 height = MULTIPLE_MOD( height, mod);
807 /* Verify we're still within max dimensions */
808 if( job->maxWidth && width > job->maxWidth )
809 width = job->maxWidth - (mod/2);
810 if( job->maxHeight && height > job->maxHeight )
811 height = job->maxHeight - (mod/2);
813 /* Re-ensure we have picture dimensions that divide cleanly. */
814 width = MULTIPLE_MOD( width, mod );
815 height = MULTIPLE_MOD( height, mod );
817 /* That finishes the storage dimensions. On to display. */
818 if( job->anamorphic.dar_width && job->anamorphic.dar_height )
820 /* We need to adjust the PAR to produce this aspect. */
821 pixel_aspect_width = height * job->anamorphic.dar_width / job->anamorphic.dar_height;
822 pixel_aspect_height = width;
826 /* If we're doing ana 3 and not specifying a DAR, care needs to be taken.
827 This indicates a PAR is potentially being set by the interface. But
828 this is an output PAR, to correct a source, and it should not be assumed
829 that it properly creates a display aspect ratio when applied to the source,
830 which could easily be stored in a different resolution. */
831 if( job->anamorphic.keep_display_aspect )
833 /* We can ignore the possibility of a PAR change */
834 pixel_aspect_width = height * ( (double)source_display_width / (double)cropped_height );
835 pixel_aspect_height = width;
839 int output_display_width = width * (double)pixel_aspect_width /
840 (double)pixel_aspect_height;
841 pixel_aspect_width = output_display_width;
842 pixel_aspect_height = width;
847 *output_width = width;
848 *output_height = height;
852 /* While x264 is smart enough to reduce fractions on its own, libavcodec
853 needs some help with the math, so lose superfluous factors. */
854 hb_reduce( output_par_width, output_par_height,
855 pixel_aspect_width, pixel_aspect_height );
859 * Calculates job width, height, and cropping parameters.
860 * @param job Handle to hb_job_t.
861 * @param aspect Desired aspect ratio. Value of -1 uses title aspect.
862 * @param pixels Maximum desired pixel count.
864 void hb_set_size( hb_job_t * job, double aspect, int pixels )
866 hb_title_t * title = job->title;
868 int croppedWidth = title->width - title->crop[2] - title->crop[3];
869 int croppedHeight = title->height - title->crop[0] - title->crop[1];
870 double croppedAspect = title->aspect * title->height * croppedWidth /
871 croppedHeight / title->width;
877 /* Keep the best possible aspect ratio */
878 aspect = croppedAspect;
881 /* Crop if necessary to obtain the desired ratio */
882 memcpy( job->crop, title->crop, 4 * sizeof( int ) );
883 if( aspect < croppedAspect )
885 /* Need to crop on the left and right */
886 addCrop = croppedWidth - aspect * croppedHeight * title->width /
887 title->aspect / title->height;
890 addCrop = ( addCrop + 1 ) / 2;
891 job->crop[2] += addCrop;
892 job->crop[3] += addCrop;
894 else if( addCrop & 2 )
897 job->crop[2] += addCrop - 1;
898 job->crop[3] += addCrop + 1;
903 job->crop[2] += addCrop;
904 job->crop[3] += addCrop;
907 else if( aspect > croppedAspect )
909 /* Need to crop on the top and bottom */
910 addCrop = croppedHeight - croppedWidth * title->aspect *
911 title->height / aspect / title->width;
914 addCrop = ( addCrop + 1 ) / 2;
915 job->crop[0] += addCrop;
916 job->crop[1] += addCrop;
918 else if( addCrop & 2 )
921 job->crop[0] += addCrop - 1;
922 job->crop[1] += addCrop + 1;
927 job->crop[0] += addCrop;
928 job->crop[1] += addCrop;
932 /* Compute a resolution from the number of pixels and aspect */
936 h = MULTIPLE_16( (int)( (double)w / aspect ) );
944 job->height = MULTIPLE_16( (int)( (double)job->width / aspect ) );
948 * Returns the number of jobs in the queue.
949 * @param h Handle to hb_handle_t.
950 * @return Number of jobs.
952 int hb_count( hb_handle_t * h )
954 return hb_list_count( h->jobs );
958 * Returns handle to job at index i within the job list.
959 * @param h Handle to hb_handle_t.
960 * @param i Index of job.
961 * @returns Handle to hb_job_t of desired job.
963 hb_job_t * hb_job( hb_handle_t * h, int i )
965 return hb_list_item( h->jobs, i );
968 hb_job_t * hb_current_job( hb_handle_t * h )
970 return( h->current_job );
974 * Adds a job to the job list.
975 * @param h Handle to hb_handle_t.
976 * @param job Handle to hb_job_t.
978 void hb_add( hb_handle_t * h, hb_job_t * job )
981 hb_title_t * title, * title_copy;
982 hb_chapter_t * chapter, * chapter_copy;
984 hb_subtitle_t * subtitle, * subtitle_copy;
990 title_copy = malloc( sizeof( hb_title_t ) );
991 memcpy( title_copy, title, sizeof( hb_title_t ) );
993 title_copy->list_chapter = hb_list_init();
994 for( i = 0; i < hb_list_count( title->list_chapter ); i++ )
996 chapter = hb_list_item( title->list_chapter, i );
997 chapter_copy = malloc( sizeof( hb_chapter_t ) );
998 memcpy( chapter_copy, chapter, sizeof( hb_chapter_t ) );
999 hb_list_add( title_copy->list_chapter, chapter_copy );
1005 if( title->metadata )
1007 title_copy->metadata = malloc( sizeof( hb_metadata_t ) );
1009 if( title_copy->metadata )
1011 memcpy( title_copy->metadata, title->metadata, sizeof( hb_metadata_t ) );
1014 * Need to copy the artwork seperatly (TODO).
1016 if( title->metadata->coverart )
1018 title_copy->metadata->coverart = malloc( title->metadata->coverart_size );
1019 if( title_copy->metadata->coverart )
1021 memcpy( title_copy->metadata->coverart, title->metadata->coverart,
1022 title->metadata->coverart_size );
1024 title_copy->metadata->coverart_size = 0;
1030 /* Copy the audio track(s) we want */
1031 title_copy->list_audio = hb_list_init();
1033 for( i = 0; i < hb_list_count(job->list_audio); i++ )
1035 if( ( audio = hb_list_item( job->list_audio, i ) ) )
1037 hb_list_add( title_copy->list_audio, hb_audio_copy(audio) );
1041 title_copy->list_subtitle = hb_list_init();
1044 * The following code is confusing, there are two ways in which
1045 * we select subtitles and it depends on whether this is single or
1048 * subtitle_scan may be enabled, in which case the first pass
1049 * scans all subtitles of that language. The second pass does not
1050 * select any because they are set at the end of the first pass.
1052 * We may have manually selected a subtitle, in which case that is
1053 * selected in the first pass of a single pass, or the second of a
1056 memset( audio_lang, 0, sizeof( audio_lang ) );
1058 if ( job->indepth_scan ) {
1061 * Find the first audio language that is being encoded
1063 for( i = 0; i < hb_list_count(job->list_audio); i++ )
1065 if( ( audio = hb_list_item( job->list_audio, i ) ) )
1067 strncpy(audio_lang, audio->config.lang.iso639_2, sizeof(audio_lang));
1074 * If doing a subtitle scan then add all the matching subtitles for this
1077 if ( job->indepth_scan )
1079 for( i=0; i < hb_list_count( title->list_subtitle ); i++ )
1081 subtitle = hb_list_item( title->list_subtitle, i );
1082 if( strcmp( subtitle->iso639_2, audio_lang ) == 0 &&
1083 subtitle->source == VOBSUB )
1086 * Matched subtitle language with audio language, so
1087 * add this to our list to scan.
1089 * We will update the subtitle list on the second pass
1090 * later after the first pass has completed.
1092 subtitle_copy = malloc( sizeof( hb_subtitle_t ) );
1093 memcpy( subtitle_copy, subtitle, sizeof( hb_subtitle_t ) );
1094 hb_list_add( title_copy->list_subtitle, subtitle_copy );
1099 * Not doing a subtitle scan in this pass, but maybe we are in the
1102 if( job->pass != 1 )
1105 * Copy all of them from the input job, to the title_copy/job_copy.
1107 for( i = 0; i < hb_list_count(job->list_subtitle); i++ ) {
1108 if( ( subtitle = hb_list_item( job->list_subtitle, i ) ) )
1110 subtitle_copy = malloc( sizeof( hb_subtitle_t ) );
1111 memcpy( subtitle_copy, subtitle, sizeof( hb_subtitle_t ) );
1112 hb_list_add( title_copy->list_subtitle, subtitle_copy );
1119 job_copy = calloc( sizeof( hb_job_t ), 1 );
1120 memcpy( job_copy, job, sizeof( hb_job_t ) );
1121 title_copy->job = job_copy;
1122 job_copy->title = title_copy;
1123 job_copy->list_audio = title_copy->list_audio;
1124 job_copy->list_subtitle = title_copy->list_subtitle; // sharing list between title and job
1125 job_copy->file = strdup( job->file );
1127 job_copy->pause = h->pause_lock;
1129 /* Copy the job filter list */
1133 int filter_count = hb_list_count( job->filters );
1134 job_copy->filters = hb_list_init();
1135 for( i = 0; i < filter_count; i++ )
1138 * Copy the filters, since the MacGui reuses the global filter objects
1139 * meaning that queued up jobs overwrite the previous filter settings.
1140 * In reality, settings is probably the only field that needs duplicating
1141 * since it's the only value that is ever changed. But name is duplicated
1142 * as well for completeness. Not copying private_data since it gets
1143 * created for each job in renderInit.
1145 hb_filter_object_t * filter = hb_list_item( job->filters, i );
1146 hb_filter_object_t * filter_copy = malloc( sizeof( hb_filter_object_t ) );
1147 memcpy( filter_copy, filter, sizeof( hb_filter_object_t ) );
1149 filter_copy->name = strdup( filter->name );
1150 if( filter->settings )
1151 filter_copy->settings = strdup( filter->settings );
1152 hb_list_add( job_copy->filters, filter_copy );
1156 /* Add the job to the list */
1157 hb_list_add( h->jobs, job_copy );
1158 h->job_count = hb_count(h);
1159 h->job_count_permanent++;
1163 * Removes a job from the job list.
1164 * @param h Handle to hb_handle_t.
1165 * @param job Handle to hb_job_t.
1167 void hb_rem( hb_handle_t * h, hb_job_t * job )
1169 hb_list_rem( h->jobs, job );
1171 h->job_count = hb_count(h);
1172 if (h->job_count_permanent)
1173 h->job_count_permanent--;
1175 /* XXX free everything XXX */
1179 * Starts the conversion process.
1180 * Sets state to HB_STATE_WORKING.
1181 * calls hb_work_init, to launch work thread. Stores handle to work thread.
1182 * @param h Handle to hb_handle_t.
1184 void hb_start( hb_handle_t * h )
1187 h->job_count = hb_list_count( h->jobs );
1188 h->job_count_permanent = h->job_count;
1190 hb_lock( h->state_lock );
1191 h->state.state = HB_STATE_WORKING;
1192 #define p h->state.param.working
1195 p.job_count = h->job_count;
1203 hb_unlock( h->state_lock );
1208 h->work_thread = hb_work_init( h->jobs, h->cpu_count,
1209 &h->work_die, &h->work_error, &h->current_job );
1213 * Pauses the conversion process.
1214 * @param h Handle to hb_handle_t.
1216 void hb_pause( hb_handle_t * h )
1220 hb_lock( h->pause_lock );
1223 hb_current_job( h )->st_pause_date = hb_get_date();
1225 hb_lock( h->state_lock );
1226 h->state.state = HB_STATE_PAUSED;
1227 hb_unlock( h->state_lock );
1232 * Resumes the conversion process.
1233 * @param h Handle to hb_handle_t.
1235 void hb_resume( hb_handle_t * h )
1239 #define job hb_current_job( h )
1240 if( job->st_pause_date != -1 )
1242 job->st_paused += hb_get_date() - job->st_pause_date;
1246 hb_unlock( h->pause_lock );
1252 * Stops the conversion process.
1253 * @param h Handle to hb_handle_t.
1255 void hb_stop( hb_handle_t * h )
1259 h->job_count = hb_count(h);
1260 h->job_count_permanent = 0;
1266 * Stops the conversion process.
1267 * @param h Handle to hb_handle_t.
1269 void hb_scan_stop( hb_handle_t * h )
1273 h->job_count = hb_count(h);
1274 h->job_count_permanent = 0;
1280 * Returns the state of the conversion process.
1281 * @param h Handle to hb_handle_t.
1282 * @param s Handle to hb_state_t which to copy the state data.
1284 void hb_get_state( hb_handle_t * h, hb_state_t * s )
1286 hb_lock( h->state_lock );
1288 memcpy( s, &h->state, sizeof( hb_state_t ) );
1289 if ( h->state.state == HB_STATE_SCANDONE || h->state.state == HB_STATE_WORKDONE )
1290 h->state.state = HB_STATE_IDLE;
1292 hb_unlock( h->state_lock );
1295 void hb_get_state2( hb_handle_t * h, hb_state_t * s )
1297 hb_lock( h->state_lock );
1299 memcpy( s, &h->state, sizeof( hb_state_t ) );
1301 hb_unlock( h->state_lock );
1305 * Called in MacGui in UpdateUI to check
1306 * for a new scan being completed to set a new source
1308 int hb_get_scancount( hb_handle_t * h)
1310 return h->scanCount;
1314 * Closes access to libhb by freeing the hb_handle_t handle ontained in hb_init.
1315 * @param _h Pointer to handle to hb_handle_t.
1317 void hb_close( hb_handle_t ** _h )
1319 hb_handle_t * h = *_h;
1323 hb_thread_close( &h->main_thread );
1325 while( ( title = hb_list_item( h->list_title, 0 ) ) )
1327 hb_list_rem( h->list_title, title );
1328 if( title->job && title->job->filters )
1330 hb_list_close( &title->job->filters );
1333 hb_title_close( &title );
1335 hb_list_close( &h->list_title );
1337 hb_list_close( &h->jobs );
1338 hb_lock_close( &h->state_lock );
1339 hb_lock_close( &h->pause_lock );
1346 * Monitors the state of the update, scan, and work threads.
1347 * Sets scan done state when scan thread exits.
1348 * Sets work done state when work thread exits.
1349 * @param _h Handle to hb_handle_t
1351 static void thread_func( void * _h )
1353 hb_handle_t * h = (hb_handle_t *) _h;
1356 struct dirent * entry;
1360 /* Create folder for temporary files */
1361 memset( dirname, 0, 1024 );
1362 hb_get_tempory_directory( h, dirname );
1364 hb_mkdir( dirname );
1368 /* In case the check_update thread hangs, it'll die sooner or
1369 later. Then, we join it here */
1370 if( h->update_thread &&
1371 hb_thread_has_exited( h->update_thread ) )
1373 hb_thread_close( &h->update_thread );
1376 /* Check if the scan thread is done */
1377 if( h->scan_thread &&
1378 hb_thread_has_exited( h->scan_thread ) )
1380 hb_thread_close( &h->scan_thread );
1386 hb_remove_previews( h );
1387 while( ( title = hb_list_item( h->list_title, 0 ) ) )
1389 hb_list_rem( h->list_title, title );
1390 hb_title_close( &title );
1393 hb_log( "hb_scan: canceled" );
1397 hb_log( "libhb: scan thread found %d valid title(s)",
1398 hb_list_count( h->list_title ) );
1400 hb_lock( h->state_lock );
1401 h->state.state = HB_STATE_SCANDONE; //originally state.state
1402 hb_unlock( h->state_lock );
1403 /*we increment this sessions scan count by one for the MacGui
1404 to trigger a new source being set */
1408 /* Check if the work thread is done */
1409 if( h->work_thread &&
1410 hb_thread_has_exited( h->work_thread ) )
1412 hb_thread_close( &h->work_thread );
1414 hb_log( "libhb: work result = %d",
1416 hb_lock( h->state_lock );
1417 h->state.state = HB_STATE_WORKDONE;
1418 h->state.param.workdone.error = h->work_error;
1420 h->job_count = hb_count(h);
1421 if (h->job_count < 1)
1422 h->job_count_permanent = 0;
1423 hb_unlock( h->state_lock );
1429 if( h->work_thread )
1432 hb_thread_close( &h->work_thread );
1435 /* Remove temp folder */
1436 dir = opendir( dirname );
1439 while( ( entry = readdir( dir ) ) )
1441 char filename[1024];
1442 if( entry->d_name[0] == '.' )
1446 memset( filename, 0, 1024 );
1447 snprintf( filename, 1023, "%s/%s", dirname, entry->d_name );
1457 * @param h Handle to hb_handle_t
1459 int hb_get_pid( hb_handle_t * h )
1465 * Sets the current state.
1466 * @param h Handle to hb_handle_t
1467 * @param s Handle to new hb_state_t
1469 void hb_set_state( hb_handle_t * h, hb_state_t * s )
1471 hb_lock( h->pause_lock );
1472 hb_lock( h->state_lock );
1473 memcpy( &h->state, s, sizeof( hb_state_t ) );
1474 if( h->state.state == HB_STATE_WORKING ||
1475 h->state.state == HB_STATE_SEARCHING )
1478 if (h->job_count < 1)
1479 h->job_count_permanent = 1;
1481 h->state.param.working.job_cur =
1482 h->job_count_permanent - hb_list_count( h->jobs );
1483 h->state.param.working.job_count = h->job_count_permanent;
1485 // Set which job is being worked on
1487 h->state.param.working.sequence_id = h->current_job->sequence_id;
1489 h->state.param.working.sequence_id = 0;
1491 hb_unlock( h->state_lock );
1492 hb_unlock( h->pause_lock );
1495 /* Passes a pointer to persistent data */
1496 hb_interjob_t * hb_interjob_get( hb_handle_t * h )