OSDN Git Service

Change CC608 decoder to be its own thread
authoreddyg <eddyg@b64f7644-9d1e-0410-96f1-a4d463321fa5>
Thu, 7 May 2009 04:37:47 +0000 (04:37 +0000)
committereddyg <eddyg@b64f7644-9d1e-0410-96f1-a4d463321fa5>
Thu, 7 May 2009 04:37:47 +0000 (04:37 +0000)
git-svn-id: svn://localhost/HandBrake/trunk@2396 b64f7644-9d1e-0410-96f1-a4d463321fa5

libhb/common.h
libhb/deccc608sub.c
libhb/deccc608sub.h
libhb/decmpeg2.c
libhb/decvobsub.c
libhb/encvobsub.c
libhb/hb.c
libhb/hb.h
libhb/internal.h
libhb/sync.c
libhb/work.c

index f8921f6..5163189 100644 (file)
@@ -443,7 +443,7 @@ struct hb_subtitle_s
     int track;
     int  id;
     enum subtype { PICTURESUB, TEXTSUB } format;
-    enum subsource { VOBSUB, SRTSUB, CCSUB } source;
+    enum subsource { VOBSUB, SRTSUB, CC608SUB, CC708SUB } source;
     enum subdest { RENDERSUB, PASSTHRUSUB } dest;
     char lang[1024];
     char iso639_2[4];
@@ -654,8 +654,9 @@ struct hb_work_object_s
 
 extern hb_work_object_t hb_sync;
 extern hb_work_object_t hb_decmpeg2;
-extern hb_work_object_t hb_decsub;
-extern hb_work_object_t hb_encsub;
+extern hb_work_object_t hb_decvobsub;
+extern hb_work_object_t hb_encvobsub;
+extern hb_work_object_t hb_deccc608;
 extern hb_work_object_t hb_render;
 extern hb_work_object_t hb_encavcodec;
 extern hb_work_object_t hb_encxvid;
index 18d0e6b..dbbc2d3 100644 (file)
@@ -177,6 +177,10 @@ int general_608_init (struct s_write *wb)
     wb->new_sentence = 1;
     wb->new_channel = 1;
     wb->in_xds_mode = 0;
+
+    wb->hb_buffer = NULL;
+    wb->hb_last_buffer = NULL;
+    wb->last_pts = 0;
     return 0;
 }
 
@@ -195,6 +199,10 @@ void general_608_close (struct s_write *wb)
     if( wb->subline ) {
         free(wb->subline);
     }
+
+    if( wb->hb_buffer ) {
+        hb_buffer_close( &wb->hb_buffer );
+    }
 }
 
 
@@ -1496,7 +1504,12 @@ void write_cc_line_as_transcript (struct eia608_screen *data, struct s_write *wb
         memcpy( buffer->data, wb->subline, length + 1 );
         //hb_log("CC %lld: %s", buffer->stop, wb->subline);
 
-        hb_fifo_push( wb->subtitle->fifo_raw, buffer );
+        if (wb->hb_last_buffer) {
+            wb->hb_last_buffer->next = buffer;
+        } else {
+            wb->hb_buffer = buffer;
+        }
+        wb->hb_last_buffer = buffer;
 
         XMLRPC_APPEND(wb->subline,length);
         //fwrite (encoded_crlf, 1, encoded_crlf_length,wb->fh);
@@ -1622,7 +1635,12 @@ int write_cc_buffer_as_srt (struct eia608_screen *data, struct s_write *wb)
                 buffer->stop = ms_end;
                 memcpy( buffer->data, wb->subline, length + 1 );
                 
-                hb_fifo_push( wb->subtitle->fifo_raw, buffer );
+                if (wb->hb_last_buffer) {
+                    wb->hb_last_buffer->next = buffer;
+                } else {
+                    wb->hb_buffer = buffer;
+                }
+                wb->hb_last_buffer = buffer;
                 
                 //fwrite (wb->subline, 1, length, wb->fh);
                 XMLRPC_APPEND(wb->subline,length);
@@ -2059,17 +2077,9 @@ void handle_command (/*const */ unsigned char c1, const unsigned char c2, struct
 
 void handle_end_of_data (struct s_write *wb)
 { 
-    hb_buffer_t *buffer;
-
     // We issue a EraseDisplayedMemory here so if there's any captions pending
     // they get written to file. 
     handle_command (0x14, 0x2c, wb); // EDM
-
-    /*
-     * At the end of the subtitle stream HB wants an empty buffer
-     */
-    buffer = hb_buffer_init( 0 );
-    hb_fifo_push( wb->subtitle->fifo_raw, buffer );
 }
 
 void handle_double (const unsigned char c1, const unsigned char c2, struct s_write *wb)
@@ -2419,3 +2429,98 @@ unsigned char *debug_608toASC (unsigned char *cc_data, int channel)
     }
     return output;
 }
