Mercurial > mplayer.hg
comparison libmpdemux/demux_ts.c @ 9610:76c6d8f1ebf5
this is a combo patch that:
1) adds an experimental TS demuxer to mplayer
2) adds an input (streaming) interface from DVB cards.
It compiles and runs with the following versions of the drivers:
dvb-kernel (HEAD) (with stock kernel 2.4.20) and 0.9.4 (with kernel 2.4.18)
patch by Nico <nsabbi@libero.it>
some cleanups, ts demuxer fixes by me
author | arpi |
---|---|
date | Sun, 16 Mar 2003 20:13:28 +0000 |
parents | |
children | 872b8d422a05 |
comparison
equal
deleted
inserted
replaced
9609:bb8593ea37cb | 9610:76c6d8f1ebf5 |
---|---|
1 /* | |
2 * Copyright (C) 2000-2002 the xine project | |
3 * | |
4 * This file is part of xine, a free video player. | |
5 * | |
6 * xine is free software; you can redistribute it and/or modify | |
7 * it under the terms of the GNU General Public License as published by | |
8 * the Free Software Foundation; either version 2 of the License, or | |
9 * (at your option) any later version. | |
10 * | |
11 * xine is distributed in the hope that it will be useful, | |
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 * GNU General Public License for more details. | |
15 * | |
16 * You should have received a copy of the GNU General Public License | |
17 * along with this program; if not, write to the Free Software | |
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA | |
19 * | |
20 * $Id$ | |
21 * | |
22 * Demultiplexer for MPEG2 Transport Streams. | |
23 * | |
24 * For the purposes of playing video, we make some assumptions about the | |
25 * kinds of TS we have to process. The most important simplification is to | |
26 * assume that the TS contains a single program (SPTS) because this then | |
27 * allows significant simplifications to be made in processing PATs. | |
28 | |
29 | |
30 | |
31 /* | |
32 * WARNING: Quite a hack was required in order to get files by MultiDec played back correctly. | |
33 * If it breaks anything else, just comment out the "#define DEMUX_PVA_MULTIDEC_HACK" below | |
34 * and it will not be compiled in. | |
35 * | |
36 * Feedback is appreciated. | |
37 * | |
38 * written by Matteo Giani | |
39 */ | |
40 | |
41 | |
42 /* | |
43 * MPEG2 transport stream (aka DVB) demux | |
44 * Copyright (c) 2002 Fabrice Bellard. | |
45 * | |
46 * This library is free software; you can redistribute it and/or | |
47 * modify it under the terms of the GNU Lesser General Public | |
48 * License as published by the Free Software Foundation; either | |
49 * version 2 of the License, or (at your option) any later version. | |
50 * | |
51 * This library is distributed in the hope that it will be useful, | |
52 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
53 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
54 * Lesser General Public License for more details. | |
55 * | |
56 * You should have received a copy of the GNU Lesser General Public | |
57 * License along with this library; if not, write to the Free Software | |
58 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
59 */ | |
60 | |
61 | |
62 #include <stdio.h> | |
63 #include <stdlib.h> | |
64 #include <string.h> | |
65 | |
66 #include "config.h" | |
67 #include "mp_msg.h" | |
68 #include "help_mp.h" | |
69 | |
70 #include "stream.h" | |
71 #include "demuxer.h" | |
72 #include "stheader.h" | |
73 | |
74 #include "bswap.h" | |
75 | |
76 | |
77 typedef struct { | |
78 off_t offset; | |
79 long size; | |
80 uint8_t type; | |
81 uint8_t is_packet_start; | |
82 float pts; | |
83 uint8_t packet_size; | |
84 } ts_payload_t; | |
85 | |
86 | |
87 typedef struct { | |
88 float last_audio_pts; | |
89 float last_video_pts; | |
90 uint8_t just_synced; | |
91 uint8_t synced_stream_id; | |
92 char *buffer; | |
93 int buffer_size; | |
94 int buffer_offset; | |
95 int packet_size; | |
96 } ts_priv_t; | |
97 | |
98 #define TS_FEC_PACKET_SIZE 204 | |
99 #define TS_PACKET_SIZE 188 | |
100 #define NB_PID_MAX 8192 | |
101 | |
102 #define MAX_HEADER_SIZE 6 /* enough for PES header + length */ | |
103 #define MAX_PROBE_SIZE 1000000 | |
104 #define NUM_CONSECUTIVE_TS_PACKETS 5 | |
105 | |
106 | |
107 enum MpegTSState { | |
108 MPEGTS_HEADER = 0, | |
109 MPEGTS_PESHEADER_FILL, | |
110 MPEGTS_PESHEADER_FLAGS, | |
111 MPEGTS_PESHEADER_SIZE, | |
112 MPEGTS_PESHEADER_READ, | |
113 MPEGTS_PAYLOAD, | |
114 MPEGTS_SKIP, | |
115 }; | |
116 | |
117 | |
118 int ts_fastparse = 0; | |
119 | |
120 typedef enum | |
121 { | |
122 UNKNOWN = -1, | |
123 VIDEO_MPEG2 = 0x10000002, | |
124 AUDIO_MP2 = 0x50, | |
125 AUDIO_A52 = 0x2000, | |
126 AUDIO_LPCM_BE = 0x2000000, | |
127 SPU_DVD = 0x3000000, | |
128 SPU_DVB = 0x3000001, | |
129 } es_stream_type_t; | |
130 | |
131 typedef struct MpegTSStream // IT'S AN ES | |
132 { | |
133 int pid; | |
134 enum MpegTSState state; | |
135 int last_cc; /* last cc code (-1 if first packet) */ | |
136 /* used to get the format */ | |
137 int header_size; | |
138 int payload_size; | |
139 int pes_header_size; | |
140 //AVStream *st; | |
141 es_stream_type_t type; | |
142 unsigned char header[MAX_HEADER_SIZE]; | |
143 char *pes_buffer; | |
144 int offset; | |
145 float pts; | |
146 float last_pts; | |
147 } MpegTSStream; | |
148 | |
149 | |
150 typedef struct MpegTSContext { | |
151 int raw_packet_size; /* raw packet size, including FEC if present */ | |
152 MpegTSStream *pids[NB_PID_MAX]; | |
153 demuxer_t *demuxer; | |
154 } MpegTSContext; | |
155 | |
156 | |
157 typedef struct { | |
158 int size; | |
159 unsigned char *start; | |
160 es_stream_type_t type; | |
161 float pts; | |
162 int pid; | |
163 } ES_info_t; | |
164 | |
165 MpegTSContext ts; | |
166 | |
167 //FILE *outfile; | |
168 | |
169 | |
170 static uint8_t get_packet_size(const unsigned char *buf, int size) | |
171 { | |
172 int i; | |
173 | |
174 if (size < (TS_FEC_PACKET_SIZE * NUM_CONSECUTIVE_TS_PACKETS)) | |
175 return 0; | |
176 | |
177 for(i=0; i<NUM_CONSECUTIVE_TS_PACKETS; i++) | |
178 { | |
179 if (buf[i * TS_PACKET_SIZE] != 0x47) | |
180 { | |
181 mp_msg(MSGT_DEMUX, MSGL_DBG2, "GET_PACKET_SIZE, pos %d, char: %2x\n", i, buf[i * TS_PACKET_SIZE]); | |
182 goto try_fec; | |
183 } | |
184 } | |
185 return TS_PACKET_SIZE; | |
186 | |
187 try_fec: | |
188 for(i=0; i<NUM_CONSECUTIVE_TS_PACKETS; i++) | |
189 { | |
190 if (buf[i * TS_FEC_PACKET_SIZE] != 0x47) | |
191 return 0; | |
192 } | |
193 return TS_FEC_PACKET_SIZE; | |
194 } | |
195 | |
196 | |
197 | |
198 | |
199 int ts_check_file(demuxer_t * demuxer) | |
200 { | |
201 const int buf_size = (TS_FEC_PACKET_SIZE * NUM_CONSECUTIVE_TS_PACKETS); | |
202 char buf[buf_size], c, done = 0; | |
203 uint32_t _read, i=1; | |
204 uint8_t size = 0; | |
205 off_t pos = 0; | |
206 | |
207 mp_msg(MSGT_DEMUX, MSGL_V, "************Checking for TS************\n"); | |
208 | |
209 while(! done) | |
210 { | |
211 while(((c=stream_read_char(demuxer->stream)) != 0x47) | |
212 && (i < MAX_PROBE_SIZE) | |
213 && ! demuxer->stream->eof | |
214 ) i++; | |
215 | |
216 if(c != 0x47) | |
217 { | |
218 mp_msg(MSGT_DEMUX, MSGL_V, "NOT A TS FILE1\n"); | |
219 done = 1; | |
220 continue; | |
221 } | |
222 | |
223 pos = stream_tell(demuxer->stream) - 1; | |
224 buf[0] = c; | |
225 _read = stream_read(demuxer->stream, &buf[1], buf_size-1); | |
226 | |
227 if(_read < buf_size-1) | |
228 { | |
229 mp_msg(MSGT_DEMUX, MSGL_V, "COULDN'T READ ENOUGH DATA, EXITING TS_CHECK\n"); | |
230 stream_reset(demuxer->stream); | |
231 return 0; | |
232 } | |
233 | |
234 size = get_packet_size(buf, buf_size); | |
235 if(size) | |
236 done = 1; | |
237 } | |
238 | |
239 mp_msg(MSGT_DEMUX, MSGL_V, "TRIED UP TO POSITION %u, FUOND %x, packet_size= %d\n", i, c, size); | |
240 stream_seek(demuxer->stream, pos); | |
241 return size; | |
242 } | |
243 | |
244 | |
245 | |
246 | |
247 | |
248 demuxer_t *demux_open_ts(demuxer_t * demuxer) | |
249 { | |
250 uint8_t packet_size; | |
251 //demuxer_t *vd, *ad; | |
252 //stream_t *s; | |
253 sh_video_t *sh_video; | |
254 sh_audio_t *sh_audio; | |
255 ts_priv_t * priv; | |
256 int i; | |
257 | |
258 | |
259 mp_msg(MSGT_DEMUX, MSGL_V, "DEMUX OPEN, AUDIO_ID: %d, VIDEO_ID: %d, SUBTITLE_ID: %d,\n", | |
260 demuxer->audio->id, demuxer->video->id, demuxer->sub->id); | |
261 | |
262 for(i=0; i < 8192; i++) | |
263 ts.pids[i] = NULL; | |
264 | |
265 demuxer->type= DEMUXER_TYPE_MPEG_TS; | |
266 | |
267 stream_reset(demuxer->stream); | |
268 stream_seek(demuxer->stream, 0); | |
269 | |
270 packet_size = ts_check_file(demuxer); | |
271 if(!packet_size) | |
272 return NULL; | |
273 | |
274 priv = malloc(sizeof(ts_priv_t)); | |
275 priv->last_video_pts=-1; | |
276 priv->last_audio_pts=-1; | |
277 priv->packet_size = packet_size; | |
278 demuxer->priv = priv; | |
279 | |
280 if(demuxer->stream->type != STREAMTYPE_FILE) demuxer->seekable=0; | |
281 else demuxer->seekable = 1; | |
282 | |
283 | |
284 sh_video = new_sh_video(demuxer, 0); | |
285 sh_video->ds = demuxer->video; | |
286 demuxer->video->sh = sh_video; | |
287 | |
288 | |
289 | |
290 sh_audio = new_sh_audio(demuxer, 0); | |
291 sh_audio->ds = demuxer->audio; | |
292 demuxer->audio->sh = sh_audio; | |
293 | |
294 | |
295 mp_msg(MSGT_DEMUXER,MSGL_INFO, "Opened TS demuxer..."); | |
296 | |
297 if(! ts_fastparse) | |
298 ts_detect_streams(demuxer); | |
299 | |
300 | |
301 /* | |
302 demuxer->movi_start = 0; | |
303 demuxer->movi_end = demuxer->stream->end_pos; | |
304 */ | |
305 | |
306 | |
307 /* | |
308 s= new_ds_stream(demuxer->video); | |
309 return demux_open_stream(s, DEMUXER_TYPE_MPEG_ES, demuxer->audio->id, demuxer->video->id, demuxer->sub->id, NULL); | |
310 */ | |
311 | |
312 stream_seek(demuxer->stream, 0); //IF IT'S FROM A PIPE IT WILL FAIL, BUT WHO CARES? | |
313 return demuxer; | |
314 } | |
315 | |
316 | |
317 | |
318 void ts_detect_streams(demuxer_t *demuxer) | |
319 { | |
320 int video_found = 0, audio_found = 0; | |
321 off_t pos=0; | |
322 ES_info_t es; | |
323 int *apid, *vpid, *spid; | |
324 unsigned char tmp[TS_FEC_PACKET_SIZE]; | |
325 sh_video_t *sh_video = demuxer->video->sh; | |
326 sh_audio_t *sh_audio = demuxer->audio->sh; | |
327 | |
328 apid = &(demuxer->audio->id); | |
329 vpid = &(demuxer->video->id); | |
330 spid = &(demuxer->sub->id); | |
331 | |
332 | |
333 mp_msg(MSGT_DEMUXER, MSGL_INFO, "PROBING UP TO %u\n", MAX_PROBE_SIZE); | |
334 while(pos <= MAX_PROBE_SIZE) | |
335 { | |
336 if(ts_parse(demuxer, &es, tmp)) | |
337 { | |
338 mp_msg(MSGT_DEMUXER, MSGL_V, "TYPE: %x, PID: %d\n", es.type, es.pid); | |
339 if(es.type == VIDEO_MPEG2) | |
340 { | |
341 sh_video->format = VIDEO_MPEG2; //MPEG2 video | |
342 if(*vpid == -1) | |
343 *vpid = es.pid; | |
344 video_found = 1; | |
345 } | |
346 | |
347 if(es.type == AUDIO_MP2) | |
348 { | |
349 sh_audio->format = AUDIO_MP2; //MPEG1L2 audio | |
350 if(*apid == -1) | |
351 *apid = es.pid; | |
352 audio_found = 1; | |
353 } | |
354 | |
355 if(es.type == AUDIO_A52) | |
356 { | |
357 sh_audio->format = AUDIO_MP2; //MPEG1L2 audio | |
358 if(*apid == -1) | |
359 *apid = es.pid; | |
360 audio_found = 1; | |
361 } | |
362 | |
363 pos = stream_tell(demuxer->stream); | |
364 if(video_found && audio_found) | |
365 break; | |
366 } | |
367 } | |
368 | |
369 if(video_found) | |
370 mp_msg(MSGT_DEMUXER, MSGL_INFO, "VIDEO MPEG2..."); | |
371 else | |
372 { | |
373 *vpid = -2; //WE DIDN'T MATCH ANY VIDEO STREAM, SO WE FORCE THE DEMUXER TO IGNORE VIDEO | |
374 mp_msg(MSGT_DEMUXER, MSGL_INFO, "NO VIDEO!\n"); | |
375 } | |
376 | |
377 if(sh_audio->format == AUDIO_MP2) | |
378 mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO MP2\n"); | |
379 else if(sh_audio->format == AUDIO_A52) | |
380 mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO A52\n"); | |
381 else | |
382 { | |
383 *apid = -2; //WE DIDN'T MATCH ANY AUDIO STREAM, SO WE FORCE THE DEMUXER TO IGNORE AUDIO | |
384 mp_msg(MSGT_DEMUXER, MSGL_INFO, "NO AUDIO!\n"); | |
385 } | |
386 } | |
387 | |
388 | |
389 void demux_close_ts(demuxer_t * demuxer) | |
390 { | |
391 if(demuxer->priv) | |
392 { | |
393 free(demuxer->priv); | |
394 demuxer->priv=NULL; | |
395 } | |
396 } | |
397 | |
398 | |
399 | |
400 | |
401 //MpegTSStream *tss, const unsigned char *buf, int buf_size, int is_start, ES_info_t *es | |
402 static int pes_parse2(MpegTSStream *tss, unsigned char *buf, uint16_t packet_len, int is_start, ES_info_t *es) | |
403 { | |
404 unsigned char *p; | |
405 uint32_t header_len; | |
406 int64_t pts; | |
407 uint32_t stream_id; | |
408 uint32_t pkt_len; | |
409 | |
410 mp_msg(MSGT_DEMUX, MSGL_DBG2, "pes_parse2(%X, %X, %d, %d, ): \n", tss, buf, packet_len, is_start); | |
411 | |
412 if(packet_len == 0) | |
413 { | |
414 mp_msg(MSGT_DEMUX, MSGL_DBG2, "pes_parse2(,PACKET_LEN = 0, EXIT\n"); | |
415 return 0; | |
416 } | |
417 | |
418 if(packet_len > 184) | |
419 { | |
420 mp_msg(MSGT_DEMUX, MSGL_DBG2, "pes_parse2, BUFFER LEN IS TOO BIG: %d, EXIT\n", packet_len); | |
421 return 0; | |
422 } | |
423 | |
424 | |
425 p = buf; | |
426 pkt_len = packet_len; | |
427 | |
428 if(! is_start) | |
429 { | |
430 tss->pts = tss->last_pts; | |
431 es->start = p; | |
432 es->size = packet_len; | |
433 return es->size; | |
434 } | |
435 | |
436 /* we should have a PES packet here */ | |
437 | |
438 if (p[0] || p[1] || (p[2] != 1)) | |
439 { | |
440 mp_msg(MSGT_DEMUX, MSGL_DBG2, "pes_parse2: error HEADER %02x %02x %02x (should be 0x000001) \n", p[0], p[1], p[2]); | |
441 return 0 ; | |
442 } | |
443 | |
444 packet_len -= 6; | |
445 | |
446 tss->payload_size = p[4] << 8 | p[5]; | |
447 if (tss->payload_size == 0) | |
448 tss->payload_size = 65536; | |
449 | |
450 stream_id = p[3]; | |
451 | |
452 if(packet_len==0) | |
453 return 0; | |
454 | |
455 //mp_msg(MSGT_DEMUX, MSGL_V, "pes_parse2: packet stream id: %.2X (%d) len: %d (%x)\n", stream_id, stream_id, packet_len, packet_len); | |
456 | |
457 if (p[7] & 0x80) | |
458 { /* pts avail */ | |
459 pts = (int64_t)(p[9] & 0x0E) << 29 ; | |
460 pts |= p[10] << 22 ; | |
461 pts |= (p[11] & 0xFE) << 14 ; | |
462 pts |= p[12] << 7 ; | |
463 pts |= (p[13] & 0xFE) >> 1 ; | |
464 | |
465 tss->pts = tss->last_pts = pts / 90000.0f; | |
466 } | |
467 else | |
468 tss->pts = tss->last_pts; | |
469 | |
470 header_len = p[8]; | |
471 | |
472 /* sometimes corruption on header_len causes segfault in memcpy below */ | |
473 if (header_len + 9 > pkt_len) | |
474 { | |
475 mp_msg(MSGT_DEMUX, MSGL_DBG2, "demux_ts: illegal value for PES_header_data_length (0x%02x)\n", header_len); | |
476 return 0; | |
477 } | |
478 | |
479 p += header_len + 9; | |
480 packet_len -= header_len + 3; | |
481 | |
482 if (stream_id == 0xbd) | |
483 { | |
484 int track, spu_id; | |
485 | |
486 mp_msg(MSGT_DEMUX, MSGL_DBG2, "pes_parse2: audio buf = %02X %02X %02X %02X %02X %02X %02X %02X\n", | |
487 p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); | |
488 | |
489 track = p[0] & 0x0F; /* hack : ac3 track */ | |
490 /* | |
491 * we check the descriptor tag first because some stations | |
492 * do not include any of the ac3 header info in their audio tracks | |
493 * these "raw" streams may begin with a byte that looks like a stream type. | |
494 */ | |
495 if( //(m->descriptor_tag == 0x81) || /* ac3 - raw */ | |
496 (p[0] == 0x0B && p[1] == 0x77)) /* ac3 - syncword */ | |
497 { | |
498 es->start = p; | |
499 es->size = packet_len; | |
500 tss->type = AUDIO_A52; | |
501 return es->size; | |
502 } | |
503 else if (//m->descriptor_tag == 0x06 && | |
504 p[0] == 0x20 && p[1] == 0x00) | |
505 { | |
506 /* DVBSUB */ | |
507 long payload_len = ((buf[4] << 8) | buf[5]) - header_len - 3; | |
508 es->start = p; | |
509 es->size = packet_len; | |
510 tss->type = SPU_DVB + payload_len; | |
511 | |
512 return es->size; | |
513 } | |
514 else if ((p[0] & 0xE0) == 0x20) | |
515 { | |
516 spu_id = (p[0] & 0x1f); | |
517 es->start = p+1; | |
518 es->size = packet_len-1; | |
519 tss->type = SPU_DVD + spu_id; | |
520 return es->size; | |
521 } | |
522 else if ((p[0] & 0xF0) == 0x80) | |
523 { | |
524 es->start = p+4; | |
525 es->size = packet_len - 4; | |
526 tss->type = AUDIO_A52; // + track; | |
527 return es->size; | |
528 } | |
529 else if ((p[0]&0xf0) == 0xa0) | |
530 { | |
531 int pcm_offset; | |
532 | |
533 for (pcm_offset=0; ++pcm_offset < packet_len-1 ; ) | |
534 { | |
535 if (p[pcm_offset] == 0x01 && p[pcm_offset+1] == 0x80) | |
536 { /* START */ | |
537 pcm_offset += 2; | |
538 break; | |
539 } | |
540 } | |
541 | |
542 es->start = p + pcm_offset; | |
543 es->size = packet_len - pcm_offset; | |
544 tss->type = AUDIO_LPCM_BE; // + track; | |
545 return es->size; | |
546 } | |
547 } | |
548 else if ((stream_id >= 0xbc) && ((stream_id & 0xf0) == 0xe0)) | |
549 { | |
550 es->start = p; | |
551 es->size = packet_len; | |
552 tss->type = VIDEO_MPEG2; | |
553 return es->size; | |
554 } | |
555 else if ((stream_id & 0xe0) == 0xc0) | |
556 { | |
557 int track; | |
558 track = stream_id & 0x1f; | |
559 es->start = p; | |
560 es->size = packet_len; | |
561 tss->type = AUDIO_MP2; // + track; | |
562 return es->size; | |
563 } | |
564 else | |
565 { | |
566 mp_msg(MSGT_DEMUX, MSGL_DBG2, "pes_parse2: unknown packet, id: %x\n", stream_id); | |
567 } | |
568 | |
569 return 0; | |
570 } | |
571 | |
572 | |
573 | |
574 | |
575 int ts_sync(demuxer_t *demuxer) | |
576 { | |
577 uint8_t c=0; | |
578 | |
579 mp_msg(MSGT_DEMUX, MSGL_DBG2, "TS_SYNC \n"); | |
580 | |
581 while(((c=stream_read_char(demuxer->stream)) != 0x47) && ! demuxer->stream->eof); | |
582 | |
583 if(c == 0x47) | |
584 return c; | |
585 else | |
586 return 0; | |
587 } | |
588 | |
589 | |
590 | |
591 | |
592 | |
593 | |
594 // 0 = EOF or no stream found | |
595 // 1 = successfully read a packet | |
596 int ts_parse(demuxer_t * demuxer , ES_info_t *es, unsigned char *packet) | |
597 { | |
598 MpegTSStream *tss; | |
599 uint8_t done = 0; | |
600 ts_priv_t *priv = demuxer->priv; | |
601 uint16_t buf_size, is_start; | |
602 int len, pid, cc, cc_ok, afc; | |
603 unsigned char *p; | |
604 | |
605 while(! done) | |
606 { | |
607 if(! ts_sync(demuxer)) | |
608 { | |
609 mp_msg(MSGT_DEMUX, MSGL_V, "TS_FILL_BUFFER: COULDN'T SYNC\n"); | |
610 return 0; | |
611 } | |
612 | |
613 len = stream_read(demuxer->stream, &packet[1], priv->packet_size-1); | |
614 if (len != priv->packet_size-1) | |
615 return 0; | |
616 | |
617 | |
618 | |
619 pid = ((packet[1] & 0x1f) << 8) | packet[2]; | |
620 tss = ts.pids[pid]; //an ES stream | |
621 if(tss == NULL) | |
622 { | |
623 /* if no pid found, then add a pid context */ | |
624 tss = malloc(sizeof(MpegTSStream)); | |
625 if (!tss) | |
626 continue; | |
627 memset(tss, 0, sizeof(MpegTSStream)); | |
628 ts.pids[pid] = tss; | |
629 tss->pid = pid; | |
630 tss->last_cc = -1; | |
631 tss->type = UNKNOWN; | |
632 mp_msg(MSGT_DEMUX, MSGL_DBG2, "new TS pid=%u\n", pid); | |
633 } | |
634 | |
635 cc = (packet[3] & 0xf); | |
636 cc_ok = (tss->last_cc < 0) || ((((tss->last_cc + 1) & 0x0f) == cc)); | |
637 if(! cc_ok) | |
638 { | |
639 mp_msg(MSGT_DEMUX, MSGL_V, "ts_parse: CCCheck NOT OK: %d -> %d\n", tss->last_cc, cc); | |
640 } | |
641 tss->last_cc = cc; | |
642 | |
643 | |
644 | |
645 /* skip adaptation field */ | |
646 afc = (packet[3] >> 4) & 3; | |
647 p = packet + 4; | |
648 if (afc == 0) /* reserved value */ | |
649 continue; | |
650 if (afc == 2) /* adaptation field only */ | |
651 continue; | |
652 if (afc == 3) | |
653 { | |
654 /* skip adapation field */ | |
655 p += p[0] + 1; | |
656 } | |
657 /* if past the end of packet, ignore */ | |
658 if (p >= packet + TS_PACKET_SIZE) | |
659 continue; | |
660 | |
661 // PES CONTENT STARTS HERE | |
662 | |
663 buf_size = TS_PACKET_SIZE - (p - packet); | |
664 | |
665 is_start = packet[1] & 0x40; | |
666 if((len = pes_parse2(tss, p, buf_size, is_start, es))) | |
667 { | |
668 tss->offset += es->size; | |
669 es->pid = tss->pid; | |
670 es->pts = tss->pts; | |
671 es->type = tss->type; | |
672 | |
673 mp_msg(MSGT_DEMUX, MSGL_DBG2, "ts_parse, type=%X, start=%X, len=%d\n", tss->type, es->start, es->size); | |
674 | |
675 return len; | |
676 } | |
677 } | |
678 | |
679 return 0; | |
680 } | |
681 | |
682 | |
683 int demux_ts_fill_buffer(demuxer_t * demuxer) | |
684 { | |
685 ES_info_t es; | |
686 demux_packet_t *dp; | |
687 int len; | |
688 unsigned char packet[TS_FEC_PACKET_SIZE]; | |
689 int *apid, *vpid, *spid; | |
690 | |
691 apid = &(demuxer->audio->id); | |
692 vpid = &(demuxer->video->id); | |
693 spid = &(demuxer->sub->id); | |
694 | |
695 while(len = ts_parse(demuxer, &es, packet)) | |
696 { | |
697 mp_msg(MSGT_DEMUX, MSGL_V, "NEW_FILL_BUFFER, NEW_ADD_PACKET(%x, %d) type: %x, PTS: %f\n", es.start, es.size, es.type, es.pts); | |
698 | |
699 if(es.type == VIDEO_MPEG2) | |
700 { | |
701 if(ts_fastparse) | |
702 { | |
703 if(*vpid == -2) | |
704 continue; | |
705 | |
706 if(*vpid == -1) | |
707 *vpid = es.pid; | |
708 } | |
709 | |
710 if(*vpid != es.pid) | |
711 continue; | |
712 | |
713 dp = new_demux_packet(es.size); | |
714 if(! dp || ! dp->buffer) | |
715 { | |
716 fprintf(stderr, "fill_buffer, NEW_ADD_PACKET(%d) FAILED\n", es.size); | |
717 continue; | |
718 } | |
719 memcpy(dp->buffer, es.start, es.size); | |
720 dp->pts = es.pts; | |
721 dp->flags = 0; | |
722 dp->pos = stream_tell(demuxer->stream); | |
723 ds_add_packet(demuxer->video, dp); | |
724 mp_msg(MSGT_DEMUX, MSGL_V, "VIDEO pts=%f\n", es.pts); | |
725 return len; | |
726 } | |
727 | |
728 if((es.type == AUDIO_MP2) || (es.type == AUDIO_A52)) | |
729 { | |
730 if(ts_fastparse) | |
731 { | |
732 if(*apid == -2) | |
733 continue; | |
734 | |
735 if(*apid == -1) | |
736 *apid = es.pid; | |
737 } | |
738 | |
739 if(*apid != es.pid) | |
740 continue; | |
741 | |
742 dp = new_demux_packet(es.size); | |
743 if(! dp || ! dp->buffer) | |
744 { | |
745 fprintf(stderr, "fill_buffer, NEW_ADD_PACKET(%d) FAILED\n", es.size); | |
746 continue; | |
747 } | |
748 memcpy(dp->buffer, es.start, es.size); | |
749 dp->flags = 0; | |
750 dp->pts = es.pts; | |
751 dp->pos = stream_tell(demuxer->stream); | |
752 ds_add_packet(demuxer->audio, dp); | |
753 mp_msg(MSGT_DEMUX, MSGL_V, "AUDIO pts=%f\r\n", es.pts); | |
754 return len; | |
755 } | |
756 | |
757 mp_msg(MSGT_DEMUX, MSGL_V, "SKIP--------\n"); | |
758 } | |
759 } | |
760 | |
761 | |
762 | |
763 | |
764 int stringent_ts_sync(demuxer_t *demuxer) | |
765 { | |
766 ts_priv_t *priv = demuxer->priv; | |
767 uint8_t c = 0, done = 0, i, buf[TS_FEC_PACKET_SIZE * NUM_CONSECUTIVE_TS_PACKETS]; | |
768 off_t pos; | |
769 | |
770 mp_msg(MSGT_DEMUX, MSGL_DBG2, "STRINGENT_TS_SYNC packet_size: %d\n", priv->packet_size); | |
771 | |
772 | |
773 if(! demuxer->seekable) | |
774 return 0; | |
775 | |
776 | |
777 while(! done) | |
778 { | |
779 while(((c=stream_read_char(demuxer->stream)) != 0x47) && !demuxer->stream->eof); | |
780 | |
781 if(c != 0x47) | |
782 { | |
783 stream_reset(demuxer->stream); | |
784 return 0; | |
785 } | |
786 | |
787 pos = stream_tell(demuxer->stream); | |
788 if(pos < 1) | |
789 pos = 1; | |
790 mp_msg(MSGT_DEMUX, MSGL_DBG2, "dopo il while, pos=%u\n", pos); | |
791 | |
792 done = 1; | |
793 buf[0] = c; | |
794 stream_read(demuxer->stream, &buf[1], (priv->packet_size * NUM_CONSECUTIVE_TS_PACKETS) - 1); | |
795 for(i = 0; i < 5; i++) | |
796 { | |
797 if (buf[i * priv->packet_size] != 0x47) | |
798 done = 0; | |
799 mp_msg(MSGT_DEMUX, MSGL_DBG2, "i: %d, char: %x\n", i, buf[i * priv->packet_size]); | |
800 } | |
801 | |
802 if(done) | |
803 stream_seek(demuxer->stream, pos); | |
804 else | |
805 stream_seek(demuxer->stream, pos); | |
806 } | |
807 //stream_seek(demuxer->stream, pos+1); | |
808 mp_msg(MSGT_DEMUX, MSGL_DBG2, "STRINGENT_TS_SYNC, STREAM_POS: %lu\n", stream_tell(demuxer->stream)); | |
809 return 0x47; | |
810 } | |
811 | |
812 | |
813 extern void resync_audio_stream(sh_audio_t *); | |
814 | |
815 | |
816 int demux_seek_ts(demuxer_t * demuxer, float rel_seek_secs, int flags) | |
817 { | |
818 int total_bitrate=0; | |
819 off_t dest_offset; | |
820 ts_priv_t * priv = demuxer->priv; | |
821 int a_bps, v_bps; | |
822 demux_stream_t *d_audio=demuxer->audio; | |
823 demux_stream_t *d_video=demuxer->video; | |
824 sh_audio_t *sh_audio=d_audio->sh; | |
825 sh_video_t *sh_video=d_video->sh; | |
826 | |
827 | |
828 /* | |
829 * Compute absolute offset inside the stream. Approximate total bitrate with sum of bitrates | |
830 * reported by the audio and video codecs. The seek is not accurate because, just like | |
831 * with MPEG streams, the bitrate is not constant. Moreover, we do not take into account | |
832 * the overhead caused by PVA and PES headers. | |
833 * If the calculated absolute offset is negative, seek to the beginning of the file. | |
834 */ | |
835 | |
836 | |
837 if(demuxer->audio->id != -2) | |
838 { | |
839 a_bps = ((sh_audio_t *)demuxer->audio->sh)->i_bps; | |
840 total_bitrate += a_bps; | |
841 } | |
842 | |
843 if(demuxer->video->id != -2) | |
844 { | |
845 v_bps = ((sh_video_t *)demuxer->video->sh)->i_bps; | |
846 total_bitrate += v_bps; | |
847 } | |
848 | |
849 if(! total_bitrate) | |
850 { | |
851 mp_msg(MSGT_DEMUX, MSGL_V, "SEEK_TS, couldn't determine bitrate, no seek\n"); | |
852 return 0; | |
853 } | |
854 | |
855 dest_offset = stream_tell(demuxer->stream) + rel_seek_secs*total_bitrate; | |
856 if(dest_offset < 0) dest_offset = 0; | |
857 | |
858 mp_msg(MSGT_DEMUX, MSGL_V, "SEEK TO: %f, BITRATE: %lu, FINAL_POS: %u \n", rel_seek_secs, total_bitrate, dest_offset); | |
859 | |
860 stream_seek(demuxer->stream, dest_offset); | |
861 | |
862 /*if(!ts_sync(demuxer)) | |
863 { | |
864 mp_msg(MSGT_DEMUX, MSGL_V, "demux_ts: Couldn't seek!\n"); | |
865 return 0; | |
866 } | |
867 */ | |
868 | |
869 ds_fill_buffer(d_video); | |
870 if(sh_audio) | |
871 { | |
872 ds_fill_buffer(d_audio); | |
873 resync_audio_stream(sh_audio); | |
874 } | |
875 | |
876 | |
877 /* | |
878 * Reset the PTS info inside the ts_priv_t structure. This way we don't deliver | |
879 * data with the wrong PTSs (the ones we had before seeking). | |
880 * | |
881 */ | |
882 | |
883 | |
884 priv->last_video_pts=-1; | |
885 priv->last_audio_pts=-1; | |
886 | |
887 return 1; | |
888 } | |
889 | |
890 | |
891 | |
892 | |
893 | |
894 static int mpegts_read_close(MpegTSContext *ts) | |
895 { | |
896 int i; | |
897 for(i=0;i<NB_PID_MAX;i++) | |
898 free(ts->pids[i]); | |
899 return 0; | |
900 } | |
901 | |
902 | |
903 |