diff options
author | eddyg <[email protected]> | 2007-08-21 03:24:39 +0000 |
---|---|---|
committer | eddyg <[email protected]> | 2007-08-21 03:24:39 +0000 |
commit | b4be9fecbbe66767fcf3b25aec8628d3f6b789ec (patch) | |
tree | b14084f5f504abc08826d2cd7662f21c7b0e5982 /libhb | |
parent | a035bfd29afeb4560d85a295a405a83b76e68784 (diff) |
Add Subtitle scanning for forced subtitles and normal subtitles from the CLI
and the MacOS GUI. See the new subtitle language options in the GUI.
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@844 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'libhb')
-rw-r--r-- | libhb/common.h | 3 | ||||
-rw-r--r-- | libhb/decsub.c | 33 | ||||
-rw-r--r-- | libhb/dvd.c | 18 | ||||
-rw-r--r-- | libhb/encavcodec.c | 2 | ||||
-rw-r--r-- | libhb/hb.c | 35 | ||||
-rw-r--r-- | libhb/internal.h | 2 | ||||
-rw-r--r-- | libhb/muxcommon.c | 8 | ||||
-rw-r--r-- | libhb/reader.c | 20 | ||||
-rw-r--r-- | libhb/render.c | 2 | ||||
-rw-r--r-- | libhb/work.c | 83 |
10 files changed, 162 insertions, 44 deletions
diff --git a/libhb/common.h b/libhb/common.h index 22591c602..416a93eb6 100644 --- a/libhb/common.h +++ b/libhb/common.h @@ -145,7 +145,7 @@ struct hb_job_s vquality: output quality (0.0..1.0) if < 0.0 or > 1.0, bitrate is used instead vbitrate: output bitrate (kbps) - pass: 0, 1 or 2 + pass: 0, 1 or 2 (or -1 for scan) vrate, vrate_base: output framerate is vrate / vrate_base h264_level: boolean for whether or not we're encoding for iPod crf: boolean for whether to use constant rate factor with x264 @@ -378,6 +378,7 @@ struct hb_subtitle_s char iso639_2[4]; int hits; /* How many hits/occurrences of this subtitle */ + int forced_hits; /* How many forced hits in this subtitle */ #ifdef __LIBHB__ /* Internal data */ diff --git a/libhb/decsub.c b/libhb/decsub.c index 443c0865a..ee269c53b 100644 --- a/libhb/decsub.c +++ b/libhb/decsub.c @@ -22,6 +22,7 @@ struct hb_work_private_s int y; int width; int height; + int stream_id; int offsets[2]; uint8_t lum[4]; @@ -53,6 +54,8 @@ int decsubWork( hb_work_object_t * w, hb_buffer_t ** buf_in, int size_sub, size_rle; + pv->stream_id = in->id; + size_sub = ( in->data[0] << 8 ) | in->data[1]; size_rle = ( in->data[2] << 8 ) | in->data[3]; @@ -129,8 +132,9 @@ static void ParseControls( hb_work_object_t * w ) hb_work_private_t * pv = w->private_data; hb_job_t * job = pv->job; hb_title_t * title = job->title; + hb_subtitle_t * subtitle; - int i; + int i, n; int command; int date, next; @@ -164,6 +168,23 @@ static void ParseControls( hb_work_object_t * w ) case 0x00: // 0x00 - FSTA_DSP - Forced Start Display, no arguments pv->pts_start = pv->pts + date * 900; pv->pts_forced = 1; + + /* + * If we are doing a subtitle scan then note down + */ + if( job->subtitle_scan ) + { + for( n=0; n < hb_list_count(title->list_subtitle); n++ ) + { + subtitle = hb_list_item( title->list_subtitle, n); + if( pv->stream_id == subtitle->id ) { + /* + * A hit, count it. + */ + subtitle->forced_hits++; + } + } + } break; case 0x01: // 0x01 - STA_DSP - Start Display, no arguments @@ -215,7 +236,7 @@ static void ParseControls( hb_work_object_t * w ) pv->chromaU[3-j], pv->chromaV[3-j]); */ - } + } i += 2; break; } @@ -412,17 +433,19 @@ static hb_buffer_t * Decode( hb_work_object_t * w ) /* Get infos about the subtitle */ ParseControls( w ); - if( job->subtitle_force && pv->pts_forced == 0 ) + if( job->subtitle_scan || ( job->subtitle_force && pv->pts_forced == 0 ) ) { /* + * Don't encode subtitles when doing a scan. + * * When forcing subtitles, ignore all those that don't * have the forced flag set. */ return NULL; - } + } /* Do the actual decoding now */ - buf_raw = malloc( pv->width * pv->height * 4 ); + buf_raw = malloc( ( pv->width * pv->height ) * 4 ); #define GET_NEXT_NIBBLE code = ( code << 4 ) | ( ( ( *offset & 1 ) ? \ ( pv->buf[((*offset)>>1)] & 0xF ) : ( pv->buf[((*offset)>>1)] >> 4 ) ) ); \ diff --git a/libhb/dvd.c b/libhb/dvd.c index 870664f2c..c231b378c 100644 --- a/libhb/dvd.c +++ b/libhb/dvd.c @@ -654,9 +654,23 @@ int hb_dvd_read( hb_dvd_t * d, hb_buffer_t * b ) for( ;; ) { - int block, pack_len, next_vobu; + int block, pack_len, next_vobu, read_retry; - if( DVDReadBlocks( d->file, d->next_vobu, 1, b->data ) != 1 ) + for( read_retry = 0; read_retry < 3; read_retry++ ) + { + if( DVDReadBlocks( d->file, d->next_vobu, 1, b->data ) == 1 ) + { + /* + * Successful read. + */ + break; + } else { + hb_log( "dvd: Read Error on blk %d, attempt %d", + d->next_vobu, read_retry ); + } + } + + if( read_retry == 3 ) { hb_log( "dvd: Unrecoverable Read Error from DVD, potential HD or DVD Failure (blk: %d)", d->next_vobu ); return 0; diff --git a/libhb/encavcodec.c b/libhb/encavcodec.c index 7bccfc759..85aa6085f 100644 --- a/libhb/encavcodec.c +++ b/libhb/encavcodec.c @@ -87,7 +87,7 @@ int encavcodecInit( hb_work_object_t * w, hb_job_t * job ) context->flags |= CODEC_FLAG_GRAY; } - if( job->pass ) + if( job->pass != 0 && job->pass != -1 ) { char filename[1024]; memset( filename, 0, 1024 ); hb_get_tempory_filename( job->h, filename, "ffmpeg.log" ); diff --git a/libhb/hb.c b/libhb/hb.c index 861da0702..4ffb62c85 100644 --- a/libhb/hb.c +++ b/libhb/hb.c @@ -23,6 +23,7 @@ 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; @@ -186,6 +187,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; @@ -509,6 +511,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. @@ -542,7 +549,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++ ) { @@ -562,19 +569,21 @@ void hb_add( hb_handle_t * h, hb_job_t * job ) title_copy->list_subtitle = hb_list_init(); /* - * 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. + * 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. + * 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. + * 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. + * 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 ) ); @@ -666,7 +675,7 @@ void hb_add( hb_handle_t * h, hb_job_t * job ) { /* * Don't add subtitles here, we'll add them via select_subtitle - * at the end of pass 1 + * at the end of the subtitle_scan. */ } else { /* @@ -786,7 +795,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 ); } /** diff --git a/libhb/internal.h b/libhb/internal.h index b4870a128..cf0f7fade 100644 --- a/libhb/internal.h +++ b/libhb/internal.h @@ -86,7 +86,7 @@ hb_thread_t * hb_update_init( int * build, char * version ); hb_thread_t * hb_scan_init( hb_handle_t *, const char * path, int title_index, hb_list_t * list_title ); hb_thread_t * hb_work_init( hb_list_t * jobs, int cpu_count, - volatile int * die, int * error ); + volatile int * die, int * error, hb_job_t ** job ); hb_thread_t * hb_reader_init( hb_job_t * ); hb_thread_t * hb_muxer_init( hb_job_t * ); diff --git a/libhb/muxcommon.c b/libhb/muxcommon.c index 009b81bd6..d6a8270da 100644 --- a/libhb/muxcommon.c +++ b/libhb/muxcommon.c @@ -65,7 +65,7 @@ static void MuxerFunc( void * _mux ) hb_mux_object_t * m = NULL; /* Get a real muxer */ - if( job->pass != 1 ) + if( job->pass == 0 || job->pass == 2) { switch( job->mux ) { @@ -114,7 +114,7 @@ static void MuxerFunc( void * _mux ) } /* Create file, write headers */ - if( job->pass != 1 ) + if( job->pass == 0 || job->pass == 2 ) { m->init( m ); } @@ -148,7 +148,7 @@ static void MuxerFunc( void * _mux ) // thread_sleep_interval = MAX(1, (thread_sleep_interval - 1)); buf = hb_fifo_get( track->fifo ); - if( job->pass != 1 ) + if( job->pass == 0 || job->pass == 2 ) { m->mux( m, track->mux_data, buf ); track->frames += 1; @@ -158,7 +158,7 @@ static void MuxerFunc( void * _mux ) hb_buffer_close( &buf ); } - if( job->pass != 1 ) + if( job->pass == 0 || job->pass == 2 ) { struct stat sb; uint64_t bytes_total, frames_total; diff --git a/libhb/reader.c b/libhb/reader.c index 335dfb80d..8980c1cc6 100644 --- a/libhb/reader.c +++ b/libhb/reader.c @@ -172,12 +172,23 @@ static hb_fifo_t * GetFifoForId( hb_job_t * job, int id ) if( id == 0xE0 ) { - return job->fifo_mpeg2; + if( !job->subtitle_scan ) + { + return job->fifo_mpeg2; + } else { + /* + * Ditch the mpeg2 video when doing a subtitle scan. + */ + return NULL; + } } if (job->subtitle_scan) { /* - * Count the occurances of the subtitles, don't actually return any to encode. + * Count the occurances of the subtitles, don't actually + * return any to encode unless we are looking fro forced + * subtitles in which case we need to look in the sub picture + * to see if it has the forced flag enabled. */ for (i=0; i < hb_list_count(title->list_subtitle); i++) { subtitle = hb_list_item( title->list_subtitle, i); @@ -186,6 +197,11 @@ static hb_fifo_t * GetFifoForId( hb_job_t * job, int id ) * A hit, count it. */ subtitle->hits++; + if( job->subtitle_force ) + { + return subtitle->fifo_in; + } + break; } } } else { diff --git a/libhb/render.c b/libhb/render.c index a8abd0e75..e8fe0aef2 100644 --- a/libhb/render.c +++ b/libhb/render.c @@ -112,7 +112,7 @@ static void ApplySub( hb_job_t * job, hb_buffer_t * buf, * Merge the luminance and alpha with the picture */ out[j] = ( (uint16_t) out[j] * ( 16 - (uint16_t) alpha[j] ) + - (uint16_t) lum[j] * (uint16_t) alpha[j] ) >> 4; + (uint16_t) lum[j] * (uint16_t) alpha[j] ) >> 4; /* * Set the chroma (colour) based on whether there is * any alpha at all. Don't try to blend with the picture. diff --git a/libhb/work.c b/libhb/work.c index 77e0c921c..0302a3d14 100644 --- a/libhb/work.c +++ b/libhb/work.c @@ -11,6 +11,7 @@ typedef struct { hb_list_t * jobs; + hb_job_t ** current_job; int cpu_count; int * error; volatile int * die; @@ -29,11 +30,12 @@ static void work_loop( void * ); * @param error Handle to error indicator. */ hb_thread_t * hb_work_init( hb_list_t * jobs, int cpu_count, - volatile int * die, int * error ) + volatile int * die, int * error, hb_job_t ** job ) { hb_work_t * work = calloc( sizeof( hb_work_t ), 1 ); work->jobs = jobs; + work->current_job = job; work->cpu_count = cpu_count; work->die = die; work->error = error; @@ -56,7 +58,9 @@ static void work_func( void * _work ) { hb_list_rem( work->jobs, job ); job->die = work->die; + *(work->current_job) = job; do_job( job, work->cpu_count ); + *(work->current_job) = NULL; } *(work->error) = HB_ERROR_NONE; @@ -96,6 +100,7 @@ static void do_job( hb_job_t * job, int cpu_count ) /* FIXME: This feels really hackish, anything better? */ hb_work_object_t * audio_w = NULL; + hb_work_object_t * sub_w = NULL; hb_audio_t * audio; hb_subtitle_t * subtitle; @@ -104,6 +109,7 @@ static void do_job( hb_job_t * job, int cpu_count ) unsigned int subtitle_highest_id = 0; unsigned int subtitle_lowest = -1; unsigned int subtitle_lowest_id = 0; + unsigned int subtitle_forced_id = 0; unsigned int subtitle_hit = 0; title = job->title; @@ -217,7 +223,10 @@ static void do_job( hb_job_t * job, int cpu_count ) * add the subtitle that we found on the first pass for use in this * pass. */ - hb_list_add( title->list_subtitle, *( job->select_subtitle ) ); + if (*(job->select_subtitle)) + { + hb_list_add( title->list_subtitle, *( job->select_subtitle ) ); + } } for( i=0; i < hb_list_count(title->list_subtitle); i++ ) @@ -231,13 +240,40 @@ static void do_job( hb_job_t * job, int cpu_count ) subtitle->fifo_in = hb_fifo_init( 8 ); subtitle->fifo_raw = hb_fifo_init( 8 ); - if (!job->subtitle_scan) { + /* + * Disable forced subtitles if we didn't find any in the scan + * so that we display normal subtitles instead. + * + * select_subtitle implies that we did a scan. + */ + if( !job->subtitle_scan && job->subtitle_force && + job->select_subtitle ) + { + if( subtitle->forced_hits == 0 ) + { + job->subtitle_force = 0; + } + } + + if (!job->subtitle_scan || job->subtitle_force) { /* - * Don't add threads for subtitles when we are scanning + * Don't add threads for subtitles when we are scanning, unless + * looking for forced subtitles. */ - hb_list_add( job->list_work, ( w = getWork( WORK_DECSUB ) ) ); - w->fifo_in = subtitle->fifo_in; - w->fifo_out = subtitle->fifo_raw; + if( sub_w != NULL ) + { + /* + * Need to copy the prior subtitle structure so that we + * don't overwrite the fifos. + */ + sub_w = calloc( sizeof( hb_work_object_t ), 1 ); + sub_w = memcpy( sub_w, w, sizeof( hb_work_object_t )); + } else { + w = sub_w = getWork( WORK_DECSUB ); + } + hb_list_add( job->list_work, sub_w ); + sub_w->fifo_in = subtitle->fifo_in; + sub_w->fifo_out = subtitle->fifo_raw; } } } @@ -563,8 +599,9 @@ static void do_job( hb_job_t * job, int cpu_count ) for( i=0; i < hb_list_count( title->list_subtitle ); i++ ) { subtitle = hb_list_item( title->list_subtitle, i ); - hb_log( "Subtitle stream 0x%x '%s': %d hits", - subtitle->id, subtitle->lang, subtitle->hits ); + hb_log( "Subtitle stream 0x%x '%s': %d hits (%d forced)", + subtitle->id, subtitle->lang, subtitle->hits, + subtitle->forced_hits ); if( subtitle->hits > subtitle_highest ) { subtitle_highest = subtitle->hits; @@ -576,6 +613,11 @@ static void do_job( hb_job_t * job, int cpu_count ) subtitle_lowest = subtitle->hits; subtitle_lowest_id = subtitle->id; } + + if ( subtitle->forced_hits > 0 ) + { + subtitle_forced_id = subtitle->id; + } } if( job->native_language ) { @@ -587,11 +629,21 @@ static void do_job( hb_job_t * job, int cpu_count ) subtitle_hit = subtitle_highest_id; hb_log( "Found a native-language subtitle id 0x%x", subtitle_hit); } else { - if( subtitle_lowest < subtitle_highest ) + if( subtitle_forced_id ) + { + /* + * If there are any subtitle streams with forced subtitles + * then select it in preference to the lowest. + */ + subtitle_hit = subtitle_forced_id; + hb_log("Found a subtitle candidate id 0x%x (contains forced subs)", + subtitle_hit); + } else if( subtitle_lowest < subtitle_highest ) { /* - * OK we have more than one, and the lowest is lower, but how much - * lower to qualify for turning it on by default? + * OK we have more than one, and the lowest is lower, + * but how much lower to qualify for turning it on by + * default? * * Let's say 10% as a default. */ @@ -614,7 +666,7 @@ static void do_job( hb_job_t * job, int cpu_count ) for( i=0; i < hb_list_count( title->list_subtitle ); i++ ) { subtitle = hb_list_item( title->list_subtitle, i ); - if( subtitle->id = subtitle_hit ) + if( subtitle->id == subtitle_hit ) { hb_list_rem( title->list_subtitle, subtitle ); *( job->select_subtitle ) = subtitle; @@ -622,7 +674,10 @@ static void do_job( hb_job_t * job, int cpu_count ) } } else { /* - * Must be the second pass - we don't need this anymore. + * Must be the end of pass 0 or 2 - we don't need this anymore. + * + * Have to put the subtitle list back together in the title though + * or the GUI will have a hissy fit. */ free( job->select_subtitle ); job->select_subtitle = NULL; |