+
+
+struct hb_work_private_s
+{
+    hb_job_t           * job;
+    struct s_write     * cc608;
+};
+
+int decccInit( hb_work_object_t * w, hb_job_t * job )
+{
+    int retval = 1;
+    hb_work_private_t * pv;
+
+    pv = calloc( 1, sizeof( hb_work_private_t ) );
+    if( pv )
+    {
+        w->private_data = pv;
+
+        pv->job = job;
+
+        pv->cc608 = calloc(1, sizeof(struct s_write));
+
+        if( pv->cc608 )
+        {
+            retval = general_608_init(pv->cc608);
+            if( !retval )
+            {
+                pv->cc608->data608 = calloc(1, sizeof(struct eia608));
+                if( !pv->cc608->data608 )
+                {
+                    retval = 1;
+                }
+            }
+        }
+    }
+    return retval;
+}
+
+int decccWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
+               hb_buffer_t ** buf_out )
+{
+    hb_work_private_t * pv = w->private_data;
+    hb_buffer_t * in = *buf_in;
+
+    if ( in->size <= 0 )
+    {
+        /* EOF on input stream - send it downstream & say that we're done */
+        handle_end_of_data(pv->cc608);
+        /*
+         * Grab any pending buffer and output them with the EOF on the end
+         */
+        if (pv->cc608->hb_last_buffer) {
+            pv->cc608->hb_last_buffer->next = in;
+            *buf_out = pv->cc608->hb_buffer;
+            *buf_in = NULL;
+            pv->cc608->hb_buffer = NULL;
+            pv->cc608->hb_last_buffer = NULL;
+        } else {
+            *buf_out = in;
+            *buf_in = NULL;
+        }
+        return HB_WORK_DONE;
+    }
+
+    pv->cc608->last_pts = in->start;
+
+    process608(in->data, in->size, pv->cc608);
+
+    /*
+     * If there is one waiting then pass it on
+     */
+    *buf_out = pv->cc608->hb_buffer;
+    pv->cc608->hb_buffer = NULL;
+    pv->cc608->hb_last_buffer = NULL;
+
+    return HB_WORK_OK; 
+}
+
+void decccClose( hb_work_object_t * w )
+{
+    hb_work_private_t * pv = w->private_data;
+    general_608_close( pv->cc608 );
+    free( pv->cc608->data608 );
+    free( pv->cc608 );
+    free( w->private_data );
+}
+
+hb_work_object_t hb_deccc608 =
+{
+    WORK_DECCC608,
+    "Closed Caption (608) decoder",
+    decccInit,
+    decccWork,
+    decccClose
+};
index e6c1518..3e02883 100644 (file)
@@ -90,7 +90,8 @@ struct s_write {
     int new_sentence;
     int new_channel;
     int in_xds_mode;
-    hb_subtitle_t * subtitle;
+    hb_buffer_t *hb_buffer;
+    hb_buffer_t *hb_last_buffer;
     uint64_t last_pts;
 };
 
index 756eb97..2d5c7c4 100644 (file)
@@ -7,7 +7,6 @@
 #include "hb.h"
 #include "hbffmpeg.h"
 #include "mpeg2dec/mpeg2.h"
-#include "deccc608sub.h"
 
 /* Cadence tracking */
 #ifndef PIC_FLAG_REPEAT_FIRST_FIELD
@@ -47,7 +46,6 @@ typedef struct hb_libmpeg2_s
     int64_t              last_pts;
     int cadence[12];
     int flag;
-    struct s_write       cc608;             /* Closed Captions */
     hb_subtitle_t      * subtitle;
 } hb_libmpeg2_t;
 
@@ -64,9 +62,6 @@ static hb_libmpeg2_t * hb_libmpeg2_init()
     m->info     = mpeg2_info( m->libmpeg2 );
     m->last_pts = -1;
 
-   /* Closed Captions init, whether needed or not */
-    general_608_init( &m->cc608 );
-    m->cc608.data608 = calloc(1, sizeof(struct eia608));
     return m;
 }
 
