X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=libhb%2Fdeccc608sub.c;h=2f137494305fc8dad4fe929f2d556a86c13a2790;hb=033e32de9c380f54c7d1362a3979da205ebc3a29;hp=2b0b199fac42d91c4496c8d4f3ac07a3f282f6b1;hpb=5c5aaf3564f95386860c5a7fd66993cd85d06751;p=handbrake-jp%2Fhandbrake-jp-git.git diff --git a/libhb/deccc608sub.c b/libhb/deccc608sub.c index 2b0b199f..2f137494 100644 --- a/libhb/deccc608sub.c +++ b/libhb/deccc608sub.c @@ -11,12 +11,12 @@ * ccextractor static configuration variables. */ static int debug_608 = 0; -static int trim_subs = 0; +static int trim_subs = 1; static int nofontcolor = 0; static enum encoding_type encoding = ENC_UTF_8; static int cc_channel = 1; -static enum output_format write_format = OF_TRANSCRIPT; -static int sentence_cap = 1; +static enum output_format write_format = OF_SRT; +static int sentence_cap = 0; static int subs_delay = 0; static LLONG screens_to_process = -1; static int processed_enough = 0; @@ -24,9 +24,12 @@ static int gui_mode_reports = 0; static int norollup = 1; static int direct_rollup = 0; -static LLONG get_fts(void) +/* + * Get the time of the last buffer that we have received. + */ +static LLONG get_fts(struct s_write *wb) { - return 0; + return wb->last_pts; } #define fatal(N, ...) // N @@ -39,14 +42,11 @@ int rowdata[] = {11,-1,1,2,3,4,12,13,14,15,5,6,7,8,9,10}; // we need to bring it into the swrite struct. Same for "str". #define INITIAL_ENC_BUFFER_CAPACITY 2048 -unsigned char *enc_buffer=NULL; // Generic general purpose buffer unsigned char str[2048]; // Another generic general purpose buffer -unsigned enc_buffer_used; -unsigned enc_buffer_capacity; -#define GUARANTEE(length) if (length>enc_buffer_capacity) \ -{enc_buffer_capacity*=2; enc_buffer=(unsigned char*) realloc (enc_buffer, enc_buffer_capacity); \ - if (enc_buffer==NULL) { fatal (EXIT_NOT_ENOUGH_MEMORY, "Not enough memory, bailing out\n"); } \ +#define GUARANTEE(wb, length) if (length>wb->enc_buffer_capacity) \ +{wb->enc_buffer_capacity*=2; wb->enc_buffer=(unsigned char*) realloc (wb->enc_buffer, wb->enc_buffer_capacity); \ + if (wb->enc_buffer==NULL) { fatal (EXIT_NOT_ENOUGH_MEMORY, "Not enough memory, bailing out\n"); } \ } const unsigned char pac2_attribs[][3]= // Color, font, ident @@ -153,17 +153,13 @@ const char *color_text[][2]= int general_608_init (struct s_write *wb) { - /* - * Not currently used. - * - if( !enc_buffer ) + if( !wb->enc_buffer ) { - enc_buffer=(unsigned char *) malloc (INITIAL_ENC_BUFFER_CAPACITY); - if (enc_buffer==NULL) + wb->enc_buffer=(unsigned char *) malloc (INITIAL_ENC_BUFFER_CAPACITY); + if (wb->enc_buffer==NULL) return -1; - enc_buffer_capacity=INITIAL_ENC_BUFFER_CAPACITY; + wb->enc_buffer_capacity=INITIAL_ENC_BUFFER_CAPACITY; } - */ if( !wb->subline) { wb->subline = malloc(2048); @@ -177,6 +173,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; } @@ -187,14 +187,18 @@ int general_608_init (struct s_write *wb) */ void general_608_close (struct s_write *wb) { - if( enc_buffer ) { - free(enc_buffer); - enc_buffer_capacity = 0; - enc_buffer_used = 0; + if( wb->enc_buffer ) { + free(wb->enc_buffer); + wb->enc_buffer_capacity = 0; + wb->enc_buffer_used = 0; } if( wb->subline ) { free(wb->subline); } + + if( wb->hb_buffer ) { + hb_buffer_close( &wb->hb_buffer ); + } } @@ -531,6 +535,8 @@ void get_char_in_unicode (unsigned char *buffer, unsigned char c) int get_char_in_utf_8 (unsigned char *buffer, unsigned char c) // Returns number of bytes used { + if (c==0x00) + return 0; if (c<0x80) // Regular line-21 character set, mostly ASCII except these exceptions { switch (c) @@ -675,7 +681,7 @@ int get_char_in_utf_8 (unsigned char *buffer, unsigned char c) // Returns number *buffer=0x27; return 1; case 0x97: // inverted exclamation mark - *buffer=0xc1; + *buffer=0xc2; *(buffer+1)=0xa1; return 2; case 0x98: // asterisk @@ -1431,9 +1437,9 @@ void write_subtitle_file_footer (struct s_write *wb) { hb_log ("\r%s\n", str); } - enc_buffer_used=encode_line (enc_buffer,(unsigned char *) str); + wb->enc_buffer_used=encode_line (wb->enc_buffer,(unsigned char *) str); //fwrite (enc_buffer,enc_buffer_used,1,wb->fh); - XMLRPC_APPEND(enc_buffer,enc_buffer_used); + XMLRPC_APPEND(wb->enc_buffer,wb->enc_buffer_used); break; default: // Nothing to do. Only SAMI has a footer break; @@ -1442,9 +1448,9 @@ void write_subtitle_file_footer (struct s_write *wb) void fhb_log_encoded (FILE *fh, const char *string) { - GUARANTEE(strlen (string)*3); - enc_buffer_used=encode_line (enc_buffer,(unsigned char *) string); - fwrite (enc_buffer,enc_buffer_used,1,fh); + //GUARANTEE(wb, strlen (string)*3); + //wb->enc_buffer_used=encode_line (wb->enc_buffer,(unsigned char *) string); + //fwrite (wb->enc_buffer,wb->enc_buffer_used,1,fh); } void write_subtitle_file_header (struct s_write *wb) @@ -1455,10 +1461,10 @@ void write_subtitle_file_header (struct s_write *wb) break; case OF_SAMI: // This header brought to you by McPoodle's CCASDI //fhb_log_encoded (wb->fh, sami_header); - GUARANTEE(strlen (sami_header)*3); - enc_buffer_used=encode_line (enc_buffer,(unsigned char *) sami_header); + GUARANTEE(wb, strlen (sami_header)*3); + wb->enc_buffer_used=encode_line (wb->enc_buffer,(unsigned char *) sami_header); //fwrite (enc_buffer,enc_buffer_used,1,wb->fh); - XMLRPC_APPEND(enc_buffer,enc_buffer_used); + XMLRPC_APPEND(wb->enc_buffer,wb->enc_buffer_used); break; case OF_RCWT: // Write header //fwrite (rcwt_header, sizeof(rcwt_header),1,wb->fh); @@ -1490,13 +1496,18 @@ void write_cc_line_as_transcript (struct eia608_screen *data, struct s_write *wb /* * Put this subtitle in a hb_buffer_t and shove it into the subtitle fifo */ - buffer = hb_buffer_init( strlen( wb->subline ) + 1 ); - buffer->start = wb->last_pts; - buffer->stop = wb->last_pts+1; - strcpy( buffer->data, wb->subline ); + buffer = hb_buffer_init( length + 1 ); + buffer->start = wb->data608->current_visible_start_ms; + buffer->stop = get_fts(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); @@ -1548,7 +1559,7 @@ void write_cc_buffer_to_gui (struct eia608_screen *data, struct s_write *wb) hb_log ("###SUBTITLE#"); if (!time_reported) { - LLONG ms_end = get_fts()+subs_delay; + LLONG ms_end = get_fts(wb)+subs_delay; mstotime (ms_start,&h1,&m1,&s1,&ms1); mstotime (ms_end-1,&h2,&m2,&s2,&ms2); // -1 To prevent overlapping with next line. // Note, only MM:SS here as we need to save space in the preview window @@ -1581,25 +1592,32 @@ int write_cc_buffer_as_srt (struct eia608_screen *data, struct s_write *wb) if (ms_start<0) // Drop screens that because of subs_delay start too early return 0; - LLONG ms_end = get_fts()+subs_delay; + LLONG ms_end = get_fts(wb)+subs_delay; mstotime (ms_start,&h1,&m1,&s1,&ms1); mstotime (ms_end-1,&h2,&m2,&s2,&ms2); // -1 To prevent overlapping with next line. char timeline[128]; wb->data608->srt_counter++; sprintf (timeline,"%u\r\n",wb->data608->srt_counter); - enc_buffer_used=encode_line (enc_buffer,(unsigned char *) timeline); - fwrite (enc_buffer,enc_buffer_used,1,wb->fh); - XMLRPC_APPEND(enc_buffer,enc_buffer_used); - sprintf (timeline, "%02u:%02u:%02u,%03u --> %02u:%02u:%02u,%03u\r\n", - h1,m1,s1,ms1, h2,m2,s2,ms2); - enc_buffer_used=encode_line (enc_buffer,(unsigned char *) timeline); + //wb->enc_buffer_used=encode_line (wb->enc_buffer,(unsigned char *) timeline); + //fwrite (wb->enc_buffer,wb->enc_buffer_used,1,wb->fh); + XMLRPC_APPEND(wb->enc_buffer,wb->enc_buffer_used); + //sprintf (timeline, "%02u:%02u:%02u,%03u --> %02u:%02u:%02u,%03u\r\n", + // h1,m1,s1,ms1, h2,m2,s2,ms2); + //wb->enc_buffer_used=encode_line (wb->enc_buffer,(unsigned char *) timeline); if (debug_608) { hb_log ("\n- - - SRT caption - - -\n"); hb_log (timeline); } - fwrite (enc_buffer,enc_buffer_used,1,wb->fh); - XMLRPC_APPEND(enc_buffer,enc_buffer_used); + //fwrite (enc_buffer,enc_buffer_used,1,wb->fh); + XMLRPC_APPEND(wb->enc_buffer,wb->enc_buffer_used); + + /* + * Write all the lines into enc_buffer, and then write that out at the end + * ensure that we only have two lines, insert a newline after the first one, + * and have a big bottom line (strip spaces from any joined lines). + */ + int line = 1; for (i=0;i<15;i++) { if (data->row_used[i]) @@ -1609,26 +1627,47 @@ int write_cc_buffer_as_srt (struct eia608_screen *data, struct s_write *wb) capitalize(i,data, &wb->new_sentence); correct_case(i,data); } - int length = get_decoder_line_encoded (wb->subline, i, data); - if (debug_608 && encoding!=ENC_UNICODE) - { - hb_log ("\r"); - hb_log ("%s\n",wb->subline); + /* + * The intention was to use a newline but QT doesn't like it, old code still + * here just in case.. + */ + if (line == 1) { + wb->enc_buffer_used = get_decoder_line_encoded (wb->enc_buffer, i, data); + line = 2; + } else { + if (line == 2) { + wb->enc_buffer_used += encode_line (wb->enc_buffer+wb->enc_buffer_used, + (unsigned char *) "\n"); + line = 3; + } else { + wb->enc_buffer_used += encode_line (wb->enc_buffer+wb->enc_buffer_used, + (unsigned char *) " "); + } + wb->enc_buffer_used += get_decoder_line_encoded (wb->enc_buffer+wb->enc_buffer_used, i, data); } - fwrite (wb->subline, 1, length, wb->fh); - XMLRPC_APPEND(wb->subline,length); - fwrite (encoded_crlf, 1, encoded_crlf_length,wb->fh); - XMLRPC_APPEND(encoded_crlf,encoded_crlf_length); - wrote_something=1; - // fhb_log (wb->fh,encoded_crlf); } } + if (wb->enc_buffer_used) + { + hb_buffer_t *buffer = hb_buffer_init( wb->enc_buffer_used + 1 ); + buffer->start = ms_start; + buffer->stop = ms_end; + memcpy( buffer->data, wb->enc_buffer, wb->enc_buffer_used + 1 ); + if (wb->hb_last_buffer) { + wb->hb_last_buffer->next = buffer; + } else { + wb->hb_buffer = buffer; + } + wb->hb_last_buffer = buffer; + + wrote_something=1; + } if (debug_608) { hb_log ("- - - - - - - - - - - -\r\n"); } // fhb_log (wb->fh, encoded_crlf); - fwrite (encoded_crlf, 1, encoded_crlf_length,wb->fh); + //fwrite (encoded_crlf, 1, encoded_crlf_length,wb->fh); XMLRPC_APPEND(encoded_crlf,encoded_crlf_length); return wrote_something; } @@ -1643,16 +1682,16 @@ int write_cc_buffer_as_sami (struct eia608_screen *data, struct s_write *wb) if (startms<0) // Drop screens that because of subs_delay start too early return 0; - LLONG endms = get_fts()+subs_delay; + LLONG endms = get_fts(wb)+subs_delay; endms--; // To prevent overlapping with next line. sprintf ((char *) str,"

