From c0545943835f67e3df986e6b87bd433b5d40f7e7 Mon Sep 17 00:00:00 2001 From: Anshul Maheshwari Date: Wed, 30 Jul 2014 21:17:04 +0530 Subject: [PATCH] output of dvb in srt sami smptett format --- src/608_sami.c | 150 ++++++++++++++++++++++++++++++++++++++- src/608_smptett.c | 136 +++++++++++++++++++++++++++++++++++ src/608_srt.c | 140 ++++++++++++++++++++++++++++++++++++ src/cc_decoders_common.h | 6 -- src/cc_encoders_common.c | 12 +++- src/cc_encoders_common.h | 3 + src/constants.h | 9 ++- src/spupng_encoder.c | 4 -- src/spupng_encoder.h | 4 ++ src/ts_tables.c | 4 +- src/utility.h | 4 -- 11 files changed, 452 insertions(+), 20 deletions(-) diff --git a/src/608_sami.c b/src/608_sami.c index 847b48d7..eeca0596 100644 --- a/src/608_sami.c +++ b/src/608_sami.c @@ -1,6 +1,9 @@ #include "ccextractor.h" #include "cc_encoders_common.h" - +#include "png.h" +#include "spupng_encoder.h" +#include "ocr.h" +#include "utility.h" void write_stringz_as_sami(char *string, struct encoder_ctx *context, LLONG ms_start, LLONG ms_end) { int used; @@ -74,7 +77,152 @@ void write_stringz_as_sami(char *string, struct encoder_ctx *context, LLONG ms_s } +int write_cc_bitmap_as_sami(struct cc_subtitle *sub, struct encoder_ctx *context) +{ + struct spupng_t *sp = (struct spupng_t *)context->out->spupng_data; + int x_pos, y_pos, width, height, i; + int x, y, y_off, x_off, ret; + uint8_t *pbuf; + char *filename; + struct cc_bitmap* rect; + png_color *palette = NULL; + png_byte *alpha = NULL; +#ifdef ENABLE_OCR + char*str = NULL; +#endif + int used; + unsigned h1,m1,s1,ms1; + unsigned h2,m2,s2,ms2; + LLONG ms_start, ms_end; + char timeline[128]; + int len = 0; + x_pos = -1; + y_pos = -1; + width = 0; + height = 0; + + if (context->prev_start != -1 && (sub->flags & SUB_EOD_MARKER)) + { + ms_start = context->prev_start + subs_delay; + ms_end = sub->start_time - 1; + } + else if ( !(sub->flags & SUB_EOD_MARKER)) + { + ms_start = sub->start_time + subs_delay; + ms_end = sub->end_time - 1; + } + + if(sub->nb_data == 0 ) + return 0; + rect = sub->data; + for(i = 0;i < sub->nb_data;i++) + { + if(x_pos == -1) + { + x_pos = rect[i].x; + y_pos = rect[i].y; + width = rect[i].w; + height = rect[i].h; + } + else + { + if(x_pos > rect[i].x) + { + width += (x_pos - rect[i].x); + x_pos = rect[i].x; + } + + if (rect[i].y < y_pos) + { + height += (y_pos - rect[i].y); + y_pos = rect[i].y; + } + + if (rect[i].x + rect[i].w > x_pos + width) + { + width = rect[i].x + rect[i].w - x_pos; + } + + if (rect[i].y + rect[i].h > y_pos + height) + { + height = rect[i].y + rect[i].h - y_pos; + } + + } + } + if ( sub->flags & SUB_EOD_MARKER ) + context->prev_start = sub->start_time; + pbuf = (uint8_t*) malloc(width * height); + memset(pbuf, 0x0, width * height); + + for(i = 0;i < sub->nb_data;i++) + { + x_off = rect[i].x - x_pos; + y_off = rect[i].y - y_pos; + for (y = 0; y < rect[i].h; y++) + { + for (x = 0; x < rect[i].w; x++) + pbuf[((y + y_off) * width) + x_off + x] = rect[i].data[0][y * rect[i].w + x]; + + } + } + palette = (png_color*) malloc(rect[0].nb_colors * sizeof(png_color)); + if(!palette) + { + ret = -1; + goto end; + } + alpha = (png_byte*) malloc(rect[0].nb_colors * sizeof(png_byte)); + if(!alpha) + { + ret = -1; + goto end; + } + /* TODO do rectangle, wise one color table should not be used for all rectangle */ + mapclut_paletee(palette, alpha, (uint32_t *)rect[0].data[1],rect[0].nb_colors); + quantize_map(alpha, palette, pbuf, width*height, 3, rect[0].nb_colors); +#ifdef ENABLE_OCR + str = ocr_bitmap(palette,alpha,pbuf,width,height); + if(str && str[0]) + { + if (context->prev_start != -1 || !(sub->flags & SUB_EOD_MARKER)) + { + char *token = NULL; + sprintf(context->buffer, + "

