1 #include "lib_ccx.h"
2 #include "ccx_common_option.h"
3 #include "dvb_subtitle_decoder.h"
4 #include "utility.h"
5 #include <stdbool.h>
6 #ifdef WIN32
7 	#include "..\\win_iconv\\iconv.h"
8 #else
9 	#include "iconv.h"
10 #endif
11 
12 //Prints a string to a file pointer, escaping XML special chars
13 //Works with UTF-8
EPG_fprintxml(FILE * f,char * string)14 void EPG_fprintxml(FILE *f, char *string)
15 {
16 	char *p = string;
17 	char *start = p;
18 	while(*p!='\0')
19 	{
20 		switch(*p) {
21 		case '<':
22 			fwrite(start, 1, p-start, f);
23 			fprintf(f, "&lt;");
24 			start = p+1;
25 			break;
26 		case '>':
27 			fwrite(start, 1, p-start, f);
28 			fprintf(f, "&gt;");
29 			start = p+1;
30 			break;
31 		case '"':
32 			fwrite(start, 1, p-start, f);
33 			fprintf(f, "&quot;");
34 			start = p+1;
35 			break;
36 		case '&':
37 			fwrite(start, 1, p-start, f);
38 			fprintf(f, "&amp;");
39 			start = p+1;
40 			break;
41 		case '\'':
42 			fwrite(start, 1, p-start, f);
43 			fprintf(f, "&apos;");
44 			start = p+1;
45 			break;
46 		}
47 		p++;
48 	}
49 	fwrite(start, 1, p-start, f);
50 }
51 
52 // Fills given string with given (event.*_time_string) ATSC time converted to XMLTV style time string
EPG_ATSC_calc_time(char * output,uint32_t time)53 void EPG_ATSC_calc_time(char *output, uint32_t time)
54 {
55 	struct tm timeinfo;
56 	timeinfo.tm_year = 1980-1900;
57 	timeinfo.tm_mon = 0;
58 	timeinfo.tm_mday = 6;
59 	timeinfo.tm_sec = 0+time;
60 	timeinfo.tm_min = 0;
61 	timeinfo.tm_hour = 0;
62 	timeinfo.tm_isdst = -1;
63 	mktime(&timeinfo);
64 	sprintf(output, "%02d%02d%02d%02d%02d%02d +0000", timeinfo.tm_year+1900, timeinfo.tm_mon+1, timeinfo.tm_mday, timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);
65 }
66 
67 // Fills event.start_time_string in XMLTV format with passed DVB time
EPG_DVB_calc_start_time(struct EPG_event * event,uint64_t time)68 void EPG_DVB_calc_start_time(struct EPG_event *event, uint64_t time)
69 {
70 	uint64_t mjd = time>>24;
71 	event->start_time_string[0]='\0';
72 	if (mjd > 0)
73 	{
74 		long   y,m,d ,k;
75 
76 		// algo: ETSI EN 300 468 - ANNEX C
77 		y =  (long) ((mjd  - 15078.2) / 365.25);
78 		m =  (long) ((mjd - 14956.1 - (long)(y * 365.25) ) / 30.6001);
79 		d =  (long) (mjd - 14956 - (long)(y * 365.25) - (long)(m * 30.6001));
80 		k =  (m == 14 || m == 15) ? 1 : 0;
81 		y = y + k + 1900;
82 		m = m - 1 - k*12;
83 
84 		sprintf(event->start_time_string, "%02ld%02ld%02ld%06"PRIu64 "+0000",y,m,d,time&0xffffff);
85 	}
86 }
87 
88 // Fills event.end_time_string in XMLTV with passed DVB time + duration
EPG_DVB_calc_end_time(struct EPG_event * event,uint64_t time,uint32_t duration)89 void EPG_DVB_calc_end_time(struct EPG_event *event, uint64_t time, uint32_t duration)
90 {
91 	uint64_t mjd = time>>24;
92 	event->end_time_string[0]='\0';
93 	if (mjd > 0)
94 	{
95 		long   y,m,d ,k;
96 		struct tm timeinfo;
97 
98 		// algo: ETSI EN 300 468 - ANNEX C
99 		y =  (long) ((mjd  - 15078.2) / 365.25);
100 		m =  (long) ((mjd - 14956.1 - (long)(y * 365.25) ) / 30.6001);
101 		d =  (long) (mjd - 14956 - (long)(y * 365.25) - (long)(m * 30.6001));
102 		k =  (m == 14 || m == 15) ? 1 : 0;
103 		y = y + k + 1900;
104 		m = m - 1 - k*12;
105 
106 		timeinfo.tm_year = y-1900;
107 		timeinfo.tm_mon = m-1;
108 		timeinfo.tm_mday = d;
109 
110 		timeinfo.tm_sec = (time&0x0f) + (10*((time&0xf0)>>4)) + (duration&0x0f) + (10*((duration&0xf0)>>4));
111 		timeinfo.tm_min = ((time&0x0f00)>>8) + (10*((time&0xf000)>>4)>>8) + ((duration&0x0f00)>>8) + (10*((duration&0xf000)>>4)>>8);
112 		timeinfo.tm_hour = ((time&0x0f0000)>>16) + (10*((time&0xf00000)>>4)>>16) + ((duration&0x0f0000)>>16) + (10*((duration&0xf00000)>>4)>>16);
113 		timeinfo.tm_isdst = -1;
114 		mktime(&timeinfo);
115 		sprintf(event->end_time_string, "%02d%02d%02d%02d%02d%02d +0000", timeinfo.tm_year+1900, timeinfo.tm_mon+1, timeinfo.tm_mday, timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);
116 	}
117 }
118 
119 // returns english string description of the passed DVB category ID
EPG_DVB_content_type_to_string(uint8_t cat)120 char *EPG_DVB_content_type_to_string(uint8_t cat)
121 {
122 	struct table {
123 		uint8_t cat;
124 		char *name;
125 	};
126 	struct table t[] = {
127 		{0x00, "reserved"}, { 0x10, "movie/drama (general)" }, { 0x11, "detective/thriller" }, { 0x12, "adventure/western/war" }, { 0x13, "science fiction/fantasy/horror" },{ 0x14, "comedy" },
128 		{ 0x15, "soap/melodram/folkloric" }, { 0x16, "romance" }, { 0x17, "serious/classical/religious/historical movie/drama" }, { 0x18, "adult movie/drama" }, { 0x1E, "reserved" },
129 		{ 0x1F, "user defined" }, { 0x20, "news/current affairs (general)" }, { 0x21, "news/weather report" }, { 0x22, "news magazine" }, { 0x23, "documentary" }, { 0x24, "discussion/interview/debate" },
130 		{ 0x2E, "reserved" }, { 0x2F, "user defined" }, { 0x30, "show/game show (general)" }, { 0x31, "game show/quiz/contest" }, { 0x32, "variety show" }, { 0x33, "talk show" }, { 0x3E, "reserved" },
131 		{ 0x3F, "user defined" }, { 0x40, "sports (general)" }, { 0x41, "special events" }, { 0x42, "sports magazine" }, { 0x43, "football/soccer" }, { 0x44, "tennis/squash" }, { 0x45, "team sports" },
132 		{ 0x46, "athletics" }, { 0x47, "motor sport" }, { 0x48, "water sport" }, { 0x49, "winter sport" }, { 0x4A, "equestrian" }, { 0x4B, "martial sports" }, { 0x4E, "reserved" }, { 0x4F, "user defined" },
133 		{ 0x50, "childrens's/youth program (general)" }, { 0x51, "pre-school children's program" }, { 0x52, "entertainment (6-14 year old)" }, { 0x53, "entertainment (10-16 year old)" },
134 		{ 0x54, "information/education/school program" }, { 0x55, "cartoon/puppets" }, { 0x5E, "reserved" }, { 0x5F, "user defined" }, { 0x60, "music/ballet/dance (general)" }, { 0x61, "rock/pop" },
135 		{ 0x62, "serious music/classic music" }, { 0x63, "folk/traditional music" }, { 0x64, "jazz" }, { 0x65, "musical/opera" }, { 0x66, "ballet" }, { 0x6E, "reserved" }, { 0x6F, "user defined" },
136 		{ 0x70, "arts/culture (without music, general)" },{ 0x71, "performing arts" }, { 0x72, "fine arts" }, { 0x73, "religion" }, { 0x74, "popular culture/traditional arts" }, { 0x75, "literature" },
137 		{ 0x76, "film/cinema" }, { 0x77, "experimental film/video" }, { 0x78, "broadcasting/press" }, { 0x79, "new media" }, { 0x7A, "arts/culture magazine" }, { 0x7B, "fashion" }, { 0x7E, "reserved" },
138 		{ 0x7F, "user defined" }, { 0x80, "social/political issues/economics (general)" }, { 0x81, "magazines/reports/documentary" }, { 0x82, "economics/social advisory" }, { 0x83, "remarkable people" },
139 		{ 0x8E, "reserved" }, { 0x8F, "user defined" }, { 0x90, "education/science/factual topics (general)" }, { 0x91, "nature/animals/environment" }, { 0x92, "technology/natural science" },
140 		{ 0x93, "medicine/physiology/psychology" }, { 0x94, "foreign countries/expeditions" }, { 0x95, "social/spiritual science" }, { 0x96, "further education" }, { 0x97, "languages" },
141 		{ 0x9E, "reserved" }, { 0x9F, "user defined" }, { 0xA0, "leisure hobbies (general)" }, { 0xA1, "tourism/travel" }, { 0xA2, "handicraft" }, { 0xA3, "motoring" }, { 0xA4, "fitness & health" },
142 		{ 0xA5, "cooking" }, { 0xA6, "advertisement/shopping" }, { 0xA7, "gardening" }, { 0xAE, "reserved" }, { 0xAF, "user defined" }, { 0xB0, "original language" }, { 0xB1, "black & white" },
143 		{ 0xB2, "unpublished" }, { 0xB3, "live broadcast" }, { 0xBE, "reserved" }, { 0xBF, "user defined" }, { 0xEF, "reserved" }, { 0xFF, "user defined" }, {0x00, NULL},
144 	};
145 	struct table *p = t;
146 	while(p->name!=NULL)
147 	{
148 		if(cat==p->cat)
149 			return p->name;
150 		p++;
151 	}
152 	return "undefined content";
153 
154 }
155 
156 // Prints given event to already opened XMLTV file.
EPG_print_event(struct EPG_event * event,uint32_t channel,FILE * f)157 void EPG_print_event(struct EPG_event *event, uint32_t channel, FILE *f)
158 {
159 	int i;
160 	fprintf(f, "  <program  ");
161 	fprintf(f, "start=\"");
162 	fprintf(f, "%s", event->start_time_string);
163 	fprintf(f, "\" ");
164 	fprintf(f, "stop=\"");
165 	fprintf(f, "%s", event->end_time_string);
166 	fprintf(f, "\" ");
167 	fprintf(f, "channel=\"%i\">\n", channel);
168 	if(event->has_simple)
169 	{
170 		fprintf(f, "    <title lang=\"%s\">", event->ISO_639_language_code);
171 		EPG_fprintxml(f, event->event_name);
172 		fprintf(f, "</title>\n");
173 		fprintf(f, "    <sub-title lang=\"%s\">", event->ISO_639_language_code);
174 		EPG_fprintxml(f, event->text);
175 		fprintf(f, "</sub-title>\n");
176 	}
177 	if(event->extended_text!=NULL)
178 	{
179 		fprintf(f, "    <desc lang=\"%s\">", event->extended_ISO_639_language_code);
180 		EPG_fprintxml(f, event->extended_text);
181 		fprintf(f, "</desc>\n");
182 	}
183 	for(i=0; i<event->num_ratings; i++)
184 		if(event->ratings[i].age>0 && event->ratings[i].age<0x10)
185 			fprintf(f, "    <rating system=\"dvb:%s\">%i</rating>\n", event->ratings[i].country_code, event->ratings[i].age+3);
186 	for(i=0; i<event->num_categories; i++)
187 	{
188 		fprintf(f, "    <category lang=\"en\">");
189 		EPG_fprintxml(f, EPG_DVB_content_type_to_string(event->categories[i]));
190 		fprintf(f, "</category>\n");
191 	}
192 	fprintf(f, "    <ts-meta-id>%i</ts-meta-id>\n", event->id);
193 	fprintf(f, "  </program>\n");
194 }
195 
EPG_output_net(struct lib_ccx_ctx * ctx)196 void EPG_output_net(struct lib_ccx_ctx *ctx)
197 {
198 	int i;
199 	unsigned j;
200 	struct EPG_event *event;
201 
202 	/* TODO: don't remove untill someone fixes segfault with -xmltv 2 */
203 	if (ctx->demux_ctx == NULL)
204 		return;
205 
206 	if (ctx->demux_ctx->nb_program == 0)
207 		return;
208 
209 	for (i = 0; i < ctx->demux_ctx->nb_program; i++)
210 	{
211 		if (ctx->demux_ctx->pinfo[i].program_number == ccx_options.demux_cfg.ts_forced_program)
212 			break;
213 	}
214 
215 	if (i == ctx->demux_ctx->nb_program)
216 		return;
217 
218 	for (j = 0; j < ctx->eit_programs[i].array_len; j++)
219 	{
220 		event = &(ctx->eit_programs[i].epg_events[j]);
221 		if (event->live_output == true)
222 			continue;
223 
224 		event->live_output = true;
225 
226 		char *category = NULL;
227 		if (event->num_categories > 0)
228 			category = EPG_DVB_content_type_to_string(event->categories[0]);
229 
230 		net_send_epg(
231 				event->start_time_string, event->end_time_string,
232 				event->event_name,
233 				event->extended_text,
234 				event->ISO_639_language_code,
235 				category
236 				);
237 	}
238 }
239 
240 // Creates fills and closes a new XMLTV file for live mode output.
241 // File should include only events not previously output.
EPG_output_live(struct lib_ccx_ctx * ctx)242 void EPG_output_live(struct lib_ccx_ctx *ctx)
243 {
244 	int c=false, i, j;
245 	FILE *f;
246 	char *filename, *finalfilename;
247 	for(i=0; i < ctx->demux_ctx->nb_program; i++)
248 	{
249 		for(j=0; j<ctx->eit_programs[i].array_len; j++)
250 			if(ctx->eit_programs[i].epg_events[j].live_output==false)
251 			{
252 				c=true;
253 			}
254 	}
255 	if(!c)
256 		return;
257 
258 	filename = malloc(strlen(ctx->basefilename)+30);
259 	sprintf(filename, "%s_%i.xml.part", ctx->basefilename, ctx->epg_last_live_output);
260 	f = fopen(filename, "w");
261 
262 	fprintf(f, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE tv SYSTEM \"xmltv.dtd\">\n\n<tv>\n");
263 	for(i=0; i < ctx->demux_ctx->nb_program; i++)
264 	{
265 		fprintf(f, "  <channel id=\"%i\">\n", ctx->demux_ctx->pinfo[i].program_number);
266 		fprintf(f, "    <display-name>%i</display-name>\n", ctx->demux_ctx->pinfo[i].program_number);
267 		fprintf(f, "  </channel>\n");
268 	}
269 	for(i=0; i < ctx->demux_ctx->nb_program; i++)
270 	{
271 		for(j=0; j<ctx->eit_programs[i].array_len; j++)
272 			if(ctx->eit_programs[i].epg_events[j].live_output==false)
273 			{
274 				ctx->eit_programs[i].epg_events[j].live_output=true;
275 				EPG_print_event(&ctx->eit_programs[i].epg_events[j], ctx->demux_ctx->pinfo[i].program_number, f);
276 			}
277 	}
278 	fprintf(f, "</tv>");
279 	fclose(f);
280 	finalfilename = malloc(strlen(filename)+30);
281 	memcpy(finalfilename, filename, strlen(filename)-5);
282 	finalfilename[strlen(filename)-5]='\0';
283 	rename(filename, finalfilename);
284 	free(filename);
285 	free(finalfilename);
286 }
287 
288 // Creates fills and closes a new XMLTV file for full output mode.
289 // File should include all events in memory.
EPG_output(struct lib_ccx_ctx * ctx)290 void EPG_output(struct lib_ccx_ctx *ctx)
291 {
292 	FILE *f;
293 	char *filename;
294 	int i,j, ce;
295 
296 	filename = malloc(strlen(ctx->basefilename) + 9);
297 	if(filename == NULL)
298 		return;
299 
300 	memcpy(filename, ctx->basefilename, strlen(ctx->basefilename)+1);
301 	strcat(filename, "_epg.xml");
302 	f = fopen(filename, "w");
303 	if(!f)
304 	{
305 		dbg_print (CCX_DMT_GENERIC_NOTICES, "\rUnable to open %s\n", filename);
306         	freep(&filename);
307 		return;
308 	}
309 	freep(&filename);
310 
311 	fprintf(f, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE tv SYSTEM \"xmltv.dtd\">\n\n<tv>\n");
312 	for(i=0; i<ctx->demux_ctx->nb_program; i++)
313 	{
314 		fprintf(f, "  <channel id=\"%i\">\n", ctx->demux_ctx->pinfo[i].program_number);
315 		fprintf(f, "    <display-name>");
316 		if(ctx->demux_ctx->pinfo[i].name[0] != '\0')
317 			EPG_fprintxml(f, ctx->demux_ctx->pinfo[i].name);
318 		else
319 			fprintf(f, "%i\n", ctx->demux_ctx->pinfo[i].program_number);
320 		fprintf(f, "</display-name>\n");
321 		fprintf(f, "  </channel>\n");
322 	}
323 	if(ccx_options.xmltvonlycurrent==0)
324 	{ // print all events
325 		for(i=0; i<ctx->demux_ctx->nb_program; i++)
326 		{
327 			for(j=0; j<ctx->eit_programs[i].array_len; j++)
328 				EPG_print_event(&ctx->eit_programs[i].epg_events[j], ctx->demux_ctx->pinfo[i].program_number, f);
329 		}
330 
331 		if(ctx->demux_ctx->nb_program==0) //Stream has no PMT, fall back to unordered events
332 			for(j=0; j<ctx->eit_programs[TS_PMT_MAP_SIZE].array_len; j++)
333 				EPG_print_event(&ctx->eit_programs[TS_PMT_MAP_SIZE].epg_events[j], ctx->eit_programs[TS_PMT_MAP_SIZE].epg_events[j].service_id, f);
334 	}
335 	else
336 	{ // print current events only
337 		for(i=0; i<ctx->demux_ctx->nb_program; i++)
338 		{
339 			ce = ctx->eit_current_events[i];
340 			for(j=0; j<ctx->eit_programs[i].array_len; j++)
341 			{
342 				if(ce==ctx->eit_programs[i].epg_events[j].id)
343 					EPG_print_event(&ctx->eit_programs[i].epg_events[j], ctx->demux_ctx->pinfo[i].program_number, f);
344 			}
345 		}
346 	}
347 	fprintf(f, "</tv>");
348 	fclose(f);
349 }
350 
351 // Free all memory allocated for given event
EPG_free_event(struct EPG_event * event)352 void EPG_free_event(struct EPG_event *event)
353 {
354 	if(event->has_simple)
355 	{
356 		free(event->event_name);
357 		free(event->text);
358 	}
359 	if(event->extended_text!=NULL)
360 		free(event->extended_text);
361 	if(event->num_ratings>0)
362 		free(event->ratings);
363 	if(event->num_categories>0)
364 		free(event->categories);
365 }
366 
367 //compare 2 events. Return false if they are different.
EPG_event_cmp(struct EPG_event * e1,struct EPG_event * e2)368 int EPG_event_cmp(struct EPG_event *e1, struct EPG_event *e2)
369 {
370 	if(e1->id != e2->id || (strcmp(e1->start_time_string, e2->start_time_string)!=0) || (strcmp(e1->end_time_string, e2->end_time_string)!=0))
371 		return false;
372 	// could add full checking of strings here if desired.
373 	return true;
374 }
375 
376 // Add given event to array of events.
377 // Return FALSE if nothing changed, TRUE if this is a new or updated event.
EPG_add_event(struct lib_ccx_ctx * ctx,int32_t pmt_map,struct EPG_event * event)378 int EPG_add_event(struct lib_ccx_ctx *ctx, int32_t pmt_map, struct EPG_event *event)
379 {
380 	int isnew=true, j;
381 
382 	for(j=0; j<ctx->eit_programs[pmt_map].array_len; j++)
383 	{
384 		if(ctx->eit_programs[pmt_map].epg_events[j].id==event->id)
385 		{
386 			if(EPG_event_cmp(event, &ctx->eit_programs[pmt_map].epg_events[j]))
387 				return false; //event already in array, nothing to do
388 			else
389 			{ //event with this id is already in the array but something has changed. Update it.
390 				event->count=ctx->eit_programs[pmt_map].epg_events[j].count;
391 				EPG_free_event(&ctx->eit_programs[pmt_map].epg_events[j]);
392 				memcpy(&ctx->eit_programs[pmt_map].epg_events[j], event, sizeof(struct EPG_event));
393 				return true;
394 			}
395 		}
396 	}
397 	// id not in array. Add new event;
398 	event->count=0;
399 	memcpy(&ctx->eit_programs[pmt_map].epg_events[ctx->eit_programs[pmt_map].array_len], event, sizeof(struct EPG_event));
400 	ctx->eit_programs[pmt_map].array_len++;
401 	return true;
402 }
403 
404 //EN 300 468 V1.3.1 (1998-02)
405 //6.2.4 Content descriptor
EPG_decode_content_descriptor(uint8_t * offset,uint32_t descriptor_length,struct EPG_event * event)406 void EPG_decode_content_descriptor(uint8_t *offset, uint32_t descriptor_length, struct EPG_event *event)
407 {
408 	int i;
409 	int num_items = descriptor_length/2;
410 	if(num_items == 0)
411 	{
412 		dbg_print (CCX_DMT_GENERIC_NOTICES, "\rWarning: Invalid EIT content_descriptor length detected.\n");
413 		return;
414 	}
415 	event->categories = malloc(1*num_items);
416 	event->num_categories = num_items;
417 	for(i=0; i<num_items; i++)
418 	{
419 		event->categories[i] = offset[0];
420 		offset+=2;
421 	}
422 }
423 
424 //EN 300 468 V1.3.1 (1998-02)
425 //6.2.20 Parental rating descripto
EPG_decode_parental_rating_descriptor(uint8_t * offset,uint32_t descriptor_length,struct EPG_event * event)426 void EPG_decode_parental_rating_descriptor(uint8_t *offset, uint32_t descriptor_length, struct EPG_event *event)
427 {
428 	int i;
429 	int num_items = descriptor_length/4;
430 	struct EPG_rating *ratings;
431 
432 	if(num_items == 0)
433 	{
434 		dbg_print (CCX_DMT_GENERIC_NOTICES, "\rWarning: Invalid EIT parental_rating length detected.\n");
435 		return;
436 	}
437 	event->ratings = malloc(sizeof(struct EPG_rating)*num_items);
438 
439 	ratings = event->ratings;
440 	event->num_ratings = num_items;
441 	for(i=0; i<descriptor_length/4; i++)
442 	{
443 		ratings[i].country_code[0] = offset[0];
444 		ratings[i].country_code[1] = offset[1];
445 		ratings[i].country_code[2] = offset[2];
446 		ratings[i].country_code[3] = '\0';
447 		if(offset[3] == 0x00 || offset[3] >=0x10)
448 			ratings[i].age = 0;
449 		else
450 			ratings[i].age = offset[3];
451 		offset+=4;
452 	}
453 }
454 
455 // an ugly function to convert from dvb codepages to UTF-8859-9 using iconv
456 // returns a null terminated UTF8-strings
457 // EN 300 468 V1.7.1 (2006-05)
458 // A.2 Selection of Character table
EPG_DVB_decode_string(uint8_t * in,size_t size)459 char* EPG_DVB_decode_string(uint8_t *in, size_t size)
460 {
461 	uint8_t *out;
462 	uint16_t decode_buffer_size = (size*4)+1;
463 	uint8_t *decode_buffer = malloc(decode_buffer_size);
464 	char *dp = &decode_buffer[0];
465 	size_t obl=decode_buffer_size;
466 	uint16_t osize=0;
467 	iconv_t cd=(iconv_t)(-1);
468 	int skipiconv = false;
469 	int ret=-1;
470 	int x;
471 	if(size==0)
472 	{ // 0 length strings are valid
473 		decode_buffer[0]='\0';
474 		return decode_buffer;
475 	}
476 
477 	if(in[0]>=0x20)
478 	{
479 		skipiconv=true;
480 	}
481 	else if(in[0]==0x01)
482 	{
483 		size--;	in++;
484 		cd = iconv_open("UTF-8", "ISO8859-5"); //tested
485 	}
486 	else if(in[0]==0x02)
487 	{
488 		size--;	in++;
489 		cd = iconv_open("UTF-8", "ISO8859-6");
490 	}
491 	else if(in[0]==0x03)
492 	{
493 		size--;	in++;
494 		cd = iconv_open("UTF-8", "ISO8859-7");
495 	}
496 	else if(in[0]==0x04)
497 	{
498 		size--;	in++;
499 		cd = iconv_open("UTF-8", "ISO8859-8");
500 	}
501 	else if(in[0]==0x05)
502 	{
503 		size--;	in++;
504 		cd = iconv_open("UTF-8", "ISO8859-9");
505 	}
506 	else if(in[0]==0x06) {
507 		size--;	in++;
508 		cd = iconv_open("UTF-8", "ISO8859-10");
509 	}
510 	else if(in[0]==0x07)
511 	{
512 		size--;
513 		in++;
514 		cd = iconv_open("UTF-8", "ISO8859-11");
515 	}
516 	else if(in[0]==0x08)
517 	{
518 		size--;	in++;
519 		cd = iconv_open("UTF-8", "ISO8859-12"); //This doesn't even exist?
520 	}
521 	else if(in[0]==0x09)
522 	{
523 		size--;	in++;
524 		cd = iconv_open("UTF-8", "ISO8859-13");
525 	}
526 	else if(in[0]==0x0a)
527 	{
528 		size--;	in++;
529 		cd = iconv_open("UTF-8", "ISO8859-14");
530 	}
531 	else if(in[0]==0x0b)
532 	{
533 		size--;	in++;
534 		cd = iconv_open("UTF-8", "ISO8859-15"); //tested, german
535 	}
536 	else if(in[0]==0x10)
537 	{
538 		char from[14];
539 		uint16_t cpn = (in[1] << 8) | in[2];
540 		size-=3; in+=3;
541 		snprintf(from, sizeof(from), "ISO8859-%d", cpn);
542 		cd = iconv_open("UTF-8", from);
543 	}
544 	else if(in[0]==0x11)
545 	{
546 		size--;	in++;
547 		cd = iconv_open("UTF-8", "ISO-10646/UTF8");
548 	}
549 	else if(in[0]==0x12)
550 	{
551 		size--;	in++;
552 		cd = iconv_open("UTF-8", "KS_C_5601-1987");
553 	}
554 	else if(in[0]==0x13)
555 	{
556 		size--;	in++;
557 		cd = iconv_open("UTF-8", "GB2312");
558 	}
559 	else if(in[0]==0x14)
560 	{
561 		size--;	in++;
562 		cd = iconv_open("UTF-8", "BIG-5");
563 	}
564 	else if(in[0]==0x15)
565 	{
566 		size--;	in++;
567 		cd = iconv_open("UTF-8", "UTF-8");
568 	}
569 	else
570 	{
571 		dbg_print (CCX_DMT_GENERIC_NOTICES, "\rWarning: EPG_DVB_decode_string(): Reserved encoding detected: %02x.\n", in[0]);
572 		size--;	in++;
573 		cd = iconv_open("UTF-8", "ISO8859-9");
574 	}
575 
576 	if((long)cd != -1 && !skipiconv)
577 	{
578 		ret = iconv(cd, (char **)&in, &size, &dp, &obl);
579 		obl=decode_buffer_size-obl;
580 		decode_buffer[obl]=0x00;
581 	}
582 	else
583 	{
584 		uint16_t newsize=0;
585 		if(!skipiconv)
586 			dbg_print (CCX_DMT_GENERIC_NOTICES, "\rWarning: EPG_DVB_decode_string(): Failed to convert codepage.\n");
587 		/*
588 			http://dvbstreamer.sourcearchive.com/documentation/2.1.0-2/dvbtext_8c_source.html
589 			libiconv doesn't support ISO 6937, but glibc does?!
590 			so fall back to ISO8859-1 and strip out the non spacing
591 			diacritical mark/graphical characters etc.
592 			ALSO: http://lists.gnu.org/archive/html/bug-gnu-libiconv/2009-09/msg00000.html
593 		*/
594 		for(x=0; x<size; x++)
595 		{
596 			if(in[x]<=(uint8_t)127)
597 			{
598 				decode_buffer[newsize]=in[x];
599 				newsize++;
600 			}
601 		}
602 		size=newsize;
603 		decode_buffer[size]=0x00;
604 	}
605 	osize=strlen(decode_buffer);
606 	out = malloc(osize+1);
607 	memcpy(out, decode_buffer, osize);
608 	out[osize]=0x00;
609 	free(decode_buffer);
610 	if (cd != (iconv_t)-1)
611 		iconv_close(cd);
612 	return out;
613 }
614 
615 //EN 300 468 V1.3.1 (1998-02)
616 //6.2.27 Short event descriptor
EPG_decode_short_event_descriptor(uint8_t * offset,uint32_t descriptor_length,struct EPG_event * event)617 void EPG_decode_short_event_descriptor(uint8_t *offset, uint32_t descriptor_length, struct EPG_event *event)
618 {
619 	uint8_t text_length;
620 	uint8_t event_name_length;
621 	event->has_simple=true;
622 	event->ISO_639_language_code[0] = offset[0];
623 	event->ISO_639_language_code[1] = offset[1];
624 	event->ISO_639_language_code[2] = offset[2];
625 	event->ISO_639_language_code[3] = 0x00;
626 
627 	event_name_length = offset[3];
628 	if(event_name_length+4>descriptor_length)
629 	{
630 		dbg_print (CCX_DMT_GENERIC_NOTICES, "\rWarning: Invalid short_event_descriptor size detected.\n");
631 		return;
632 	}
633 	event->event_name = EPG_DVB_decode_string(&offset[4], event_name_length);
634 
635 	text_length = offset[4+event_name_length];
636 	if(text_length+event_name_length+4>descriptor_length)
637 	{
638 		dbg_print (CCX_DMT_GENERIC_NOTICES, "\rWarning: Invalid short_event_descriptor size detected.\n");
639 		return;
640 	}
641 	event->text = EPG_DVB_decode_string(&offset[5+event_name_length], text_length);
642 
643 }
644 
645 //EN 300 468 V1.3.1 (1998-02)
646 //6.2.9 Extended event descriptor
EPG_decode_extended_event_descriptor(uint8_t * offset,uint32_t descriptor_length,struct EPG_event * event)647 void EPG_decode_extended_event_descriptor(uint8_t *offset, uint32_t descriptor_length, struct EPG_event *event)
648 {
649 	uint8_t descriptor_number=offset[0]>>4;
650 	uint8_t last_descriptor_number=(offset[0]&0x0f);
651 	uint32_t text_length;
652 	uint32_t oldlen=0;
653 	uint8_t length_of_items = offset[4];
654 	event->extended_ISO_639_language_code[0] = offset[1];
655 	event->extended_ISO_639_language_code[1] = offset[2];
656 	event->extended_ISO_639_language_code[2] = offset[3];
657 	event->extended_ISO_639_language_code[3] = 0x00;
658 
659 	offset=offset+length_of_items+5;
660 	if(length_of_items>descriptor_length-5)
661 	{
662 		dbg_print (CCX_DMT_GENERIC_NOTICES, "\rWarning: Invalid extended_event_descriptor size detected.\n");
663 		return;
664 	}
665 
666 	text_length = offset[0];
667 	if(text_length>descriptor_length-5-length_of_items-1)
668 	{
669 		dbg_print (CCX_DMT_GENERIC_NOTICES, "\rWarning: Invalid extended_event_text_length size detected.\n");
670 		return;
671 	}
672 
673 	//TODO: can this leak memory with a malformed descriptor?
674 	if(descriptor_number>0) {
675 		if(offset[1]<0x20) {
676 			offset++;
677 			text_length--;
678 		}
679 		uint8_t *net = malloc(strlen(event->extended_text)+text_length+1);
680 		oldlen=strlen(event->extended_text);
681 		memcpy(net, event->extended_text, strlen(event->extended_text));
682 		free(event->extended_text);
683 		event->extended_text=net;
684 	}
685 	else
686 		event->extended_text = malloc(text_length+1);
687 
688 	memcpy(&event->extended_text[oldlen], &offset[1], text_length);
689 
690 	event->extended_text[oldlen + text_length] = '\0';
691 
692 	if(descriptor_number==last_descriptor_number) {
693 		uint8_t *old = event->extended_text;
694 		event->extended_text = EPG_DVB_decode_string(event->extended_text, strlen(event->extended_text));
695 		free(old);
696 	}
697 
698 }
699 
700 // decode an ATSC multiple_string
701 // extremely basic implementation
702 // only handles single segment, single language ANSI string!
EPG_ATSC_decode_multiple_string(uint8_t * offset,uint32_t length,struct EPG_event * event)703 void EPG_ATSC_decode_multiple_string(uint8_t *offset, uint32_t length, struct EPG_event *event)
704 {
705 	uint8_t number_strings;
706 	int i, j;
707 	char ISO_639_language_code[4];
708 	uint8_t *offset_end = offset + length;
709 #define CHECK_OFFSET(val) if(offset + val < offset_end) return
710 
711 	CHECK_OFFSET(1);
712 	number_strings = offset[0];
713 	offset++;
714 
715 	for(i=0; i<number_strings; i++)
716 	{
717 		uint8_t number_segments;
718 
719 		CHECK_OFFSET(4);
720 		number_segments = offset[3];
721 		ISO_639_language_code[0] = offset[0];
722 		ISO_639_language_code[1] = offset[1];
723 		ISO_639_language_code[2] = offset[2];
724 		ISO_639_language_code[3] = 0x00;
725 		offset+=4;
726 		for (j=0; j< number_segments; j++)
727 		{
728 			uint8_t compression_type;
729 			uint8_t mode;
730 			uint8_t number_bytes;
731 			CHECK_OFFSET(3);
732 			compression_type = offset[0];
733 			mode = offset[1];
734 			number_bytes = offset[2];
735 			offset+=3;
736 			if(mode==0 && compression_type==0 && j==0)
737 			{
738 				CHECK_OFFSET(number_bytes);
739 				event->has_simple=true;
740 				event->ISO_639_language_code[0]=ISO_639_language_code[0];
741 				event->ISO_639_language_code[1]=ISO_639_language_code[1];
742 				event->ISO_639_language_code[2]=ISO_639_language_code[2];
743 				event->ISO_639_language_code[3]=0x00;
744 				event->event_name = malloc(number_bytes+1);
745 				memcpy(event->event_name, &offset[0], number_bytes);
746 				event->event_name[number_bytes]='\0';
747 				event->text = malloc(number_bytes+1);
748 				memcpy(event->text, &offset[0], number_bytes);
749 				event->text[number_bytes]='\0';
750 			}
751 			else
752 			{
753 				dbg_print (CCX_DMT_GENERIC_NOTICES, "\rWarning: Unsupported ATSC multiple_string encoding detected!.\n");
754 			}
755 			offset+=number_bytes;
756 		}
757 	}
758 #undef CHECK_OFFSET
759 }
760 
761 // decode ATSC EIT table.
EPG_ATSC_decode_EIT(struct lib_ccx_ctx * ctx,uint8_t * payload_start,uint32_t size)762 void EPG_ATSC_decode_EIT(struct lib_ccx_ctx *ctx, uint8_t *payload_start, uint32_t size)
763 {
764 	uint8_t table_id;
765 	struct EPG_event event;
766 	uint8_t num_events_in_section;
767 	uint8_t *offset;
768 	int hasnew=false;
769 	int i, j;
770 	uint16_t source_id;
771 	int32_t pmt_map = -1;
772 
773 	if (size < 11)
774 		return;
775 
776 	table_id = payload_start[0];
777 	source_id = ((payload_start[3]) << 8) | payload_start[4];
778 
779 	event.has_simple=false;
780 	event.extended_text=NULL;
781 	event.num_ratings=0;
782 	event.num_categories=0;
783 	event.live_output=false;
784 	for (i = 0; i < ctx->demux_ctx->nb_program; i++)
785 	{
786 		if (ctx->demux_ctx->pinfo[i].program_number == ctx->ATSC_source_pg_map[source_id])
787 			pmt_map=i;
788 	}
789 
790 	//Don't know how to store EPG until we know the programs. Ignore it.
791 	if(pmt_map==-1)
792 		pmt_map=TS_PMT_MAP_SIZE;
793 
794 	num_events_in_section = payload_start[9];
795 
796 #define CHECK_OFFSET(val) if(offset + val < (payload_start + size) ) return
797 	offset=&payload_start[10];
798 
799 	for(j = 0; j < num_events_in_section && offset < payload_start + size; j++)
800 	{
801 		uint16_t descriptors_loop_length;
802 		uint8_t title_length, emt_location;
803 		uint32_t length_in_seconds, start_time, full_id;
804 		uint16_t event_id;
805 
806 		CHECK_OFFSET(10);
807 
808 		event_id = ((offset[0]&0x3F) << 8) | offset[1];
809 		full_id = (source_id << 16) | event_id;
810 		event.id=full_id;
811 		event.service_id=source_id;
812 		start_time = (offset[2] << 24) | (offset[3] << 16) | (offset[4] << 8)| (offset[5] << 0);
813 		EPG_ATSC_calc_time(event.start_time_string, start_time);
814 		emt_location = (offset[6]&0x30)>>4;
815 		length_in_seconds = (((offset[6]&0x0F) << 16) | (offset[7] << 8) | (offset[8] << 0));
816 		EPG_ATSC_calc_time(event.end_time_string, start_time+length_in_seconds);
817 
818 		title_length = offset[9];
819 		//XXX cant decode data more then size of payload
820 		CHECK_OFFSET(11 + title_length);
821 
822 		EPG_ATSC_decode_multiple_string(&offset[10], title_length, &event);
823 
824 		descriptors_loop_length = ((offset[10+title_length] & 0x0f) << 8) | offset[10+title_length+1];
825 
826 		hasnew |= EPG_add_event(ctx, pmt_map, &event);
827 		offset += 12 + descriptors_loop_length + title_length;
828 	}
829 	if((ccx_options.xmltv==1 || ccx_options.xmltv==3) && ccx_options.xmltvoutputinterval==0 && hasnew)
830 		EPG_output(ctx);
831 #undef CHECK_OFFSET
832 }
833 
834 // decode ATSC VCT table.
EPG_ATSC_decode_VCT(struct lib_ccx_ctx * ctx,uint8_t * payload_start,uint32_t size)835 void EPG_ATSC_decode_VCT(struct lib_ccx_ctx *ctx, uint8_t *payload_start, uint32_t size)
836 {
837 	uint8_t table_id;
838 	uint8_t num_channels_in_section;
839 	uint8_t *offset;
840 	int i;
841 
842 	if (size <= 10)
843 		return;
844 
845 	table_id = payload_start[0];
846 	num_channels_in_section = payload_start[9];
847 	offset = &payload_start[10];
848 
849 	for (i=0; i< num_channels_in_section; i++)
850 	{
851 		char short_name[7*2];
852 		uint16_t program_number;
853 		uint16_t source_id;
854 		uint16_t descriptors_loop_length;
855 
856 		if(offset + 31 > payload_start+size)
857 			break;
858 
859 		program_number = offset[24]<<8 | offset[25];
860 		source_id = offset[28]<<8 | offset[29];
861 		descriptors_loop_length = ((offset[30] & 0x03) << 8) | offset[31];
862 
863 		memcpy(short_name, &offset[0], 7*2);
864 		offset += 32 + descriptors_loop_length;
865 		ctx->ATSC_source_pg_map[source_id]=program_number;
866 	}
867 }
868 
869 
EPG_DVB_decode_EIT(struct lib_ccx_ctx * ctx,uint8_t * payload_start,uint32_t size)870 void EPG_DVB_decode_EIT(struct lib_ccx_ctx *ctx, uint8_t *payload_start, uint32_t size)
871 {
872 
873 	uint8_t table_id;
874 	//uint8_t section_syntax_indicator = (0xf1&0x80)>>7;
875 	uint16_t section_length;
876 	uint16_t service_id;
877 	int32_t pmt_map = -1;
878 	int i;
879 	int hasnew = false;
880 	struct EPG_event event;
881 	uint8_t section_number;
882 	uint8_t last_section_number;
883 	uint8_t segment_last_section_number;
884 	uint32_t events_length;
885 	uint8_t *offset;
886 	uint32_t remaining;
887 
888 
889 	if(size < 13)
890 		return;
891 
892 	table_id 			= payload_start[0];
893 	//section_syntax_indicator 	= (0xf1&0x80)>>7;
894 	section_length			= (payload_start[1]&0x0F)<<8 | payload_start[2];
895 	service_id			= (payload_start[3] << 8) | payload_start[4];
896 	section_number			= payload_start[6];
897 	last_section_number		= payload_start[7];
898 	segment_last_section_number	= payload_start[12];
899 	events_length			= section_length - 11;
900 	offset				= payload_start;
901 	remaining			= events_length;
902 
903 	for (i = 0; i < ctx->demux_ctx->nb_program; i++)
904 	{
905 		if (ctx->demux_ctx->pinfo[i].program_number == service_id)
906 			pmt_map = i;
907 	}
908 
909 	//For any service we don't have an PMT for (yet), store it in the special last array pos.
910 	if(pmt_map == -1)
911 		pmt_map = TS_PMT_MAP_SIZE;
912 
913 	if(events_length > size-14)
914 	{
915 		dbg_print (CCX_DMT_GENERIC_NOTICES, "\rWarning: Invalid EIT packet size detected.\n");
916 		//XXX hack to override segfault, we should concat packets instead
917 		return;
918 	}
919 
920 	while(remaining > 4)
921 	{
922 		uint16_t descriptors_loop_length;
923 		uint8_t *descp;
924 		uint32_t duration;
925 		uint64_t start_time;
926 		event.id		= (offset[14] << 8) | offset[15];
927 		event.has_simple	= false;
928 		event.extended_text	= NULL;
929 		event.num_ratings	= 0;
930 		event.num_categories	= 0;
931 		event.live_output	= false;
932 		event.service_id	= service_id;
933 
934 		//40 bits
935 		start_time = ((uint64_t)offset[16] << 32) | ((uint64_t)offset[17] << 24) | ((uint64_t)offset[18] << 16) | ((uint64_t)offset[19] << 8)| ((uint64_t)offset[20] << 0);
936 		EPG_DVB_calc_start_time(&event, start_time);
937 		//24 bits
938 		duration = (offset[21] << 16 ) | (offset[22] << 8 ) | (offset[23] << 0 );
939 		EPG_DVB_calc_end_time(&event, start_time, duration);
940 		event.running_status = (offset[24] & 0xE0) >> 5;
941 		event.free_ca_mode = (offset[24] & 0x10) >> 4;
942 		//12 bits
943 		descriptors_loop_length = ((offset[24] & 0x0f) << 8) | offset[25];
944 		descp = &offset[26];
945 		if(descriptors_loop_length > remaining-16)
946 		{
947 			dbg_print (CCX_DMT_GENERIC_NOTICES, "\rWarning: Invalid EIT descriptors_loop_length detected.\n");
948 			return;
949 		}
950 		while(descp<&(offset[26])+descriptors_loop_length)
951 		{
952 			if(descp+descp[1]+2>payload_start+size) {
953 				dbg_print (CCX_DMT_GENERIC_NOTICES, "\rWarning: Invalid EIT descriptor_loop_length detected.\n");
954 				EPG_free_event(&event);
955 				return;
956 			}
957 			if(descp[0]==0x4d)
958 				EPG_decode_short_event_descriptor(descp+2, descp[1], &event);
959 			if(descp[0]==0x4e)
960 				EPG_decode_extended_event_descriptor(descp+2, descp[1], &event);
961 			if(descp[0]==0x54)
962 				EPG_decode_content_descriptor(descp+2, descp[1], &event);
963 			if(descp[0]==0x55)
964 				EPG_decode_parental_rating_descriptor(descp+2, descp[1], &event);
965 			if(descp[1]+2==0)
966 			{
967 				dbg_print (CCX_DMT_GENERIC_NOTICES, "\rWarning: Invalid EIT descriptor_length detected.\n");
968 				return;
969 			}
970 			descp=descp+(descp[1]+2);
971 		}
972 		remaining = remaining - (descriptors_loop_length + 12);
973 		offset = offset + descriptors_loop_length + 12;
974 		hasnew |= EPG_add_event(ctx, pmt_map, &event);
975 
976 		if(hasnew && section_number==0 && table_id==0x4e)
977 			ctx->eit_current_events[pmt_map]=event.id;
978 	}
979 
980 	if((ccx_options.xmltv==1 || ccx_options.xmltv==3) && ccx_options.xmltvoutputinterval==0 && hasnew)
981 		EPG_output(ctx);
982 }
983 	//handle outputing to xml files
EPG_handle_output(struct lib_ccx_ctx * ctx)984 void EPG_handle_output(struct lib_ccx_ctx *ctx)
985 {
986 	int cur_sec = (int) ((ctx->demux_ctx->global_timestamp - ctx->demux_ctx->min_global_timestamp) / 1000);
987 	if(ccx_options.xmltv==1 || ccx_options.xmltv==3)
988 	{ //full outout
989 		if(ccx_options.xmltvoutputinterval!=0 && cur_sec>ctx->epg_last_output+ccx_options.xmltvliveinterval)
990 		{
991 			ctx->epg_last_output=cur_sec;
992 			EPG_output(ctx);
993 		}
994 	}
995 	if(ccx_options.xmltv==2 || ccx_options.xmltv==3 || ccx_options.send_to_srv)
996 	{ //live output
997 		if(cur_sec>ctx->epg_last_live_output+ccx_options.xmltvliveinterval)
998 		{
999 			ctx->epg_last_live_output=cur_sec;
1000 			if (ccx_options.send_to_srv)
1001 				EPG_output_net(ctx);
1002 			else
1003 				EPG_output_live(ctx);
1004 		}
1005 	}
1006 }
1007 
1008 //determine table type and call the correct function to handle it
EPG_parse_table(struct lib_ccx_ctx * ctx,uint8_t * b,uint32_t size)1009 void EPG_parse_table(struct lib_ccx_ctx *ctx, uint8_t *b, uint32_t size)
1010 {
1011 	uint8_t pointer_field = b[0];
1012 	uint8_t *payload_start;
1013 	uint8_t table_id;
1014 
1015 	//XXX hack, should accumulate data
1016 	if(pointer_field + 2 > size) {
1017 		return;
1018 	}
1019 	payload_start = &b[pointer_field + 1];
1020 	table_id = payload_start[0];
1021 	switch (table_id) {
1022 	case 0x0cb:
1023 		EPG_ATSC_decode_EIT(ctx, payload_start, size - (payload_start - b));
1024 		break;
1025 	case 0xc8:
1026 		EPG_ATSC_decode_VCT(ctx, payload_start, size - (payload_start - b));
1027 		break;
1028 	default:
1029 		if (table_id>=0x4e && table_id<=0x6f)
1030 			EPG_DVB_decode_EIT(ctx, payload_start, size - (payload_start - b));
1031 		break;
1032 	}
1033 	EPG_handle_output(ctx);
1034 }
1035 
1036 // reconstructs DVB EIT and ATSC tables
parse_EPG_packet(struct lib_ccx_ctx * ctx)1037 void parse_EPG_packet(struct lib_ccx_ctx *ctx)
1038 {
1039 	unsigned char *payload_start = tspacket + 4;
1040 	unsigned payload_length = 188 - 4;
1041 	unsigned transport_error_indicator = (tspacket[1]&0x80)>>7;
1042 	unsigned payload_start_indicator = (tspacket[1]&0x40)>>6;
1043 	// unsigned transport_priority = (tspacket[1]&0x20)>>5;
1044 	unsigned pid = (((tspacket[1] & 0x1F) << 8) | tspacket[2]) & 0x1FFF;
1045 	// unsigned transport_scrambling_control = (tspacket[3]&0xC0)>>6;
1046 	unsigned adaptation_field_control = (tspacket[3]&0x30)>>4;
1047 	unsigned ccounter = tspacket[3] & 0xF;
1048 	unsigned adaptation_field_length = 0;
1049 	int buffer_map = 0xfff;
1050 	if ( adaptation_field_control & 2 )
1051 	{
1052 		adaptation_field_length = tspacket[4];
1053 		payload_start = payload_start + adaptation_field_length + 1;
1054 		payload_length = tspacket+188-payload_start;
1055 	}
1056 
1057 	if((pid!=0x12 && pid!=0x1ffb && pid<0x1000) || pid==0x1fff)
1058 		return;
1059 
1060 	if(pid!=0x12)
1061 		buffer_map = pid-0x1000;
1062 
1063 	if(payload_start_indicator)
1064 	{
1065 		if(ctx->epg_buffers[buffer_map].ccounter>0) {
1066 			ctx->epg_buffers[buffer_map].ccounter=0;
1067 			EPG_parse_table(ctx, ctx->epg_buffers[buffer_map].buffer, ctx->epg_buffers[buffer_map].buffer_length);
1068 		}
1069 
1070 
1071 		ctx->epg_buffers[buffer_map].prev_ccounter = ccounter;
1072 
1073 		if(ctx->epg_buffers[buffer_map].buffer!=NULL)
1074 			free(ctx->epg_buffers[buffer_map].buffer);
1075 		else {
1076 			// must be first EIT packet
1077 		}
1078 		ctx->epg_buffers[buffer_map].buffer = (uint8_t *)malloc(payload_length);
1079 		memcpy(ctx->epg_buffers[buffer_map].buffer, payload_start, payload_length);
1080 		ctx->epg_buffers[buffer_map].buffer_length=payload_length;
1081 		ctx->epg_buffers[buffer_map].ccounter++;
1082 
1083 	}
1084 	else if(ccounter==ctx->epg_buffers[buffer_map].prev_ccounter+1 || (ctx->epg_buffers[buffer_map].prev_ccounter==0x0f && ccounter==0))
1085 	{
1086 		ctx->epg_buffers[buffer_map].prev_ccounter = ccounter;
1087 		ctx->epg_buffers[buffer_map].buffer = (uint8_t *)realloc(ctx->epg_buffers[buffer_map].buffer, ctx->epg_buffers[buffer_map].buffer_length+payload_length);
1088 		memcpy(ctx->epg_buffers[buffer_map].buffer+ctx->epg_buffers[buffer_map].buffer_length, payload_start, payload_length);
1089 		ctx->epg_buffers[buffer_map].ccounter++;
1090 		ctx->epg_buffers[buffer_map].buffer_length+=payload_length;
1091 	}
1092 	else
1093 	{
1094 		dbg_print (CCX_DMT_GENERIC_NOTICES, "\rWarning: Out of order EPG packets detected.\n");
1095 	}
1096 }
1097 
1098 // Free all memory used for EPG parsing
EPG_free(struct lib_ccx_ctx * ctx)1099 void EPG_free(struct lib_ccx_ctx *ctx)
1100 {
1101 	if(ctx->epg_inited)
1102 	{
1103 		if(ccx_options.xmltv==2 || ccx_options.xmltv==3 || ccx_options.send_to_srv)
1104 		{
1105 			if (ccx_options.send_to_srv)
1106 				EPG_output_net(ctx);
1107 			else
1108 				EPG_output_live(ctx);
1109 		}
1110 	}
1111 	free(ctx->epg_buffers);
1112 	free(ctx->eit_programs);
1113 	free(ctx->eit_current_events);
1114 	free(ctx->ATSC_source_pg_map);
1115 }
1116