X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=libhb%2Fhb.c;h=cde51322cb3a2d95ae30b06aec4b14acf2e7d617;hb=07cc0ebf6a7141a76fd9b6e2da6cf510def1ebc7;hp=b2d6728726aaa6075d6300274cfc52634077a0ad;hpb=365c4fcd07f5d852cc281224d6addef8abda6cd0;p=handbrake-jp%2Fhandbrake-jp-git.git diff --git a/libhb/hb.c b/libhb/hb.c index b2d67287..cde51322 100644 --- a/libhb/hb.c +++ b/libhb/hb.c @@ -1,7 +1,8 @@ #include "hb.h" -#include "ffmpeg/avcodec.h" -#include "ffmpeg/swscale.h" +#include "libavcodec/avcodec.h" +#include "libavformat/avformat.h" +#include "libswscale/swscale.h" struct hb_handle_s { @@ -34,13 +35,13 @@ struct hb_handle_s hb_lock_t * state_lock; hb_state_t state; - + int paused; hb_lock_t * pause_lock; /* For MacGui active queue increments each time the scan thread completes*/ int scanCount; - + }; hb_work_object_t * hb_objects = NULL; @@ -72,7 +73,6 @@ hb_handle_t * hb_init_real( int verbose, int update_check ) if( verbose > HB_DEBUG_NONE ) { putenv( "HB_DEBUG=1" ); - av_log_set_level(AV_LOG_DEBUG); } /* Check for an update on the website if asked to */ @@ -122,10 +122,8 @@ hb_handle_t * hb_init_real( int verbose, int update_check ) h->pause_lock = hb_lock_init(); /* libavcodec */ - avcodec_init(); - avcodec_register_all(); - av_register_codec_parser( &mpegaudio_parser); - + av_register_all(); + /* Start library thread */ hb_log( "hb_init: starting libhb thread" ); h->die = 0; @@ -133,7 +131,7 @@ hb_handle_t * hb_init_real( int verbose, int update_check ) HB_NORMAL_PRIORITY ); return h; - + /* Set the scan count to start at 0 */ //scan_count = 0; } @@ -154,7 +152,6 @@ hb_handle_t * hb_init_dl( int verbose, int update_check ) if( verbose > HB_DEBUG_NONE ) { putenv( "HB_DEBUG=1" ); - av_log_set_level(AV_LOG_DEBUG); } /* Check for an update on the website if asked to */ @@ -209,21 +206,25 @@ hb_handle_t * hb_init_dl( int verbose, int update_check ) h->main_thread = hb_thread_init( "libhb", thread_func, h, HB_NORMAL_PRIORITY ); - hb_register( &hb_sync ); - hb_register( &hb_decmpeg2 ); - hb_register( &hb_decsub ); - hb_register( &hb_render ); - hb_register( &hb_encavcodec ); - hb_register( &hb_encxvid ); - hb_register( &hb_encx264 ); - hb_register( &hb_deca52 ); - hb_register( &hb_decdca ); - hb_register( &hb_decavcodec ); - hb_register( &hb_declpcm ); - hb_register( &hb_encfaac ); - hb_register( &hb_enclame ); - hb_register( &hb_encvorbis ); - + hb_register( &hb_sync ); + hb_register( &hb_decmpeg2 ); + hb_register( &hb_decsub ); + hb_register( &hb_render ); + hb_register( &hb_encavcodec ); + hb_register( &hb_encxvid ); + hb_register( &hb_encx264 ); + hb_register( &hb_enctheora ); + hb_register( &hb_deca52 ); + hb_register( &hb_decdca ); + hb_register( &hb_decavcodec ); + hb_register( &hb_decavcodecv ); + hb_register( &hb_decavcodecvi ); + hb_register( &hb_decavcodecai ); + hb_register( &hb_declpcm ); + hb_register( &hb_encfaac ); + hb_register( &hb_enclame ); + hb_register( &hb_encvorbis ); + return h; } @@ -288,7 +289,7 @@ void hb_scan( hb_handle_t * h, const char * path, int title_index ) hb_list_rem( h->list_title, title ); hb_title_close( &title ); } - + hb_log( "hb_scan: path=%s, title_index=%d", path, title_index ); h->scan_thread = hb_scan_init( h, path, title_index, h->list_title ); } @@ -317,11 +318,16 @@ void hb_get_preview( hb_handle_t * h, hb_title_t * title, int picture, char filename[1024]; FILE * file; uint8_t * buf1, * buf2, * buf3, * buf4, * pen; - uint32_t * p32; + uint32_t * p32, swsflags; AVPicture pic_in, pic_preview, pic_deint, pic_crop, pic_scale; struct SwsContext * context; int i; + swsflags = SWS_LANCZOS; +#ifndef __x86_64__ + swsflags |= SWS_ACCURATE_RND; +#endif /* __x86_64__ */ + buf1 = malloc( title->width * title->height * 3 / 2 ); buf2 = malloc( title->width * title->height * 3 / 2 ); buf3 = malloc( title->width * title->height * 3 / 2 ); @@ -369,7 +375,7 @@ void hb_get_preview( hb_handle_t * h, hb_title_t * title, int picture, title->height - (job->crop[0] + job->crop[1]), PIX_FMT_YUV420P, job->width, job->height, PIX_FMT_YUV420P, - (uint16_t)(SWS_LANCZOS|SWS_ACCURATE_RND), NULL, NULL, NULL); + swsflags, NULL, NULL, NULL); // Scale sws_scale(context, @@ -382,8 +388,8 @@ void hb_get_preview( hb_handle_t * h, hb_title_t * title, int picture, // Get preview context context = sws_getContext(job->width, job->height, PIX_FMT_YUV420P, - job->width, job->height, PIX_FMT_RGBA32, - (uint16_t)(SWS_LANCZOS|SWS_ACCURATE_RND), NULL, NULL, NULL); + job->width, job->height, PIX_FMT_RGBA32, + swsflags, NULL, NULL, NULL); // Create preview sws_scale(context, @@ -426,100 +432,373 @@ void hb_get_preview( hb_handle_t * h, hb_title_t * title, int picture, avpicture_free( &pic_in ); } + /** + * Analyzes a frame to detect interlacing artifacts + * and returns true if interlacing (combing) is found. + * + * Code taken from Thomas Oestreich's 32detect filter + * in the Transcode project, with minor formatting changes. + * + * @param buf An hb_buffer structure holding valid frame data + * @param width The frame's width in pixels + * @param height The frame's height in pixels + * @param color_equal Sensitivity for detecting similar colors + * @param color_diff Sensitivity for detecting different colors + * @param threshold Sensitivity for flagging planes as combed + * @param prog_equal Sensitivity for detecting similar colors on progressive frames + * @param prog_diff Sensitivity for detecting different colors on progressive frames + * @param prog_threshold Sensitivity for flagging progressive frames as combed + */ +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 ) +{ + int j, k, n, off, cc_1, cc_2, cc[3], flag[3] ; + uint16_t s1, s2, s3, s4; + cc_1 = 0; cc_2 = 0; + + int offset = 0; + + if ( buf->flags & 16 ) + { + /* Frame is progressive, be more discerning. */ + color_diff = prog_diff; + color_equal = prog_equal; + threshold = prog_threshold; + } + + /* One pas for Y, one pass for Cb, one pass for Cr */ + for( k = 0; k < 3; k++ ) + { + if( k == 1 ) + { + /* Y has already been checked, now offset by Y's dimensions + and divide all the other values by 2, since Cr and Cb + are half-size compared to Y. */ + offset = width * height; + width >>= 1; + height >>= 1; + } + else if ( k == 2 ) + { + /* Y and Cb are done, so the offset needs to be bumped + so it's width*height + (width / 2) * (height / 2) */ + offset *= 5/4; + } + + for( j = 0; j < width; ++j ) + { + off = 0; + + for( n = 0; n < ( height - 4 ); n = n + 2 ) + { + /* Look at groups of 4 sequential horizontal lines */ + s1 = ( ( buf->data + offset )[ off + j ] & 0xff ); + s2 = ( ( buf->data + offset )[ off + j + width ] & 0xff ); + s3 = ( ( buf->data + offset )[ off + j + 2 * width ] & 0xff ); + s4 = ( ( buf->data + offset )[ off + j + 3 * width ] & 0xff ); + + /* Note if the 1st and 2nd lines are more different in + color than the 1st and 3rd lines are similar in color.*/ + if ( ( abs( s1 - s3 ) < color_equal ) && + ( abs( s1 - s2 ) > color_diff ) ) + ++cc_1; + + /* Note if the 2nd and 3rd lines are more different in + color than the 2nd and 4th lines are similar in color.*/ + if ( ( abs( s2 - s4 ) < color_equal ) && + ( abs( s2 - s3 ) > color_diff) ) + ++cc_2; + + /* Now move down 2 horizontal lines before starting over.*/ + off += 2 * width; + } + } + + // compare results + /* The final cc score for a plane is the percentage of combed pixels it contains. + Because sensitivity goes down to hundreths of a percent, multiply by 1000 + so it will be easy to compare against the threhold value which is an integer. */ + cc[k] = (int)( ( cc_1 + cc_2 ) * 1000.0 / ( width * height ) ); + } + + + /* HandBrake is all yuv420, so weight the average percentage of all 3 planes accordingly.*/ + int average_cc = ( 2 * cc[0] + ( cc[1] / 2 ) + ( cc[2] / 2 ) ) / 3; + + /* Now see if that average percentage of combed pixels surpasses the threshold percentage given by the user.*/ + if( average_cc > threshold ) + { +#if 0 + 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" ); +#endif + return 1; + } + +#if 0 + 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" ); +#endif + + /* Reaching this point means no combing detected. */ + return 0; + +} + /** - * Calculates job width, height, and cropping parameters. - * @param job Handle to hb_job_t. - * @param aspect Desired aspect ratio. Value of -1 uses title aspect. - * @param pixels Maximum desired pixel count. - * @param par If true, skip the cropping and keep-aspect-ratio stuff. + * Calculates job width and height for anamorphic content, + * + * @param job Handle to hb_job_t + * @param output_width Pointer to returned storage width + * @param output_height Pointer to returned storage height + * @param output_par_width Pointer to returned pixel width + @ param output_par_height Pointer to returned pixel height */ -void hb_set_size( hb_job_t * job, int aspect, int pixels, int par ) +void hb_set_anamorphic_size( hb_job_t * job, + int *output_width, int *output_height, + int *output_par_width, int *output_par_height ) { - hb_title_t * title = job->title; + /* "Loose" anamorphic. + - Uses mod16-compliant dimensions, + - Allows users to set the width + - Handles ITU pixel aspects + */ - int croppedWidth = title->width - title->crop[2] - title->crop[3]; - int croppedHeight = title->height - title->crop[0] - title->crop[1]; - - int croppedAspect; - if (par) + /* Set up some variables to make the math easier to follow. */ + hb_title_t * title = job->title; + int cropped_width = title->width - job->crop[2] - job->crop[3] ; + int cropped_height = title->height - job->crop[0] - job->crop[1] ; + double storage_aspect = (double)cropped_width / (double)cropped_height; + int width = job->width; + int height; // Gets set later, ignore user value + int mod = job->modulus; + double aspect = title->aspect; + + /* Gotta handle bounding dimensions differently + than for non-anamorphic encodes: + If the width is too big, just reset it with no rescaling. + Instead of using the aspect-scaled job height, + we need to see if the job width divided by the storage aspect + is bigger than the max. If so, set it to the max (this is sloppy). + If not, set job height to job width divided by storage aspect. + */ + + if ( job->maxWidth && (job->maxWidth < job->width) ) + width = job->maxWidth; + + height = (double)width / storage_aspect; + if ( job->maxHeight && (job->maxHeight < height) ) { - /* That means we're setting size for video with non-square pixels */ - croppedAspect = croppedWidth * HB_ASPECT_BASE / croppedHeight; - aspect = croppedAspect; + height = job->maxHeight; + } + else + { + height = (double)width / storage_aspect; } + + + /* Time to get picture dimensions that divide cleanly. + These variables will store temporary dimensions as we iterate. */ + int i, w, h; + + /* In case the user specified a modulus, use it */ + if (job->modulus) + mod = job->modulus; else + mod = 16; + + /* Iterate through multiples of mod to find one close to job->width. */ + for( i = 1;; i++ ) { - /* We're free to change cropping and maintain display aspect ratio */ - croppedAspect = title->aspect * title->height * croppedWidth / - croppedHeight / title->width; - - int addCrop; + w = mod * i; - if( aspect <= 0 ) + if (w < width) { - /* Keep the best possible aspect ratio */ - aspect = croppedAspect; + if ( ( width - w ) <= ( mod / 2 ) ) + /* We'll take a width that's + smaller, but close enough. */ + break; } - - /* Crop if necessary to obtain the desired ratio */ - memcpy( job->crop, title->crop, 4 * sizeof( int ) ); - if( aspect < croppedAspect ) + if (w == width) + /* Mod 16 dimensions, how nice! */ + break; + if( w > width ) { - /* Need to crop on the left and right */ - addCrop = croppedWidth - aspect * croppedHeight * title->width / - title->aspect / title->height; - if( addCrop & 3 ) + if ( ( w - width ) < (mod/2) ) + /* We'll take a width that's bigger, if we have to. */ + break; + } + } + width = mod * (i); + + /* Now do the same for a mod-friendly value near job->height. */ + for( i = 1;; i++) + { + h = i * mod; + + if (h < height) { - addCrop = ( addCrop + 1 ) / 2; - job->crop[2] += addCrop; - job->crop[3] += addCrop; + if ( ( height - h ) <= ( mod / 2 )) + /* Go with a smaller height, + if it's close enough. */ + break; } - else if( addCrop & 2 ) + if (h == height) + /* Mod 16 dimensions, how nice! */ + break; + + if ( h > height) + { + if ( ( h - height ) < ( mod / 2 )) + /* Use a taller height if necessary */ + break; + } + } + height = mod * (i); + + int pixel_aspect_width = job->pixel_aspect_width; + int pixel_aspect_height = job->pixel_aspect_height; + + /* If a source was really 704*480 and hard matted with cropping + to 720*480, replace the PAR values with the ITU broadcast ones. */ + if (title->width == 720 && cropped_width <= 706) + { + // convert aspect to a scaled integer so we can test for 16:9 & 4:3 + // aspect ratios ignoring insignificant differences in the LSBs of + // the floating point representation. + int iaspect = aspect * 9.; + + /* Handle ITU PARs */ + if (title->height == 480) + { + /* It's NTSC */ + if (iaspect == 16) { - addCrop /= 2; - job->crop[2] += addCrop - 1; - job->crop[3] += addCrop + 1; + /* It's widescreen */ + pixel_aspect_width = 40; + pixel_aspect_height = 33; } - else + else if (iaspect == 12) { - addCrop /= 2; - job->crop[2] += addCrop; - job->crop[3] += addCrop; + /* It's 4:3 */ + pixel_aspect_width = 10; + pixel_aspect_height = 11; } } - else if( aspect > croppedAspect ) + else if (title->height == 576) { - /* Need to crop on the top and bottom */ - addCrop = croppedHeight - croppedWidth * title->aspect * - title->height / aspect / title->width; - if( addCrop & 3 ) + /* It's PAL */ + if(iaspect == 16) { - addCrop = ( addCrop + 1 ) / 2; - job->crop[0] += addCrop; - job->crop[1] += addCrop; + /* It's widescreen */ + pixel_aspect_width = 16; + pixel_aspect_height = 11; } - else if( addCrop & 2 ) + else if (iaspect == 12) { - addCrop /= 2; - job->crop[0] += addCrop - 1; - job->crop[1] += addCrop + 1; - } - else - { - addCrop /= 2; - job->crop[0] += addCrop; - job->crop[1] += addCrop; + /* It's 4:3 */ + pixel_aspect_width = 12; + pixel_aspect_height = 11; } } - } - + + /* Figure out what dimensions the source would display at. */ + int source_display_width = cropped_width * (double)pixel_aspect_width / + (double)pixel_aspect_height ; + + /* The film AR is the source's display width / cropped source height. + The output display width is the output height * film AR. + The output PAR is the output display width / output storage width. */ + pixel_aspect_width = height * source_display_width / cropped_height; + pixel_aspect_height = width; + + /* Pass the results back to the caller */ + *output_width = width; + *output_height = height; + + /* While x264 is smart enough to reduce fractions on its own, libavcodec + needs some help with the math, so lose superfluous factors. */ + hb_reduce( output_par_width, output_par_height, + pixel_aspect_width, pixel_aspect_height ); +} + +/** + * Calculates job width, height, and cropping parameters. + * @param job Handle to hb_job_t. + * @param aspect Desired aspect ratio. Value of -1 uses title aspect. + * @param pixels Maximum desired pixel count. + */ +void hb_set_size( hb_job_t * job, double aspect, int pixels ) +{ + hb_title_t * title = job->title; + + int croppedWidth = title->width - title->crop[2] - title->crop[3]; + int croppedHeight = title->height - title->crop[0] - title->crop[1]; + double croppedAspect = title->aspect * title->height * croppedWidth / + croppedHeight / title->width; + int addCrop; int i, w, h; + + if( aspect <= 0 ) + { + /* Keep the best possible aspect ratio */ + aspect = croppedAspect; + } + + /* Crop if necessary to obtain the desired ratio */ + memcpy( job->crop, title->crop, 4 * sizeof( int ) ); + if( aspect < croppedAspect ) + { + /* Need to crop on the left and right */ + addCrop = croppedWidth - aspect * croppedHeight * title->width / + title->aspect / title->height; + if( addCrop & 3 ) + { + addCrop = ( addCrop + 1 ) / 2; + job->crop[2] += addCrop; + job->crop[3] += addCrop; + } + else if( addCrop & 2 ) + { + addCrop /= 2; + job->crop[2] += addCrop - 1; + job->crop[3] += addCrop + 1; + } + else + { + addCrop /= 2; + job->crop[2] += addCrop; + job->crop[3] += addCrop; + } + } + else if( aspect > croppedAspect ) + { + /* Need to crop on the top and bottom */ + addCrop = croppedHeight - croppedWidth * title->aspect * + title->height / aspect / title->width; + if( addCrop & 3 ) + { + addCrop = ( addCrop + 1 ) / 2; + job->crop[0] += addCrop; + job->crop[1] += addCrop; + } + else if( addCrop & 2 ) + { + addCrop /= 2; + job->crop[0] += addCrop - 1; + job->crop[1] += addCrop + 1; + } + else + { + addCrop /= 2; + job->crop[0] += addCrop; + job->crop[1] += addCrop; + } + } + /* Compute a resolution from the number of pixels and aspect */ for( i = 0;; i++ ) { w = 16 * i; - h = MULTIPLE_16( w * HB_ASPECT_BASE / aspect ); + h = MULTIPLE_16( (int)( (double)w / aspect ) ); if( w * h > pixels ) { break; @@ -527,7 +806,7 @@ void hb_set_size( hb_job_t * job, int aspect, int pixels, int par ) } i--; job->width = 16 * i; - job->height = MULTIPLE_16( 16 * i * HB_ASPECT_BASE / aspect ); + job->height = MULTIPLE_16( (int)( (double)job->width / aspect ) ); } /** @@ -566,7 +845,7 @@ void hb_add( hb_handle_t * h, hb_job_t * job ) hb_job_t * job_copy; hb_title_t * title, * title_copy; hb_chapter_t * chapter, * chapter_copy; - hb_audio_t * audio, * audio_copy; + hb_audio_t * audio; hb_subtitle_t * subtitle, * subtitle_copy; int i; char audio_lang[4]; @@ -588,21 +867,11 @@ void hb_add( hb_handle_t * h, hb_job_t * job ) /* Copy the audio track(s) we want */ title_copy->list_audio = hb_list_init(); - /* Do nothing about audio during first pass */ - if( job->pass == 0 || job->pass == 2 ) + for( i = 0; i < hb_list_count(job->list_audio); i++ ) { - for( i = 0; i < 8; i++ ) + if( ( audio = hb_list_item( job->list_audio, i ) ) ) { - if( job->audios[i] < 0 ) - { - break; - } - if( ( audio = hb_list_item( title->list_audio, job->audios[i] ) ) ) - { - audio_copy = malloc( sizeof( hb_audio_t ) ); - memcpy( audio_copy, audio, sizeof( hb_audio_t ) ); - hb_list_add( title_copy->list_audio, audio_copy ); - } + hb_list_add( title_copy->list_audio, hb_audio_copy(audio) ); } } @@ -628,19 +897,15 @@ void hb_add( hb_handle_t * h, hb_job_t * job ) memset( audio_lang, 0, sizeof( audio_lang ) ); if ( job->indepth_scan || job->native_language ) { - + /* * Find the first audio language that is being encoded */ - for( i = 0; i < 8; i++ ) + for( i = 0; i < hb_list_count(job->list_audio); i++ ) { - if( job->audios[i] < 0 ) + if( ( audio = hb_list_item( job->list_audio, i ) ) ) { - break; - } - if( ( audio = hb_list_item( title->list_audio, job->audios[i] ) ) ) - { - strncpy(audio_lang, audio->iso639_2, sizeof(audio_lang)); + strncpy(audio_lang, audio->config.lang.iso639_2, sizeof(audio_lang)); break; } } @@ -649,12 +914,12 @@ void hb_add( hb_handle_t * h, hb_job_t * job ) * In all cases switch the language if we need to to our native * language. */ - if( job->native_language ) + if( job->native_language ) { - if( strncasecmp( job->native_language, audio_lang, + if( strncasecmp( job->native_language, audio_lang, sizeof( audio_lang ) ) != 0 ) - { - + { + if( job->pass != 2 ) { hb_log( "Enabled subtitles in native language '%s', audio is in '%s'", @@ -679,12 +944,12 @@ void hb_add( hb_handle_t * h, hb_job_t * job ) * If doing a subtitle scan then add all the matching subtitles for this * language. */ - if ( job->indepth_scan ) + if ( job->indepth_scan ) { - for( i=0; i < hb_list_count( title->list_subtitle ); i++ ) + for( i=0; i < hb_list_count( title->list_subtitle ); i++ ) { subtitle = hb_list_item( title->list_subtitle, i ); - if( strcmp( subtitle->iso639_2, audio_lang ) == 0 ) + if( strcmp( subtitle->iso639_2, audio_lang ) == 0 ) { /* * Matched subtitle language with audio language, so @@ -721,17 +986,17 @@ void hb_add( hb_handle_t * h, hb_job_t * job ) /* * Definitely not doing a subtitle scan. */ - if( job->pass != 1 && job->native_language ) + if( job->pass != 1 && job->native_language ) { /* * We are not doing a subtitle scan but do want the - * native langauge subtitle selected, so select it + * native langauge subtitle selected, so select it * for pass 0 or pass 2 of a two pass. */ - for( i=0; i < hb_list_count( title->list_subtitle ); i++ ) + for( i=0; i < hb_list_count( title->list_subtitle ); i++ ) { subtitle = hb_list_item( title->list_subtitle, i ); - if( strcmp( subtitle->iso639_2, audio_lang ) == 0 ) + if( strcmp( subtitle->iso639_2, audio_lang ) == 0 ) { /* * Matched subtitle language with audio language, so @@ -749,7 +1014,7 @@ void hb_add( hb_handle_t * h, hb_job_t * job ) * bother adding them for pass 0 or pass 2 of a two * pass. */ - if( job->pass != 1 ) + if( job->pass != 1 ) { if( ( subtitle = hb_list_item( title->list_subtitle, job->subtitle ) ) ) { @@ -767,6 +1032,7 @@ void hb_add( hb_handle_t * h, hb_job_t * job ) memcpy( job_copy, job, sizeof( hb_job_t ) ); title_copy->job = job_copy; job_copy->title = title_copy; + job_copy->list_audio = title_copy->list_audio; job_copy->file = strdup( job->file ); job_copy->h = h; job_copy->pause = h->pause_lock; @@ -776,14 +1042,28 @@ void hb_add( hb_handle_t * h, hb_job_t * job ) { int i; int filter_count = hb_list_count( job->filters ); - job_copy->filters = hb_list_init(); + job_copy->filters = hb_list_init(); for( i = 0; i < filter_count; i++ ) { + /* + * Copy the filters, since the MacGui reuses the global filter objects + * meaning that queued up jobs overwrite the previous filter settings. + * In reality, settings is probably the only field that needs duplicating + * since it's the only value that is ever changed. But name is duplicated + * as well for completeness. Not copying private_data since it gets + * created for each job in renderInit. + */ hb_filter_object_t * filter = hb_list_item( job->filters, i ); - hb_list_add( job_copy->filters, filter ); - } + hb_filter_object_t * filter_copy = malloc( sizeof( hb_filter_object_t ) ); + memcpy( filter_copy, filter, sizeof( hb_filter_object_t ) ); + if( filter->name ) + filter_copy->name = strdup( filter->name ); + if( filter->settings ) + filter_copy->settings = strdup( filter->settings ); + hb_list_add( job_copy->filters, filter_copy ); + } } - + /* Add the job to the list */ hb_list_add( h->jobs, job_copy ); h->job_count = hb_count(h); @@ -798,7 +1078,7 @@ void hb_add( hb_handle_t * h, hb_job_t * job ) void hb_rem( hb_handle_t * h, hb_job_t * job ) { hb_list_rem( h->jobs, job ); - + h->job_count = hb_count(h); if (h->job_count_permanent) h->job_count_permanent--; @@ -829,6 +1109,7 @@ void hb_start( hb_handle_t * h ) p.hours = -1; p.minutes = -1; p.seconds = -1; + p.sequence_id = 0; #undef p hb_unlock( h->state_lock ); @@ -1007,7 +1288,7 @@ static void thread_func( void * _h ) hb_lock( h->state_lock ); h->state.state = HB_STATE_WORKDONE; h->state.param.workdone.error = h->work_error; - + h->job_count = hb_count(h); if (h->job_count < 1) h->job_count_permanent = 0; @@ -1064,10 +1345,16 @@ void hb_set_state( hb_handle_t * h, hb_state_t * s ) /* XXX Hack */ if (h->job_count < 1) h->job_count_permanent = 1; - + h->state.param.working.job_cur = h->job_count_permanent - hb_list_count( h->jobs ); h->state.param.working.job_count = h->job_count_permanent; + + // Set which job is being worked on + if (h->current_job) + h->state.param.working.sequence_id = h->current_job->sequence_id; + else + h->state.param.working.sequence_id = 0; } hb_unlock( h->state_lock ); hb_unlock( h->pause_lock );