1 #include "lib_ccx.h"
2 #include "ccx_common_option.h"
3 #include "activity.h"
4 #include "utility.h"
5 #include "dvb_subtitle_decoder.h"
6 #include "ccx_decoders_708.h"
7 #include "ccx_decoders_isdb.h"
8 
9 struct ccx_common_logging_t ccx_common_logging;
init_decoder_setting(struct ccx_s_options * opt)10 static struct ccx_decoders_common_settings_t *init_decoder_setting(
11 		struct ccx_s_options *opt)
12 {
13 	struct ccx_decoders_common_settings_t *setting;
14 
15 	setting = malloc(sizeof(struct ccx_decoders_common_settings_t));
16 	if(!setting)
17 		return NULL;
18 
19 	setting->subs_delay = opt->subs_delay;
20 	setting->output_format = opt->write_format;
21 	setting->fix_padding = opt->fix_padding;
22 	setting->extract = opt->extract;
23 	setting->fullbin = opt->fullbin;
24 	setting->no_rollup = opt->no_rollup;
25 	setting->noscte20 = opt->noscte20;
26 	memcpy(&setting->extraction_start,&opt->extraction_start,sizeof(struct ccx_boundary_time));
27 	memcpy(&setting->extraction_end,&opt->extraction_end,sizeof(struct ccx_boundary_time));
28 	setting->cc_to_stdout = opt->cc_to_stdout;
29 	setting->settings_608 = &opt->settings_608;
30 	setting->settings_dtvcc = &opt->settings_dtvcc;
31 	setting->cc_channel = opt->cc_channel;
32 	setting->send_to_srv = opt->send_to_srv;
33 	setting->hauppauge_mode = opt->hauppauge_mode;
34 	setting->xds_write_to_file = opt->transcript_settings.xds;
35 
36 	return setting;
37 }
dinit_decoder_setting(struct ccx_decoders_common_settings_t ** setting)38 static void dinit_decoder_setting (struct ccx_decoders_common_settings_t **setting)
39 {
40 	freep(setting);
41 }
42 
43 
init_ctx_outbase(struct ccx_s_options * opt,struct lib_ccx_ctx * ctx)44 static int init_ctx_outbase(struct ccx_s_options *opt, struct lib_ccx_ctx *ctx)
45 {
46 	char *file;
47 
48 	if (opt->output_filename)
49 	{
50 		ctx->basefilename = get_basename(opt->output_filename);
51 	}
52 	else
53 	{
54 		switch (opt->input_source)
55 		{
56 			case CCX_DS_FILE:
57 				if(!ctx->inputfile || !ctx->inputfile[0])
58 				{
59 					errno = EINVAL;
60 					return -1;
61 				}
62 				file = ctx->inputfile[0];
63 				break;
64 			case CCX_DS_STDIN:
65 				file = "stdin";
66 				break;
67 			case CCX_DS_NETWORK:
68 			case CCX_DS_TCP:
69 				file = "network";
70 				break;
71 			default:
72 				errno = EINVAL;
73 				return -1;
74 		}
75 
76 		ctx->basefilename = get_basename(file);
77 	}
78 	return 0;
79 }
80 
get_encoder_by_pn(struct lib_ccx_ctx * ctx,int pn)81 struct encoder_ctx *get_encoder_by_pn(struct lib_ccx_ctx *ctx, int pn)
82 {
83 	struct  encoder_ctx *enc_ctx;
84 	list_for_each_entry(enc_ctx, &ctx->enc_ctx_head, list, struct encoder_ctx)
85 	{
86 		if (enc_ctx && enc_ctx->program_number == pn)
87 			return enc_ctx;
88 	}
89 	return NULL;
90 }
91 
init_libraries(struct ccx_s_options * opt)92 struct lib_ccx_ctx* init_libraries(struct ccx_s_options *opt)
93 {
94 	int ret = 0;
95 
96 	struct lib_ccx_ctx *ctx = malloc(sizeof(struct lib_ccx_ctx));
97 	if(!ctx)
98 		ccx_common_logging.fatal_ftn(EXIT_NOT_ENOUGH_MEMORY, "init_libraries: Not enough memory allocating lib_ccx_ctx context.");
99 	memset(ctx, 0, sizeof(struct lib_ccx_ctx));
100 
101 	if(opt->xmltv)
102 	{
103 		ctx->epg_inited = 1;
104 		ctx->epg_buffers = (struct PSI_buffer *)malloc(sizeof(struct PSI_buffer)*(0xfff+1));
105 		ctx->eit_programs = (struct EIT_program *)malloc(sizeof(struct EIT_program)*(TS_PMT_MAP_SIZE+1));
106 		ctx->eit_current_events = (int32_t *)malloc(sizeof(int32_t)*(TS_PMT_MAP_SIZE+1));
107 		ctx->ATSC_source_pg_map = (int16_t *)malloc(sizeof(int16_t)*(0xffff));
108 		memset(ctx->epg_buffers, 0, sizeof(struct PSI_buffer)*(0xfff+1));
109 		memset(ctx->eit_programs, 0, sizeof(struct EIT_program)*(TS_PMT_MAP_SIZE+1));
110 		memset(ctx->eit_current_events, 0, sizeof(int32_t)*(TS_PMT_MAP_SIZE+1));
111 		memset(ctx->ATSC_source_pg_map, 0, sizeof(int16_t)*(0xffff));
112 		if(!ctx->epg_buffers || !ctx->eit_programs || !ctx->eit_current_events || !ctx->ATSC_source_pg_map)
113 			ccx_common_logging.fatal_ftn(EXIT_NOT_ENOUGH_MEMORY, "lib_ccx_ctx");
114 	}
115 	else
116 	{
117 		ctx->epg_inited = 0;
118 		ctx->epg_buffers = NULL;
119 		ctx->eit_programs = NULL;
120 		ctx->eit_current_events = NULL;
121 		ctx->ATSC_source_pg_map = NULL;
122 	}
123 
124 	struct ccx_decoder_608_report *report_608 = malloc(sizeof(struct ccx_decoder_608_report));
125 	if (!report_608)
126 		ccx_common_logging.fatal_ftn(EXIT_NOT_ENOUGH_MEMORY, "init_libraries: Not enough memory allocating report_608");
127 	memset(report_608, 0, sizeof(struct ccx_decoder_608_report));
128 
129 	ccx_decoder_dtvcc_report *report_dtvcc = (ccx_decoder_dtvcc_report *)
130 			malloc(sizeof(ccx_decoder_dtvcc_report));
131 	if (!report_dtvcc)
132 		ccx_common_logging.fatal_ftn(EXIT_NOT_ENOUGH_MEMORY, "init_libraries: Not enough memory allocating report_dtvcc");
133 	memset(report_dtvcc, 0, sizeof(ccx_decoder_dtvcc_report));
134 
135 	// Initialize some constants
136 	ctx->screens_to_process = -1;
137 	ctx->current_file = -1;
138 
139 	// Set logging functions for libraries
140 	ccx_common_logging.debug_ftn = &dbg_print;
141 	ccx_common_logging.debug_mask = opt->debug_mask;
142 	ccx_common_logging.fatal_ftn = &fatal;
143 	ccx_common_logging.log_ftn = &mprint;
144 	ccx_common_logging.gui_ftn = &activity_library_process;
145 
146 	// Init shared decoder settings
147 	ctx->dec_global_setting = init_decoder_setting(opt);
148 	if (!ctx->dec_global_setting){
149 		free(report_dtvcc);
150 		return NULL;
151     }
152 
153 	// Need to set the 608 data for the report to the correct variable.
154 	ctx->freport.data_from_608 = report_608;
155 	ctx->dec_global_setting->settings_608->report = report_608;
156 	ctx->freport.data_from_708 = report_dtvcc;
157 	ctx->dec_global_setting->settings_dtvcc->report = report_dtvcc;
158 	ctx->mp4_cfg.mp4vidtrack = opt->mp4vidtrack;
159 	//Initialize input files
160 	ctx->inputfile = opt->inputfile;
161 	ctx->num_input_files = opt->num_input_files;
162 
163 	ret = init_ctx_outbase(opt, ctx);
164 	if (ret < 0) {
165 		goto end;
166 	}
167 	ctx->extension = get_file_extension(opt->write_format);
168 
169 	ctx->subs_delay = opt->subs_delay;
170 
171 	ctx->pesheaderbuf = (unsigned char *) malloc (188); // Never larger anyway
172 
173 	ctx->cc_to_stdout = opt->cc_to_stdout;
174 	ctx->pes_header_to_stdout = opt->pes_header_to_stdout;
175 	ctx->dvb_debug_traces_to_stdout = opt->dvb_debug_traces_to_stdout;
176 	ctx->ignore_pts_jumps = opt->ignore_pts_jumps;
177 
178 	ctx->hauppauge_mode = opt->hauppauge_mode;
179 	ctx->live_stream = opt->live_stream;
180 	ctx->binary_concat = opt->binary_concat;
181 	build_parity_table();
182 
183 	ctx->demux_ctx = init_demuxer(ctx, &opt->demux_cfg);
184 	INIT_LIST_HEAD(&ctx->dec_ctx_head);
185 	INIT_LIST_HEAD(&ctx->enc_ctx_head);
186 
187 	// Init timing
188 	ccx_common_timing_init(&ctx->demux_ctx->past,opt->nosync);
189 	ctx->multiprogram = opt->multiprogram;
190 	ctx->write_format = opt->write_format;
191 	ctx->out_interval = opt->out_interval;
192 	ctx->segment_counter = 0;
193 	ctx->system_start_time = -1;
194 
195 end:
196 	if (ret != EXIT_OK)
197 	{
198 		free(ctx);
199 		return NULL;
200 	}
201 	return ctx;
202 }
203 
dinit_libraries(struct lib_ccx_ctx ** ctx)204 void dinit_libraries( struct lib_ccx_ctx **ctx)
205 {
206 	struct lib_ccx_ctx *lctx = *ctx;
207 	struct encoder_ctx *enc_ctx;
208 	struct lib_cc_decode *dec_ctx;
209 	struct lib_cc_decode *dec_ctx1;
210 	int i;
211 	list_for_each_entry_safe(dec_ctx, dec_ctx1, &lctx->dec_ctx_head, list, struct lib_cc_decode)
212 	{
213 		LLONG cfts;
214 		if (dec_ctx->codec == CCX_CODEC_DVB)
215 			dvbsub_close_decoder(&dec_ctx->private_data);
216 		//Test memory for teletext
217 		else if (dec_ctx->codec == CCX_CODEC_TELETEXT)
218 			telxcc_close(&dec_ctx->private_data, NULL);
219 		else if (dec_ctx->codec == CCX_CODEC_ISDB_CC)
220 			delete_isdb_decoder(&dec_ctx->private_data);
221 
222 		flush_cc_decode(dec_ctx, &dec_ctx->dec_sub);
223 		cfts = get_fts(dec_ctx->timing, dec_ctx->current_field);
224 		enc_ctx = get_encoder_by_pn(lctx, dec_ctx->program_number);
225 		if (enc_ctx && dec_ctx->dec_sub.got_output == CCX_TRUE)
226 		{
227 			encode_sub(enc_ctx, &dec_ctx->dec_sub);
228 			dec_ctx->dec_sub.got_output = CCX_FALSE;
229 		}
230 		list_del(&dec_ctx->list);
231 		dinit_cc_decode(&dec_ctx);
232 		if (enc_ctx)
233 		{
234 			list_del(&enc_ctx->list);
235 			dinit_encoder(&enc_ctx, cfts);
236 		}
237 	}
238 
239 	// free EPG memory
240 	EPG_free(lctx);
241 	freep(&lctx->freport.data_from_608);
242 	freep(&lctx->freport.data_from_708);
243 	ccx_demuxer_delete(&lctx->demux_ctx);
244 	dinit_decoder_setting(&lctx->dec_global_setting);
245 	freep(&ccx_options.enc_cfg.output_filename);
246 	freep(&lctx->basefilename);
247 	freep(&lctx->pesheaderbuf);
248 	for(i = 0;i < lctx->num_input_files;i++)
249 		freep(&lctx->inputfile[i]);
250 	freep(&lctx->inputfile);
251 	freep(ctx);
252 }
253 
is_decoder_processed_enough(struct lib_ccx_ctx * ctx)254 int is_decoder_processed_enough(struct lib_ccx_ctx *ctx)
255 {
256 	struct lib_cc_decode *dec_ctx;
257 	list_for_each_entry(dec_ctx, &ctx->dec_ctx_head, list, struct lib_cc_decode)
258 	{
259 		if (dec_ctx->processed_enough == CCX_TRUE && ctx->multiprogram == CCX_FALSE)
260 			return CCX_TRUE;
261 	}
262 
263 	return CCX_FALSE;
264 }
update_decoder_list(struct lib_ccx_ctx * ctx)265 struct lib_cc_decode *update_decoder_list(struct lib_ccx_ctx *ctx)
266 {
267 	struct lib_cc_decode *dec_ctx;
268 	list_for_each_entry(dec_ctx, &ctx->dec_ctx_head, list, struct lib_cc_decode)
269 	{
270 		return dec_ctx;
271 	}
272 
273 	if (list_empty(&ctx->dec_ctx_head))
274 	{
275 		ctx->dec_global_setting->codec = CCX_CODEC_ATSC_CC;
276 		ctx->dec_global_setting->program_number = 0;
277 		dec_ctx = init_cc_decode(ctx->dec_global_setting);
278 		if (!dec_ctx)
279 			fatal(EXIT_NOT_ENOUGH_MEMORY, "update_decoder_list: init_cc_decode failed. Not enough memory.\n");
280 		list_add_tail( &(dec_ctx->list), &(ctx->dec_ctx_head) );
281 
282 		//DVB related
283 		dec_ctx->prev = NULL;
284 		dec_ctx->dec_sub.prev = NULL;
285 		if (dec_ctx->codec == CCX_CODEC_DVB)
286 		{
287 			dec_ctx->prev = malloc(sizeof(struct lib_cc_decode));
288 			dec_ctx->dec_sub.prev = malloc(sizeof(struct cc_subtitle));
289 		}
290 	}
291 	return dec_ctx;
292 }
293 
update_decoder_list_cinfo(struct lib_ccx_ctx * ctx,struct cap_info * cinfo)294 struct lib_cc_decode *update_decoder_list_cinfo(struct lib_ccx_ctx *ctx, struct cap_info* cinfo)
295 {
296 	struct lib_cc_decode *dec_ctx = NULL;
297 
298 	list_for_each_entry(dec_ctx, &ctx->dec_ctx_head, list, struct lib_cc_decode)
299 	{
300 		if (!cinfo || ctx->multiprogram == CCX_FALSE)
301 			return dec_ctx;
302 
303 		if (dec_ctx->program_number == cinfo->program_number)
304 			return dec_ctx;
305 	}
306 	if(cinfo)
307 	{
308 		ctx->dec_global_setting->program_number = cinfo->program_number;
309 		ctx->dec_global_setting->codec = cinfo->codec;
310 		ctx->dec_global_setting->private_data = cinfo->codec_private_data;
311 	}
312 	else
313 	{
314 		ctx->dec_global_setting->program_number = 0;
315 		ctx->dec_global_setting->codec = CCX_CODEC_ATSC_CC;
316 	}
317 	if(ctx->multiprogram == CCX_FALSE)
318 	{
319 		if (list_empty(&ctx->dec_ctx_head))
320 		{
321 			dec_ctx = init_cc_decode(ctx->dec_global_setting);
322 			if (!dec_ctx)
323 				fatal(EXIT_NOT_ENOUGH_MEMORY, "update_decoder_list_cinfo: Not enough memory allocating dec_ctx (multiprogram == false)\n");
324 			list_add_tail( &(dec_ctx->list), &(ctx->dec_ctx_head) );
325 		}
326 	}
327 	else
328 	{
329 		dec_ctx = init_cc_decode(ctx->dec_global_setting);
330 		if (!dec_ctx)
331 			fatal(EXIT_NOT_ENOUGH_MEMORY, "update_decoder_list_cinfo: Not enough memory allocating dec_ctx ((multiprogram == true)\n");
332 		list_add_tail( &(dec_ctx->list), &(ctx->dec_ctx_head) );
333 	}
334 
335 	//DVB related
336 	dec_ctx->prev = NULL;
337 	dec_ctx->dec_sub.prev = NULL;
338 
339 	return dec_ctx;
340 }
341 
update_encoder_list_cinfo(struct lib_ccx_ctx * ctx,struct cap_info * cinfo)342 struct encoder_ctx *update_encoder_list_cinfo(struct lib_ccx_ctx *ctx, struct cap_info* cinfo)
343 {
344 	struct encoder_ctx *enc_ctx;
345 	unsigned int pn = 0;
346 	unsigned char in_format = 1;
347 	char *extension;
348 
349 
350 	if (ctx->write_format == CCX_OF_NULL)
351 		return NULL;
352 
353 	if(cinfo)
354 	{
355 		pn = cinfo->program_number;
356 		if (cinfo->codec == CCX_CODEC_ISDB_CC)
357 			in_format = 3;
358 		else if (cinfo->codec == CCX_CODEC_TELETEXT)
359 			in_format = 2;
360 		else
361 			in_format = 1;
362 	}
363 	list_for_each_entry(enc_ctx, &ctx->enc_ctx_head, list, struct encoder_ctx)
364 	{
365 		if ( ctx->multiprogram == CCX_FALSE)
366 			return enc_ctx;
367 
368 		if (enc_ctx->program_number == pn)
369 			return enc_ctx;
370 	}
371 
372 	extension = get_file_extension(ccx_options.enc_cfg.write_format);
373 	if (!extension && ccx_options.enc_cfg.write_format != CCX_OF_CURL)
374 		return NULL;
375 
376 	if(ctx->multiprogram == CCX_FALSE)
377 	{
378 		if(ctx->out_interval != -1)
379 		{
380 			int len;
381 
382 			len = strlen(ctx->basefilename) + 10 + strlen(extension);
383 
384 			freep(&ccx_options.enc_cfg.output_filename);
385 			ccx_options.enc_cfg.output_filename = malloc(len);
386 
387 			sprintf(ccx_options.enc_cfg.output_filename, "%s_%06d%s", ctx->basefilename, ctx->segment_counter+1, extension);
388 		}
389 		if (list_empty(&ctx->enc_ctx_head))
390 		{
391 			ccx_options.enc_cfg.program_number = pn;
392 			ccx_options.enc_cfg.in_format = in_format;
393 			enc_ctx = init_encoder(&ccx_options.enc_cfg);
394 			if (!enc_ctx)
395 				return NULL;
396 			list_add_tail( &(enc_ctx->list), &(ctx->enc_ctx_head) );
397 		}
398 	}
399 	else
400 	{
401 		int len;
402 
403 		len = strlen(ctx->basefilename) + 10 + strlen(extension);
404 
405 		ccx_options.enc_cfg.program_number = pn;
406 		ccx_options.enc_cfg.output_filename = malloc(len);
407 		if (!ccx_options.enc_cfg.output_filename)
408 		{
409 			freep(&extension);
410 			return NULL;
411 		}
412 
413 		sprintf(ccx_options.enc_cfg.output_filename, "%s_%d%s", ctx->basefilename, pn, extension);
414 		enc_ctx = init_encoder(&ccx_options.enc_cfg);
415 		if (!enc_ctx)
416 		{
417 			freep(&extension);
418 			freep(&ccx_options.enc_cfg.output_filename);
419 			return NULL;
420 		}
421 
422 		list_add_tail( &(enc_ctx->list), &(ctx->enc_ctx_head) );
423 		freep(&extension);
424 		freep(&ccx_options.enc_cfg.output_filename);
425 	}
426 	// DVB related
427 	enc_ctx->prev = NULL;
428 	if (cinfo)
429 		if (cinfo->codec == CCX_CODEC_DVB)
430 			enc_ctx->write_previous = 0;
431 	freep(&extension);
432 	return enc_ctx;
433 }
434 
update_encoder_list(struct lib_ccx_ctx * ctx)435 struct encoder_ctx *update_encoder_list(struct lib_ccx_ctx *ctx)
436 {
437 	return update_encoder_list_cinfo(ctx, NULL);
438 }
439