\r\n" + ,(unsigned long long)ms_start); + write(context->out->fh,context->buffer,strlen(context->buffer)); + token = strtok(str,"\r\n"); + while (token) + { + + sprintf(context->buffer,"%s",token); + token = strtok(NULL,"\r\n"); + if(token) + strcat(context->buffer,"
\n"); + else + strcat(context->buffer,"\n"); + write(context->out->fh,context->buffer,strlen(context->buffer)); + + } + sprintf(context->buffer, + "

 

\r\n\r\n" + ,(unsigned long long)ms_end); + write(context->out->fh,context->buffer,strlen(context->buffer)); + + } + } +#endif + +end: + sub->nb_data = 0; + freep(&sub->data); + freep(&palette); + freep(&alpha); + return ret; + +} int write_cc_buffer_as_sami(struct eia608_screen *data, struct encoder_ctx *context) { int used; diff --git a/src/608_smptett.c b/src/608_smptett.c index 32d5ce08..eb68acd4 100644 --- a/src/608_smptett.c +++ b/src/608_smptett.c @@ -1,5 +1,9 @@ #include "ccextractor.h" #include "cc_encoders_common.h" +#include "png.h" +#include "spupng_encoder.h" +#include "ocr.h" +#include "utility.h" // Produces minimally-compliant SMPTE Timed Text (W3C TTML) // format-compatible output @@ -99,6 +103,138 @@ void write_stringz_as_smptett(char *string, struct encoder_ctx *context, LLONG m } +int write_cc_bitmap_as_smptett(struct cc_subtitle *sub, struct encoder_ctx *context) +{ + struct spupng_t *sp = (struct spupng_t *)context->out->spupng_data; + int x_pos, y_pos, width, height, i; + int x, y, y_off, x_off, ret; + uint8_t *pbuf; + char *filename; + struct cc_bitmap* rect; + png_color *palette = NULL; + png_byte *alpha = NULL; +#ifdef ENABLE_OCR + char*str = NULL; +#endif + int used; + unsigned h1,m1,s1,ms1; + unsigned h2,m2,s2,ms2; + LLONG ms_start, ms_end; + char timeline[128]; + int len = 0; + + x_pos = -1; + y_pos = -1; + width = 0; + height = 0; + + if (context->prev_start != -1 && (sub->flags & SUB_EOD_MARKER)) + { + ms_start = context->prev_start + subs_delay; + ms_end = sub->start_time - 1; + } + else if ( !(sub->flags & SUB_EOD_MARKER)) + { + ms_start = sub->start_time + subs_delay; + ms_end = sub->end_time - 1; + } + + if(sub->nb_data == 0 ) + return 0; + rect = sub->data; + for(i = 0;i < sub->nb_data;i++) + { + if(x_pos == -1) + { + x_pos = rect[i].x; + y_pos = rect[i].y; + width = rect[i].w; + height = rect[i].h; + } + else + { + if(x_pos > rect[i].x) + { + width += (x_pos - rect[i].x); + x_pos = rect[i].x; + } + + if (rect[i].y < y_pos) + { + height += (y_pos - rect[i].y); + y_pos = rect[i].y; + } + + if (rect[i].x + rect[i].w > x_pos + width) + { + width = rect[i].x + rect[i].w - x_pos; + } + + if (rect[i].y + rect[i].h > y_pos + height) + { + height = rect[i].y + rect[i].h - y_pos; + } + + } + } + if ( sub->flags & SUB_EOD_MARKER ) + context->prev_start = sub->start_time; + pbuf = (uint8_t*) malloc(width * height); + memset(pbuf, 0x0, width * height); + + for(i = 0;i < sub->nb_data;i++) + { + x_off = rect[i].x - x_pos; + y_off = rect[i].y - y_pos; + for (y = 0; y < rect[i].h; y++) + { + for (x = 0; x < rect[i].w; x++) + pbuf[((y + y_off) * width) + x_off + x] = rect[i].data[0][y * rect[i].w + x]; + + } + } + palette = (png_color*) malloc(rect[0].nb_colors * sizeof(png_color)); + if(!palette) + { + ret = -1; + goto end; + } + alpha = (png_byte*) malloc(rect[0].nb_colors * sizeof(png_byte)); + if(!alpha) + { + ret = -1; + goto end; + } + /* TODO do rectangle, wise one color table should not be used for all rectangle */ + mapclut_paletee(palette, alpha, (uint32_t *)rect[0].data[1],rect[0].nb_colors); + quantize_map(alpha, palette, pbuf, width*height, 3, rect[0].nb_colors); +#ifdef ENABLE_OCR + str = ocr_bitmap(palette,alpha,pbuf,width,height); + if(str && str[0]) + { + if (context->prev_start != -1 || !(sub->flags & SUB_EOD_MARKER)) + { + mstotime (ms_start,&h1,&m1,&s1,&ms1); + mstotime (ms_end-1,&h2,&m2,&s2,&ms2); // -1 To prevent overlapping with next line. + sprintf ((char *) context->buffer,"

