OSDN Git Service

Stage 1 Soft Subtitle Support - Allow multiple subtitle tracks to be selected, and...
authoreddyg <eddyg@b64f7644-9d1e-0410-96f1-a4d463321fa5>
Mon, 4 May 2009 01:39:48 +0000 (01:39 +0000)
committereddyg <eddyg@b64f7644-9d1e-0410-96f1-a4d463321fa5>
Mon, 4 May 2009 01:39:48 +0000 (01:39 +0000)
git-svn-id: svn://localhost/HandBrake/trunk@2373 b64f7644-9d1e-0410-96f1-a4d463321fa5

libhb/common.h
libhb/dvd.c
libhb/hb.c
libhb/reader.c
libhb/scan.c
libhb/sync.c
libhb/work.c
macosx/Controller.mm
test/test.c

index 60ba93e..f195110 100644 (file)
@@ -213,11 +213,9 @@ struct hb_job_s
     /* List of audio settings. */
     hb_list_t     * list_audio;
 
-    /* Subtitle settings:
-         subtitle: index in hb_title_t's subtitles list, starting
-         from 0. -1 means no subtitle */
-    int             subtitle;
-    int             subtitleSmartAdjust;
+    /* Subtitles
+     */
+    hb_list_t     * list_subtitle;
 
     /* Muxer settings
          mux:  output file format
@@ -442,7 +440,11 @@ struct hb_chapter_s
 
 struct hb_subtitle_s
 {
+    int track;
     int  id;
+    enum subtype { PICTURESUB, TEXTSUB } format;
+    enum subsource { VOBSUB, SRTSUB, CCSUB } source;
+    enum subdest { RENDERSUB, PASSTHRUSUB } dest;
     char lang[1024];
     char iso639_2[4];
     uint8_t type; /* Closed Caption, Childrens, Directors etc */
index cf6eefe..58ce9ad 100644 (file)
@@ -463,11 +463,15 @@ static hb_title_t * hb_dvdread_title_scan( hb_dvd_t * e, int t )
         lang = lang_for_code( vts->vtsi_mat->vts_subp_attr[i].lang_code );
 
         subtitle = calloc( sizeof( hb_subtitle_t ), 1 );
+        subtitle->track = i+1;
         subtitle->id = ( ( 0x20 + position ) << 8 ) | 0xbd;
         snprintf( subtitle->lang, sizeof( subtitle->lang ), "%s",
              strlen(lang->native_name) ? lang->native_name : lang->eng_name);
         snprintf( subtitle->iso639_2, sizeof( subtitle->iso639_2 ), "%s",
                   lang->iso639_2);
+        subtitle->format = PICTURESUB;
+        subtitle->source = VOBSUB;
+        subtitle->dest   = RENDERSUB;  // By default render (burn-in) the VOBSUB.
 
         subtitle->type = lang_extension;
 
index ff85249..943e238 100644 (file)
@@ -1125,17 +1125,22 @@ void hb_add( hb_handle_t * h, hb_job_t * job )
                 }
             } else {
                 /*
-                 * Manually selected subtitle, in which case only
+                 * Manually selected subtitles, 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 all of them from the input job, to the title_copy/job_copy.
+                     */
+                    for(  i = 0; i < hb_list_count(job->list_subtitle); i++ ) {
+                        if( ( subtitle = hb_list_item( job->list_subtitle, i ) ) )
+                        {
+                            subtitle_copy = malloc( sizeof( hb_subtitle_t ) );
+                            memcpy( subtitle_copy, subtitle, sizeof( hb_subtitle_t ) );
+                            hb_list_add( title_copy->list_subtitle, subtitle_copy );
+                        }
                     }
                 }
             }
@@ -1148,6 +1153,7 @@ void hb_add( hb_handle_t * h, hb_job_t * job )
     title_copy->job = job_copy;
     job_copy->title = title_copy;
     job_copy->list_audio = title_copy->list_audio;
+    job_copy->list_subtitle = title_copy->list_subtitle;   // sharing list between title and job
     job_copy->file  = strdup( job->file );
     job_copy->h     = h;
     job_copy->pause = h->pause_lock;
