1 #include "ccx_decoders_common.h"
2 #include "ccx_encoders_common.h"
3 #include "spupng_encoder.h"
4 #include "ccx_encoders_spupng.h"
5 #include "utility.h"
6 #include "ocr.h"
7 #include "ccx_decoders_608.h"
8 #include "ccx_decoders_708.h"
9 #include "ccx_decoders_708_output.h"
10 #include "ccx_encoders_xds.h"
11 #include "ccx_encoders_helpers.h"
12
13 #ifdef ENABLE_SHARING
14 #include "ccx_share.h"
15 #endif //ENABLE_SHARING
16
write_cc_bitmap_as_transcript(struct cc_subtitle * sub,struct encoder_ctx * context)17 int write_cc_bitmap_as_transcript(struct cc_subtitle *sub, struct encoder_ctx *context)
18 {
19 int ret = 0;
20 #ifdef ENABLE_OCR
21 struct cc_bitmap* rect;
22
23 unsigned h1, m1, s1, ms1;
24
25 LLONG start_time, end_time;
26
27 start_time = sub->start_time;
28 end_time = sub->end_time;
29
30 if (sub->nb_data == 0)
31 return ret;
32 rect = sub->data;
33
34 if (sub->flags & SUB_EOD_MARKER)
35 context->prev_start = sub->start_time;
36
37
38 if (rect[0].ocr_text && *(rect[0].ocr_text))
39 {
40 if (context->prev_start != -1 || !(sub->flags & SUB_EOD_MARKER))
41 {
42 char *token = NULL;
43 token = paraof_ocrtext(sub, context->encoded_crlf, context->encoded_crlf_length);
44 if (context->transcript_settings->showStartTime)
45 {
46 char buf1[80];
47 if (context->transcript_settings->relativeTimestamp)
48 {
49 millis_to_date(start_time + context->subs_delay, buf1, context->date_format, context->millis_separator);
50 fdprintf(context->out->fh, "%s|", buf1);
51 }
52 else
53 {
54 millis_to_time(start_time + context->subs_delay, &h1, &m1, &s1, &ms1);
55 time_t start_time_int = (start_time + context->subs_delay) / 1000;
56 int start_time_dec = (start_time + context->subs_delay) % 1000;
57 struct tm *start_time_struct = gmtime(&start_time_int);
58 strftime(buf1, sizeof(buf1), "%Y%m%d%H%M%S", start_time_struct);
59 fdprintf(context->out->fh, "%s%c%03d|", buf1, context->millis_separator, start_time_dec);
60 }
61 }
62
63 if (context->transcript_settings->showEndTime)
64 {
65 char buf2[80];
66 if (context->transcript_settings->relativeTimestamp)
67 {
68 millis_to_date(end_time, buf2, context->date_format, context->millis_separator);
69 fdprintf(context->out->fh, "%s|", buf2);
70 }
71 else
72 {
73 time_t end_time_int = end_time / 1000;
74 int end_time_dec = end_time % 1000;
75 struct tm *end_time_struct = gmtime(&end_time_int);
76 strftime(buf2, sizeof(buf2), "%Y%m%d%H%M%S", end_time_struct);
77 fdprintf(context->out->fh, "%s%c%03d|", buf2, context->millis_separator, end_time_dec);
78 }
79 }
80 if (context->transcript_settings->showCC)
81 {
82 fdprintf(context->out->fh, "%s|", language[sub->lang_index]);
83 }
84 if (context->transcript_settings->showMode)
85 {
86 fdprintf(context->out->fh, "DVB|");
87 }
88
89 while (token)
90 {
91 char *newline_pos = strstr(token, context->encoded_crlf);
92 if (!newline_pos)
93 {
94 fdprintf(context->out->fh, "%s", token);
95 break;
96 }
97 else
98 {
99 while (token != newline_pos)
100 {
101 fdprintf(context->out->fh, "%c", *token);
102 token++;
103 }
104 token += context->encoded_crlf_length;
105 fdprintf(context->out->fh, "%c", ' ');
106 }
107 }
108
109 write(context->out->fh, context->encoded_crlf, context->encoded_crlf_length);
110
111 }
112 }
113 #endif
114
115 sub->nb_data = 0;
116 freep(&sub->data);
117 return ret;
118
119 }
120
121
write_cc_subtitle_as_transcript(struct cc_subtitle * sub,struct encoder_ctx * context)122 int write_cc_subtitle_as_transcript(struct cc_subtitle *sub, struct encoder_ctx *context)
123 {
124 int length;
125 int ret = 0;
126 LLONG start_time = -1;
127 LLONG end_time = -1;
128 char *str;
129 char *save_str;
130 struct cc_subtitle *osub = sub;
131 struct cc_subtitle *lsub = sub;
132
133 while (sub)
134 {
135 if (sub->type == CC_TEXT)
136 {
137 start_time = sub->start_time;
138 end_time = sub->end_time;
139 }
140 if (context->sentence_cap)
141 {
142 //TODO capitalize (context, line_number,data);
143 //TODO correct_case_with_dictionary(line_number, data);
144 }
145
146 if (start_time == -1)
147 {
148 // CFS: Means that the line has characters but we don't have a timestamp for the first one. Since the timestamp
149 // is set for example by the write_char function, it possible that we don't have one in empty lines (unclear)
150 // For now, let's not consider this a bug as before and just return.
151 // fatal (EXIT_BUG_BUG, "Bug in timedtranscript (ts_start_of_current_line==-1). Please report.");
152 return 0;
153 }
154
155 str = sub->data;
156
157 str = strtok_r(str, "\r\n", &save_str);
158 do
159 {
160 length = get_str_basic(context->subline, (unsigned char*)str, context->trim_subs, sub->enc_type, context->encoding, strlen(str));
161 if (length <= 0)
162 {
163 continue;
164 }
165
166 if (context->transcript_settings->showStartTime)
167 {
168 char buf[80];
169 if (context->transcript_settings->relativeTimestamp)
170 {
171 millis_to_date(start_time + context->subs_delay, buf, context->date_format, context->millis_separator);
172 fdprintf(context->out->fh, "%s|", buf);
173 }
174 else
175 {
176 time_t start_time_int = (start_time + context->subs_delay) / 1000;
177 int start_time_dec = (start_time + context->subs_delay) % 1000;
178 struct tm *start_time_struct = gmtime(&start_time_int);
179 strftime(buf, sizeof(buf), "%Y%m%d%H%M%S", start_time_struct);
180 fdprintf(context->out->fh, "%s%c%03d|", buf, context->millis_separator, start_time_dec);
181 }
182 }
183
184 if (context->transcript_settings->showEndTime)
185 {
186 char buf[80];
187 if (context->transcript_settings->relativeTimestamp)
188 {
189 millis_to_date(end_time + context->subs_delay, buf, context->date_format, context->millis_separator);
190 fdprintf(context->out->fh, "%s|", buf);
191 }
192 else
193 {
194 time_t end_time_int = (end_time + context->subs_delay) / 1000;
195 int end_time_dec = (end_time + context->subs_delay) % 1000;
196 struct tm *end_time_struct = gmtime(&end_time_int);
197 strftime(buf, sizeof(buf), "%Y%m%d%H%M%S", end_time_struct);
198 fdprintf(context->out->fh, "%s%c%03d|", buf, context->millis_separator, end_time_dec);
199 }
200 }
201
202 if (context->transcript_settings->showCC)
203 {
204 if (context->in_fileformat == 1)
205 //TODO, data->my_field == 1 ? data->channel : data->channel + 2); // Data from field 2 is CC3 or 4
206 fdprintf(context->out->fh, "CC?|");
207 else if (!context->ucla || !strcmp(sub->mode, "TLT"))
208 fdprintf(context->out->fh, sub->info);
209 }
210 if (context->transcript_settings->showMode)
211 {
212 if (context->ucla && strcmp(sub->mode, "TLT") == 0)
213 fdprintf(context->out->fh, "|");
214 else
215 fdprintf(context->out->fh, "%s|", sub->mode);
216 }
217 ret = write(context->out->fh, context->subline, length);
218 if (ret < length)
219 {
220 mprint("Warning:Loss of data\n");
221 }
222
223 ret = write(context->out->fh, context->encoded_crlf, context->encoded_crlf_length);
224 if (ret < context->encoded_crlf_length)
225 {
226 mprint("Warning:Loss of data\n");
227 }
228
229 } while ((str = strtok_r(NULL, "\r\n", &save_str)));
230
231 freep(&sub->data);
232 lsub = sub;
233 sub = sub->next;
234 }
235
236 while (lsub != osub)
237 {
238 sub = lsub->prev;
239 freep(&lsub);
240 lsub = sub;
241 }
242
243 return ret;
244 }
245
246
247 //TODO Convert CC line to TEXT format and remove this function
write_cc_line_as_transcript2(struct eia608_screen * data,struct encoder_ctx * context,int line_number)248 void write_cc_line_as_transcript2(struct eia608_screen *data, struct encoder_ctx *context, int line_number)
249 {
250 int ret = 0;
251 LLONG start_time = data->start_time;
252 LLONG end_time = data->end_time;
253 if (context->sentence_cap)
254 {
255 if (clever_capitalize(context, line_number, data))
256 correct_case_with_dictionary(line_number, data);
257 }
258 int length = get_str_basic(context->subline, data->characters[line_number],
259 context->trim_subs, CCX_ENC_ASCII, context->encoding, CCX_DECODER_608_SCREEN_WIDTH);
260
261 if (context->encoding != CCX_ENC_UNICODE)
262 {
263 dbg_print(CCX_DMT_DECODER_608, "\r");
264 dbg_print(CCX_DMT_DECODER_608, "%s\n", context->subline);
265 }
266 if (length>0)
267 {
268 if (data->start_time == -1)
269 {
270 // CFS: Means that the line has characters but we don't have a timestamp for the first one. Since the timestamp
271 // is set for example by the write_char function, it possible that we don't have one in empty lines (unclear)
272 // For now, let's not consider this a bug as before and just return.
273 // fatal (EXIT_BUG_BUG, "Bug in timedtranscript (ts_start_of_current_line==-1). Please report.");
274 return;
275 }
276
277 if (context->transcript_settings->showStartTime){
278 char buf1[80];
279 if (context->transcript_settings->relativeTimestamp){
280 millis_to_date(start_time + context->subs_delay, buf1, context->date_format, context->millis_separator);
281 fdprintf(context->out->fh, "%s|", buf1);
282 }
283 else {
284 time_t start_time_int = (start_time + context->subs_delay) / 1000;
285 int start_time_dec = (start_time + context->subs_delay) % 1000;
286 struct tm *start_time_struct = gmtime(&start_time_int);
287 strftime(buf1, sizeof(buf1), "%Y%m%d%H%M%S", start_time_struct);
288 fdprintf(context->out->fh, "%s%c%03d|", buf1, context->millis_separator, start_time_dec);
289 }
290 }
291
292 if (context->transcript_settings->showEndTime){
293 char buf2[80];
294 if (context->transcript_settings->relativeTimestamp){
295 millis_to_date(end_time, buf2, context->date_format, context->millis_separator);
296 fdprintf(context->out->fh, "%s|", buf2);
297 }
298 else {
299 time_t end_time_int = end_time / 1000;
300 int end_time_dec = end_time % 1000;
301 struct tm *end_time_struct = gmtime(&end_time_int);
302 strftime(buf2, sizeof(buf2), "%Y%m%d%H%M%S", end_time_struct);
303 fdprintf(context->out->fh, "%s%c%03d|", buf2, context->millis_separator, end_time_dec);
304 }
305 }
306
307 if (context->transcript_settings->showCC){
308 fdprintf(context->out->fh, "CC%d|", data->my_field == 1 ? data->channel : data->channel + 2); // Data from field 2 is CC3 or 4
309 }
310 if (context->transcript_settings->showMode){
311 const char *mode = "???";
312 switch (data->mode)
313 {
314 case MODE_POPON:
315 mode = "POP";
316 break;
317 case MODE_FAKE_ROLLUP_1:
318 mode = "RU1";
319 break;
320 case MODE_ROLLUP_2:
321 mode = "RU2";
322 break;
323 case MODE_ROLLUP_3:
324 mode = "RU3";
325 break;
326 case MODE_ROLLUP_4:
327 mode = "RU4";
328 break;
329 case MODE_TEXT:
330 mode = "TXT";
331 break;
332 case MODE_PAINTON:
333 mode = "PAI";
334 break;
335 }
336 fdprintf(context->out->fh, "%s|", mode);
337 }
338
339 ret = write(context->out->fh, context->subline, length);
340 if (ret < length)
341 {
342 mprint("Warning:Loss of data\n");
343 }
344
345 ret = write(context->out->fh, context->encoded_crlf, context->encoded_crlf_length);
346 if (ret < context->encoded_crlf_length)
347 {
348 mprint("Warning:Loss of data\n");
349 }
350 }
351 // fprintf (wb->fh,encoded_crlf);
352 }
353
write_cc_buffer_as_transcript2(struct eia608_screen * data,struct encoder_ctx * context)354 int write_cc_buffer_as_transcript2(struct eia608_screen *data, struct encoder_ctx *context)
355 {
356 int wrote_something = 0;
357 dbg_print(CCX_DMT_DECODER_608, "\n- - - TRANSCRIPT caption - - -\n");
358
359 for (int i = 0; i<15; i++)
360 {
361 if (data->row_used[i])
362 {
363 write_cc_line_as_transcript2(data, context, i);
364 }
365 wrote_something = 1;
366 }
367 dbg_print(CCX_DMT_DECODER_608, "- - - - - - - - - - - -\r\n");
368 return wrote_something;
369 }
370