From 00615bb3a177359ef746a476a3c2387b0e49711b Mon Sep 17 00:00:00 2001 From: eddyg Date: Thu, 7 May 2009 04:37:47 +0000 Subject: [PATCH] Change CC608 decoder to be its own thread git-svn-id: svn://localhost/HandBrake/trunk@2396 b64f7644-9d1e-0410-96f1-a4d463321fa5 --- libhb/common.h | 7 +-- libhb/deccc608sub.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++----- libhb/deccc608sub.h | 3 +- libhb/decmpeg2.c | 80 +++++++++++---------------------- libhb/decvobsub.c | 4 +- libhb/encvobsub.c | 4 +- libhb/hb.c | 7 +-- libhb/hb.h | 10 +++-- libhb/internal.h | 5 ++- libhb/sync.c | 30 ++++++++++++- libhb/work.c | 19 ++++++-- 11 files changed, 206 insertions(+), 88 deletions(-) diff --git a/libhb/common.h b/libhb/common.h index f8921f65..51631890 100644 --- a/libhb/common.h +++ b/libhb/common.h @@ -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; diff --git a/libhb/deccc608sub.c b/libhb/deccc608sub.c index 18d0e6b1..dbbc2d3e 100644 --- a/libhb/deccc608sub.c +++ b/libhb/deccc608sub.c @@ -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 +}; diff --git a/libhb/deccc608sub.h b/libhb/deccc608sub.h index e6c1518a..3e028837 100644 --- a/libhb/deccc608sub.h +++ b/libhb/deccc608sub.h @@ -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; }; diff --git a/libhb/decmpeg2.c b/libhb/decmpeg2.c index 756eb976..2d5c7c49 100644 --- a/libhb/decmpeg2.c +++ b/libhb/decmpeg2.c @@ -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 ); + } } } diff --git a/libhb/decvobsub.c b/libhb/decvobsub.c index 102d18fe..fd1f8917 100644 --- a/libhb/decvobsub.c +++ b/libhb/decvobsub.c @@ -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, diff --git a/libhb/encvobsub.c b/libhb/encvobsub.c index e04fcd4f..ee49d7ad 100644 --- a/libhb/encvobsub.c +++ b/libhb/encvobsub.c @@ -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, diff --git a/libhb/hb.c b/libhb/hb.c index cdde54f4..661e1df4 100644 --- a/libhb/hb.c +++ b/libhb/hb.c @@ -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 ); diff --git a/libhb/hb.h b/libhb/hb.h index 860f441e..3cf308e3 100644 --- a/libhb/hb.h +++ b/libhb/hb.h @@ -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 ); \ diff --git a/libhb/internal.h b/libhb/internal.h index f5df6cec..b05e50a4 100644 --- a/libhb/internal.h +++ b/libhb/internal.h @@ -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, diff --git a/libhb/sync.c b/libhb/sync.c index 67093d1e..c5842148 100644 --- a/libhb/sync.c +++ b/libhb/sync.c @@ -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 ); diff --git a/libhb/work.c b/libhb/work.c index 323f4cf4..7b270ca7 100644 --- a/libhb/work.c +++ b/libhb/work.c @@ -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 ); -- 2.11.0