index 0acbe09..e034537 100644 (file)
@@ -516,37 +516,24 @@ static hb_fifo_t ** GetFifoForId( hb_job_t * job, int id )
         }
     }
 
-    if( job->indepth_scan ) {
-        /*
-         * 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);
-            if (id == subtitle->id) {
+    for( i=0; i < hb_list_count( title->list_subtitle ); i++ ) {
+        subtitle =  hb_list_item( title->list_subtitle, i );
+        if (id == subtitle->id) {
+            subtitle->hits++;
+            if( !job->indepth_scan || job->subtitle_force )
+            {
                 /*
-                 * A hit, count it.
+                 * Pass the subtitles to be processed if we are not scanning, or if
+                 * we are scanning and looking for forced subs, then pass them up
+                 * to decode whether the sub is a forced one.
                  */
-                subtitle->hits++;
-                if( job->subtitle_force )
-                {
-
-                    fifos[0] = subtitle->fifo_in;
-                    return fifos;
-                }
-                break;
+                fifos[0] = subtitle->fifo_in;
+                return fifos;
             }
-        }
-    } else {
-        if( ( subtitle = hb_list_item( title->list_subtitle, 0 ) ) &&
-            id == subtitle->id )
-        {
-            fifos[0] = subtitle->fifo_in;
-            return fifos;
+            break;
         }
     }
+    
     if( !job->indepth_scan )
     {
         n = 0;
index a549285..420904b 100644 (file)
@@ -224,8 +224,7 @@ static void ScanFunc( void * _data )
         job->vrate_base = title->rate_base;
 
         job->list_audio = hb_list_init();
-
-        job->subtitle = -1;
+        job->list_subtitle = hb_list_init();
 
         job->mux = HB_MUX_MP4;
     }
index a1a7f1a..798c01b 100644 (file)
@@ -44,7 +44,6 @@ struct hb_work_private_s
                                 // an eof buf. syncWork returns done when all
                                 // bits are clear.
     /* Video */
-    hb_subtitle_t * subtitle;
     int64_t pts_offset;
     int64_t next_start;         /* start time of next output frame */
     int64_t next_pts;           /* start time of next input frame */
@@ -125,16 +124,13 @@ int syncInit( hb_work_object_t * w, hb_job_t * job )
     /* Initialize libsamplerate for every audio track we have */
     if ( ! job->indepth_scan )
     {
-        for( i = 0; i < hb_list_count( title->list_audio ); i++ )
+        for( i = 0; i < hb_list_count( title->list_audio ) && i < 8; i++ )
         {
             pv->busy |= ( 1 << (i + 1) );
             InitAudio( w, i );
         }
     }
 
-    /* Get subtitle info, if any */
-    pv->subtitle = hb_list_item( title->list_subtitle, 0 );
-
     return 0;
 }
 
@@ -284,6 +280,8 @@ static void SyncVideo( hb_work_object_t * w )
     hb_work_private_t * pv = w->private_data;
     hb_buffer_t * cur, * next, * sub = NULL;
     hb_job_t * job = pv->job;
