summaryrefslogtreecommitdiffstats
path: root/libhb
diff options
context:
space:
mode:
authoreddyg <[email protected]>2007-08-21 03:24:39 +0000
committereddyg <[email protected]>2007-08-21 03:24:39 +0000
commitb4be9fecbbe66767fcf3b25aec8628d3f6b789ec (patch)
treeb14084f5f504abc08826d2cd7662f21c7b0e5982 /libhb
parenta035bfd29afeb4560d85a295a405a83b76e68784 (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.h3
-rw-r--r--libhb/decsub.c33
-rw-r--r--libhb/dvd.c18
-rw-r--r--libhb/encavcodec.c2
-rw-r--r--libhb/hb.c35
-rw-r--r--libhb/internal.h2
-rw-r--r--libhb/muxcommon.c8
-rw-r--r--libhb/reader.c20
-rw-r--r--libhb/render.c2
-rw-r--r--libhb/work.c83
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;