X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=libhb%2Fhb.c;h=a53bd1f4a50879f6328f94fea998d536e06ba93b;hb=516553c65ad905dad51054dffb76fee8f217a1c9;hp=e9d7aa129ecde0b82b65bdbccddedbeed8a7599c;hpb=8888fe1daf29d0194b6958f544125fb7036a9e03;p=handbrake-jp%2Fhandbrake-jp-git.git diff --git a/libhb/hb.c b/libhb/hb.c index e9d7aa12..a53bd1f4 100644 --- a/libhb/hb.c +++ b/libhb/hb.c @@ -1,6 +1,7 @@ #include "hb.h" #include "ffmpeg/avcodec.h" +#include "ffmpeg/swscale.h" struct hb_handle_s { @@ -22,7 +23,9 @@ struct hb_handle_s /* The thread which processes the jobs. Others threads are launched from this one (see work.c) */ hb_list_t * jobs; + hb_job_t * current_job; int job_count; + int job_count_permanent; volatile int work_die; int work_error; hb_thread_t * work_thread; @@ -31,9 +34,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; @@ -97,6 +104,11 @@ hb_handle_t * hb_init_real( int verbose, int update_check ) } } + /* + * Initialise buffer pool + */ + hb_buffer_pool_init(); + /* CPU count detection */ hb_log( "hb_init: checking cpu count" ); h->cpu_count = hb_get_cpu_count(); @@ -111,10 +123,9 @@ hb_handle_t * hb_init_real( int verbose, int update_check ) /* libavcodec */ avcodec_init(); - register_avcodec( &mpeg4_encoder ); - register_avcodec( &mp2_decoder ); - register_avcodec( &ac3_encoder ); - + avcodec_register_all(); + av_register_codec_parser( &mpegaudio_parser); + /* Start library thread */ hb_log( "hb_init: starting libhb thread" ); h->die = 0; @@ -122,6 +133,9 @@ 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; } /** @@ -178,6 +192,7 @@ hb_handle_t * hb_init_dl( int verbose, int update_check ) h->list_title = hb_list_init(); h->jobs = hb_list_init(); + h->current_job = NULL; h->state_lock = hb_lock_init(); h->state.state = HB_STATE_IDLE; @@ -186,9 +201,7 @@ hb_handle_t * hb_init_dl( int verbose, int update_check ) /* libavcodec */ avcodec_init(); - register_avcodec( &mpeg4_encoder ); - register_avcodec( &mp2_decoder ); - register_avcodec( &ac3_encoder ); + avcodec_register_all(); /* Start library thread */ hb_log( "hb_init: starting libhb thread" ); @@ -204,6 +217,7 @@ hb_handle_t * hb_init_dl( int verbose, int update_check ) 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 ); @@ -304,23 +318,25 @@ void hb_get_preview( hb_handle_t * h, hb_title_t * title, int picture, FILE * file; uint8_t * buf1, * buf2, * buf3, * buf4, * pen; uint32_t * p32; - AVPicture pic1, pic2, pic3, pic4; - ImgReSampleContext * context; + AVPicture pic_in, pic_preview, pic_deint, pic_crop, pic_scale; + struct SwsContext * context; int i; buf1 = malloc( title->width * title->height * 3 / 2 ); buf2 = malloc( title->width * title->height * 3 / 2 ); buf3 = malloc( title->width * title->height * 3 / 2 ); buf4 = malloc( title->width * title->height * 4 ); - avpicture_fill( &pic1, buf1, PIX_FMT_YUV420P, + avpicture_fill( &pic_in, buf1, PIX_FMT_YUV420P, title->width, title->height ); - avpicture_fill( &pic2, buf2, PIX_FMT_YUV420P, + avpicture_fill( &pic_deint, buf2, PIX_FMT_YUV420P, title->width, title->height ); - avpicture_fill( &pic3, buf3, PIX_FMT_YUV420P, + avpicture_fill( &pic_scale, buf3, PIX_FMT_YUV420P, job->width, job->height ); - avpicture_fill( &pic4, buf4, PIX_FMT_RGBA32, + avpicture_fill( &pic_preview, buf4, PIX_FMT_RGBA32, job->width, job->height ); - + + // Allocate the AVPicture frames and fill in + memset( filename, 0, 1024 ); hb_get_tempory_filename( h, filename, "%x%d", @@ -336,23 +352,47 @@ void hb_get_preview( hb_handle_t * h, hb_title_t * title, int picture, fread( buf1, title->width * title->height * 3 / 2, 1, file ); fclose( file ); - context = img_resample_full_init( - job->width, job->height, title->width, title->height, - job->crop[0], job->crop[1], job->crop[2], job->crop[3], - 0, 0, 0, 0 ); - if( job->deinterlace ) { - avpicture_deinterlace( &pic2, &pic1, PIX_FMT_YUV420P, - title->width, title->height ); - img_resample( context, &pic3, &pic2 ); + // Deinterlace and crop + avpicture_deinterlace( &pic_deint, &pic_in, PIX_FMT_YUV420P, title->width, title->height ); + av_picture_crop( &pic_crop, &pic_deint, PIX_FMT_YUV420P, job->crop[0], job->crop[2] ); } else { - img_resample( context, &pic3, &pic1 ); + // Crop + av_picture_crop( &pic_crop, &pic_in, PIX_FMT_YUV420P, job->crop[0], job->crop[2] ); } - img_convert( &pic4, PIX_FMT_RGBA32, &pic3, PIX_FMT_YUV420P, - job->width, job->height ); + + // Get scaling context + context = sws_getContext(title->width - (job->crop[2] + job->crop[3]), + 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); + + // Scale + sws_scale(context, + pic_crop.data, pic_crop.linesize, + 0, title->height - (job->crop[0] + job->crop[1]), + pic_scale.data, pic_scale.linesize); + + // Free context + sws_freeContext( context ); + + // 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); + + // Create preview + sws_scale(context, + pic_scale.data, pic_scale.linesize, + 0, job->height, + pic_preview.data, pic_preview.linesize); + + // Free context + sws_freeContext( context ); /* Gray background */ p32 = (uint32_t *) buffer; @@ -379,10 +419,11 @@ void hb_get_preview( hb_handle_t * h, hb_title_t * title, int picture, } memset( pen, 0xFF, 4 * ( job->width + 2 ) ); - free( buf1 ); - free( buf2 ); - free( buf3 ); - free( buf4 ); + // Clean up + avpicture_free( &pic_preview ); + avpicture_free( &pic_scale ); + avpicture_free( &pic_deint ); + avpicture_free( &pic_in ); } /** @@ -495,6 +536,11 @@ hb_job_t * hb_job( hb_handle_t * h, int i ) return hb_list_item( h->jobs, i ); } +hb_job_t * hb_current_job( hb_handle_t * h ) +{ + return( h->current_job ); +} + /** * Adds a job to the job list. * @param h Handle to hb_handle_t. @@ -508,6 +554,7 @@ void hb_add( hb_handle_t * h, hb_job_t * job ) hb_audio_t * audio, * audio_copy; hb_subtitle_t * subtitle, * subtitle_copy; int i; + char audio_lang[4]; /* Copy the title */ title = job->title; @@ -527,7 +574,7 @@ void hb_add( hb_handle_t * h, hb_job_t * job ) title_copy->list_audio = hb_list_init(); /* Do nothing about audio during first pass */ - if( job->pass != 1 ) + if( job->pass == 0 || job->pass == 2 ) { for( i = 0; i < 8; i++ ) { @@ -544,13 +591,160 @@ void hb_add( hb_handle_t * h, hb_job_t * job ) } } - /* Copy the subtitle we want (or not) */ title_copy->list_subtitle = hb_list_init(); - if( ( subtitle = hb_list_item( title->list_subtitle, job->subtitle ) ) ) + + /* + * The following code is confusing, there are three ways in which + * we select subtitles and it depends on whether this is single or + * two pass mode. + * + * subtitle_scan may be enabled, in which case the first pass + * scans all subtitles of that language. The second pass does not + * select any because they are set at the end of the first pass. + * + * native_language may have a preferred language, in which case we + * may be switching the language we want for the subtitles in the + * first pass of a single pass, or the second pass of a two pass. + * + * We may have manually selected a subtitle, in which case that is + * selected in the first pass of a single pass, or the second of a + * two pass. + */ + 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++ ) + { + if( job->audios[i] < 0 ) + { + break; + } + if( ( audio = hb_list_item( title->list_audio, job->audios[i] ) ) ) + { + strncpy(audio_lang, audio->iso639_2, sizeof(audio_lang)); + break; + } + } + + /* + * In all cases switch the language if we need to to our native + * language. + */ + if( job->native_language ) + { + 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'", + job->native_language, audio_lang); + } + /* + * The main audio track is not in our native language, so switch + * the subtitles to use our native language instead. + */ + strncpy( audio_lang, job->native_language, sizeof( audio_lang ) ); + } else { + /* + * native language is irrelevent, free it. + */ + free( job->native_language ); + job->native_language = NULL; + } + } + } + + /* + * If doing a subtitle scan then add all the matching subtitles for this + * language. + */ + if ( job->indepth_scan ) { - subtitle_copy = malloc( sizeof( hb_subtitle_t ) ); - memcpy( subtitle_copy, subtitle, sizeof( hb_subtitle_t ) ); - hb_list_add( title_copy->list_subtitle, subtitle_copy ); + 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 ) + { + /* + * Matched subtitle language with audio language, so + * add this to our list to scan. + * + * We will update the subtitle list on the second pass + * later after the first pass has completed. + */ + subtitle_copy = malloc( sizeof( hb_subtitle_t ) ); + memcpy( subtitle_copy, subtitle, sizeof( hb_subtitle_t ) ); + hb_list_add( title_copy->list_subtitle, subtitle_copy ); + if ( job->native_language ) { + /* + * With native language just select the + * first match in our langiage, not all of + * them. Subsequent ones are likely to be commentary + */ + break; + } + } + } + } else { + /* + * Not doing a subtitle scan in this pass, but maybe we are in the + * first pass? + */ + if( job->select_subtitle ) + { + /* + * Don't add subtitles here, we'll add them via select_subtitle + * at the end of the subtitle_scan. + */ + } else { + /* + * Definitely not doing a subtitle scan. + */ + 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 + * for pass 0 or pass 2 of a two pass. + */ + 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 ) + { + /* + * Matched subtitle language with audio language, so + * add this to our list to scan. + */ + subtitle_copy = malloc( sizeof( hb_subtitle_t ) ); + memcpy( subtitle_copy, subtitle, sizeof( hb_subtitle_t ) ); + hb_list_add( title_copy->list_subtitle, subtitle_copy ); + break; + } + } + } else { + /* + * Manually selected subtitle, in which case only + * bother adding them for pass 0 or pass 2 of a two + * pass. + */ + if( job->pass != 1 ) + { + if( ( subtitle = hb_list_item( title->list_subtitle, job->subtitle ) ) ) + { + subtitle_copy = malloc( sizeof( hb_subtitle_t ) ); + memcpy( subtitle_copy, subtitle, sizeof( hb_subtitle_t ) ); + hb_list_add( title_copy->list_subtitle, subtitle_copy ); + } + } + } + } } /* Copy the job */ @@ -562,8 +756,23 @@ void hb_add( hb_handle_t * h, hb_job_t * job ) job_copy->h = h; job_copy->pause = h->pause_lock; + /* Copy the job filter list */ + if( job->filters ) + { + int i; + int filter_count = hb_list_count( job->filters ); + job_copy->filters = hb_list_init(); + for( i = 0; i < filter_count; i++ ) + { + hb_filter_object_t * filter = hb_list_item( job->filters, i ); + hb_list_add( job_copy->filters, filter ); + } + } + /* Add the job to the list */ hb_list_add( h->jobs, job_copy ); + h->job_count = hb_count(h); + h->job_count_permanent++; } /** @@ -574,6 +783,10 @@ 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--; /* XXX free everything XXX */ } @@ -588,6 +801,7 @@ void hb_start( hb_handle_t * h ) { /* XXX Hack */ h->job_count = hb_list_count( h->jobs ); + h->job_count_permanent = h->job_count; hb_lock( h->state_lock ); h->state.state = HB_STATE_WORKING; @@ -607,7 +821,7 @@ void hb_start( hb_handle_t * h ) h->work_die = 0; h->work_thread = hb_work_init( h->jobs, h->cpu_count, - &h->work_die, &h->work_error ); + &h->work_die, &h->work_error, &h->current_job ); } /** @@ -648,6 +862,9 @@ void hb_stop( hb_handle_t * h ) { h->work_die = 1; + h->job_count = hb_count(h); + h->job_count_permanent = 0; + hb_resume( h ); } @@ -661,11 +878,30 @@ void hb_get_state( hb_handle_t * h, hb_state_t * s ) hb_lock( h->state_lock ); memcpy( s, &h->state, sizeof( hb_state_t ) ); - h->state.state = HB_STATE_IDLE; + if ( h->state.state == HB_STATE_SCANDONE || h->state.state == HB_STATE_WORKDONE ) + h->state.state = HB_STATE_IDLE; hb_unlock( h->state_lock ); } +void hb_get_state2( hb_handle_t * h, hb_state_t * s ) +{ + hb_lock( h->state_lock ); + + memcpy( s, &h->state, sizeof( hb_state_t ) ); + + hb_unlock( h->state_lock ); +} + +/** + * Called in MacGui in UpdateUI to check + * for a new scan being completed to set a new source + */ +int hb_get_scancount( hb_handle_t * h) + { + return h->scanCount; + } + /** * Closes access to libhb by freeing the hb_handle_t handle ontained in hb_init_real. * @param _h Pointer to handle to hb_handle_t. @@ -681,6 +917,10 @@ void hb_close( hb_handle_t ** _h ) while( ( title = hb_list_item( h->list_title, 0 ) ) ) { hb_list_rem( h->list_title, title ); + if( title->job && title->job->filters ) + { + hb_list_close( &title->job->filters ); + } free( title->job ); hb_title_close( &title ); } @@ -691,6 +931,7 @@ void hb_close( hb_handle_t ** _h ) hb_lock_close( &h->pause_lock ); free( h ); *_h = NULL; + } /** @@ -733,8 +974,11 @@ static void thread_func( void * _h ) hb_log( "libhb: scan thread found %d valid title(s)", hb_list_count( h->list_title ) ); hb_lock( h->state_lock ); - h->state.state = HB_STATE_SCANDONE; - hb_unlock( h->state_lock ); + h->state.state = HB_STATE_SCANDONE; //originally state.state + hb_unlock( h->state_lock ); + /*we increment this sessions scan count by one for the MacGui + to trigger a new source being set */ + h->scanCount++; } /* Check if the work thread is done */ @@ -748,6 +992,10 @@ 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; hb_unlock( h->state_lock ); } @@ -799,9 +1047,12 @@ void hb_set_state( hb_handle_t * h, hb_state_t * s ) if( h->state.state == HB_STATE_WORKING ) { /* XXX Hack */ + if (h->job_count < 1) + h->job_count_permanent = 1; + h->state.param.working.job_cur = - h->job_count - hb_list_count( h->jobs ); - h->state.param.working.job_count = h->job_count; + h->job_count_permanent - hb_list_count( h->jobs ); + h->state.param.working.job_count = h->job_count_permanent; } hb_unlock( h->state_lock ); hb_unlock( h->pause_lock );