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;
53 static void thread_func( void * );
55 void hb_avcodec_init()
57 hb_avcodec_lock = hb_lock_init();
61 int hb_avcodec_open(AVCodecContext *avctx, AVCodec *codec)
64 hb_lock( hb_avcodec_lock );
65 ret = avcodec_open(avctx, codec);
66 hb_unlock( hb_avcodec_lock );
70 int hb_avcodec_close(AVCodecContext *avctx)
73 hb_lock( hb_avcodec_lock );
74 ret = avcodec_close(avctx);
75 hb_unlock( hb_avcodec_lock );
80 * Registers work objects, by adding the work object to a liked list.
81 * @param w Handle to hb_work_object_t to register.
83 void hb_register( hb_work_object_t * w )
90 * libhb initialization routine.
91 * @param verbose HB_DEBUG_NONE or HB_DEBUG_ALL.
92 * @param update_check signals libhb to check for updated version from HandBrake website.
93 * @return Handle to hb_handle_t for use on all subsequent calls to libhb.
95 hb_handle_t * hb_init( int verbose, int update_check )
97 hb_handle_t * h = calloc( sizeof( hb_handle_t ), 1 );
100 /* See hb_deep_log() and hb_log() in common.c */
101 global_verbosity_level = verbose;
103 putenv( "HB_DEBUG=1" );
105 /* Check for an update on the website if asked to */
110 hb_log( "hb_init: checking for updates" );
111 date = hb_get_date();
112 h->update_thread = hb_update_init( &h->build, h->version );
116 if( hb_thread_has_exited( h->update_thread ) )
118 /* Immediate success or failure */
119 hb_thread_close( &h->update_thread );
122 if( hb_get_date() > date + 1000 )
124 /* Still nothing after one second. Connection problem,
125 let the thread die */
126 hb_log( "hb_init: connection problem, not waiting for "
135 * Initialise buffer pool
137 hb_buffer_pool_init();
139 /* CPU count detection */
140 hb_log( "hb_init: checking cpu count" );
141 h->cpu_count = hb_get_cpu_count();
143 h->list_title = hb_list_init();
144 h->jobs = hb_list_init();
146 h->state_lock = hb_lock_init();
147 h->state.state = HB_STATE_IDLE;
149 h->pause_lock = hb_lock_init();
151 h->interjob = calloc( sizeof( hb_interjob_t ), 1 );
156 /* Start library thread */
157 hb_log( "hb_init: starting libhb thread" );
159 h->main_thread = hb_thread_init( "libhb", thread_func, h,
160 HB_NORMAL_PRIORITY );
161 hb_register( &hb_sync_video );
162 hb_register( &hb_sync_audio );
163 hb_register( &hb_decmpeg2 );
164 hb_register( &hb_decvobsub );
165 hb_register( &hb_encvobsub );
166 hb_register( &hb_deccc608 );
167 hb_register( &hb_decsrtsub );
168 hb_register( &hb_render );
169 hb_register( &hb_encavcodec );
170 hb_register( &hb_encx264 );
171 hb_register( &hb_enctheora );
172 hb_register( &hb_deca52 );
173 hb_register( &hb_decdca );
174 hb_register( &hb_decavcodec );
175 hb_register( &hb_decavcodecv );
176 hb_register( &hb_decavcodecvi );
177 hb_register( &hb_decavcodecai );
178 hb_register( &hb_declpcm );
179 hb_register( &hb_encfaac );
180 hb_register( &hb_enclame );
181 hb_register( &hb_encvorbis );
182 hb_register( &hb_muxer );
184 hb_register( &hb_encca_aac );
191 * libhb initialization routine.
192 * This version is to use when calling the dylib, the macro hb_init isn't available from a dylib call!
193 * @param verbose HB_DEBUG_NONE or HB_DEBUG_ALL.
194 * @param update_check signals libhb to check for updated version from HandBrake website.
195 * @return Handle to hb_handle_t for use on all subsequent calls to libhb.
197 hb_handle_t * hb_init_dl( int verbose, int update_check )
199 hb_handle_t * h = calloc( sizeof( hb_handle_t ), 1 );
202 /* See hb_log() in common.c */
203 if( verbose > HB_DEBUG_NONE )
205 putenv( "HB_DEBUG=1" );
208 /* Check for an update on the website if asked to */
213 hb_log( "hb_init: checking for updates" );
214 date = hb_get_date();
215 h->update_thread = hb_update_init( &h->build, h->version );
219 if( hb_thread_has_exited( h->update_thread ) )
221 /* Immediate success or failure */
222 hb_thread_close( &h->update_thread );
225 if( hb_get_date() > date + 1000 )
227 /* Still nothing after one second. Connection problem,
228 let the thread die */
229 hb_log( "hb_init: connection problem, not waiting for "
237 /* CPU count detection */
238 hb_log( "hb_init: checking cpu count" );
239 h->cpu_count = hb_get_cpu_count();
241 h->list_title = hb_list_init();
242 h->jobs = hb_list_init();
243 h->current_job = NULL;
245 h->state_lock = hb_lock_init();
246 h->state.state = HB_STATE_IDLE;
248 h->pause_lock = hb_lock_init();
252 avcodec_register_all();
254 /* Start library thread */
255 hb_log( "hb_init: starting libhb thread" );
257 h->main_thread = hb_thread_init( "libhb", thread_func, h,
258 HB_NORMAL_PRIORITY );
260 hb_register( &hb_sync_video );
261 hb_register( &hb_sync_audio );
262 hb_register( &hb_decmpeg2 );
263 hb_register( &hb_decvobsub );
264 hb_register( &hb_encvobsub );
265 hb_register( &hb_deccc608 );
266 hb_register( &hb_decsrtsub );
267 hb_register( &hb_render );
268 hb_register( &hb_encavcodec );
269 hb_register( &hb_encx264 );
270 hb_register( &hb_enctheora );
271 hb_register( &hb_deca52 );
272 hb_register( &hb_decdca );
273 hb_register( &hb_decavcodec );
274 hb_register( &hb_decavcodecv );
275 hb_register( &hb_decavcodecvi );
276 hb_register( &hb_decavcodecai );
277 hb_register( &hb_declpcm );
278 hb_register( &hb_encfaac );
279 hb_register( &hb_enclame );
280 hb_register( &hb_encvorbis );
281 hb_register( &hb_muxer );
283 hb_register( &hb_encca_aac );
291 * Returns current version of libhb.
292 * @param h Handle to hb_handle_t.
293 * @return character array of version number.
295 char * hb_get_version( hb_handle_t * h )
297 return HB_PROJECT_VERSION;
301 * Returns current build of libhb.
302 * @param h Handle to hb_handle_t.
303 * @return character array of build number.
305 int hb_get_build( hb_handle_t * h )
307 return HB_PROJECT_BUILD;
311 * Checks for needed update.
312 * @param h Handle to hb_handle_t.
313 * @param version Pointer to handle where version will be copied.
314 * @return update indicator.
316 int hb_check_update( hb_handle_t * h, char ** version )
318 *version = ( h->build < 0 ) ? NULL : h->version;
323 * Sets the cpu count to the desired value.
324 * @param h Handle to hb_handle_t
325 * @param cpu_count Number of CPUs to use.
327 void hb_set_cpu_count( hb_handle_t * h, int cpu_count )
329 cpu_count = MAX( 1, cpu_count );
330 cpu_count = MIN( cpu_count, 8 );
331 h->cpu_count = cpu_count;
335 * Deletes current previews associated with titles
336 * @param h Handle to hb_handle_t
338 void hb_remove_previews( hb_handle_t * h )
345 struct dirent * entry;
347 memset( dirname, 0, 1024 );
348 hb_get_tempory_directory( h, dirname );
349 dir = opendir( dirname );
350 if (dir == NULL) return;
352 count = hb_list_count( h->list_title );
353 while( ( entry = readdir( dir ) ) )
355 if( entry->d_name[0] == '.' )
359 for( i = 0; i < count; i++ )
361 title = hb_list_item( h->list_title, i );
362 len = snprintf( filename, 1024, "%" PRIxPTR, (intptr_t) title );
363 if (strncmp(entry->d_name, filename, len) == 0)
365 snprintf( filename, 1024, "%s/%s", dirname, entry->d_name );
375 * Initializes a scan of the by calling hb_scan_init
376 * @param h Handle to hb_handle_t
377 * @param path location of VIDEO_TS folder.
378 * @param title_index Desired title to scan. 0 for all titles.
379 * @param preview_count Number of preview images to generate.
380 * @param store_previews Whether or not to write previews to disk.
382 void hb_scan( hb_handle_t * h, const char * path, int title_index,
383 int preview_count, int store_previews )
389 /* Clean up from previous scan */
390 hb_remove_previews( h );
391 while( ( title = hb_list_item( h->list_title, 0 ) ) )
393 hb_list_rem( h->list_title, title );
394 hb_title_close( &title );
397 hb_log( "hb_scan: path=%s, title_index=%d", path, title_index );
398 h->scan_thread = hb_scan_init( h, &h->scan_die, path, title_index,
399 h->list_title, preview_count,
404 * Returns the list of titles found.
405 * @param h Handle to hb_handle_t
406 * @return Handle to hb_list_t of the title list.
408 hb_list_t * hb_get_titles( hb_handle_t * h )
410 return h->list_title;
414 * Create preview image of desired title a index of picture.
415 * @param h Handle to hb_handle_t.
416 * @param title Handle to hb_title_t of desired title.
417 * @param picture Index in title.
418 * @param buffer Handle to buufer were inage will be drawn.
420 void hb_get_preview( hb_handle_t * h, hb_title_t * title, int picture,
423 hb_job_t * job = title->job;
426 uint8_t * buf1, * buf2, * buf3, * buf4, * pen;
428 AVPicture pic_in, pic_preview, pic_deint, pic_crop, pic_scale;
429 struct SwsContext * context;
431 int rgb_width = ((job->width + 7) >> 3) << 3;
434 swsflags = SWS_LANCZOS | SWS_ACCURATE_RND;
436 buf1 = av_malloc( avpicture_get_size( PIX_FMT_YUV420P, title->width, title->height ) );
437 buf2 = av_malloc( avpicture_get_size( PIX_FMT_YUV420P, title->width, title->height ) );
438 buf3 = av_malloc( avpicture_get_size( PIX_FMT_YUV420P, rgb_width, job->height ) );
439 buf4 = av_malloc( avpicture_get_size( PIX_FMT_RGB32, rgb_width, job->height ) );
440 avpicture_fill( &pic_in, buf1, PIX_FMT_YUV420P,
441 title->width, title->height );
442 avpicture_fill( &pic_deint, buf2, PIX_FMT_YUV420P,
443 title->width, title->height );
444 avpicture_fill( &pic_scale, buf3, PIX_FMT_YUV420P,
445 rgb_width, job->height );
446 avpicture_fill( &pic_preview, buf4, PIX_FMT_RGB32,
447 rgb_width, job->height );
449 // Allocate the AVPicture frames and fill in
451 memset( filename, 0, 1024 );
453 hb_get_tempory_filename( h, filename, "%" PRIxPTR "%d",
454 (intptr_t) title, picture );
456 file = fopen( filename, "rb" );
459 hb_log( "hb_get_preview: fopen failed" );
463 fread( buf1, avpicture_get_size( PIX_FMT_YUV420P, title->width, title->height), 1, file );
466 if( job->deinterlace )
468 // Deinterlace and crop
469 avpicture_deinterlace( &pic_deint, &pic_in, PIX_FMT_YUV420P, title->width, title->height );
470 av_picture_crop( &pic_crop, &pic_deint, PIX_FMT_YUV420P, job->crop[0], job->crop[2] );
475 av_picture_crop( &pic_crop, &pic_in, PIX_FMT_YUV420P, job->crop[0], job->crop[2] );
478 // Get scaling context
479 context = sws_getContext(title->width - (job->crop[2] + job->crop[3]),
480 title->height - (job->crop[0] + job->crop[1]),
482 job->width, job->height, PIX_FMT_YUV420P,
483 swsflags, NULL, NULL, NULL);
487 pic_crop.data, pic_crop.linesize,
488 0, title->height - (job->crop[0] + job->crop[1]),
489 pic_scale.data, pic_scale.linesize);
492 sws_freeContext( context );
494 // Get preview context
495 context = sws_getContext(rgb_width, job->height, PIX_FMT_YUV420P,
496 rgb_width, job->height, PIX_FMT_RGB32,
497 swsflags, NULL, NULL, NULL);
501 pic_scale.data, pic_scale.linesize,
503 pic_preview.data, pic_preview.linesize);
506 sws_freeContext( context );
508 preview_size = pic_preview.linesize[0];
510 for( i = 0; i < job->height; i++ )
512 memcpy( pen, buf4 + preview_size * i, 4 * job->width );
513 pen += 4 * job->width;
517 avpicture_free( &pic_preview );
518 avpicture_free( &pic_scale );
519 avpicture_free( &pic_deint );
520 avpicture_free( &pic_in );
524 * Analyzes a frame to detect interlacing artifacts
525 * and returns true if interlacing (combing) is found.
527 * Code taken from Thomas Oestreich's 32detect filter
528 * in the Transcode project, with minor formatting changes.
530 * @param buf An hb_buffer structure holding valid frame data
531 * @param width The frame's width in pixels
532 * @param height The frame's height in pixels
533 * @param color_equal Sensitivity for detecting similar colors
534 * @param color_diff Sensitivity for detecting different colors
535 * @param threshold Sensitivity for flagging planes as combed
536 * @param prog_equal Sensitivity for detecting similar colors on progressive frames
537 * @param prog_diff Sensitivity for detecting different colors on progressive frames
538 * @param prog_threshold Sensitivity for flagging progressive frames as combed
540 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 )
542 int j, k, n, off, cc_1, cc_2, cc[3];
543 // int flag[3] ; // debugging flag
544 uint16_t s1, s2, s3, s4;
549 if ( buf->flags & 16 )
551 /* Frame is progressive, be more discerning. */
552 color_diff = prog_diff;
553 color_equal = prog_equal;
554 threshold = prog_threshold;
557 /* One pas for Y, one pass for Cb, one pass for Cr */
558 for( k = 0; k < 3; k++ )
562 /* Y has already been checked, now offset by Y's dimensions
563 and divide all the other values by 2, since Cr and Cb
564 are half-size compared to Y. */
565 offset = width * height;
571 /* Y and Cb are done, so the offset needs to be bumped
572 so it's width*height + (width / 2) * (height / 2) */
576 for( j = 0; j < width; ++j )
580 for( n = 0; n < ( height - 4 ); n = n + 2 )
582 /* Look at groups of 4 sequential horizontal lines */
583 s1 = ( ( buf->data + offset )[ off + j ] & 0xff );
584 s2 = ( ( buf->data + offset )[ off + j + width ] & 0xff );
585 s3 = ( ( buf->data + offset )[ off + j + 2 * width ] & 0xff );
586 s4 = ( ( buf->data + offset )[ off + j + 3 * width ] & 0xff );
588 /* Note if the 1st and 2nd lines are more different in
589 color than the 1st and 3rd lines are similar in color.*/
590 if ( ( abs( s1 - s3 ) < color_equal ) &&
591 ( abs( s1 - s2 ) > color_diff ) )
594 /* Note if the 2nd and 3rd lines are more different in
595 color than the 2nd and 4th lines are similar in color.*/
596 if ( ( abs( s2 - s4 ) < color_equal ) &&
597 ( abs( s2 - s3 ) > color_diff) )
600 /* Now move down 2 horizontal lines before starting over.*/
606 /* The final cc score for a plane is the percentage of combed pixels it contains.
607 Because sensitivity goes down to hundreths of a percent, multiply by 1000
608 so it will be easy to compare against the threhold value which is an integer. */
609 cc[k] = (int)( ( cc_1 + cc_2 ) * 1000.0 / ( width * height ) );
613 /* HandBrake is all yuv420, so weight the average percentage of all 3 planes accordingly.*/
614 int average_cc = ( 2 * cc[0] + ( cc[1] / 2 ) + ( cc[2] / 2 ) ) / 3;
616 /* Now see if that average percentage of combed pixels surpasses the threshold percentage given by the user.*/
617 if( average_cc > threshold )
620 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" );
626 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" );
629 /* Reaching this point means no combing detected. */
635 * Calculates job width and height for anamorphic content,
637 * @param job Handle to hb_job_t
638 * @param output_width Pointer to returned storage width
639 * @param output_height Pointer to returned storage height
640 * @param output_par_width Pointer to returned pixel width
641 @ param output_par_height Pointer to returned pixel height
643 void hb_set_anamorphic_size( hb_job_t * job,
644 int *output_width, int *output_height,
645 int *output_par_width, int *output_par_height )
647 /* Set up some variables to make the math easier to follow. */
648 hb_title_t * title = job->title;
649 int cropped_width = title->width - job->crop[2] - job->crop[3] ;
650 int cropped_height = title->height - job->crop[0] - job->crop[1] ;
651 double storage_aspect = (double)cropped_width / (double)cropped_height;
652 int mod = job->anamorphic.modulus ? job->anamorphic.modulus : 16;
653 double aspect = title->aspect;
655 int pixel_aspect_width = job->anamorphic.par_width;
656 int pixel_aspect_height = job->anamorphic.par_height;
658 /* If a source was really NTSC or PAL and the user specified ITU PAR
659 values, replace the standard PAR values with the ITU broadcast ones. */
660 if( title->width == 720 && job->anamorphic.itu_par )
662 // convert aspect to a scaled integer so we can test for 16:9 & 4:3
663 // aspect ratios ignoring insignificant differences in the LSBs of
664 // the floating point representation.
665 int iaspect = aspect * 9.;
667 /* Handle ITU PARs */
668 if (title->height == 480)
673 /* It's widescreen */
674 pixel_aspect_width = 40;
675 pixel_aspect_height = 33;
677 else if (iaspect == 12)
680 pixel_aspect_width = 10;
681 pixel_aspect_height = 11;
684 else if (title->height == 576)
689 /* It's widescreen */
690 pixel_aspect_width = 16;
691 pixel_aspect_height = 11;
693 else if (iaspect == 12)
696 pixel_aspect_width = 12;
697 pixel_aspect_height = 11;
702 /* Figure out what width the source would display at. */
703 int source_display_width = cropped_width * (double)pixel_aspect_width /
704 (double)pixel_aspect_height ;
707 3 different ways of deciding output dimensions:
708 - 1: Strict anamorphic, preserve source dimensions
709 - 2: Loose anamorphic, round to mod16 and preserve storage aspect ratio
710 - 3: Power user anamorphic, specify everything
713 switch( job->anamorphic.mode )
716 /* Strict anamorphic */
717 *output_width = cropped_width;
718 *output_height = cropped_height;
719 *output_par_width = title->pixel_aspect_width;
720 *output_par_height = title->pixel_aspect_height;
724 /* "Loose" anamorphic.
725 - Uses mod16-compliant dimensions,
726 - Allows users to set the width
729 // height: Gets set later, ignore user job->height value
731 /* Gotta handle bounding dimensions.
732 If the width is too big, just reset it with no rescaling.
733 Instead of using the aspect-scaled job height,
734 we need to see if the job width divided by the storage aspect
735 is bigger than the max. If so, set it to the max (this is sloppy).
736 If not, set job height to job width divided by storage aspect.
739 if ( job->maxWidth && (job->maxWidth < job->width) )
740 width = job->maxWidth;
742 /* Time to get picture width that divide cleanly.*/
743 width = MULTIPLE_MOD( width, mod);
745 /* Verify these new dimensions don't violate max height and width settings */
746 if ( job->maxWidth && (job->maxWidth < job->width) )
747 width = job->maxWidth;
749 height = ((double)width / storage_aspect) + 0.5;
751 if ( job->maxHeight && (job->maxHeight < height) )
752 height = job->maxHeight;
754 /* Time to get picture height that divide cleanly.*/
755 height = MULTIPLE_MOD( height, mod);
757 /* Verify these new dimensions don't violate max height and width settings */
758 if ( job->maxHeight && (job->maxHeight < height) )
759 height = job->maxHeight;
761 /* The film AR is the source's display width / cropped source height.
762 The output display width is the output height * film AR.
763 The output PAR is the output display width / output storage width. */
764 pixel_aspect_width = height * source_display_width / cropped_height;
765 pixel_aspect_height = width;
767 /* Pass the results back to the caller */
768 *output_width = width;
769 *output_height = height;
773 /* Anamorphic 3: Power User Jamboree
774 - Set everything based on specified values */
776 /* Use specified storage dimensions */
778 height = job->height;
780 /* Bind to max dimensions */
781 if( job->maxWidth && width > job->maxWidth )
782 width = job->maxWidth;
783 if( job->maxHeight && height > job->maxHeight )
784 height = job->maxHeight;
786 /* Time to get picture dimensions that divide cleanly.*/
787 width = MULTIPLE_MOD( width, mod);
788 height = MULTIPLE_MOD( height, mod);
790 /* Verify we're still within max dimensions */
791 if( job->maxWidth && width > job->maxWidth )
792 width = job->maxWidth - (mod/2);
793 if( job->maxHeight && height > job->maxHeight )
794 height = job->maxHeight - (mod/2);
796 /* Re-ensure we have picture dimensions that divide cleanly. */
797 width = MULTIPLE_MOD( width, mod );
798 height = MULTIPLE_MOD( height, mod );
800 /* That finishes the storage dimensions. On to display. */
801 if( job->anamorphic.dar_width && job->anamorphic.dar_height )
803 /* We need to adjust the PAR to produce this aspect. */
804 pixel_aspect_width = height * job->anamorphic.dar_width / job->anamorphic.dar_height;
805 pixel_aspect_height = width;
809 /* If we're doing ana 3 and not specifying a DAR, care needs to be taken.
810 This indicates a PAR is potentially being set by the interface. But
811 this is an output PAR, to correct a source, and it should not be assumed
812 that it properly creates a display aspect ratio when applied to the source,
813 which could easily be stored in a different resolution. */
814 if( job->anamorphic.keep_display_aspect )
816 /* We can ignore the possibility of a PAR change */
817 pixel_aspect_width = height * ( (double)source_display_width / (double)cropped_height );
818 pixel_aspect_height = width;
822 int output_display_width = width * (double)pixel_aspect_width /
823 (double)pixel_aspect_height;
824 pixel_aspect_width = output_display_width;
825 pixel_aspect_height = width;
830 *output_width = width;
831 *output_height = height;
835 /* While x264 is smart enough to reduce fractions on its own, libavcodec
836 needs some help with the math, so lose superfluous factors. */
837 hb_reduce( output_par_width, output_par_height,
838 pixel_aspect_width, pixel_aspect_height );
842 * Calculates job width, height, and cropping parameters.
843 * @param job Handle to hb_job_t.
844 * @param aspect Desired aspect ratio. Value of -1 uses title aspect.
845 * @param pixels Maximum desired pixel count.
847 void hb_set_size( hb_job_t * job, double aspect, int pixels )
849 hb_title_t * title = job->title;
851 int croppedWidth = title->width - title->crop[2] - title->crop[3];
852 int croppedHeight = title->height - title->crop[0] - title->crop[1];
853 double croppedAspect = title->aspect * title->height * croppedWidth /
854 croppedHeight / title->width;
860 /* Keep the best possible aspect ratio */
861 aspect = croppedAspect;
864 /* Crop if necessary to obtain the desired ratio */
865 memcpy( job->crop, title->crop, 4 * sizeof( int ) );
866 if( aspect < croppedAspect )
868 /* Need to crop on the left and right */
869 addCrop = croppedWidth - aspect * croppedHeight * title->width /
870 title->aspect / title->height;
873 addCrop = ( addCrop + 1 ) / 2;
874 job->crop[2] += addCrop;
875 job->crop[3] += addCrop;
877 else if( addCrop & 2 )
880 job->crop[2] += addCrop - 1;
881 job->crop[3] += addCrop + 1;
886 job->crop[2] += addCrop;
887 job->crop[3] += addCrop;
890 else if( aspect > croppedAspect )
892 /* Need to crop on the top and bottom */
893 addCrop = croppedHeight - croppedWidth * title->aspect *
894 title->height / aspect / title->width;
897 addCrop = ( addCrop + 1 ) / 2;
898 job->crop[0] += addCrop;
899 job->crop[1] += addCrop;
901 else if( addCrop & 2 )
904 job->crop[0] += addCrop - 1;
905 job->crop[1] += addCrop + 1;
910 job->crop[0] += addCrop;
911 job->crop[1] += addCrop;
915 /* Compute a resolution from the number of pixels and aspect */
919 h = MULTIPLE_16( (int)( (double)w / aspect ) );
927 job->height = MULTIPLE_16( (int)( (double)job->width / aspect ) );
931 * Returns the number of jobs in the queue.
932 * @param h Handle to hb_handle_t.
933 * @return Number of jobs.
935 int hb_count( hb_handle_t * h )
937 return hb_list_count( h->jobs );
941 * Returns handle to job at index i within the job list.
942 * @param h Handle to hb_handle_t.
943 * @param i Index of job.
944 * @returns Handle to hb_job_t of desired job.
946 hb_job_t * hb_job( hb_handle_t * h, int i )
948 return hb_list_item( h->jobs, i );
951 hb_job_t * hb_current_job( hb_handle_t * h )
953 return( h->current_job );
957 * Adds a job to the job list.
958 * @param h Handle to hb_handle_t.
959 * @param job Handle to hb_job_t.
961 void hb_add( hb_handle_t * h, hb_job_t * job )
964 hb_title_t * title, * title_copy;
965 hb_chapter_t * chapter, * chapter_copy;
967 hb_subtitle_t * subtitle, * subtitle_copy;
973 title_copy = malloc( sizeof( hb_title_t ) );
974 memcpy( title_copy, title, sizeof( hb_title_t ) );
976 title_copy->list_chapter = hb_list_init();
977 for( i = 0; i < hb_list_count( title->list_chapter ); i++ )
979 chapter = hb_list_item( title->list_chapter, i );
980 chapter_copy = malloc( sizeof( hb_chapter_t ) );
981 memcpy( chapter_copy, chapter, sizeof( hb_chapter_t ) );
982 hb_list_add( title_copy->list_chapter, chapter_copy );
988 if( title->metadata )
990 title_copy->metadata = malloc( sizeof( hb_metadata_t ) );
992 if( title_copy->metadata )
994 memcpy( title_copy->metadata, title->metadata, sizeof( hb_metadata_t ) );
997 * Need to copy the artwork seperatly (TODO).
999 if( title->metadata->coverart )
1001 title_copy->metadata->coverart = malloc( title->metadata->coverart_size );
1002 if( title_copy->metadata->coverart )
1004 memcpy( title_copy->metadata->coverart, title->metadata->coverart,
1005 title->metadata->coverart_size );
1007 title_copy->metadata->coverart_size = 0;
1013 /* Copy the audio track(s) we want */
1014 title_copy->list_audio = hb_list_init();
1016 for( i = 0; i < hb_list_count(job->list_audio); i++ )
1018 if( ( audio = hb_list_item( job->list_audio, i ) ) )
1020 hb_list_add( title_copy->list_audio, hb_audio_copy(audio) );
1024 title_copy->list_subtitle = hb_list_init();
1027 * The following code is confusing, there are two ways in which
1028 * we select subtitles and it depends on whether this is single or
1031 * subtitle_scan may be enabled, in which case the first pass
1032 * scans all subtitles of that language. The second pass does not
1033 * select any because they are set at the end of the first pass.
1035 * We may have manually selected a subtitle, in which case that is
1036 * selected in the first pass of a single pass, or the second of a
1039 memset( audio_lang, 0, sizeof( audio_lang ) );
1041 if ( job->indepth_scan ) {
1044 * Find the first audio language that is being encoded
1046 for( i = 0; i < hb_list_count(job->list_audio); i++ )
1048 if( ( audio = hb_list_item( job->list_audio, i ) ) )
1050 strncpy(audio_lang, audio->config.lang.iso639_2, sizeof(audio_lang));
1057 * If doing a subtitle scan then add all the matching subtitles for this
1060 if ( job->indepth_scan )
1062 for( i=0; i < hb_list_count( title->list_subtitle ); i++ )
1064 subtitle = hb_list_item( title->list_subtitle, i );
1065 if( strcmp( subtitle->iso639_2, audio_lang ) == 0 &&
1066 subtitle->source == VOBSUB )
1069 * Matched subtitle language with audio language, so
1070 * add this to our list to scan.
1072 * We will update the subtitle list on the second pass
1073 * later after the first pass has completed.
1075 subtitle_copy = malloc( sizeof( hb_subtitle_t ) );
1076 memcpy( subtitle_copy, subtitle, sizeof( hb_subtitle_t ) );
1077 hb_list_add( title_copy->list_subtitle, subtitle_copy );
1082 * Not doing a subtitle scan in this pass, but maybe we are in the
1085 if( job->pass != 1 )
1088 * Copy all of them from the input job, to the title_copy/job_copy.
1090 for( i = 0; i < hb_list_count(job->list_subtitle); i++ ) {
1091 if( ( subtitle = hb_list_item( job->list_subtitle, i ) ) )
1093 subtitle_copy = malloc( sizeof( hb_subtitle_t ) );
1094 memcpy( subtitle_copy, subtitle, sizeof( hb_subtitle_t ) );
1095 hb_list_add( title_copy->list_subtitle, subtitle_copy );
1102 job_copy = calloc( sizeof( hb_job_t ), 1 );
1103 memcpy( job_copy, job, sizeof( hb_job_t ) );
1104 title_copy->job = job_copy;
1105 job_copy->title = title_copy;
1106 job_copy->list_audio = title_copy->list_audio;
1107 job_copy->list_subtitle = title_copy->list_subtitle; // sharing list between title and job
1108 job_copy->file = strdup( job->file );
1110 job_copy->pause = h->pause_lock;
1112 /* Copy the job filter list */
1116 int filter_count = hb_list_count( job->filters );
1117 job_copy->filters = hb_list_init();
1118 for( i = 0; i < filter_count; i++ )
1121 * Copy the filters, since the MacGui reuses the global filter objects
1122 * meaning that queued up jobs overwrite the previous filter settings.
1123 * In reality, settings is probably the only field that needs duplicating
1124 * since it's the only value that is ever changed. But name is duplicated
1125 * as well for completeness. Not copying private_data since it gets
1126 * created for each job in renderInit.
1128 hb_filter_object_t * filter = hb_list_item( job->filters, i );
1129 hb_filter_object_t * filter_copy = malloc( sizeof( hb_filter_object_t ) );
1130 memcpy( filter_copy, filter, sizeof( hb_filter_object_t ) );
1132 filter_copy->name = strdup( filter->name );
1133 if( filter->settings )
1134 filter_copy->settings = strdup( filter->settings );
1135 hb_list_add( job_copy->filters, filter_copy );
1139 /* Add the job to the list */
1140 hb_list_add( h->jobs, job_copy );
1141 h->job_count = hb_count(h);
1142 h->job_count_permanent++;
1146 * Removes a job from the job list.
1147 * @param h Handle to hb_handle_t.
1148 * @param job Handle to hb_job_t.
1150 void hb_rem( hb_handle_t * h, hb_job_t * job )
1152 hb_list_rem( h->jobs, job );
1154 h->job_count = hb_count(h);
1155 if (h->job_count_permanent)
1156 h->job_count_permanent--;
1158 /* XXX free everything XXX */
1162 * Starts the conversion process.
1163 * Sets state to HB_STATE_WORKING.
1164 * calls hb_work_init, to launch work thread. Stores handle to work thread.
1165 * @param h Handle to hb_handle_t.
1167 void hb_start( hb_handle_t * h )
1170 h->job_count = hb_list_count( h->jobs );
1171 h->job_count_permanent = h->job_count;
1173 hb_lock( h->state_lock );
1174 h->state.state = HB_STATE_WORKING;
1175 #define p h->state.param.working
1178 p.job_count = h->job_count;
1186 hb_unlock( h->state_lock );
1191 h->work_thread = hb_work_init( h->jobs, h->cpu_count,
1192 &h->work_die, &h->work_error, &h->current_job );
1196 * Pauses the conversion process.
1197 * @param h Handle to hb_handle_t.
1199 void hb_pause( hb_handle_t * h )
1203 hb_lock( h->pause_lock );
1206 hb_current_job( h )->st_pause_date = hb_get_date();
1208 hb_lock( h->state_lock );
1209 h->state.state = HB_STATE_PAUSED;
1210 hb_unlock( h->state_lock );
1215 * Resumes the conversion process.
1216 * @param h Handle to hb_handle_t.
1218 void hb_resume( hb_handle_t * h )
1222 #define job hb_current_job( h )
1223 if( job->st_pause_date != -1 )
1225 job->st_paused += hb_get_date() - job->st_pause_date;
1229 hb_unlock( h->pause_lock );
1235 * Stops the conversion process.
1236 * @param h Handle to hb_handle_t.
1238 void hb_stop( hb_handle_t * h )
1242 h->job_count = hb_count(h);
1243 h->job_count_permanent = 0;
1249 * Stops the conversion process.
1250 * @param h Handle to hb_handle_t.
1252 void hb_scan_stop( hb_handle_t * h )
1256 h->job_count = hb_count(h);
1257 h->job_count_permanent = 0;
1263 * Returns the state of the conversion process.
1264 * @param h Handle to hb_handle_t.
1265 * @param s Handle to hb_state_t which to copy the state data.
1267 void hb_get_state( hb_handle_t * h, hb_state_t * s )
1269 hb_lock( h->state_lock );
1271 memcpy( s, &h->state, sizeof( hb_state_t ) );
1272 if ( h->state.state == HB_STATE_SCANDONE || h->state.state == HB_STATE_WORKDONE )
1273 h->state.state = HB_STATE_IDLE;
1275 hb_unlock( h->state_lock );
1278 void hb_get_state2( hb_handle_t * h, hb_state_t * s )
1280 hb_lock( h->state_lock );
1282 memcpy( s, &h->state, sizeof( hb_state_t ) );
1284 hb_unlock( h->state_lock );
1288 * Called in MacGui in UpdateUI to check
1289 * for a new scan being completed to set a new source
1291 int hb_get_scancount( hb_handle_t * h)
1293 return h->scanCount;
1297 * Closes access to libhb by freeing the hb_handle_t handle ontained in hb_init.
1298 * @param _h Pointer to handle to hb_handle_t.
1300 void hb_close( hb_handle_t ** _h )
1302 hb_handle_t * h = *_h;
1306 hb_thread_close( &h->main_thread );
1308 while( ( title = hb_list_item( h->list_title, 0 ) ) )
1310 hb_list_rem( h->list_title, title );
1311 if( title->job && title->job->filters )
1313 hb_list_close( &title->job->filters );
1316 hb_title_close( &title );
1318 hb_list_close( &h->list_title );
1320 hb_list_close( &h->jobs );
1321 hb_lock_close( &h->state_lock );
1322 hb_lock_close( &h->pause_lock );
1329 * Monitors the state of the update, scan, and work threads.
1330 * Sets scan done state when scan thread exits.
1331 * Sets work done state when work thread exits.
1332 * @param _h Handle to hb_handle_t
1334 static void thread_func( void * _h )
1336 hb_handle_t * h = (hb_handle_t *) _h;
1339 struct dirent * entry;
1343 /* Create folder for temporary files */
1344 memset( dirname, 0, 1024 );
1345 hb_get_tempory_directory( h, dirname );
1347 hb_mkdir( dirname );
1351 /* In case the check_update thread hangs, it'll die sooner or
1352 later. Then, we join it here */
1353 if( h->update_thread &&
1354 hb_thread_has_exited( h->update_thread ) )
1356 hb_thread_close( &h->update_thread );
1359 /* Check if the scan thread is done */
1360 if( h->scan_thread &&
1361 hb_thread_has_exited( h->scan_thread ) )
1363 hb_thread_close( &h->scan_thread );
1369 hb_remove_previews( h );
1370 while( ( title = hb_list_item( h->list_title, 0 ) ) )
1372 hb_list_rem( h->list_title, title );
1373 hb_title_close( &title );
1376 hb_log( "hb_scan: canceled" );
1380 hb_log( "libhb: scan thread found %d valid title(s)",
1381 hb_list_count( h->list_title ) );
1383 hb_lock( h->state_lock );
1384 h->state.state = HB_STATE_SCANDONE; //originally state.state
1385 hb_unlock( h->state_lock );
1386 /*we increment this sessions scan count by one for the MacGui
1387 to trigger a new source being set */
1391 /* Check if the work thread is done */
1392 if( h->work_thread &&
1393 hb_thread_has_exited( h->work_thread ) )
1395 hb_thread_close( &h->work_thread );
1397 hb_log( "libhb: work result = %d",
1399 hb_lock( h->state_lock );
1400 h->state.state = HB_STATE_WORKDONE;
1401 h->state.param.workdone.error = h->work_error;
1403 h->job_count = hb_count(h);
1404 if (h->job_count < 1)
1405 h->job_count_permanent = 0;
1406 hb_unlock( h->state_lock );
1412 if( h->work_thread )
1415 hb_thread_close( &h->work_thread );
1418 /* Remove temp folder */
1419 dir = opendir( dirname );
1422 while( ( entry = readdir( dir ) ) )
1424 char filename[1024];
1425 if( entry->d_name[0] == '.' )
1429 memset( filename, 0, 1024 );
1430 snprintf( filename, 1023, "%s/%s", dirname, entry->d_name );
1440 * @param h Handle to hb_handle_t
1442 int hb_get_pid( hb_handle_t * h )
1448 * Sets the current state.
1449 * @param h Handle to hb_handle_t
1450 * @param s Handle to new hb_state_t
1452 void hb_set_state( hb_handle_t * h, hb_state_t * s )
1454 hb_lock( h->pause_lock );
1455 hb_lock( h->state_lock );
1456 memcpy( &h->state, s, sizeof( hb_state_t ) );
1457 if( h->state.state == HB_STATE_WORKING ||
1458 h->state.state == HB_STATE_SEARCHING )
1461 if (h->job_count < 1)
1462 h->job_count_permanent = 1;
1464 h->state.param.working.job_cur =
1465 h->job_count_permanent - hb_list_count( h->jobs );
1466 h->state.param.working.job_count = h->job_count_permanent;
1468 // Set which job is being worked on
1470 h->state.param.working.sequence_id = h->current_job->sequence_id;
1472 h->state.param.working.sequence_id = 0;
1474 hb_unlock( h->state_lock );
1475 hb_unlock( h->pause_lock );
1478 /* Passes a pointer to persistent data */
1479 hb_interjob_t * hb_interjob_get( hb_handle_t * h )