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