\r\n",startms); if (debug_608 && encoding!=ENC_UNICODE) { hb_log ("\r%s\n", str); } - enc_buffer_used=encode_line (enc_buffer,(unsigned char *) str); - fwrite (enc_buffer,enc_buffer_used,1,wb->fh); - XMLRPC_APPEND(enc_buffer,enc_buffer_used); + wb->enc_buffer_used=encode_line (wb->enc_buffer,(unsigned char *) str); + fwrite (wb->enc_buffer,wb->enc_buffer_used,1,wb->fh); + XMLRPC_APPEND(wb->enc_buffer,wb->enc_buffer_used); for (i=0;i<15;i++) { if (data->row_used[i]) @@ -1680,17 +1719,17 @@ int write_cc_buffer_as_sami (struct eia608_screen *data, struct s_write *wb) { hb_log ("\r%s\n", str); } - enc_buffer_used=encode_line (enc_buffer,(unsigned char *) str); - fwrite (enc_buffer,enc_buffer_used,1,wb->fh); - XMLRPC_APPEND(enc_buffer,enc_buffer_used); + wb->enc_buffer_used=encode_line (wb->enc_buffer,(unsigned char *) str); + fwrite (wb->enc_buffer,wb->enc_buffer_used,1,wb->fh); + XMLRPC_APPEND(wb->enc_buffer,wb->enc_buffer_used); sprintf ((char *) str,"

 

