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