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