1 #include "ccx_demuxer.h"
2 #include "activity.h"
3 #include "lib_ccx.h"
4 #include "utility.h"
5 #include "ffmpeg_intgr.h"
6 
ccx_demuxer_reset(struct ccx_demuxer * ctx)7 static void ccx_demuxer_reset(struct ccx_demuxer *ctx)
8 {
9 	ctx->startbytes_pos=0;
10 	ctx->startbytes_avail=0;
11 	ctx->num_of_PIDs = 0;
12 	memset(ctx->have_PIDs, -1, (MAX_PSI_PID + 1) * sizeof(int));
13 	memset (ctx->PIDs_seen, 0, 65536*sizeof (int));
14 	memset(ctx->min_pts, UINT64_MAX, (MAX_PSI_PID + 1) * sizeof(uint64_t));
15 	memset(ctx->stream_id_of_each_pid, 0, (MAX_PSI_PID + 1) * sizeof(uint8_t));
16 	memset (ctx->PIDs_programs, 0, 65536*sizeof (struct PMT_entry *));
17 }
18 
ccx_demuxer_close(struct ccx_demuxer * ctx)19 static void ccx_demuxer_close(struct ccx_demuxer *ctx)
20 {
21 	ctx->past = 0;
22 	if (ctx->infd!=-1 && ccx_options.input_source==CCX_DS_FILE)
23 	{
24 		close (ctx->infd);
25 		ctx->infd=-1;
26 		activity_input_file_closed();
27 	}
28 }
29 
ccx_demuxer_isopen(struct ccx_demuxer * ctx)30 static int ccx_demuxer_isopen(struct ccx_demuxer *ctx)
31 {
32 	return ctx->infd != -1;
33 }
ccx_demuxer_open(struct ccx_demuxer * ctx,const char * file)34 static int ccx_demuxer_open(struct ccx_demuxer *ctx, const char *file)
35 {
36 	ctx->past = 0;
37 	ctx->min_global_timestamp = 0;
38 	ctx->global_timestamp_inited = 0;
39 	ctx->last_global_timestamp = 0;
40 	ctx->offset_global_timestamp = 0;
41 
42 #ifdef ENABLE_FFMPEG
43 	ctx->ffmpeg_ctx =  init_ffmpeg(file);
44 	if(ctx->ffmpeg_ctx)
45 	{
46 		ctx->stream_mode = CCX_SM_FFMPEG;
47 		ctx->auto_stream = CCX_SM_FFMPEG;
48 		return 0;
49 	}
50 	else
51 	{
52 		mprint ("\rFailed to initialized ffmpeg falling back to legacy\n");
53 	}
54 #endif
55 	init_file_buffer(ctx);
56 	if (ccx_options.input_source==CCX_DS_STDIN)
57 	{
58 		if (ctx->infd != -1) // Means we had already processed stdin. So we're done.
59 		{
60 			if (ccx_options.print_file_reports)
61 				print_file_report(ctx->parent);
62 			return -1;
63 		}
64 		ctx->infd = 0;
65 		mprint ("\n\r-----------------------------------------------------------------\n");
66 		mprint ("\rReading from standard input\n");
67 	}
68 	else if (ccx_options.input_source == CCX_DS_NETWORK)
69 	{
70 		if (ctx->infd != -1) // Means we have already bound a socket.
71 		{
72 			if (ccx_options.print_file_reports)
73 				print_file_report(ctx->parent);
74 
75 			return -1;
76 		}
77 
78 		ctx->infd = start_upd_srv(ccx_options.udpaddr, ccx_options.udpport);
79 		if(ctx->infd < 0)
80 		{
81 			print_error(ccx_options.gui_mode_reports,"socket() failed.");
82 			return CCX_COMMON_EXIT_BUG_BUG;
83 		}
84 
85 	}
86 
87 	else if (ccx_options.input_source == CCX_DS_TCP)
88 	{
89 		if (ctx->infd != -1)
90 		{
91 			if (ccx_options.print_file_reports)
92 				print_file_report(ctx->parent);
93 
94 			return -1;
95 		}
96 
97 		ctx->infd = start_tcp_srv(ccx_options.tcpport, ccx_options.tcp_password);
98 	}
99 	else
100 	{
101 #ifdef _WIN32
102 		ctx->infd = OPEN (file, O_RDONLY | O_BINARY);
103 #else
104 		ctx->infd = OPEN (file, O_RDONLY);
105 #endif
106 		if (ctx->infd < 0)
107 			return -1;
108 	}
109 
110 	if (ctx->auto_stream == CCX_SM_AUTODETECT)
111 	{
112 		detect_stream_type(ctx);
113 		switch (ctx->stream_mode)
114 		{
115 			case CCX_SM_ELEMENTARY_OR_NOT_FOUND:
116 				mprint ("\rFile seems to be an elementary stream, enabling ES mode\n");
117 				break;
118 			case CCX_SM_TRANSPORT:
119 				mprint ("\rFile seems to be a transport stream, enabling TS mode\n");
120 				break;
121 			case CCX_SM_PROGRAM:
122 				mprint ("\rFile seems to be a program stream, enabling PS mode\n");
123 				break;
124 			case CCX_SM_ASF:
125 				mprint ("\rFile seems to be an ASF, enabling DVR-MS mode\n");
126 				break;
127 			case CCX_SM_WTV:
128 				mprint ("\rFile seems to be a WTV, enabling WTV mode\n");
129 				break;
130 			case CCX_SM_MCPOODLESRAW:
131 				mprint ("\rFile seems to be McPoodle raw data\n");
132 				break;
133 			case CCX_SM_RCWT:
134 				mprint ("\rFile seems to be a raw caption with time data\n");
135 				break;
136 			case CCX_SM_MP4:
137 				mprint ("\rFile seems to be a MP4\n");
138 				break;
139 			case CCX_SM_GXF:
140 				mprint ("\rFile seems to be a GXF\n");
141 				break;
142 #ifdef WTV_DEBUG
143 			case CCX_SM_HEX_DUMP:
144 				mprint ("\rFile seems to be an hexadecimal dump\n");
145 				break;
146 #endif
147 			case CCX_SM_MYTH:
148 			case CCX_SM_AUTODETECT:
149 				fatal(CCX_COMMON_EXIT_BUG_BUG, "In ccx_demuxer_open: Impossible value in stream_mode. Please file a bug report in GitHub.\n");
150 				break;
151 		}
152 	}
153 	else
154 	{
155 		ctx->stream_mode = ctx->auto_stream;
156 	}
157 
158 	// The myth loop autodetect will only be used with ES or PS streams
159 	switch (ccx_options.auto_myth)
160 	{
161 		case 0:
162 			// Use whatever stream mode says
163 			break;
164 		case 1:
165 			// Force stream mode to myth
166 			ctx->stream_mode=CCX_SM_MYTH;
167 			break;
168 		case 2:
169 			// autodetect myth files, but only if it does not conflict with
170 			// the current stream mode
171 			switch (ctx->stream_mode)
172 			{
173 				case CCX_SM_ELEMENTARY_OR_NOT_FOUND:
174 				case CCX_SM_PROGRAM:
175 					if ( detect_myth(ctx) )
176 					{
177 						ctx->stream_mode=CCX_SM_MYTH;
178 					}
179 					break;
180 				default:
181 					// Keep stream_mode
182 					break;
183 			}
184 			break;
185 	}
186 
187 	return 0;
188 }
ccx_demuxer_get_file_size(struct ccx_demuxer * ctx)189 LLONG ccx_demuxer_get_file_size (struct ccx_demuxer *ctx)
190 {
191 	LLONG ret = 0;
192 	int in = ctx->infd;
193 	LLONG current=LSEEK (in, 0, SEEK_CUR);
194 	LLONG length = LSEEK (in,0,SEEK_END);
195 	if(current < 0 ||length < 0)
196 		return -1;
197 
198 	ret = LSEEK (in, current, SEEK_SET);
199 	if (ret < 0)
200 		return -1;
201 
202 	return length;
203 }
204 
ccx_demuxer_get_stream_mode(struct ccx_demuxer * ctx)205 static int ccx_demuxer_get_stream_mode(struct ccx_demuxer *ctx)
206 {
207 	return ctx->stream_mode;
208 }
209 
210 
ccx_demuxer_print_cfg(struct ccx_demuxer * ctx)211 static void ccx_demuxer_print_cfg(struct ccx_demuxer *ctx)
212 {
213 	switch (ctx->auto_stream)
214 	{
215 		case CCX_SM_ELEMENTARY_OR_NOT_FOUND:
216 			mprint ("Elementary");
217 			break;
218 		case CCX_SM_TRANSPORT:
219 			mprint ("Transport");
220 			break;
221 		case CCX_SM_PROGRAM:
222 			mprint ("Program");
223 			break;
224 		case CCX_SM_ASF:
225 			mprint ("DVR-MS");
226 			break;
227 		case CCX_SM_WTV:
228 			mprint ("Windows Television (WTV)");
229 			break;
230 		case CCX_SM_MCPOODLESRAW:
231 			mprint ("McPoodle's raw");
232 			break;
233 		case CCX_SM_AUTODETECT:
234 			mprint ("Autodetect");
235 			break;
236 		case CCX_SM_RCWT:
237 			mprint ("BIN");
238 			break;
239 		case CCX_SM_MP4:
240 			mprint ("MP4");
241 			break;
242 #ifdef WTV_DEBUG
243 		case CCX_SM_HEX_DUMP:
244 			mprint ("Hex");
245 			break;
246 #endif
247 		default:
248 			fatal(CCX_COMMON_EXIT_BUG_BUG, "BUG: Unknown stream mode.\n");
249 			break;
250 	}
251 }
ccx_demuxer_write_es(struct ccx_demuxer * ctx,unsigned char * buf,size_t len)252 int ccx_demuxer_write_es(struct ccx_demuxer *ctx, unsigned char* buf, size_t len)
253 {
254 	if (ctx->fh_out_elementarystream!=NULL)
255 		fwrite (buf, 1, len,ctx->fh_out_elementarystream);
256 	return CCX_OK;
257 }
258 
ccx_demuxer_delete(struct ccx_demuxer ** ctx)259 void ccx_demuxer_delete(struct ccx_demuxer **ctx)
260 {
261 	struct ccx_demuxer *lctx = *ctx;
262 	int i;
263 	dinit_cap(lctx);
264 	freep(&lctx->last_pat_payload);
265 	for (i = 0; i < MAX_PSI_PID; i++)
266 	{
267 		if(lctx->PID_buffers[i]!=NULL && lctx->PID_buffers[i]->buffer!=NULL)
268 		{
269 			free(lctx->PID_buffers[i]->buffer);
270 			lctx->PID_buffers[i]->buffer=NULL;
271 			lctx->PID_buffers[i]->buffer_length=0;
272 		}
273 		freep(&lctx->PID_buffers[i]);
274 	}
275 	for (i = 0; i < MAX_PID; i++)
276 	{
277 		if( lctx->PIDs_programs[i])
278 			freep(lctx->PIDs_programs + i);
279 	}
280 	if (lctx->fh_out_elementarystream != NULL)
281 		fclose (lctx->fh_out_elementarystream);
282 
283 	freep(&lctx->filebuffer);
284 	freep(ctx);
285 }
286 
init_demuxer(void * parent,struct demuxer_cfg * cfg)287 struct ccx_demuxer *init_demuxer(void *parent, struct demuxer_cfg *cfg)
288 {
289 	int i;
290 	struct ccx_demuxer *ctx = malloc(sizeof(struct ccx_demuxer));
291 	if(!ctx)
292 		return NULL;
293 
294 	ctx->infd = -1;//Set to -1 to indicate no file is open.
295 	ctx->m2ts = cfg->m2ts;
296 	ctx->auto_stream = cfg->auto_stream;
297 	ctx->stream_mode = CCX_SM_ELEMENTARY_OR_NOT_FOUND;
298 
299 	ctx->ts_autoprogram = cfg->ts_autoprogram;
300 	ctx->ts_allprogram = cfg->ts_allprogram;
301 	ctx->ts_datastreamtype = cfg->ts_datastreamtype;
302 	ctx->nb_program = 0;
303 	ctx->multi_stream_per_prog = 0;
304 
305 	if(cfg->ts_forced_program  != -1)
306 	{
307 		ctx->pinfo[ctx->nb_program].pid = CCX_UNKNOWN;
308 		ctx->pinfo[ctx->nb_program].program_number = cfg->ts_forced_program;
309 		ctx->flag_ts_forced_pn = CCX_TRUE;
310 		ctx->nb_program++;
311 	}
312 	else
313 	{
314 		ctx->flag_ts_forced_pn = CCX_FALSE;
315 	}
316 
317 	INIT_LIST_HEAD(&ctx->cinfo_tree.all_stream);
318 	INIT_LIST_HEAD(&ctx->cinfo_tree.sib_stream);
319 	INIT_LIST_HEAD(&ctx->cinfo_tree.pg_stream);
320 
321 	ctx->codec = cfg->codec;
322 
323 	ctx->flag_ts_forced_cappid = CCX_FALSE;
324 	for(i = 0; i < cfg->nb_ts_cappid; i++)
325 	{
326 		if(ctx->codec == CCX_CODEC_ANY)
327 			update_capinfo(ctx, cfg->ts_cappids[i], cfg->ts_datastreamtype, CCX_CODEC_NONE, 0, NULL);
328 		else
329 			update_capinfo(ctx, cfg->ts_cappids[i], cfg->ts_datastreamtype, ctx->codec, 0, NULL);
330 	}
331 
332 	ctx->flag_ts_forced_cappid = cfg->nb_ts_cappid ? CCX_TRUE : CCX_FALSE;
333 	ctx->nocodec = cfg->nocodec;
334 
335 	ctx->reset = ccx_demuxer_reset;
336 	ctx->close = ccx_demuxer_close;
337 	ctx->open = ccx_demuxer_open;
338 	ctx->is_open = ccx_demuxer_isopen;
339 	ctx->get_filesize = ccx_demuxer_get_file_size;
340 	ctx->get_stream_mode = ccx_demuxer_get_stream_mode;
341 	ctx->print_cfg = ccx_demuxer_print_cfg;
342 	ctx->write_es = ccx_demuxer_write_es;
343 	ctx->hauppauge_warning_shown = 0;
344 	ctx->parent = parent;
345 	ctx->last_pat_payload = NULL;
346 	ctx->last_pat_length = 0;
347 
348 	ctx->fh_out_elementarystream = NULL;
349 	ctx->warning_program_not_found_shown = CCX_FALSE;
350 	ctx->strangeheader = 0;
351 	memset(&ctx->freport, 0, sizeof(ctx->freport));
352 	if (cfg->out_elementarystream_filename != NULL)
353 	{
354 		if ((ctx->fh_out_elementarystream = fopen (cfg->out_elementarystream_filename,"wb"))==NULL)
355 		{
356 			print_error(CCX_COMMON_EXIT_FILE_CREATION_FAILED, "Unable to open clean file: %s \nDetails : %s .\n", cfg->out_elementarystream_filename,strerror(errno)); //printing specific error - Permission Denied/ Wrong Path etc..
357 			return NULL;
358 		}
359 	}
360 
361 	for(i = 0; i < MAX_PSI_PID; i++)
362 		ctx->PID_buffers[i]=NULL;
363 
364 	init_ts(ctx);
365 	ctx->filebuffer = NULL;
366 
367 	return ctx;
368 }
369 
delete_demuxer_data(struct demuxer_data * data)370 void delete_demuxer_data(struct demuxer_data *data)
371 {
372 	free(data->buffer);
373 	free(data);
374 }
375 
alloc_demuxer_data(void)376 struct demuxer_data* alloc_demuxer_data(void)
377 {
378 	struct demuxer_data* data = malloc(sizeof(struct demuxer_data));
379 
380 	if(!data)
381 	{
382 		return NULL;
383 	}
384 	data->buffer = (unsigned char *) malloc (BUFSIZE);
385 	if(!data->buffer)
386 	{
387 		free(data);
388 		return NULL;
389 	}
390 	data->len = 0;
391 	data->bufferdatatype = CCX_PES;
392 
393 	data->program_number = -1;
394 	data->stream_pid = -1;
395 	data->codec = CCX_CODEC_NONE;
396 	data->len = 0;
397 	data->pts = CCX_NOPTS;
398 	data->rollover_bits = 0;
399 	data->tb.num = 1;
400 	data->tb.den = 90000;
401 	data->next_stream = 0;
402 	data->next_program = 0;
403 	return data;
404 
405 }
406