diff options
author | jstebbins <[email protected]> | 2014-04-13 16:22:16 +0000 |
---|---|---|
committer | jstebbins <[email protected]> | 2014-04-13 16:22:16 +0000 |
commit | 6db1a1e531ad62ba977f4587fb9011b0fd0b3416 (patch) | |
tree | 2c6882e9344b8181a11238835ae163d52e98e49e /libhb/decsrtsub.c | |
parent | e6ca45c979ec69bd1736bc943063083b08ce1914 (diff) |
Convert all text subtitles to ASS subs
Add support for font color to tx3g.
Allow more than one style flag at time in tx3g.
Add positioning support to CC subs
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@6163 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'libhb/decsrtsub.c')
-rw-r--r-- | libhb/decsrtsub.c | 182 |
1 files changed, 163 insertions, 19 deletions
diff --git a/libhb/decsrtsub.c b/libhb/decsrtsub.c index d4e74fdae..5854138a3 100644 --- a/libhb/decsrtsub.c +++ b/libhb/decsrtsub.c @@ -13,6 +13,8 @@ #include <iconv.h> #include <errno.h> #include "hb.h" +#include "colormap.h" +#include "decsrtsub.h" struct start_and_end { unsigned long start, end; @@ -56,17 +58,152 @@ struct hb_work_private_s hb_subtitle_t *subtitle; uint64_t start_time; // In HB time uint64_t stop_time; // In HB time + + int line; // SSA line number }; -static int +static char* srt_markup_to_ssa(char *srt, int *len) +{ + char terminator; + char color[40]; + uint32_t rgb; + + *len = 0; + if (srt[0] != '<' && srt[0] != '{') + return NULL; + + if (srt[0] == '<') + terminator = '>'; + else + terminator = '}'; + + if (srt[1] == 'i' && srt[2] == terminator) + { + *len = 3; + return hb_strdup_printf("{\\i1}"); + } + else if (srt[1] == 'b' && srt[2] == terminator) + { + *len = 3; + return hb_strdup_printf("{\\b1}"); + } + else if (srt[1] == 'u' && srt[2] == terminator) + { + *len = 3; + return hb_strdup_printf("{\\u1}"); + } + else if (srt[1] == '/' && srt[2] == 'i' && srt[3] == terminator) + { + *len = 4; + return hb_strdup_printf("{\\i0}"); + } + else if (srt[1] == '/' && srt[2] == 'b' && srt[3] == terminator) + { + *len = 4; + return hb_strdup_printf("{\\b0}"); + } + else if (srt[1] == '/' && srt[2] == 'u' && srt[3] == terminator) + { + *len = 4; + return hb_strdup_printf("{\\u0}"); + } + else if (srt[0] == '<' && !strncmp(srt + 1, "font", 4)) + { + int match; + match = sscanf(srt + 1, "font color=\"%39[^\"]\">", color); + if (match != 1) + { + return NULL; + } + while (srt[*len] != '>') (*len)++; + (*len)++; + if (color[0] == '#') + rgb = strtol(color + 1, NULL, 16); + else + rgb = hb_rgb_lookup_by_name(color); + return hb_strdup_printf("{\\1c&H%X&}", HB_RGB_TO_BGR(rgb)); + } + else if (srt[0] == '<' && srt[1] == '/' && !strncmp(srt + 2, "font", 4) && + srt[6] == '>') + { + *len = 7; + return hb_strdup_printf("{\\1c&HFFFFFF&}"); + } + + return NULL; +} + +void hb_srt_to_ssa(hb_buffer_t *sub_in, int line) +{ + if (sub_in->size == 0) + return; + + // null terminate input if not already terminated + if (sub_in->data[sub_in->size-1] != 0) + { + hb_buffer_realloc(sub_in, ++sub_in->size); + sub_in->data[sub_in->size - 1] = 0; + } + char * srt = (char*)sub_in->data; + // SSA markup expands a little over SRT, so allocate a bit of extra + // space. More will be realloc'd if needed. + hb_buffer_t * sub = hb_buffer_init(sub_in->size + 80); + char * ssa, *ssa_markup; + int skip, len, pos, ii; + + // Exchange data between input sub and new ssa_sub + // After this, sub_in contains ssa data + hb_buffer_swap_copy(sub_in, sub); + ssa = (char*)sub_in->data; + + sprintf((char*)sub_in->data, "%d,,Default,,0,0,0,,", line); + pos = strlen((char*)sub_in->data); + + ii = 0; + while (srt[ii] != '\0') + { + if ((ssa_markup = srt_markup_to_ssa(srt + ii, &skip)) != NULL) + { + len = strlen(ssa_markup); + hb_buffer_realloc(sub_in, pos + len + 1); + // After realloc, sub_in->data may change + ssa = (char*)sub_in->data; + sprintf(ssa + pos, "%s", ssa_markup); + free(ssa_markup); + pos += len; + ii += skip; + } + else + { + hb_buffer_realloc(sub_in, pos + 4); + // After realloc, sub_in->data may change + ssa = (char*)sub_in->data; + if (srt[ii] == '\n') + { + ssa[pos++] = '\\'; + ssa[pos++] = 'N'; + ii++; + } + else + { + ssa[pos++] = srt[ii++]; + } + } + } + ssa[pos] = '\0'; + sub_in->size = pos + 1; + hb_buffer_close(&sub); +} + +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; int scanned; - + scanned = sscanf(timeString, "%ld:%ld:%ld,%ld --> %ld:%ld:%ld,%ld\n", &houres1, &minutes1, &seconds1, &milliseconds1, &houres2, &minutes2, &seconds2, &milliseconds2); @@ -207,8 +344,8 @@ static hb_buffer_t *srt_read( hb_work_private_t *pv ) { return NULL; } - - while( reprocess || get_line( pv, line_buffer, sizeof( line_buffer ) ) ) + + while( reprocess || get_line( pv, line_buffer, sizeof( line_buffer ) ) ) { reprocess = 0; switch (pv->current_state) @@ -227,7 +364,7 @@ static hb_buffer_t *srt_read( hb_work_private_t *pv ) } pv->current_entry.duration = timing.end - timing.start; pv->current_entry.offset = timing.start - pv->current_time; - + pv->current_time = timing.end; pv->current_entry.start = timing.start; @@ -276,7 +413,7 @@ static hb_buffer_t *srt_read( hb_work_private_t *pv ) pv->current_state = k_state_potential_new_entry; continue; } - + q = pv->current_entry.text + pv->current_entry.pos; len = strlen( line_buffer ); size = MIN(1024 - pv->current_entry.pos - 1, len ); @@ -329,9 +466,9 @@ static hb_buffer_t *srt_read( hb_work_private_t *pv ) long length; char *p, *q; int line = 1; - uint64_t start_time = ( pv->current_entry.start + + uint64_t start_time = ( pv->current_entry.start + pv->subtitle->config.offset ) * 90; - uint64_t stop_time = ( pv->current_entry.stop + + uint64_t stop_time = ( pv->current_entry.stop + pv->subtitle->config.offset ) * 90; if( !( start_time > pv->start_time && stop_time < pv->stop_time ) ) @@ -396,7 +533,7 @@ static hb_buffer_t *srt_read( hb_work_private_t *pv ) return buffer; } continue; - } + } } } @@ -406,9 +543,9 @@ static hb_buffer_t *srt_read( hb_work_private_t *pv ) long length; char *p, *q; int line = 1; - uint64_t start_time = ( pv->current_entry.start + + uint64_t start_time = ( pv->current_entry.start + pv->subtitle->config.offset ) * 90; - uint64_t stop_time = ( pv->current_entry.stop + + uint64_t stop_time = ( pv->current_entry.stop + pv->subtitle->config.offset ) * 90; if( !( start_time > pv->start_time && stop_time < pv->stop_time ) ) @@ -467,7 +604,7 @@ static hb_buffer_t *srt_read( hb_work_private_t *pv ) { return buffer; } - + return NULL; } @@ -488,7 +625,7 @@ 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->current_state = k_state_potential_new_entry; pv->number_of_entries = 0; pv->last_entry_number = 0; @@ -540,14 +677,20 @@ static int decsrtInit( hb_work_object_t * w, hb_job_t * job ) if( !pv->file ) { - hb_error("Could not open the SRT subtitle file '%s'\n", + hb_error("Could not open the SRT subtitle file '%s'\n", w->subtitle->config.src_filename); } else { retval = 0; } } - } - + } + if (!retval) + { + // Generate generic SSA Script Info. + int height = job->title->height - job->crop[0] - job->crop[1]; + int width = job->title->width - job->crop[2] - job->crop[3]; + hb_subtitle_add_ssa_header(w->subtitle, width, height); + } return retval; } @@ -559,9 +702,10 @@ static int decsrtWork( hb_work_object_t * w, hb_buffer_t ** buf_in, hb_buffer_t * out = NULL; out = srt_read( pv ); - if( out ) { + hb_srt_to_ssa(out, ++pv->line); + /* * Keep a buffer in our input fifo so that we get run. */ @@ -573,7 +717,7 @@ static int decsrtWork( hb_work_object_t * w, hb_buffer_t ** buf_in, return HB_WORK_OK; } - return HB_WORK_OK; + return HB_WORK_OK; } static void decsrtClose( hb_work_object_t * w ) |