\n",h1,m1,s1,ms1, h2,m2,s2,ms2); + write (context->out->fh, context->buffer,strlen(context->buffer) ); + len = strlen(str); + write (context->out->fh, str, len); + write (context->out->fh, encoded_crlf, encoded_crlf_length); + sprintf ((char *) str,"

\n"); + + } + } +#endif + +end: + sub->nb_data = 0; + freep(&sub->data); + freep(&palette); + freep(&alpha); + return ret; + +} int write_cc_buffer_as_smptett(struct eia608_screen *data, struct encoder_ctx *context) { diff --git a/src/608_srt.c b/src/608_srt.c index 9ee2e241..738dcc9d 100644 --- a/src/608_srt.c +++ b/src/608_srt.c @@ -1,5 +1,9 @@ #include "ccextractor.h" #include "cc_encoders_common.h" +#include "png.h" +#include "spupng_encoder.h" +#include "ocr.h" +#include "utility.h" /* The timing here is not PTS based, but output based, i.e. user delay must be accounted for if there is any */ @@ -68,6 +72,142 @@ void write_stringz_as_srt(char *string, struct encoder_ctx *context, LLONG ms_st free(unescaped); } +int write_cc_bitmap_as_srt(struct cc_subtitle *sub, struct encoder_ctx *context) +{ + struct spupng_t *sp = (struct spupng_t *)context->out->spupng_data; + int x_pos, y_pos, width, height, i; + int x, y, y_off, x_off, ret; + uint8_t *pbuf; + char *filename; + struct cc_bitmap* rect; + png_color *palette = NULL; + png_byte *alpha = NULL; +#ifdef ENABLE_OCR + char*str = NULL; +#endif + int used; + unsigned h1,m1,s1,ms1; + unsigned h2,m2,s2,ms2; + LLONG ms_start, ms_end; + char timeline[128]; + int len = 0; + + x_pos = -1; + y_pos = -1; + width = 0; + height = 0; + + if (context->prev_start != -1 && (sub->flags & SUB_EOD_MARKER)) + { + ms_start = context->prev_start; + ms_end = sub->start_time; + } + else if ( !(sub->flags & SUB_EOD_MARKER)) + { + ms_start = sub->start_time; + ms_end = sub->end_time; + } + + if(sub->nb_data == 0 ) + return 0; + rect = sub->data; + for(i = 0;i < sub->nb_data;i++) + { + if(x_pos == -1) + { + x_pos = rect[i].x; + y_pos = rect[i].y; + width = rect[i].w; + height = rect[i].h; + } + else + { + if(x_pos > rect[i].x) + { + width += (x_pos - rect[i].x); + x_pos = rect[i].x; + } + + if (rect[i].y < y_pos) + { + height += (y_pos - rect[i].y); + y_pos = rect[i].y; + } + + if (rect[i].x + rect[i].w > x_pos + width) + { + width = rect[i].x + rect[i].w - x_pos; + } + + if (rect[i].y + rect[i].h > y_pos + height) + { + height = rect[i].y + rect[i].h - y_pos; + } + + } + } + if ( sub->flags & SUB_EOD_MARKER ) + context->prev_start = sub->start_time; + pbuf = (uint8_t*) malloc(width * height); + memset(pbuf, 0x0, width * height); + + for(i = 0;i < sub->nb_data;i++) + { + x_off = rect[i].x - x_pos; + y_off = rect[i].y - y_pos; + for (y = 0; y < rect[i].h; y++) + { + for (x = 0; x < rect[i].w; x++) + pbuf[((y + y_off) * width) + x_off + x] = rect[i].data[0][y * rect[i].w + x]; + + } + } + palette = (png_color*) malloc(rect[0].nb_colors * sizeof(png_color)); + if(!palette) + { + ret = -1; + goto end; + } + alpha = (png_byte*) malloc(rect[0].nb_colors * sizeof(png_byte)); + if(!alpha) + { + ret = -1; + goto end; + } + /* TODO do rectangle, wise one color table should not be used for all rectangle */ + mapclut_paletee(palette, alpha, (uint32_t *)rect[0].data[1],rect[0].nb_colors); + quantize_map(alpha, palette, pbuf, width*height, 3, rect[0].nb_colors); +#ifdef ENABLE_OCR + str = ocr_bitmap(palette,alpha,pbuf,width,height); + if(str && str[0]) + { + if (context->prev_start != -1 || !(sub->flags & SUB_EOD_MARKER)) + { + mstotime (ms_start,&h1,&m1,&s1,&ms1); + mstotime (ms_end-1,&h2,&m2,&s2,&ms2); // -1 To prevent overlapping with next line. + context->srt_counter++; + sprintf(timeline, "%u\r\n", context->srt_counter); + used = encode_line(context->buffer,(unsigned char *) timeline); + write(context->out->fh, context->buffer, used); + sprintf (timeline, "%02u:%02u:%02u,%03u --> %02u:%02u:%02u,%03u\r\n", + h1,m1,s1,ms1, h2,m2,s2,ms2); + used = encode_line(context->buffer,(unsigned char *) timeline); + write (context->out->fh, context->buffer, used); + len = strlen(str); + write (context->out->fh, str, len); + write (context->out->fh, encoded_crlf, encoded_crlf_length); + } + } +#endif + +end: + sub->nb_data = 0; + freep(&sub->data); + freep(&palette); + freep(&alpha); + return ret; + +} int write_cc_buffer_as_srt(struct eia608_screen *data, struct encoder_ctx *context) { int used; diff --git a/src/cc_decoders_common.h b/src/cc_decoders_common.h index b2479019..5ce58c01 100644 --- a/src/cc_decoders_common.h +++ b/src/cc_decoders_common.h @@ -3,12 +3,6 @@ /* flag raised when end of display marker arrives in Dvb Subtitle */ #define SUB_EOD_MARKER (1 << 0 ) -enum subtype -{ - CC_BITMAP, - CC_608, -}; - struct cc_bitmap { int x; diff --git a/src/cc_encoders_common.c b/src/cc_encoders_common.c index 93ef09f4..d68b5021 100644 --- a/src/cc_encoders_common.c +++ b/src/cc_encoders_common.c @@ -388,12 +388,22 @@ int encode_sub(struct encoder_ctx *context, struct cc_subtitle *sub) switch (ccx_options.write_format) { case CCX_OF_SRT: + if (!startcredits_displayed && ccx_options.start_credits_text!=NULL) + try_to_add_start_credits(context, sub->start_time); + wrote_something = write_cc_bitmap_as_srt(sub, context); case CCX_OF_SAMI: + if (!startcredits_displayed && ccx_options.start_credits_text!=NULL) + try_to_add_start_credits(context, sub->start_time); + wrote_something = write_cc_bitmap_as_sami(sub, context); case CCX_OF_SMPTETT: + if (!startcredits_displayed && ccx_options.start_credits_text!=NULL) + try_to_add_start_credits(context, sub->start_time); + wrote_something = write_cc_bitmap_as_smptett(sub, context); case CCX_OF_TRANSCRIPT: +// wrote_something = write_cc_bitmap_as_transcript(sub, context); break; case CCX_OF_SPUPNG: - write_cc_bitmap_as_spupng(sub, context); + wrote_something = write_cc_bitmap_as_spupng(sub, context); break; default: break; diff --git a/src/cc_encoders_common.h b/src/cc_encoders_common.h index f25029f7..afb0139e 100644 --- a/src/cc_encoders_common.h +++ b/src/cc_encoders_common.h @@ -61,4 +61,7 @@ void write_stringz_as_smptett(char *string, struct encoder_ctx *context, LLONG m void write_cc_buffer_to_gui(struct eia608_screen *data, struct encoder_ctx *context); int write_cc_bitmap_as_spupng(struct cc_subtitle *sub, struct encoder_ctx *context); +int write_cc_bitmap_as_srt(struct cc_subtitle *sub, struct encoder_ctx *context); +int write_cc_bitmap_as_sami(struct cc_subtitle *sub, struct encoder_ctx *context); +int write_cc_bitmap_as_smptett(struct cc_subtitle *sub, struct encoder_ctx *context); #endif diff --git a/src/constants.h b/src/constants.h index 0d87e716..8577ad94 100644 --- a/src/constants.h +++ b/src/constants.h @@ -258,8 +258,11 @@ enum cxx_code_type #define CCX_TXT_AUTO_NOT_YET_FOUND 1 #define CCX_TXT_IN_USE 2 // Positive autodetected, or forced, etc - -#define CCX_OF_TYPE_TEXT 1 -#define CCX_OF_TYPE_IMAGE 2 +enum subtype +{ + CC_BITMAP, + CC_608, + CC_TEXT, +}; #endif diff --git a/src/spupng_encoder.c b/src/spupng_encoder.c index 20c72f67..e8a27297 100644 --- a/src/spupng_encoder.c +++ b/src/spupng_encoder.c @@ -317,10 +317,6 @@ void write_spucomment(struct spupng_t *sp,const char *str) fprintf(sp->fpxml, "-->\n"); } -int get_spupng_subtype(void) -{ - return (1 << CCX_OF_TYPE_TEXT)|(1< #endif -#ifdef _MSC_VER -#define snprintf(str,size,format,...) _snprintf(str,size-1,format,__VA_ARGS__) -#endif - #define RL32(x) (*(unsigned int *)(x)) #define RB32(x) (ntohl(*(unsigned int *)(x))) #define RL16(x) (*(unsigned short int*)(x))