\r\n\r\n",endms); if (debug_608 && encoding!=ENC_UNICODE) { hb_log ("\r%s\n", str); } - enc_buffer_used=encode_line (enc_buffer,(unsigned char *) str); - fwrite (enc_buffer,enc_buffer_used,1,wb->fh); - XMLRPC_APPEND(enc_buffer,enc_buffer_used); + wb->enc_buffer_used=encode_line (wb->enc_buffer,(unsigned char *) str); + fwrite (wb->enc_buffer,wb->enc_buffer_used,1,wb->fh); + XMLRPC_APPEND(wb->enc_buffer,wb->enc_buffer_used); return wrote_something; } @@ -2000,7 +2039,7 @@ void handle_command (/*const */ unsigned char c1, const unsigned char c2, struct wb->data608->screenfuls_counter++; } roll_up(wb); - wb->data608->current_visible_start_ms=get_fts(); + wb->data608->current_visible_start_ms=get_fts(wb); wb->data608->cursor_column=0; break; case COM_ERASENONDISPLAYEDMEMORY: @@ -2024,7 +2063,7 @@ void handle_command (/*const */ unsigned char c1, const unsigned char c2, struct wb->data608->screenfuls_counter++; } erase_memory (wb,1); - wb->data608->current_visible_start_ms=get_fts(); + wb->data608->current_visible_start_ms=get_fts(wb); break; case COM_ENDOFCAPTION: // Switch buffers // The currently *visible* buffer is leaving, so now we know it's ending @@ -2032,7 +2071,7 @@ void handle_command (/*const */ unsigned char c1, const unsigned char c2, struct if (write_cc_buffer (wb)) wb->data608->screenfuls_counter++; wb->data608->visible_buffer = (wb->data608->visible_buffer==1) ? 2 : 1; - wb->data608->current_visible_start_ms=get_fts(); + wb->data608->current_visible_start_ms=get_fts(wb); wb->data608->cursor_column=0; wb->data608->cursor_row=0; wb->data608->color=default_color; @@ -2048,7 +2087,7 @@ void handle_command (/*const */ unsigned char c1, const unsigned char c2, struct } void handle_end_of_data (struct s_write *wb) -{ +{ // We issue a EraseDisplayedMemory here so if there's any captions pending // they get written to file. handle_command (0x14, 0x2c, wb); // EDM @@ -2361,7 +2400,7 @@ void process608 (const unsigned char *data, int length, struct s_write *wb) { // We don't increase screenfuls_counter here. write_cc_buffer (wb); - wb->data608->current_visible_start_ms=get_fts(); + wb->data608->current_visible_start_ms=get_fts(wb); } } } @@ -2401,3 +2440,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 +};