int write_cc_bitmap_as_srt(struct cc_subtitle *sub, struct encoder_ctx *context) { int ret = 0; #ifdef ENABLE_OCR struct cc_bitmap* rect; LLONG ms_start, ms_end; unsigned h1,m1,s1,ms1; unsigned h2,m2,s2,ms2; char timeline[128]; int len = 0; int used; 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; } else if (context->prev_start == -1 && (sub->flags & SUB_EOD_MARKER)) { ms_start = 1; ms_end = sub->start_time; } if(sub->nb_data == 0 ) return 0; if(sub->flags & SUB_EOD_MARKER) context->prev_start = sub->start_time; rect = sub->data; if (rect[0].ocr_text && *(rect[0].ocr_text)) { 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, 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, context->buffer,(unsigned char *) timeline); write (context->out->fh, context->buffer, used); len = strlen(rect[0].ocr_text); write (context->out->fh, rect[0].ocr_text, len); write (context->out->fh, context->encoded_crlf, context->encoded_crlf_length); } } #endif sub->nb_data = 0; freep(&sub->data); return ret; }
int write_cc_buffer_as_smptett (struct eia608_screen *data, struct s_write *wb) { unsigned h1,m1,s1,ms1; unsigned h2,m2,s2,ms2; int wrote_something=0; LLONG startms = wb->data608->current_visible_start_ms; startms+=subs_delay; if (startms<0) // Drop screens that because of subs_delay start too early return 0; LLONG endms = get_visible_end()+subs_delay; endms--; // To prevent overlapping with next line. mstotime (startms,&h1,&m1,&s1,&ms1); mstotime (endms-1,&h2,&m2,&s2,&ms2); sprintf ((char *) str,"<p begin=\"%02u:%02u:%02u,%03u\" end=\"%02u:%02u:%02u,%03u\">\n",h1,m1,s1,ms1, h2,m2,s2,ms2); if (encoding!=ENC_UNICODE) { dbg_print(DMT_608, "\r%s\n", str); } enc_buffer_used=encode_line (enc_buffer,(unsigned char *) str); write (wb->fh, enc_buffer,enc_buffer_used); for (int i=0;i<15;i++) { if (data->row_used[i]) { int length = get_decoder_line_encoded (subline, i, data); if (encoding!=ENC_UNICODE) { dbg_print(DMT_608, "\r"); dbg_print(DMT_608, "%s\n",subline); } write (wb->fh, subline, length); wrote_something=1; //if (i!=14) //write (wb->fh, encoded_br, encoded_br_length); write (wb->fh,encoded_crlf, encoded_crlf_length); } } sprintf ((char *) str,"</p>\n"); if (encoding!=ENC_UNICODE) { dbg_print(DMT_608, "\r%s\n", str); } enc_buffer_used=encode_line (enc_buffer,(unsigned char *) str); write (wb->fh, enc_buffer,enc_buffer_used); if (encoding!=ENC_UNICODE) { dbg_print(DMT_608, "\r%s\n", str); } enc_buffer_used=encode_line (enc_buffer,(unsigned char *) str); //write (wb->fh, enc_buffer,enc_buffer_used); return wrote_something; }
void write_cc_buffer_to_gui(struct eia608_screen *data, struct encoder_ctx *context) { unsigned h1, m1, s1, ms1; unsigned h2, m2, s2, ms2; LLONG ms_start; int with_data = 0; for (int i = 0; i<15; i++) { if (data->row_used[i]) with_data = 1; } if (!with_data) return; ms_start = data->start_time; ms_start += context->subs_delay; if (ms_start<0) // Drop screens that because of subs_delay start too early return; int time_reported = 0; for (int i = 0; i<15; i++) { if (data->row_used[i]) { fprintf(stderr, "###SUBTITLE#"); if (!time_reported) { LLONG ms_end = data->end_time; 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 fprintf(stderr, "%02u:%02u#%02u:%02u#", h1 * 60 + m1, s1, h2 * 60 + m2, s2); time_reported = 1; } else fprintf(stderr, "##"); // We don't capitalize here because whatever function that was used // before to write to file already took care of it. int length = get_decoder_line_encoded_for_gui(context->subline, i, data); fwrite(context->subline, 1, length, stderr); fwrite("\n", 1, 1, stderr); } } fflush(stderr); }
int write_cc_bitmap_as_transcript(struct cc_subtitle *sub, struct encoder_ctx *context) { int ret = 0; #ifdef ENABLE_OCR struct cc_bitmap* rect; unsigned h1,m1,s1,ms1; unsigned h2,m2,s2,ms2; LLONG start_time, end_time; if (context->prev_start != -1 && (sub->flags & SUB_EOD_MARKER)) { start_time = context->prev_start + context->subs_delay; end_time = sub->start_time - 1; } else if ( !(sub->flags & SUB_EOD_MARKER)) { start_time = sub->start_time + context->subs_delay; end_time = sub->end_time - 1; } if(sub->nb_data == 0 ) return ret; rect = sub->data; if ( sub->flags & SUB_EOD_MARKER ) context->prev_start = sub->start_time; if (rect[0].ocr_text && *(rect[0].ocr_text)) { if (context->prev_start != -1 || !(sub->flags & SUB_EOD_MARKER)) { char *token = NULL; token = strtok(rect[0].ocr_text ,"\r\n"); while (token) { if (context->transcript_settings->showStartTime) { char buf1[80]; if (context->transcript_settings->relativeTimestamp) { millis_to_date(start_time + context->subs_delay, buf1, context->date_format, context->millis_separator); fdprintf(context->out->fh, "%s|", buf1); } else { mstotime(start_time + context->subs_delay, &h1, &m1, &s1, &ms1); time_t start_time_int = (start_time + context->subs_delay) / 1000; int start_time_dec = (start_time + context->subs_delay) % 1000; struct tm *start_time_struct = gmtime(&start_time_int); strftime(buf1, sizeof(buf1), "%Y%m%d%H%M%S", start_time_struct); fdprintf(context->out->fh, "%s%c%03d|", buf1,context->millis_separator,start_time_dec); } } if (context->transcript_settings->showEndTime) { char buf2[80]; if (context->transcript_settings->relativeTimestamp) { millis_to_date(end_time, buf2, context->date_format, context->millis_separator); fdprintf(context->out->fh, "%s|", buf2); } else { mstotime(get_fts() + context->subs_delay, &h2, &m2, &s2, &ms2); time_t end_time_int = end_time / 1000; int end_time_dec = end_time % 1000; struct tm *end_time_struct = gmtime(&end_time_int); strftime(buf2, sizeof(buf2), "%Y%m%d%H%M%S", end_time_struct); fdprintf(context->out->fh, "%s%c%03d|", buf2,context->millis_separator,end_time_dec); } } if (context->transcript_settings->showCC) { fdprintf(context->out->fh,"%s|",language[sub->lang_index]); } if (context->transcript_settings->showMode) { fdprintf(context->out->fh,"DVB|"); } fdprintf(context->out->fh,"%s\n",token); token = strtok(NULL,"\r\n"); } } } #endif sub->nb_data = 0; freep(&sub->data); return ret; }
void write_cc_line_as_transcript2(struct eia608_screen *data, struct encoder_ctx *context, int line_number) { int ret = 0; unsigned int h1,m1,s1,ms1; unsigned int h2,m2,s2,ms2; LLONG start_time = data->start_time; LLONG end_time = data->end_time; if (context->sentence_cap) { capitalize (line_number,data); correct_case(line_number,data); } int length = get_decoder_str_basic (context->subline, data->characters[line_number], context->trim_subs, context->encoding); if (context->encoding!=CCX_ENC_UNICODE) { dbg_print(CCX_DMT_DECODER_608, "\r"); dbg_print(CCX_DMT_DECODER_608, "%s\n",context->subline); } if (length>0) { if (data->start_time == -1) { // CFS: Means that the line has characters but we don't have a timestamp for the first one. Since the timestamp // is set for example by the write_char function, it possible that we don't have one in empty lines (unclear) // For now, let's not consider this a bug as before and just return. // fatal (EXIT_BUG_BUG, "Bug in timedtranscript (ts_start_of_current_line==-1). Please report."); return; } if (context->transcript_settings->showStartTime){ char buf1[80]; if (context->transcript_settings->relativeTimestamp){ millis_to_date(start_time + context->subs_delay, buf1, context->date_format, context->millis_separator); fdprintf(context->out->fh, "%s|", buf1); } else { mstotime(start_time + context->subs_delay, &h1, &m1, &s1, &ms1); time_t start_time_int = (start_time + context->subs_delay) / 1000; int start_time_dec = (start_time + context->subs_delay) % 1000; struct tm *start_time_struct = gmtime(&start_time_int); strftime(buf1, sizeof(buf1), "%Y%m%d%H%M%S", start_time_struct); fdprintf(context->out->fh, "%s%c%03d|", buf1,context->millis_separator,start_time_dec); } } if (context->transcript_settings->showEndTime){ char buf2[80]; if (context->transcript_settings->relativeTimestamp){ millis_to_date(end_time, buf2, context->date_format, context->millis_separator); fdprintf(context->out->fh, "%s|", buf2); } else { mstotime(get_fts() + context->subs_delay, &h2, &m2, &s2, &ms2); time_t end_time_int = (end_time + context->subs_delay) / 1000; int end_time_dec = (end_time + context->subs_delay) % 1000; struct tm *end_time_struct = gmtime(&end_time_int); strftime(buf2, sizeof(buf2), "%Y%m%d%H%M%S", end_time_struct); fdprintf(context->out->fh, "%s%c%03d|", buf2,context->millis_separator,end_time_dec); } } if (context->transcript_settings->showCC){ fdprintf(context->out->fh, "CC%d|", data->my_field == 1 ? data->channel : data->channel + 2); // Data from field 2 is CC3 or 4 } if (context->transcript_settings->showMode){ const char *mode = "???"; switch (data->mode) { case MODE_POPON: mode = "POP"; break; case MODE_FAKE_ROLLUP_1: mode = "RU1"; break; case MODE_ROLLUP_2: mode = "RU2"; break; case MODE_ROLLUP_3: mode = "RU3"; break; case MODE_ROLLUP_4: mode = "RU4"; break; case MODE_TEXT: mode = "TXT"; break; case MODE_PAINTON: mode = "PAI"; break; } fdprintf(context->out->fh, "%s|", mode); } ret = write(context->out->fh, context->subline, length); if(ret < length) { mprint("Warning:Loss of data\n"); } ret = write(context->out->fh, encoded_crlf, encoded_crlf_length); if(ret < encoded_crlf_length) { mprint("Warning:Loss of data\n"); } } // fprintf (wb->fh,encoded_crlf); }
int write_cc_subtitle_as_transcript(struct cc_subtitle *sub, struct encoder_ctx *context) { int length; int ret = 0; unsigned int h1,m1,s1,ms1; unsigned int h2,m2,s2,ms2; LLONG start_time; LLONG end_time; char *str; struct cc_subtitle *osub = sub; struct cc_subtitle *lsub = sub; while(sub) { if(sub->type == CC_TEXT) { start_time = sub->start_time; end_time = sub->end_time; } if (context->sentence_cap) { //TODO capitalize (line_number,data); //TODO correct_case(line_number,data); } str = sub->data; length = strlen(str); if (context->encoding!=CCX_ENC_UNICODE) { dbg_print(CCX_DMT_DECODER_608, "\r"); dbg_print(CCX_DMT_DECODER_608, "%s\n", str); } if (length>0) { if (start_time == -1) { // CFS: Means that the line has characters but we don't have a timestamp for the first one. Since the timestamp // is set for example by the write_char function, it possible that we don't have one in empty lines (unclear) // For now, let's not consider this a bug as before and just return. // fatal (EXIT_BUG_BUG, "Bug in timedtranscript (ts_start_of_current_line==-1). Please report."); return 0; } if (context->transcript_settings->showStartTime){ char buf1[80]; if (context->transcript_settings->relativeTimestamp){ millis_to_date(start_time + context->subs_delay, buf1, context->date_format, context->millis_separator); fdprintf(context->out->fh, "%s|", buf1); } else { mstotime(start_time + context->subs_delay, &h1, &m1, &s1, &ms1); time_t start_time_int = (start_time + context->subs_delay) / 1000; int start_time_dec = (start_time + context->subs_delay) % 1000; struct tm *start_time_struct = gmtime(&start_time_int); strftime(buf1, sizeof(buf1), "%Y%m%d%H%M%S", start_time_struct); fdprintf(context->out->fh, "%s%c%03d|", buf1,context->millis_separator,start_time_dec); } } if (context->transcript_settings->showEndTime){ char buf2[80]; if (context->transcript_settings->relativeTimestamp){ millis_to_date(end_time, buf2, context->date_format, context->millis_separator); fdprintf(context->out->fh, "%s|", buf2); } else { mstotime(get_fts() + context->subs_delay, &h2, &m2, &s2, &ms2); time_t end_time_int = (end_time + context->subs_delay) / 1000; int end_time_dec = (end_time + context->subs_delay) % 1000; struct tm *end_time_struct = gmtime(&end_time_int); strftime(buf2, sizeof(buf2), "%Y%m%d%H%M%S", end_time_struct); fdprintf(context->out->fh, "%s%c%03d|", buf2,context->millis_separator,end_time_dec); } } if (context->transcript_settings->showCC) { if(context->in_fileformat == 2 ) fdprintf(context->out->fh, sub->info); else //TODO, data->my_field == 1 ? data->channel : data->channel + 2); // Data from field 2 is CC3 or 4 fdprintf(context->out->fh, "CC?|"); } if (context->transcript_settings->showMode){ fdprintf(context->out->fh, "%s|", sub->mode); } ret = write(context->out->fh, str, length); if(ret < length) { mprint("Warning:Loss of data\n"); } ret = write(context->out->fh, encoded_crlf, encoded_crlf_length); if(ret < encoded_crlf_length) { mprint("Warning:Loss of data\n"); } } freep(&sub->data); lsub = sub; sub = sub->next; } while(lsub != osub) { sub = lsub->prev; freep(&lsub); lsub = sub; } return ret; }
/* The timing here is not PTS based, but output based, i.e. user delay must be accounted for if there is any */ int write_stringz_as_srt(char *string, struct encoder_ctx *context, LLONG ms_start, LLONG ms_end) { int used; unsigned h1,m1,s1,ms1; unsigned h2,m2,s2,ms2; char timeline[128]; if(!string || !string[0]) return 0; 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%s", context->srt_counter, context->encoded_crlf); used = encode_line(context, context->buffer,(unsigned char *) timeline); write(context->out->fh, context->buffer, used); sprintf (timeline, "%02u:%02u:%02u,%03u --> %02u:%02u:%02u,%03u%s", h1, m1, s1, ms1, h2, m2, s2, ms2, context->encoded_crlf); used = encode_line(context, context->buffer,(unsigned char *) timeline); dbg_print(CCX_DMT_DECODER_608, "\n- - - SRT caption - - -\n"); dbg_print(CCX_DMT_DECODER_608, "%s",timeline); write(context->out->fh, context->buffer, used); int len=strlen (string); unsigned char *unescaped= (unsigned char *) malloc (len+1); unsigned char *el = (unsigned char *) malloc (len*3+1); // Be generous if (el==NULL || unescaped==NULL) fatal (EXIT_NOT_ENOUGH_MEMORY, "In write_stringz_as_srt() - not enough memory.\n"); int pos_r=0; int pos_w=0; // Scan for \n in the string and replace it with a 0 while (pos_r<len) { if (string[pos_r]=='\\' && string[pos_r+1]=='n') { unescaped[pos_w]=0; pos_r+=2; } else { unescaped[pos_w]=string[pos_r]; pos_r++; } pos_w++; } unescaped[pos_w]=0; // Now read the unescaped string (now several string'z and write them) unsigned char *begin=unescaped; while (begin<unescaped+len) { unsigned int u = encode_line (context, el, begin); if (context->encoding != CCX_ENC_UNICODE) { dbg_print(CCX_DMT_DECODER_608, "\r"); dbg_print(CCX_DMT_DECODER_608, "%s\n",context->subline); } write(context->out->fh, el, u); write(context->out->fh, context->encoded_crlf, context->encoded_crlf_length); begin+= strlen ((const char *) begin)+1; } dbg_print(CCX_DMT_DECODER_608, "- - - - - - - - - - - -\r\n"); write(context->out->fh, context->encoded_crlf, context->encoded_crlf_length); free(el); free(unescaped); return 0; }
int write_cc_buffer_as_srt(struct eia608_screen *data, struct encoder_ctx *context) { int used; unsigned h1,m1,s1,ms1; unsigned h2,m2,s2,ms2; LLONG ms_start, ms_end; int wrote_something = 0; ms_start = data->start_time; int prev_line_start=-1, prev_line_end=-1; // Column in which the previous line started and ended, for autodash int prev_line_center1=-1, prev_line_center2=-1; // Center column of previous line text int empty_buf=1; for (int i=0;i<15;i++) { if (data->row_used[i]) { empty_buf=0; break; } } if (empty_buf) // Prevent writing empty screens. Not needed in .srt return 0; ms_start+=context->subs_delay; if (ms_start<0) // Drop screens that because of subs_delay start too early return 0; ms_end = data->end_time; 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]; context->srt_counter++; sprintf(timeline, "%u%s", context->srt_counter, context->encoded_crlf); used = encode_line(context, context->buffer,(unsigned char *) timeline); write(context->out->fh, context->buffer, used); sprintf (timeline, "%02u:%02u:%02u,%03u --> %02u:%02u:%02u,%03u%s", h1, m1, s1, ms1, h2, m2, s2, ms2, context->encoded_crlf); used = encode_line(context, context->buffer,(unsigned char *) timeline); dbg_print(CCX_DMT_DECODER_608, "\n- - - SRT caption ( %d) - - -\n", context->srt_counter); dbg_print(CCX_DMT_DECODER_608, "%s",timeline); write (context->out->fh, context->buffer, used); for (int i=0;i<15;i++) { if (data->row_used[i]) { if (context->sentence_cap) { capitalize (i,data); correct_case(i,data); } if (context->autodash && context->trim_subs) { int first=0, last=31, center1=-1, center2=-1; unsigned char *line = data->characters[i]; int do_dash=1, colon_pos=-1; find_limit_characters(line,&first,&last); if (first==-1 || last==-1) // Probably a bug somewhere though break; // Is there a speaker named, for example: TOM: What are you doing? for (int j=first;j<=last;j++) { if (line[j]==':') { colon_pos=j; break; } if (!isupper (line[j])) break; } if (prev_line_start==-1) do_dash=0; if (first==prev_line_start) // Case of left alignment do_dash=0; if (last==prev_line_end) // Right align do_dash=0; if (first>prev_line_start && last<prev_line_end) // Fully contained do_dash=0; if ((first>prev_line_start && first<prev_line_end) || // Overlap (last>prev_line_start && last<prev_line_end)) do_dash=0; center1=(first+last)/2; if (colon_pos!=-1) { while (colon_pos<CCX_DECODER_608_SCREEN_WIDTH && (line[colon_pos]==':' || line[colon_pos]==' ' || line[colon_pos]==0x89)) colon_pos++; // Find actual text center2=(colon_pos+last)/2; } else center2=center1; if (center1>=prev_line_center1-1 && center1<=prev_line_center1+1 && center1!=-1) // Center align do_dash=0; if (center2>=prev_line_center2-2 && center1<=prev_line_center2+2 && center1!=-1) // Center align do_dash=0; if (do_dash) write(context->out->fh, "- ", 2); prev_line_start=first; prev_line_end=last; prev_line_center1=center1; prev_line_center2=center2; } int length = get_decoder_line_encoded (context, context->subline, i, data); if (context->encoding!=CCX_ENC_UNICODE) { dbg_print(CCX_DMT_DECODER_608, "\r"); dbg_print(CCX_DMT_DECODER_608, "%s\n",context->subline); } write(context->out->fh, context->subline, length); write(context->out->fh, context->encoded_crlf, context->encoded_crlf_length); wrote_something=1; // fprintf (wb->fh,context->encoded_crlf); } } dbg_print(CCX_DMT_DECODER_608, "- - - - - - - - - - - -\r\n"); // fprintf (wb->fh, context->encoded_crlf); write (context->out->fh, context->encoded_crlf, context->encoded_crlf_length); return wrote_something; }
int write_cc_buffer_as_srt (struct eia608_screen *data, struct s_write *wb) { unsigned h1,m1,s1,ms1; unsigned h2,m2,s2,ms2; int wrote_something = 0; LLONG ms_start= wb->data608->current_visible_start_ms; int empty_buf=1; for (int i=0;i<15;i++) { if (data->row_used[i]) { empty_buf=0; break; } } if (empty_buf) // Prevent writing empty screens. Not needed in .srt return 0; ms_start+=subs_delay; if (ms_start<0) // Drop screens that because of subs_delay start too early return 0; LLONG ms_end = get_visible_end()+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); write (wb->fh, 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); dbg_print(DMT_608, "\n- - - SRT caption - - -\n"); dbg_print(DMT_608, "%s",timeline); write (wb->fh, enc_buffer,enc_buffer_used); for (int i=0;i<15;i++) { if (data->row_used[i]) { if (sentence_cap) { capitalize (i,data); correct_case(i,data); } int length = get_decoder_line_encoded (subline, i, data); if (encoding!=ENC_UNICODE) { dbg_print(DMT_608, "\r"); dbg_print(DMT_608, "%s\n",subline); } write (wb->fh, subline, length); write (wb->fh, encoded_crlf, encoded_crlf_length); wrote_something=1; // fprintf (wb->fh,encoded_crlf); } } dbg_print(DMT_608, "- - - - - - - - - - - -\r\n"); // fprintf (wb->fh, encoded_crlf); write (wb->fh, encoded_crlf, encoded_crlf_length); return wrote_something; }
void write_stringz_as_smptett (char *string, struct s_write *wb, LLONG ms_start, LLONG ms_end) { unsigned h1,m1,s1,ms1; unsigned h2,m2,s2,ms2; mstotime (ms_start,&h1,&m1,&s1,&ms1); mstotime (ms_end-1,&h2,&m2,&s2,&ms2); sprintf ((char *) str,"<p begin=\"%02u:%02u:%02u,%03u\" end=\"%02u:%02u:%02u.%03u\">\r\n",h1,m1,s1,ms1, h2,m2,s2,ms2); if (encoding!=ENC_UNICODE) { dbg_print(DMT_608, "\r%s\n", str); } enc_buffer_used=encode_line (enc_buffer,(unsigned char *) str); write (wb->fh, enc_buffer,enc_buffer_used); int len=strlen (string); unsigned char *unescaped= (unsigned char *) malloc (len+1); unsigned char *el = (unsigned char *) malloc (len*3+1); // Be generous if (el==NULL || unescaped==NULL) fatal (EXIT_NOT_ENOUGH_MEMORY, "In write_stringz_as_sami() - not enough memory.\n"); int pos_r=0; int pos_w=0; // Scan for \n in the string and replace it with a 0 while (pos_r<len) { if (string[pos_r]=='\\' && string[pos_r+1]=='n') { unescaped[pos_w]=0; pos_r+=2; } else { unescaped[pos_w]=string[pos_r]; pos_r++; } pos_w++; } unescaped[pos_w]=0; // Now read the unescaped string (now several string'z and write them) unsigned char *begin=unescaped; while (begin<unescaped+len) { unsigned int u = encode_line (el, begin); if (encoding!=ENC_UNICODE) { dbg_print(DMT_608, "\r"); dbg_print(DMT_608, "%s\n",subline); } write (wb->fh, el, u); //write (wb->fh, encoded_br, encoded_br_length); write (wb->fh, encoded_crlf, encoded_crlf_length); begin+= strlen ((const char *) begin)+1; } sprintf ((char *) str,"</p>\n"); if (encoding!=ENC_UNICODE) { dbg_print(DMT_608, "\r%s\n", str); } enc_buffer_used=encode_line (enc_buffer,(unsigned char *) str); write (wb->fh, enc_buffer,enc_buffer_used); sprintf ((char *) str,"<p begin=\"%02u:%02u:%02u,%03u\">\n\n",h2,m2,s2,ms2); if (encoding!=ENC_UNICODE) { dbg_print(DMT_608, "\r%s\n", str); } enc_buffer_used=encode_line (enc_buffer,(unsigned char *) str); write (wb->fh, enc_buffer,enc_buffer_used); sprintf ((char *) str,"</p>\n"); }
int write_cc_bitmap_as_transcript(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; #ifdef ENABLE_OCR unsigned h1,m1,s1,ms1; unsigned h2,m2,s2,ms2; #endif LLONG start_time, end_time; //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)) { start_time = context->prev_start + context->subs_delay; end_time = sub->start_time - 1; } else if ( !(sub->flags & SUB_EOD_MARKER)) { start_time = sub->start_time + context->subs_delay; end_time = 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; token = strtok(str,"\r\n"); while (token) { if (ccx_options.transcript_settings.showStartTime) { char buf1[80]; if (ccx_options.transcript_settings.relativeTimestamp) { millis_to_date(start_time + context->subs_delay, buf1); fdprintf(context->out->fh, "%s|", buf1); } else { mstotime(start_time + context->subs_delay, &h1, &m1, &s1, &ms1); time_t start_time_int = (start_time + context->subs_delay) / 1000; int start_time_dec = (start_time + context->subs_delay) % 1000; struct tm *start_time_struct = gmtime(&start_time_int); strftime(buf1, sizeof(buf1), "%Y%m%d%H%M%S", start_time_struct); fdprintf(context->out->fh, "%s%c%03d|", buf1,ccx_options.millis_separator,start_time_dec); } } if (ccx_options.transcript_settings.showEndTime) { char buf2[80]; if (ccx_options.transcript_settings.relativeTimestamp) { millis_to_date(end_time, buf2); fdprintf(context->out->fh, "%s|", buf2); } else { mstotime(get_fts() + context->subs_delay, &h2, &m2, &s2, &ms2); time_t end_time_int = end_time / 1000; int end_time_dec = end_time % 1000; struct tm *end_time_struct = gmtime(&end_time_int); strftime(buf2, sizeof(buf2), "%Y%m%d%H%M%S", end_time_struct); fdprintf(context->out->fh, "%s%c%03d|", buf2,ccx_options.millis_separator,end_time_dec); } } if (ccx_options.transcript_settings.showCC) { fdprintf(context->out->fh,"%s|",language[sub->lang_index]); } if (ccx_options.transcript_settings.showMode) { fdprintf(context->out->fh,"DVB|"); } fdprintf(context->out->fh,"%s\n",token); token = strtok(NULL,"\r\n"); } } } #endif end: sub->nb_data = 0; freep(&sub->data); freep(&palette); freep(&alpha); return ret; }