+    hb_subtitle_t *subtitle;
+    int i;
 
     if( !pv->cur && !( pv->cur = hb_fifo_get( job->fifo_raw ) ) )
     {
@@ -385,138 +383,160 @@ static void SyncVideo( hb_work_object_t * w )
          */
         pv->video_sequence = cur->sequence;
 
-        /* Look for a subtitle for this frame */
-        if( pv->subtitle )
+        /*
+         * Look for a subtitle for this frame.
+         *
+         * If found then it will be tagged onto a video buffer of the correct time and 
+         * sent in to the render pipeline. This only needs to be done for VOBSUBs which
+         * get rendered, other types of subtitles can just sit in their raw_queue until
+         * delt with at muxing.
+         */
+        for( i = 0; i < hb_list_count( job->list_subtitle ); i++)
         {
-            hb_buffer_t * sub2;
-            while( ( sub = hb_fifo_see( pv->subtitle->fifo_raw ) ) )
+            subtitle = hb_list_item( job->list_subtitle, i );
+            if( subtitle->dest == RENDERSUB ) 
             {
-                /* If two subtitles overlap, make the first one stop
-                   when the second one starts */
-                sub2 = hb_fifo_see2( pv->subtitle->fifo_raw );
-                if( sub2 && sub->stop > sub2->start )
-                    sub->stop = sub2->start;
-
-                // hb_log("0x%x: video seq: %lld  subtitle sequence: %lld",
-                //       sub, cur->sequence, sub->sequence);
-
-                if( sub->sequence > cur->sequence )
+                hb_buffer_t * sub2;
+                while( ( sub = hb_fifo_see( subtitle->fifo_raw ) ) )
                 {
+                    /* If two subtitles overlap, make the first one stop
+                       when the second one starts */
+                    sub2 = hb_fifo_see2( subtitle->fifo_raw );
+                    if( sub2 && sub->stop > sub2->start )
+                        sub->stop = sub2->start;
+                    
+                    // hb_log("0x%x: video seq: %lld  subtitle sequence: %lld",
+                    //       sub, cur->sequence, sub->sequence);
+                    
+                    if( sub->sequence > cur->sequence )
+                    {
+                        /*
+                         * The video is behind where we are, so wait until
+                         * it catches up to the same reader point on the
+                         * DVD. Then our PTS should be in the same region
+                         * as the video.
+                         */
+                        sub = NULL;
+                        break;
+                    }
+                    
+                    if( sub->stop > cur->start ) {
+                        /*
+                         * The stop time is in the future, so fall through
+                         * and we'll deal with it in the next block of
+                         * code.
+                         */
+                        break;
+                    }
+                    
                     /*
-                     * The video is behind where we are, so wait until
-                     * it catches up to the same reader point on the
-                     * DVD. Then our PTS should be in the same region
-                     * as the video.
-                     */
-                    sub = NULL;
-                    break;
-                }
-
-                if( sub->stop > cur->start ) {
-                    /*
-                     * The stop time is in the future, so fall through
-                     * and we'll deal with it in the next block of
-                     * code.
+                     * The subtitle is older than this picture, trash it
                      */
-                    break;
+                    sub = hb_fifo_get( subtitle->fifo_raw );
+                    hb_buffer_close( &sub );
                 }
-
+                
                 /*
-                 * The subtitle is older than this picture, trash it
+                 * There is a valid subtitle, is it time to display it?
                  */
-                sub = hb_fifo_get( pv->subtitle->fifo_raw );
-                hb_buffer_close( &sub );
-            }
-
-            /*
-             * There is a valid subtitle, is it time to display it?
-             */
-            if( sub )
-            {
-                if( sub->stop > sub->start)
+                if( sub )
                 {
-                    /*
-                     * Normal subtitle which ends after it starts, check to
-                     * see that the current video is between the start and end.
-                     */
-                    if( cur->start > sub->start &&
-                        cur->start < sub->stop )
+                    if( sub->stop > sub->start)
                     {
                         /*
-                         * We should be playing this, so leave the
-                         * subtitle in place.
-                         *
-                         * fall through to display
+                         * Normal subtitle which ends after it starts, check to
+                         * see that the current video is between the start and end.
                          */
-                        if( ( sub->stop - sub->start ) < ( 3 * 90000 ) )
+                        if( cur->start > sub->start &&
+                            cur->start < sub->stop )
                         {
                             /*
-                             * Subtitle is on for less than three seconds, extend
-                             * the time that it is displayed to make it easier
-                             * to read. Make it 3 seconds or until the next
-                             * subtitle is displayed.
+                             * We should be playing this, so leave the
+                             * subtitle in place.
                              *
-                             * This is in response to Indochine which only
-                             * displays subs for 1 second - too fast to read.
+                             * fall through to display
                              */
-                            sub->stop = sub->start + ( 3 * 90000 );
-
-                            sub2 = hb_fifo_see2( pv->subtitle->fifo_raw );
-
-                            if( sub2 && sub->stop > sub2->start )
+                            if( ( sub->stop - sub->start ) < ( 3 * 90000 ) )
                             {
-                                sub->stop = sub2->start;
+                                /*
+                                 * Subtitle is on for less than three seconds, extend
+                                 * the time that it is displayed to make it easier
+                                 * to read. Make it 3 seconds or until the next
+                                 * subtitle is displayed.
+                                 *
+                                 * This is in response to Indochine which only
+                                 * displays subs for 1 second - too fast to read.
+                                 */
+                                sub->stop = sub->start + ( 3 * 90000 );
+                                
+                                sub2 = hb_fifo_see2( subtitle->fifo_raw );
+                                
+                                if( sub2 && sub->stop > sub2->start )
+                                {
+                                    sub->stop = sub2->start;
+                                }
                             }
                         }
+                        else
+                        {
+                            /*
+                             * Defer until the play point is within the subtitle
+                             */
+                            sub = NULL;
+                        }
                     }
                     else
                     {
                         /*
-                         * Defer until the play point is within the subtitle
-                         */
-                        sub = NULL;
-                    }
-                }
-                else
-                {
-                    /*
-                     * The end of the subtitle is less than the start, this is a
-                     * sign of a PTS discontinuity.
-                     */
-                    if( sub->start > cur->start )
-                    {
-                        /*
-                         * we haven't reached the start time yet, or
-                         * we have jumped backwards after having
-                         * already started this subtitle.
+                         * The end of the subtitle is less than the start, this is a
+                         * sign of a PTS discontinuity.
                          */
-                        if( cur->start < sub->stop )
+                        if( sub->start > cur->start )
                         {
                             /*
-                             * We have jumped backwards and so should
-                             * continue displaying this subtitle.
-                             *
-                             * fall through to display.
+                             * we haven't reached the start time yet, or
+                             * we have jumped backwards after having
+                             * already started this subtitle.
                              */
-                        }
-                        else
-                        {
+                            if( cur->start < sub->stop )
+                            {
+                                /*
+                                 * We have jumped backwards and so should
+                                 * continue displaying this subtitle.
+                                 *
+                                 * fall through to display.
+                                 */
+                            }
+                            else
+                            {
+                                /*
+                                 * Defer until the play point is within the subtitle
+                                 */
+                                sub = NULL;
+                            }
+                        } else {
                             /*
-                             * Defer until the play point is within the subtitle
+                             * Play this subtitle as the start is greater than our
+                             * video point.
+                             *
+                             * fall through to display/
                              */
-                            sub = NULL;
                         }
-                    } else {
-                        /*
-                         * Play this subtitle as the start is greater than our
-                         * video point.
-                         *
-                         * fall through to display/
-                         */
                     }
                 }
             }
-        }
+            if( sub )
+            {
+                /*
+                 * Don't overwrite the current sub, we'll check the
+                 * other subtitle streams on the next video buffer. 
+                 *
+                 * It doesn't make much sense having multiple rendered
+                 * subtitle tracks anyway.
+                 */
+                break;
+            }
+        } // end subtitles
 
         /*
          * Adjust the pts of the current frame so that it's contiguous
index 8e0734c..8c6db7d 100644 (file)
@@ -278,7 +278,7 @@ void hb_display_job_info( hb_job_t * job )
 
         if( subtitle )
         {
-            hb_log( " * subtitle track %i, %s (id %x)", job->subtitle+1, subtitle->lang, subtitle->id);
+            hb_log( " * subtitle track %i, %s (id %x)", subtitle->track, subtitle->lang, subtitle->id);
         }
     }
 
@@ -503,7 +503,7 @@ static void do_job( hb_job_t * job, int cpu_count )
                 }
             }
 
-            if (!job->indepth_scan || job->subtitle_force) {
+            if( !job->indepth_scan || job->subtitle_force ) {
                 /*
                  * Don't add threads for subtitles when we are scanning, unless
                  * looking for forced subtitles.
index 0253040..1872e5f 100644 (file)
@@ -2617,9 +2617,9 @@ fWorkingCount = 0;
         job->subtitle_force = 0;
     
     /*
-     * subtitle of -1 is a scan
+     * If scanning we need to do some extra setup of the job.
      */