@@ -74,6 +69,7 @@ static void hb_mpeg2_cc( hb_libmpeg2_t * m, uint8_t *cc_block )
 {
     uint8_t cc_valid = (*cc_block & 4) >>2;
     uint8_t cc_type = *cc_block & 3;
+    hb_buffer_t *cc_buf;
     
     if( !m->job )
     {
@@ -89,7 +85,13 @@ static void hb_mpeg2_cc( hb_libmpeg2_t * m, uint8_t *cc_block )
         {
         case 0:
             // CC1 stream
-            process608( cc_block+1, 2, &m->cc608 );
+            cc_buf = hb_buffer_init( 2 );
+            if( cc_buf )
+            {
+                cc_buf->start = m->last_pts;
+                memcpy( cc_buf->data, cc_block+1, 2 );
+                hb_fifo_push( m->subtitle->fifo_in, cc_buf );
+            }
             break;
         case 1:
             // CC2 stream
@@ -403,6 +405,8 @@ static int hb_libmpeg2_decode( hb_libmpeg2_t * m, hb_buffer_t * buf_es,
 
         /*
          * Look for Closed Captions if scanning (!job) or if closed captions have been requested.
+         *
+         * Send them on to the closed caption decoder if requested and found.
          */
         if( ( !m->job || m->subtitle) &&
             ( m->info->user_data_len != 0 &&
@@ -418,8 +422,6 @@ static int hb_libmpeg2_decode( hb_libmpeg2_t * m, hb_buffer_t * buf_es,
             int capcount=(header[0] & 0x1e) / 2;
             header++;
             
-            m->cc608.last_pts = m->last_pts;
-
             /*
              * Add closed captions to the title if we are scanning (no job).
              *
@@ -439,7 +441,11 @@ static int hb_libmpeg2_decode( hb_libmpeg2_t * m, hb_buffer_t * buf_es,
                 for( i = 0; i < hb_list_count( m->title->list_subtitle ); i++ )
                 {
                     subtitle = hb_list_item( m->title->list_subtitle, i);
-                    if( subtitle && subtitle->source == CCSUB ) 
+                    /*
+                     * Let's call them 608 subs for now even if they aren't, since they 
+                     * are the only types we grok.
+                     */
+                    if( subtitle && subtitle->source == CC608SUB ) 
                     {
                         found = 1;
                         break;
@@ -454,7 +460,7 @@ static int hb_libmpeg2_decode( hb_libmpeg2_t * m, hb_buffer_t * buf_es,
                     snprintf( subtitle->lang, sizeof( subtitle->lang ), "Closed Captions");
                     snprintf( subtitle->iso639_2, sizeof( subtitle->iso639_2 ), "und");
                     subtitle->format = TEXTSUB;
-                    subtitle->source = CCSUB;
+                    subtitle->source = CC608SUB;
                     subtitle->dest   = PASSTHRUSUB;
                     subtitle->type = 5; 
                     
@@ -525,9 +531,6 @@ static void hb_libmpeg2_close( hb_libmpeg2_t ** _m )
 
     mpeg2_close( m->libmpeg2 );
 
-    free( m->cc608.data608 );
-    general_608_close( &m->cc608 );
-
     free( m );
     *_m = NULL;
 }
@@ -565,7 +568,8 @@ static int decmpeg2Init( hb_work_object_t * w, hb_job_t * job )
     }
 
     /*
-     * If not scanning, then are we supposed to extract Closed Captions?
+     * If not scanning, then are we supposed to extract Closed Captions
+     * and send them to the decoder? 
      */
     if( job )
     {
@@ -575,54 +579,15 @@ static int decmpeg2Init( hb_work_object_t * w, hb_job_t * job )
         for( i = 0; i < hb_list_count( job->list_subtitle ); i++ )
         {
             subtitle = hb_list_item( job->list_subtitle, i);
-            if( subtitle && subtitle->source == CCSUB ) 
+            if( subtitle && subtitle->source == CC608SUB ) 
             {
                 pv->libmpeg2->subtitle = subtitle;
-                pv->libmpeg2->cc608.subtitle = subtitle;
                 break;
             }
         }
 
     }
 
-    /*
-     * During a scan add a Closed Caption subtitle track to the title, 
-     * since we may have CC. Don't bother actually trying to detect CC
-     * since we'd have to go through too much of the source.
-     *
-    if( !job && w->title )
-    {
-        hb_subtitle_t * subtitle;
-        int found = 0;
-        int i;
-
-        for( i = 0; i < hb_list_count( w->title->list_subtitle ); i++ )
-        {
-            subtitle = hb_list_item( w->title->list_subtitle, i);
-            if( subtitle && subtitle->source == CCSUB ) 
-            {
-                found = 1;
-                break;
-            }
-        }
-
-        if( !found )
-        {
-            subtitle = calloc( sizeof( hb_subtitle_t ), 1 );
-            subtitle->track = 0;
-            subtitle->id = 0x0;
-            snprintf( subtitle->lang, sizeof( subtitle->lang ), "Closed Captions");
-            snprintf( subtitle->iso639_2, sizeof( subtitle->iso639_2 ), "und");
-            subtitle->format = TEXTSUB;
-            subtitle->source = CCSUB;
-            subtitle->dest   = PASSTHRUSUB;
-            subtitle->type = 5; 
-
-            hb_list_add( w->title->list_subtitle, subtitle );
-        }
-    }
-    */
-
     return 0;
 }
 
@@ -663,7 +628,12 @@ static int decmpeg2Work( hb_work_object_t * w, hb_buffer_t ** buf_in,
          */
         if( pv->libmpeg2->subtitle )
         {
-            handle_end_of_data( &pv->libmpeg2->cc608 );
+            hb_buffer_t *buf_eof = hb_buffer_init( 0 );
+            
+            if( buf_eof )
+            {
+                hb_fifo_push( pv->libmpeg2->subtitle->fifo_in, buf_eof );
+            }
         }
     }
 
index 102d18f..fd1f891 100644 (file)
@@ -122,9 +122,9 @@ void decsubClose( hb_work_object_t * w )
     free( w->private_data );
 }
 
-hb_work_object_t hb_decsub =
+hb_work_object_t hb_decvobsub =
 {
-    WORK_DECSUB,
+    WORK_DECVOBSUB,
     "VOBSUB decoder",
     decsubInit,
     decsubWork,
index e04fcd4..ee49d7a 100644 (file)
@@ -51,9 +51,9 @@ void encsubClose( hb_work_object_t * w )
     free( w->private_data );
 }
 
-hb_work_object_t hb_encsub =
+hb_work_object_t hb_encvobsub =
 {
-    WORK_ENCSUB,
+    WORK_ENCVOBSUB,
     "VOBSUB encoder",
     encsubInit,
     encsubWork,
index cdde54f..661e1df 100644 (file)
@@ -229,13 +229,14 @@ hb_handle_t * hb_init_dl( int verbose, int update_check )
 
     hb_register( &hb_sync );
        hb_register( &hb_decmpeg2 );
-       hb_register( &hb_decsub );
-        hb_register( &hb_encsub );
+       hb_register( &hb_decvobsub );
+        hb_register( &hb_encvobsub );
+        hb_register( &hb_deccc608 );
        hb_register( &hb_render );
        hb_register( &hb_encavcodec );
        hb_register( &hb_encxvid );
        hb_register( &hb_encx264 );
-    hb_register( &hb_enctheora );
+        hb_register( &hb_enctheora );
        hb_register( &hb_deca52 );
        hb_register( &hb_decdca );
        hb_register( &hb_decavcodec );
index 860f441..3cf308e 100644 (file)
@@ -21,8 +21,9 @@ hb_handle_t * hb_init_dl ( int verbose, int update_check ); // hb_init for use w
 hb_init_real( v, u ); \
 hb_register( &hb_sync ); \
 hb_register( &hb_decmpeg2 ); \
-hb_register( &hb_decsub ); \
-hb_register( &hb_encsub ); \
+hb_register( &hb_decvobsub ); \
+hb_register( &hb_encvobsub ); \
+hb_register( &hb_deccc608 ); \
 hb_register( &hb_render ); \
 hb_register( &hb_encavcodec ); \
 hb_register( &hb_encxvid ); \
@@ -43,8 +44,9 @@ hb_register( &hb_encvorbis ); \
 hb_init_real( v, u ); \
 hb_register( &hb_sync ); \
 hb_register( &hb_decmpeg2 ); \
-hb_register( &hb_decsub ); \
-hb_register( &hb_encsub ); \
+hb_register( &hb_decvobsub ); \
+hb_register( &hb_encvobsub ); \
+hb_register( &hb_deccc608 ); \
 hb_register( &hb_render ); \
 hb_register( &hb_encavcodec ); \
 hb_register( &hb_encx264 ); \
index f5df6ce..b05e50a 100644 (file)
@@ -254,8 +254,9 @@ enum
 {
     WORK_SYNC = 1,
     WORK_DECMPEG2,
-    WORK_DECSUB,
-    WORK_ENCSUB,
+    WORK_DECCC608,
+    WORK_DECVOBSUB,
+    WORK_ENCVOBSUB,
     WORK_RENDER,
     WORK_ENCAVCODEC,
     WORK_ENCXVID,
index 67093d1..c584214 100644 (file)
@@ -293,6 +293,19 @@ static void SyncVideo( hb_work_object_t * w )
     {
         /* we got an end-of-stream. Feed it downstream & signal that we're done. */
         hb_fifo_push( job->fifo_sync, hb_buffer_init( 0 ) );
+
+        /*
+         * Push through any subtitle EOFs in case they were not synced through.
+         */
+        for( i = 0; i < hb_list_count( job->list_subtitle ); i++)
+        {
+            subtitle = hb_list_item( job->list_subtitle, i );
+            if( subtitle->dest == PASSTHRUSUB )
+            {
+                hb_fifo_push( subtitle->fifo_out, hb_buffer_init( 0 ) );
+            }
+        }
+
         pv->busy &=~ 1;
         return;
     }
@@ -313,6 +326,18 @@ static void SyncVideo( hb_work_object_t * w )
              * video (we don't know its duration). On DVDs the final frame
              * is often strange and dropping it seems to be a good idea. */
             hb_fifo_push( job->fifo_sync, hb_buffer_init( 0 ) );
+
+            /*
+             * Push through any subtitle EOFs in case they were not synced through.
+             */
+            for( i = 0; i < hb_list_count( job->list_subtitle ); i++)
+            {
+                subtitle = hb_list_item( job->list_subtitle, i );
+                if( subtitle->dest == PASSTHRUSUB )
+                {
+                    hb_fifo_push( subtitle->fifo_out, hb_buffer_init( 0 ) );
+                }
+            }
             pv->busy &=~ 1;
             return;
         }
@@ -398,7 +423,8 @@ static void SyncVideo( hb_work_object_t * w )
             /*
              * Rewrite timestamps on subtitles that need it (on raw queue).
              */
-            if( subtitle->source == CCSUB )
+            if( subtitle->source == CC608SUB ||
+                subtitle->source == CC708SUB )
             {
                 /*
                  * Rewrite timestamps on subtitles that came from Closed Captions
@@ -416,7 +442,7 @@ static void SyncVideo( hb_work_object_t * w )
                      *
                      * Bypass the sync fifo altogether.
                      */
-                    if( sub->size == 0 )
+                    if( sub->size <= 0 )
                     {
                         sub = hb_fifo_get( subtitle->fifo_raw );
                         hb_fifo_push( subtitle->fifo_out, sub );
index 323f4cf..7b270ca 100644 (file)
@@ -280,7 +280,9 @@ void hb_display_job_info( hb_job_t * job )
         {
             hb_log( " * subtitle track %i, %s (id %x) %s [%s] -> %s ", subtitle->track, subtitle->lang, subtitle->id,
                     subtitle->format == PICTURESUB ? "Picture" : "Text",
-                    subtitle->source == VOBSUB ? "VOBSUB" : (subtitle->source == CCSUB ? "CC" : "SRT"),
+                    subtitle->source == VOBSUB ? "VOBSUB" : 
+                    ((subtitle->source == CC608SUB ||
+                      subtitle->source == CC708SUB) ? "CC" : "SRT"),
                     subtitle->dest == RENDERSUB ? "Render/Burn in" : "Pass-Through");
         }
     }
@@ -508,12 +510,21 @@ 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) && 
+                subtitle->source == VOBSUB ) {
                 /*
                  * Don't add threads for subtitles when we are scanning, unless
                  * looking for forced subtitles.
                  */
-                w = hb_get_work( WORK_DECSUB );
+                w = hb_get_work( WORK_DECVOBSUB );
+                w->fifo_in  = subtitle->fifo_in;
+                w->fifo_out = subtitle->fifo_raw;
+                hb_list_add( job->list_work, w );
+            }
+
+            if( !job->indepth_scan && subtitle->source == CC608SUB )
+            {
+                w = hb_get_work( WORK_DECCC608 );
                 w->fifo_in  = subtitle->fifo_in;
                 w->fifo_out = subtitle->fifo_raw;
                 hb_list_add( job->list_work, w );
@@ -527,7 +538,7 @@ static void do_job( hb_job_t * job, int cpu_count )
                  * Passing through a subtitle picture, this will have to
                  * be rle encoded before muxing.
                  */
-                w = hb_get_work( WORK_ENCSUB );
+                w = hb_get_work( WORK_ENCVOBSUB );
                 w->fifo_in  = subtitle->fifo_sync;
                 w->fifo_out = subtitle->fifo_out;
                 hb_list_add( job->list_work, w );