X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=libhb%2Fdecsrtsub.c;h=daf210d6f1358712872877daf376dcb12cd5867e;hb=814438ce8ec7b400d211ef9050278e283d2bba5f;hp=bf35c9e4503e4a3e8a0433ed296fc65679d6c176;hpb=87e9d4250f836aec55bd3a0eae5ae23e59c9daaa;p=handbrake-jp%2Fhandbrake-jp-git.git diff --git a/libhb/decsrtsub.c b/libhb/decsrtsub.c index bf35c9e4..daf210d6 100644 --- a/libhb/decsrtsub.c +++ b/libhb/decsrtsub.c @@ -17,6 +17,7 @@ struct start_and_end { enum { k_state_inEntry, + k_state_inEntry_or_new, k_state_potential_new_entry, k_state_timecode, }; @@ -41,8 +42,10 @@ struct hb_work_private_s char utf8_buf[2048]; int utf8_pos; int utf8_end; + int utf8_bom_skipped; unsigned long current_time; unsigned long number_of_entries; + unsigned long last_entry_number; unsigned long current_state; srt_entry_t current_entry; iconv_t *iconv_context; @@ -51,20 +54,27 @@ struct hb_work_private_s uint64_t stop_time; // In HB time }; -static struct start_and_end read_time_from_string( const char* timeString ) +static int +read_time_from_string( const char* timeString, struct start_and_end *result ) { // for ex. 00:00:15,248 --> 00:00:16,545 long houres1, minutes1, seconds1, milliseconds1, - houres2, minutes2, seconds2, milliseconds2; + houres2, minutes2, seconds2, milliseconds2; + int scanned; - sscanf(timeString, "%ld:%ld:%ld,%ld --> %ld:%ld:%ld,%ld\n", &houres1, &minutes1, &seconds1, &milliseconds1, - &houres2, &minutes2, &seconds2, &milliseconds2); - - struct start_and_end result = { - milliseconds1 + seconds1*1000 + minutes1*60*1000 + houres1*60*60*1000, - milliseconds2 + seconds2*1000 + minutes2*60*1000 + houres2*60*60*1000}; - return result; + scanned = sscanf(timeString, "%ld:%ld:%ld,%ld --> %ld:%ld:%ld,%ld\n", + &houres1, &minutes1, &seconds1, &milliseconds1, + &houres2, &minutes2, &seconds2, &milliseconds2); + if (scanned != 8) + { + return 0; + } + result->start = + milliseconds1 + seconds1*1000 + minutes1*60*1000 + houres1*60*60*1000; + result->end = + milliseconds2 + seconds2*1000 + minutes2*60*1000 + houres2*60*60*1000; + return 1; } static int utf8_fill( hb_work_private_t * pv ) @@ -89,7 +99,12 @@ static int utf8_fill( hb_work_private_t * pv ) pv->pos = 0; pv->end = bytes; if( bytes == 0 ) - return 0; + { + if( conversion ) + return 1; + else + return 0; + } } p = pv->buf + pv->pos; @@ -103,6 +118,16 @@ static int utf8_fill( hb_work_private_t * pv ) pv->utf8_end = q - pv->utf8_buf; pv->pos = p - pv->buf; + if ( !pv->utf8_bom_skipped ) + { + uint8_t *buf = (uint8_t*)pv->utf8_buf; + if (buf[0] == 0xef && buf[1] == 0xbb && buf[2] == 0xbf) + { + pv->utf8_pos = 3; + } + pv->utf8_bom_skipped = 1; + } + if( ( retval == -1 ) && ( errno == EINVAL ) ) { /* Incomplete multibyte sequence, read more data */ @@ -169,19 +194,30 @@ static int get_line( hb_work_private_t * pv, char *buf, int size ) static hb_buffer_t *srt_read( hb_work_private_t *pv ) { char line_buffer[1024]; + int reprocess = 0, resync = 0; if( !pv->file ) { return NULL; } - while( get_line( pv, line_buffer, sizeof( line_buffer ) ) ) + while( reprocess || get_line( pv, line_buffer, sizeof( line_buffer ) ) ) { + reprocess = 0; switch (pv->current_state) { case k_state_timecode: { - struct start_and_end timing = read_time_from_string( line_buffer ); + struct start_and_end timing; + int result; + + result = read_time_from_string( line_buffer, &timing ); + if (!result) + { + resync = 1; + pv->current_state = k_state_potential_new_entry; + continue; + } pv->current_entry.duration = timing.end - timing.start; pv->current_entry.offset = timing.start - pv->current_time; @@ -191,9 +227,36 @@ static hb_buffer_t *srt_read( hb_work_private_t *pv ) pv->current_entry.stop = timing.end; pv->current_state = k_state_inEntry; - continue; + continue; } - + + case k_state_inEntry_or_new: + { + char *endpoint; + long entry_number; + /* + * Is this really new next entry begin? + */ + entry_number = strtol(line_buffer, &endpoint, 10); + if (endpoint == line_buffer || + (endpoint && *endpoint != '\n' && *endpoint != '\r')) + { + /* + * Doesn't resemble an entry number + * must still be in an entry + */ + if (!resync) + { + reprocess = 1; + pv->current_state = k_state_inEntry; + } + continue; + } + reprocess = 1; + pv->current_state = k_state_potential_new_entry; + break; + } + case k_state_inEntry: { char *q; @@ -213,83 +276,179 @@ static hb_buffer_t *srt_read( hb_work_private_t *pv ) memcpy(q, line_buffer, size); pv->current_entry.pos += size; pv->current_entry.text[pv->current_entry.pos] = '\0'; - break; + break; } - + case k_state_potential_new_entry: { - const char endpoint[] = "\0"; - const unsigned long potential_entry_number = strtol(line_buffer, (char**)&endpoint, 10); + char *endpoint; + long entry_number; hb_buffer_t *buffer = NULL; /* * Is this really new next entry begin? */ - if (potential_entry_number == pv->number_of_entries + 1) + entry_number = strtol(line_buffer, &endpoint, 10); + if (!resync && (*line_buffer == '\n' || *line_buffer == '\r')) + { + /* + * Well.. looks like we are in the wrong mode.. lets add the + * newline we misinterpreted... + */ + strncat(pv->current_entry.text, " ", 1024); + pv->current_state = k_state_inEntry_or_new; + continue; + } + if (endpoint == line_buffer || + (endpoint && *endpoint != '\n' && *endpoint != '\r')) { /* - * We found the next entry - or a really rare error condition + * Well.. looks like we are in the wrong mode.. lets add the + * line we misinterpreted... */ - if( *pv->current_entry.text ) + if (!resync) { - long length; - char *p; - uint64_t start_time = ( pv->current_entry.start + - pv->subtitle->config.offset ) * 90; - uint64_t stop_time = ( pv->current_entry.stop + - pv->subtitle->config.offset ) * 90; - - if( !( start_time > pv->start_time && stop_time < pv->stop_time ) ) - { - hb_deep_log( 3, "Discarding SRT at time start %"PRId64", stop %"PRId64, start_time, stop_time); - memset( &pv->current_entry, 0, sizeof( srt_entry_t ) ); - ++(pv->number_of_entries); - pv->current_state = k_state_timecode; - continue; - } + reprocess = 1; + pv->current_state = k_state_inEntry; + } + continue; + } + /* + * We found the next entry - or a really rare error condition + */ + pv->last_entry_number = entry_number; + resync = 0; + if( *pv->current_entry.text ) + { + long length; + char *p, *q; + int line = 1; + uint64_t start_time = ( pv->current_entry.start + + pv->subtitle->config.offset ) * 90; + uint64_t stop_time = ( pv->current_entry.stop + + pv->subtitle->config.offset ) * 90; + + if( !( start_time > pv->start_time && stop_time < pv->stop_time ) ) + { + hb_deep_log( 3, "Discarding SRT at time start %"PRId64", stop %"PRId64, start_time, stop_time); + memset( &pv->current_entry, 0, sizeof( srt_entry_t ) ); + ++(pv->number_of_entries); + pv->current_state = k_state_timecode; + continue; + } - length = strlen( pv->current_entry.text ); + length = strlen( pv->current_entry.text ); - for( p = pv->current_entry.text; *p; p++) + for( q = p = pv->current_entry.text; *p; p++) + { + if( *p == '\n' ) { - if( *p == '\n' || *p == '\r' ) + if ( line == 1 ) { - *p = ' '; + *q = *p; + line = 2; } + else + { + *q = ' '; + } + q++; } - - buffer = hb_buffer_init( length + 1 ); - - if( buffer ) + else if( *p != '\r' ) { - buffer->start = start_time - pv->start_time; - buffer->stop = stop_time - pv->start_time; - - memcpy( buffer->data, pv->current_entry.text, length + 1 ); + *q = *p; + q++; + } + else + { + length--; } } - memset( &pv->current_entry, 0, sizeof( srt_entry_t ) ); - ++(pv->number_of_entries); - pv->current_state = k_state_timecode; + *q = '\0'; + + buffer = hb_buffer_init( length + 1 ); + if( buffer ) { - return buffer; + buffer->start = start_time - pv->start_time; + buffer->stop = stop_time - pv->start_time; + + memcpy( buffer->data, pv->current_entry.text, length + 1 ); } - continue; - } - else + } + memset( &pv->current_entry, 0, sizeof( srt_entry_t ) ); + ++(pv->number_of_entries); + pv->current_state = k_state_timecode; + if( buffer ) { - /* - * Well.. looks like we are in the wrong mode.. lets add the - * newline we misinterpreted... - */ - strncat(pv->current_entry.text, " ", 1024); - pv->current_state = k_state_inEntry; + return buffer; } - - break; + continue; + } } + } + + hb_buffer_t *buffer = NULL; + if( *pv->current_entry.text ) + { + long length; + char *p, *q; + int line = 1; + uint64_t start_time = ( pv->current_entry.start + + pv->subtitle->config.offset ) * 90; + uint64_t stop_time = ( pv->current_entry.stop + + pv->subtitle->config.offset ) * 90; + + if( !( start_time > pv->start_time && stop_time < pv->stop_time ) ) + { + hb_deep_log( 3, "Discarding SRT at time start %"PRId64", stop %"PRId64, start_time, stop_time); + memset( &pv->current_entry, 0, sizeof( srt_entry_t ) ); + return NULL; + } + + length = strlen( pv->current_entry.text ); + + for( q = p = pv->current_entry.text; *p; p++) + { + if( *p == '\n' ) + { + if ( line == 1 ) + { + *q = *p; + line = 2; + } + else + { + *q = ' '; + } + q++; + } + else if( *p != '\r' ) + { + *q = *p; + q++; + } + else + { + length--; + } + } + *q = '\0'; + + buffer = hb_buffer_init( length + 1 ); + + if( buffer ) + { + buffer->start = start_time - pv->start_time; + buffer->stop = stop_time - pv->start_time; + + memcpy( buffer->data, pv->current_entry.text, length + 1 ); } } + memset( &pv->current_entry, 0, sizeof( srt_entry_t ) ); + if( buffer ) + { + return buffer; + } return NULL; } @@ -313,10 +472,9 @@ static int decsrtInit( hb_work_object_t * w, hb_job_t * job ) buffer = hb_buffer_init( 0 ); hb_fifo_push( w->fifo_in, buffer); - pv->file = fopen( w->subtitle->config.src_filename, "r" ); - pv->current_state = k_state_potential_new_entry; pv->number_of_entries = 0; + pv->last_entry_number = 0; pv->current_time = 0; pv->subtitle = w->subtitle;