-    if( job->subtitle == -1 )
+    if( job->indepth_scan == 1 )
     {
         char *x264opts_tmp;
         
@@ -2629,7 +2629,6 @@ fWorkingCount = 0;
          */
         job->pass = -1;
         x264opts_tmp = job->x264opts;
-        job->subtitle = -1;
         
         job->x264opts = NULL;
         
@@ -2647,12 +2646,6 @@ fWorkingCount = 0;
     else
         job->select_subtitle = NULL;
     
-    /* No subtitle were selected, so reset the subtitle to -1 (which before
-     * this point meant we were scanning
-     */
-    if( job->subtitle == -2 )
-        job->subtitle = -1;
-    
     if( [[queueToApply objectForKey:@"VideoTwoPass"] intValue] == 1 )
     {
         hb_subtitle_t **subtitle_tmp = job->select_subtitle;
@@ -2786,7 +2779,28 @@ fWorkingCount = 0;
     }
 
     /* Subtitle settings */
-    job->subtitle = [fSubPopUp indexOfSelectedItem] - 2;
+    switch( [fSubPopUp indexOfSelectedItem] - 2 )
+    {
+    case -2:
+        /*
+         * No subtitles selected
+         */
+        break;
+    case -1:
+        /*
+         * Subtitle scan selected
+         */
+        job->indepth_scan = 1;
+        break;
+    default:
+        /*
+         * Subtitle selected, add it into the job from the title.
+         */
+        job->indepth_scan = 0;
+        hb_subtitle_t *subtitle = (hb_subtitle_t *) hb_list_item( title->list_subtitle, [fSubPopUp indexOfSelectedItem] - 2 );
+        hb_list_add( job->list_subtitle, subtitle );
+        break;
+    }
 
     /* Audio tracks and mixdowns */
     /* Lets make sure there arent any erroneous audio tracks in the job list, so lets make sure its empty*/
@@ -3184,8 +3198,31 @@ fWorkingCount = 0;
     
     job->grayscale = [[queueToApply objectForKey:@"VideoGrayScale"] intValue];
     /* Subtitle settings */
-    job->subtitle = [[queueToApply objectForKey:@"JobSubtitlesIndex"] intValue] - 2;
     
+    switch( [[queueToApply objectForKey:@"JobSubtitlesIndex"] intValue] - 2 )
+    {
+    case -2:
+        /*
+         * No subtitles selected
+         */
+        break;
+    case -1:
+        /*
+         * Subtitle scan selected
+         */
+        job->indepth_scan = 1;
+        break;
+    default:
+        /*
+         * Subtitle selected, add it into the job from the title.
+         */
+        job->indepth_scan = 0;
+        hb_subtitle_t *subtitle = (hb_subtitle_t *) hb_list_item( title->list_subtitle, 
+                                                                  [[queueToApply objectForKey:@"JobSubtitlesIndex"] intValue] - 2 );
+        hb_list_add( job->list_subtitle, subtitle );
+        break;
+    }
+
     /* Audio tracks and mixdowns */
     /* Lets make sure there arent any erroneous audio tracks in the job list, so lets make sure its empty*/
     int audiotrack_count = hb_list_count(job->list_audio);
index 2ab1594..411c20c 100644 (file)
@@ -1640,7 +1640,15 @@ static int HandleEvents( hb_handle_t * h )
 
             if( sub )
             {
-                job->subtitle = sub - 1;
+                hb_subtitle_t *subtitle;
+                /* 
+                 * Find the subtitle with the same track as "sub" and
+                 * add that to the job subtitle list
+                 */
+                subtitle = hb_list_item( title->list_subtitle, sub );
+                if( subtitle ) {
+                    hb_list_add( job->list_subtitle, subtitle );
+                }
             }
 
             if( native_language )