diff options
author | Guenter Bartsch <guenter@users.sourceforge.net> | 2002-11-07 04:08:14 +0000 |
---|---|---|
committer | Guenter Bartsch <guenter@users.sourceforge.net> | 2002-11-07 04:08:14 +0000 |
commit | ef5b02600bf4a4b96e1f65000717557967df80bc (patch) | |
tree | 49692d6e6a4269ab96ec20430be159257fb543c6 | |
parent | 832d7439fe385df89d190c7f4d48fea1fd6f6fbe (diff) | |
download | xine-lib-ef5b02600bf4a4b96e1f65000717557967df80bc.tar.gz xine-lib-ef5b02600bf4a4b96e1f65000717557967df80bc.tar.bz2 |
ts demuxer compiles again
CVS patchset: 3198
CVS date: 2002/11/07 04:08:14
-rw-r--r-- | src/demuxers/Makefile.am | 9 | ||||
-rw-r--r-- | src/demuxers/demux_ts.c | 729 |
2 files changed, 300 insertions, 438 deletions
diff --git a/src/demuxers/Makefile.am b/src/demuxers/Makefile.am index 2a6f4512f..051af1d6b 100644 --- a/src/demuxers/Makefile.am +++ b/src/demuxers/Makefile.am @@ -56,7 +56,8 @@ lib_LTLIBRARIES = $(ogg_module) $(asf_module) xineplug_dmx_avi.la\ xineplug_dmx_yuv4mpeg2.la \ xineplug_dmx_real.la \ xineplug_dmx_realaudio.la \ - xineplug_dmx_eawve.la + xineplug_dmx_eawve.la \ + xineplug_dmx_mpeg_ts.la xineplug_dmx_ogg_la_SOURCES = demux_ogg.c xineplug_dmx_ogg_la_LIBADD = $(OGG_LIBS) $(VORBIS_LIBS)\ @@ -87,9 +88,9 @@ xineplug_dmx_mpeg_elem_la_LDFLAGS = -avoid-version -module @XINE_PLUGIN_MIN_SYMS #xineplug_dmx_mpeg_pes_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la #xineplug_dmx_mpeg_pes_la_LDFLAGS = -avoid-version -module @XINE_PLUGIN_MIN_SYMS@ -#xineplug_dmx_mpeg_ts_la_SOURCES = demux_ts.c -#xineplug_dmx_mpeg_ts_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la -#xineplug_dmx_mpeg_ts_la_LDFLAGS = -avoid-version -module @XINE_PLUGIN_MIN_SYMS@ +xineplug_dmx_mpeg_ts_la_SOURCES = demux_ts.c +xineplug_dmx_mpeg_ts_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la +xineplug_dmx_mpeg_ts_la_LDFLAGS = -avoid-version -module @XINE_PLUGIN_MIN_SYMS@ xineplug_dmx_qt_la_SOURCES = demux_qt.c qtpalette.h xineplug_dmx_qt_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la diff --git a/src/demuxers/demux_ts.c b/src/demuxers/demux_ts.c index 5a75617bf..1ee74bbe4 100644 --- a/src/demuxers/demux_ts.c +++ b/src/demuxers/demux_ts.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: demux_ts.c,v 1.60 2002/11/07 03:04:31 guenter Exp $ + * $Id: demux_ts.c,v 1.61 2002/11/07 04:08:14 guenter Exp $ * * Demultiplexer for MPEG2 Transport Streams. * @@ -92,27 +92,6 @@ #include "demux.h" #define VALID_MRLS "fifo,stdin,dvb,tcp" -#define VALID_ENDS "m2t,ts,trp" - -#ifdef __GNUC__ -#define LOG_MSG_STDERR(xine, message, args...) { \ - xine_log(xine, XINE_LOG_FORMAT, message, ##args); \ - fprintf(stderr, message, ##args); \ - } -#define LOG_MSG(xine, message, args...) { \ - xine_log(xine, XINE_LOG_FORMAT, message, ##args); \ - printf(message, ##args); \ - } -#else -#define LOG_MSG_STDERR(xine, ...) { \ - xine_log(xine, XINE_LOG_FORMAT, __VA_ARGS__); \ - fprintf(stderr, __VA_ARGS__); \ - } -#define LOG_MSG(xine, ...) { \ - xine_log(xine, XINE_LOG_FORMAT, __VA_ARGS__); \ - printf(__VA_ARGS__); \ - } -#endif /* #define TS_LOG @@ -174,9 +153,9 @@ typedef struct { /* * The first field must be the "base class" for the plugin! */ - demux_plugin_t plugin; + demux_plugin_t demux_plugin; - xine_t *xine; + xine_stream_t *stream; config_values_t *config; @@ -185,10 +164,6 @@ typedef struct { input_plugin_t *input; - pthread_t thread; - int thread_running; - pthread_mutex_t mutex; - int status; int blockSize; @@ -219,29 +194,39 @@ typedef struct { int ignore_scr_discont; int send_newpts; - unsigned int scrambled_pids[MAX_PIDS]; - unsigned int scrambled_npids; + unsigned int scrambled_pids[MAX_PIDS]; + unsigned int scrambled_npids; #ifdef TS_READ_STATS - uint32_t rstat[NPKT_PER_READ + 1]; + uint32_t rstat[NPKT_PER_READ + 1]; #endif -} demux_ts; +} demux_ts_t; -static void demux_ts_build_crc32_table(demux_ts *this) { +typedef struct { + + demux_class_t demux_class; + + /* class-wide, global variables here */ + + xine_t *xine; + config_values_t *config; +} demux_ts_class_t; + + +static void demux_ts_build_crc32_table(demux_ts_t*this) { uint32_t i, j, k; - for( i = 0 ; i < 256 ; i++ ) - { - k = 0; - for (j = (i << 24) | 0x800000 ; j != 0x80000000 ; j <<= 1) { - k = (k << 1) ^ (((k ^ j) & 0x80000000) ? 0x04c11db7 : 0); - } - this->crc32_table[i] = k; + for( i = 0 ; i < 256 ; i++ ) { + k = 0; + for (j = (i << 24) | 0x800000 ; j != 0x80000000 ; j <<= 1) { + k = (k << 1) ^ (((k ^ j) & 0x80000000) ? 0x04c11db7 : 0); } + this->crc32_table[i] = k; + } } -static uint32_t demux_ts_compute_crc32(demux_ts *this, uint8_t *data, +static uint32_t demux_ts_compute_crc32(demux_ts_t*this, uint8_t *data, uint32_t length, uint32_t crc32) { uint32_t i; @@ -251,11 +236,11 @@ static uint32_t demux_ts_compute_crc32(demux_ts *this, uint8_t *data, return crc32; } -static void check_newpts( demux_ts *this, int64_t pts ) -{ +static void check_newpts( demux_ts_t*this, int64_t pts ) { + if( this->send_newpts && pts ) { - xine_demux_control_newpts(this->xine, pts, 0); + xine_demux_control_newpts (this->stream, pts, 0); this->send_newpts = 0; this->ignore_scr_discont = 1; } @@ -272,7 +257,7 @@ static void check_newpts( demux_ts *this, int64_t pts ) * The PAT is assumed to contain a single program definition, though * we can cope with the stupidity of SPTSs which contain NITs. */ -static void demux_ts_parse_pat (demux_ts *this, unsigned char *original_pkt, +static void demux_ts_parse_pat (demux_ts_t*this, unsigned char *original_pkt, unsigned char *pkt, unsigned int pusi) { uint32_t table_id; uint32_t section_syntax_indicator; @@ -338,15 +323,13 @@ static void demux_ts_parse_pat (demux_ts *this, unsigned char *original_pkt, } if (pkt - original_pkt > BODY_SIZE - 1 - 3 - section_length) { - LOG_MSG (this->xine, _("demux_ts: FIXME: (unsupported )PAT spans " - "multiple TS packets\n")); + printf ("demux_ts: FIXME: (unsupported )PAT spans multiple TS packets\n"); return; } if ((section_number != 0) || (last_section_number != 0)) { - LOG_MSG (this->xine, _("demux_ts: FIXME: (unsupported) PAT consists of " - "multiple (%d) sections\n"), - last_section_number); + printf ("demux_ts: FIXME: (unsupported) PAT consists of multiple (%d) sections\n", + last_section_number); return; } @@ -354,9 +337,8 @@ static void demux_ts_parse_pat (demux_ts *this, unsigned char *original_pkt, calc_crc32 = demux_ts_compute_crc32 (this, pkt+5, section_length+3-4, 0xffffffff); if (crc32 != calc_crc32) { - LOG_MSG (this->xine, _("demux_ts: demux error! PAT with invalid CRC32: " - "packet_crc32: %.8x calc_crc32: %.8x\n"), - crc32,calc_crc32); + printf ("demux_ts: demux error! PAT with invalid CRC32: packet_crc32: %.8x calc_crc32: %.8x\n", + crc32,calc_crc32); return; } @@ -415,7 +397,7 @@ static void demux_ts_parse_pat (demux_ts *this, unsigned char *original_pkt, static int demux_ts_parse_pes_header (demux_ts_media *m, uint8_t *buf, int packet_len, - xine_t *xine) { + xine_stream_t *stream) { unsigned char *p; uint32_t header_len; @@ -431,8 +413,6 @@ static int demux_ts_parse_pes_header (demux_ts_media *m, if (p[0] || p[1] || (p[2] != 1)) { printf ("demux_ts: error %02x %02x %02x (should be 0x000001) \n", p[0], p[1], p[2]); - LOG_MSG (xine, _("demux_ts: error %02x %02x %02x (should be 0x000001)\n"), - p[0], p[1], p[2]); return 0 ; } @@ -495,9 +475,11 @@ static int demux_ts_parse_pes_header (demux_ts_media *m, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); #endif track = p[0] & 0x0F; /* hack : ac3 track */ - // we check the descriptor tag first because some stations - // do not include any of the ac3 header info in their audio tracks - // these "raw" streams may begin with a byte that looks like a stream type. + /* + * we check the descriptor tag first because some stations + * do not include any of the ac3 header info in their audio tracks + * these "raw" streams may begin with a byte that looks like a stream type. + */ if((m->descriptor_tag == 0x81) || /* ac3 - raw */ (p[0] == 0x0B && p[1] == 0x77)) { /* ac3 - syncword */ m->content = p; @@ -567,7 +549,7 @@ static int demux_ts_parse_pes_header (demux_ts_media *m, /* * buffer arriving pes data */ -static void demux_ts_buffer_pes(demux_ts *this, unsigned char *ts, +static void demux_ts_buffer_pes(demux_ts_t*this, unsigned char *ts, unsigned int mediaIndex, unsigned int pus, unsigned int cc, @@ -577,7 +559,7 @@ static void demux_ts_buffer_pes(demux_ts *this, unsigned char *ts, if (!m->fifo) { #ifdef TS_LOG - LOG_MSG(this->xine, _("fifo unavailable (%d)\n"), mediaIndex); + printf ("fifo unavailable (%d)\n", mediaIndex); #endif return; /* To avoid segfault if video out or audio out plugin not loaded */ } @@ -607,20 +589,20 @@ static void demux_ts_buffer_pes(demux_ts *this, unsigned char *ts, m->buf = NULL; /* forget about buf -- not our responsibility anymore */ } - if (!demux_ts_parse_pes_header(m, ts, len, this->xine)) { + if (!demux_ts_parse_pes_header(m, ts, len, this->stream)) { m->corrupted_pes = 1; printf("demux_ts: PID %d: corrupted pes encountered\n", m->pid); - } - else { + + } else { + check_newpts(this, m->pts); m->corrupted_pes = 0; m->buf = m->fifo->buffer_pool_alloc(m->fifo); memcpy(m->buf->mem, ts+len-m->size, m->size); m->buffered_bytes = m->size; } - } - else if (!m->corrupted_pes) { /* no pus -- PES packet continuation */ + } else if (!m->corrupted_pes) { /* no pus -- PES packet continuation */ if ((m->buffered_bytes + len) > MAX_PES_BUF_SIZE) { m->buf->content = m->buf->mem; @@ -641,7 +623,7 @@ static void demux_ts_buffer_pes(demux_ts *this, unsigned char *ts, /* * Create a buffer for a PES stream. */ -static void demux_ts_pes_new(demux_ts *this, +static void demux_ts_pes_new(demux_ts_t*this, unsigned int mediaIndex, unsigned int pid, fifo_buffer_t *fifo, @@ -669,26 +651,26 @@ static void demux_ts_pes_new(demux_ts *this, * In other words, the PMT is assumed to describe a reasonable number of * video, audio and other streams (with descriptors). */ -static void demux_ts_parse_pmt (demux_ts *this, +static void demux_ts_parse_pmt (demux_ts_t *this, unsigned char *originalPkt, unsigned char *pkt, unsigned int pusi, uint32_t program_count) { typedef enum { - ISO_11172_VIDEO = 1, // 1 - ISO_13818_VIDEO = 2, // 2 - ISO_11172_AUDIO = 3, // 3 - ISO_13818_AUDIO = 4, // 4 - ISO_13818_PRIVATE = 5, // 5 - ISO_13818_PES_PRIVATE = 6, // 6 - ISO_13522_MHEG = 7, // 7 - ISO_13818_DSMCC = 8, // 8 - ISO_13818_TYPE_A = 9, // 9 - ISO_13818_TYPE_B = 10, // a - ISO_13818_TYPE_C = 11, // b - ISO_13818_TYPE_D = 12, // c - ISO_13818_TYPE_E = 13, // d + ISO_11172_VIDEO = 1, /* 1 */ + ISO_13818_VIDEO = 2, /* 2 */ + ISO_11172_AUDIO = 3, /* 3 */ + ISO_13818_AUDIO = 4, /* 4 */ + ISO_13818_PRIVATE = 5, /* 5 */ + ISO_13818_PES_PRIVATE = 6, /* 6 */ + ISO_13522_MHEG = 7, /* 7 */ + ISO_13818_DSMCC = 8, /* 8 */ + ISO_13818_TYPE_A = 9, /* 9 */ + ISO_13818_TYPE_B = 10, /* a */ + ISO_13818_TYPE_C = 11, /* b */ + ISO_13818_TYPE_D = 12, /* c */ + ISO_13818_TYPE_E = 13, /* d */ ISO_13818_AUX = 14, PRIVATE_A52 = 0x81 } streamType; @@ -713,7 +695,7 @@ static void demux_ts_parse_pmt (demux_ts *this, /* sections start with a pointer. Skip it! */ pkt += pkt[4]; if (pkt - originalPkt > PKT_SIZE) { - LOG_MSG_STDERR (this->xine, _("demux error! PMT with invalid pointer\n")); + printf ("demux error! PMT with invalid pointer\n"); return; } @@ -817,9 +799,9 @@ static void demux_ts_parse_pmt (demux_ts *this, this->pmt[program_count], section_length+3-4, 0xffffffff); if (crc32 != calc_crc32) { - LOG_MSG (this->xine, _("demux_ts: demux error! PMT with invalid CRC32: " - "packet_crc32: %#.8x calc_crc32: %#.8x\n"), - crc32,calc_crc32); + printf ("demux_ts: demux error! PMT with invalid CRC32: " + "packet_crc32: %#.8x calc_crc32: %#.8x\n", + crc32,calc_crc32); return; } @@ -832,8 +814,8 @@ static void demux_ts_parse_pmt (demux_ts *this, stream = &this->pmt[program_count][12] + programInfoLength; codedLength = 13 + programInfoLength; if (codedLength > section_length) { - LOG_MSG_STDERR (this->xine, _("demux error! PMT with inconsistent " - "progInfo length\n")); + printf ("demux error! PMT with inconsistent " + "progInfo length\n"); return; } section_length -= codedLength; @@ -849,8 +831,8 @@ static void demux_ts_parse_pmt (demux_ts *this, streamInfoLength = ((stream[3] << 8) | stream[4]) & 0x0fff; codedLength = 5 + streamInfoLength; if (codedLength > section_length) { - LOG_MSG_STDERR (this->xine, _("demux error! PMT with inconsistent " - "streamInfo length\n")); + printf ("demux error! PMT with inconsistent " + "streamInfo length\n"); return; } @@ -951,11 +933,7 @@ static void demux_ts_parse_pmt (demux_ts *this, } } - -/* - * - */ -static int sync_correct(demux_ts *this, uint8_t *buf, int32_t npkt_read) { +static int sync_correct(demux_ts_t*this, uint8_t *buf, int32_t npkt_read) { int p = 0; int n = 0; @@ -963,7 +941,7 @@ static int sync_correct(demux_ts *this, uint8_t *buf, int32_t npkt_read) { int sync_ok = 0; int read_length; - fprintf(stderr, "demux_ts: about to resync!\n"); + printf ("demux_ts: about to resync!\n"); for (p=0; p < npkt_read; p++) { for(n=0; n < PKT_SIZE; n++) { @@ -988,22 +966,18 @@ static int sync_correct(demux_ts *this, uint8_t *buf, int32_t npkt_read) { n + p * PKT_SIZE); /* FIXME: when read_length is not as required... we now stop demuxing */ if (read_length != (n + p * PKT_SIZE)) { - fprintf(stderr, "demux_ts sync_correct: sync found, but read failed\n"); + printf ("demux_ts_tsync_correct: sync found, but read failed\n"); return 0; } - } - else { - fprintf(stderr, "demux_ts sync_correct: sync not found! Stop demuxing\n"); + } else { + printf ("demux_ts_tsync_correct: sync not found! Stop demuxing\n"); return 0; } - fprintf(stderr, "demux_ts: resync successful!\n"); + printf ("demux_ts: resync successful!\n"); return 1; } -/* - * - */ -static int sync_detect(demux_ts *this, uint8_t *buf, int32_t npkt_read) { +static int sync_detect(demux_ts_t*this, uint8_t *buf, int32_t npkt_read) { int i, sync_ok; @@ -1023,10 +997,10 @@ static int sync_detect(demux_ts *this, uint8_t *buf, int32_t npkt_read) { /* * Main synchronisation routine. */ -static unsigned char * demux_synchronise(demux_ts * this) { +static unsigned char * demux_synchronise(demux_ts_t* this) { static int32_t packet_number = 0; - // NEW: var to keep track of number of last read packets + /* NEW: var to keep track of number of last read packets */ static int32_t npkt_read = 0; static int32_t read_zero = 0; @@ -1040,8 +1014,7 @@ static unsigned char * demux_synchronise(demux_ts * this) { read_length = this->input->read(this->input, buf, PKT_SIZE * NPKT_PER_READ); if (read_length % PKT_SIZE) { - fprintf(stderr, - "demux_ts: read returned %d bytes (not a multiple of %d!)\n", + printf ("demux_ts: read returned %d bytes (not a multiple of %d!)\n", read_length, PKT_SIZE); this->status = DEMUX_FINISHED; return NULL; @@ -1051,18 +1024,19 @@ static unsigned char * demux_synchronise(demux_ts * this) { #ifdef TS_READ_STATS this->rstat[npkt_read]++; #endif - // what if npkt_read < 5 ? --> ok in sync_detect - - // NEW: stop demuxing if read returns 0 a few times... (200) + /* + * what if npkt_read < 5 ? --> ok in sync_detect + * + * NEW: stop demuxing if read returns 0 a few times... (200) + */ if (npkt_read == 0) { - // fprintf(stderr, "demux_ts: read 0 packets! (%d)\n", read_zero); + /* printf ("demux_ts: read 0 packets! (%d)\n", read_zero); */ read_zero++; - } - else read_zero = 0; + } else read_zero = 0; if (read_zero > 200) { - fprintf(stderr, "demux_ts: read 0 packets too many times!\n"); + printf ("demux_ts: read 0 packets too many times!\n"); this->status = DEMUX_FINISHED; return NULL; } @@ -1072,7 +1046,7 @@ static unsigned char * demux_synchronise(demux_ts * this) { packet_number = 0; if (!sync_detect(this, &buf[0], npkt_read)) { - fprintf(stderr, "demux_ts: sync error.\n"); + printf ("demux_ts: sync error.\n"); this->status = DEMUX_FINISHED; return NULL; } @@ -1083,9 +1057,8 @@ static unsigned char * demux_synchronise(demux_ts * this) { } -static int64_t -demux_ts_adaptation_field_parse(uint8_t *data, - uint32_t adaptation_field_length) { +static int64_t demux_ts_adaptation_field_parse(uint8_t *data, + uint32_t adaptation_field_length) { uint32_t discontinuity_indicator=0; uint32_t random_access_indicator=0; @@ -1171,7 +1144,7 @@ demux_ts_adaptation_field_parse(uint8_t *data, } /* transport stream packet layer */ -static void demux_ts_parse_packet (demux_ts *this) { +static void demux_ts_parse_packet (demux_ts_t*this) { unsigned char *originalPkt; unsigned int sync_byte; @@ -1206,25 +1179,25 @@ static void demux_ts_parse_packet (demux_ts *this) { * Discard packets that are obviously bad. */ if (sync_byte != 0x47) { - LOG_MSG_STDERR (this->xine, _("demux error! invalid ts sync byte %.2x\n"), - originalPkt[0]); + printf ("demux error! invalid ts sync byte %.2x\n", + originalPkt[0]); return; } if (transport_error_indicator) { - LOG_MSG_STDERR(this->xine, _("demux error! transport error\n")); + printf ("demux error! transport error\n"); return; } if (transport_scrambling_control) { if (this->videoPid == pid) { - fprintf(stderr, "demux_ts: selected videoPid is scrambled; skipping...\n"); + printf ("demux_ts: selected videoPid is scrambled; skipping...\n"); } for (i=0; i < this->scrambled_npids; i++) { if (this->scrambled_pids[i] == pid) return; } this->scrambled_pids[this->scrambled_npids] = pid; this->scrambled_npids++; - // LOG_MSG_STDERR(this->xine, _("demux_ts: PID %d is scrambled!\n"), pid); - fprintf(stderr, "demux_ts: PID %d is scrambled!\n", pid); + + printf ("demux_ts: PID %d is scrambled!\n", pid); return; } @@ -1234,8 +1207,8 @@ static void demux_ts_parse_packet (demux_ts *this) { uint32_t adaptation_field_length = originalPkt[4]; if (adaptation_field_length > 0) { this->PCR = demux_ts_adaptation_field_parse (originalPkt+5, - adaptation_field_length, - this); + adaptation_field_length); + if (this->PCR) { int64_t scr_diff = this->PCR - this->last_PCR; @@ -1277,9 +1250,8 @@ static void demux_ts_parse_packet (demux_ts *this) { if (data_len > PKT_SIZE) { - LOG_MSG (this->xine, - _("demux_ts: demux error! invalid payload size %d\n"), - data_len); + printf ("demux_ts: demux error! invalid payload size %d\n", + data_len); } else { @@ -1337,65 +1309,21 @@ static void demux_ts_parse_packet (demux_ts *this) { /* - * Sit in a loop eating data. + * send a piece of data down the fifos */ -static void *demux_ts_loop(void *gen_this) { - - demux_ts *this = (demux_ts *)gen_this; - int i; - - pthread_mutex_lock( &this->mutex ); - /* do-while needed to seek after demux finished */ - do { - - /* main demuxer loop */ - while(this->status == DEMUX_OK) { - - demux_ts_parse_packet(this); - /* someone may want to interrupt us */ - pthread_mutex_unlock( &this->mutex ); - /* give demux_*_stop a chance to interrupt us */ - sched_yield(); - pthread_mutex_lock( &this->mutex ); - } +static int demux_ts_send_chunk (demux_plugin_t *this_gen) { - /* wait before sending end buffers: user might want to do a new seek */ - while(this->send_end_buffers && this->video_fifo->size(this->video_fifo) && - this->status != DEMUX_OK){ - pthread_mutex_unlock( &this->mutex ); - xine_usec_sleep(100000); - pthread_mutex_lock( &this->mutex ); - } - - } while( this->status == DEMUX_OK ); + demux_ts_t*this = (demux_ts_t*)this_gen; - -#ifdef TS_LOG - printf ("demux_ts: demux loop finished (status: %d)\n", this->status); -#endif - - for (i = 0; i < MAX_PIDS; i++) { - if (this->media[i].buf != NULL) { - this->media[i].buf->free_buffer(this->media[i].buf); - this->media[i].buf = NULL; - } - } - - this->status = DEMUX_FINISHED; - if (this->send_end_buffers) { - xine_demux_control_end(this->xine, BUF_FLAG_END_STREAM); - } + demux_ts_parse_packet(this); - this->thread_running = 0; - pthread_mutex_unlock( &this->mutex ); - pthread_exit(NULL); - return NULL; + return this->status; } -static void demux_ts_close(demux_plugin_t *this_gen) { +static void demux_ts_dispose (demux_plugin_t *this_gen) { int i; - demux_ts *this = (demux_ts *)this_gen; + demux_ts_t*this = (demux_ts_t*)this_gen; for (i=0; i < MAX_PMTS; i++) { if (this->pmt[i] != NULL) free(this->pmt[i]); @@ -1407,314 +1335,202 @@ static void demux_ts_close(demux_plugin_t *this_gen) { free(this_gen); } -static char *demux_ts_get_id(void) { - return "MPEG_TS"; -} - -static char *demux_ts_get_mimetypes(void) { - return ""; -} - static int demux_ts_get_status(demux_plugin_t *this_gen) { - demux_ts *this = (demux_ts *)this_gen; + demux_ts_t*this = (demux_ts_t*)this_gen; return this->status; } -static int demux_ts_open(demux_plugin_t *this_gen, input_plugin_t *input, - int stage) { +static void demux_ts_send_headers (demux_plugin_t *this_gen) { - demux_ts *this = (demux_ts *) this_gen; - char *mrl; - char *media; - char *ending; - char *m, *valid_mrls, *valid_ends; + demux_ts_t *this = (demux_ts_t *) this_gen; - switch (stage) { - case STAGE_BY_CONTENT: { - uint8_t buf[4096]; + this->video_fifo = this->stream->video_fifo; + this->audio_fifo = this->stream->audio_fifo; - // Mauro -- Say DEMUX_CAN_HANDLE with dvb input plugin, even if - // non-seekable and non-previewable. - if (strncasecmp(input->get_identifier(input), "dvb", 4) == 0) { - this->input = input; - return DEMUX_CAN_HANDLE; - } + this->status = DEMUX_OK; - - if((input->get_capabilities(input) & INPUT_CAP_SEEKABLE) != 0) { - input->seek(input, 0, SEEK_SET); - /* why is this a restriction ??? - if(input->get_blocksize(input)) - return DEMUX_CANNOT_HANDLE; - */ - - - if(input->read(input, buf, 2069)) { - int i, j; - int tryAgain; - - for(i = 0; i < 188; i++){ - tryAgain = 0; - if( buf[i] == 0x47 ){ - for(j = 1; j <= 10; j++){ - if( buf[i + j*188] != 0x47 ){ - tryAgain = 1; - break; - } - } - if( tryAgain == 0 ) { -#ifdef TS_LOG - printf ("demux_ts: found 0x47 pattern at offset %d\n", i); -#endif - this->input = input; - return DEMUX_CAN_HANDLE; - } - } - } - } - } + /* + * send start buffers + */ - if (input->get_optional_data (input, buf, INPUT_OPTIONAL_DATA_PREVIEW)) { - if(buf[0] == 0x47) { - this->input = input; - this->blockSize = PKT_SIZE; - return DEMUX_CAN_HANDLE; - } - } + this->videoPid = INVALID_PID; + this->audioPid = INVALID_PID; - return DEMUX_CANNOT_HANDLE; - } - break; - case STAGE_BY_EXTENSION: + xine_demux_control_start (this->stream); + + this->input->seek (this->input, 0, SEEK_SET); - xine_strdupa(valid_mrls, - (this->config->register_string(this->config, - "mrl.mrls_ts", VALID_MRLS, - _("valid mrls for ts demuxer"), - NULL, 20, NULL, NULL))); - - mrl = input->get_mrl(input); - media = strstr(mrl, ":/"); + this->send_newpts = 1; + this->ignore_scr_discont = 0; + + demux_ts_build_crc32_table (this); + + this->status = DEMUX_OK ; - if (media) { - LOG_MSG_STDERR (this->xine, _("demux %u ts_open!\n"), __LINE__); - while((m = xine_strsep(&valid_mrls, ",")) != NULL) { + this->send_end_buffers = 1; + this->last_PCR = 0; + this->scrambled_npids = 0; + + /* FIXME ? */ + this->stream->stream_info[XINE_STREAM_INFO_HAS_VIDEO] = 1; + this->stream->stream_info[XINE_STREAM_INFO_HAS_AUDIO] = 1; - while(*m == ' ' || *m == '\t') m++; + xine_demux_control_headers_done (this->stream); +} - if(!strncmp(mrl, m, strlen(m))) { +static int demux_ts_seek (demux_plugin_t *this_gen, + off_t start_pos, int start_time) { - if(!strncmp((media + 3), "ts", 2)) { - break; - } - return DEMUX_CANNOT_HANDLE; + demux_ts_t *this = (demux_ts_t *) this_gen; - } - else if(strncasecmp(mrl, "file", 4)) { - return DEMUX_CANNOT_HANDLE; - } - } - } + if (this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) { - ending = strrchr(mrl, '.'); - if (ending) { -#ifdef TS_LOG - LOG_MSG(this->xine, "demux_ts_open: ending %s of %s\n", ending, mrl); -#endif + if ((!start_pos) && (start_time)) + start_pos = start_time * this->rate * 50; - xine_strdupa(valid_ends, - (this->config->register_string(this->config, - "mrl.ends_ts", VALID_ENDS, - _("valid mrls ending for ts demuxer"), - NULL, 20, NULL, NULL))); - while((m = xine_strsep(&valid_ends, ",")) != NULL) { + this->input->seek (this->input, start_pos, SEEK_SET); - while(*m == ' ' || *m == '\t') m++; + } - if(!strcasecmp((ending + 1), m)) { - break; - } - } - } - return DEMUX_CANNOT_HANDLE; + this->send_newpts = 1; + this->ignore_scr_discont = 0; + + if( !this->stream->demux_thread_running ) { + + this->status = DEMUX_OK; - case METHOD_EXPLICIT: - break; + } else { - default: - return DEMUX_CANNOT_HANDLE; - } + xine_demux_flush_engine(this->stream); - this->input = input; - this->blockSize = PKT_SIZE; - return DEMUX_CAN_HANDLE; + } + + return this->status; } -static int demux_ts_start(demux_plugin_t *this_gen, - fifo_buffer_t *video_fifo, - fifo_buffer_t *audio_fifo, - off_t start_pos, int start_time) { - - demux_ts *this = (demux_ts *)this_gen; - int err; - int status; - - pthread_mutex_lock( &this->mutex ); +static int demux_ts_get_stream_length (demux_plugin_t *this_gen) { - this->videoPid = INVALID_PID; - this->audioPid = INVALID_PID; + demux_ts_t*this = (demux_ts_t*)this_gen; - if( !this->thread_running ) { - this->video_fifo = video_fifo; - this->audio_fifo = audio_fifo; + return this->input->get_length (this->input) / (this->rate * 50); +} - /* - * send start buffer - */ - xine_demux_control_start(this->xine); - } +static demux_plugin_t *open_plugin (demux_class_t *class_gen, + xine_stream_t *stream, + input_plugin_t *input) { - if (this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) { - - if ((!start_pos) && (start_time)) - start_pos = start_time * this->rate * 50; + demux_ts_t *this; + int i; - this->input->seek (this->input, start_pos, SEEK_SET); + switch (stream->content_detection_method) { - } - this->send_newpts = 1; - this->ignore_scr_discont = 0; - - demux_ts_build_crc32_table(this); - - this->status = DEMUX_OK ; - if( !this->thread_running ) { - /* - * Now start demuxing. - */ - this->send_end_buffers = 1; - this->last_PCR = 0; - this->thread_running = 1; - this->scrambled_npids = 0; - - if ((err = pthread_create(&this->thread, NULL, demux_ts_loop, this)) != 0) { - LOG_MSG_STDERR(this->xine, - _("demux_ts: can't create new thread (%s)\n"), - strerror(err)); - abort(); - } - } - else { - xine_demux_flush_engine(this->xine); - } + case METHOD_BY_CONTENT: { + uint8_t buf[4096]; + int got_sample; + int i, j; + int try_again, ts_detected; - /* this->status is saved because we can be interrupted between - * pthread_mutex_unlock and return - */ - status = this->status; - pthread_mutex_unlock( &this->mutex ); - return status; -} + got_sample = 0; -static int demux_ts_seek (demux_plugin_t *this_gen, - off_t start_pos, int start_time) { - demux_ts *this = (demux_ts *)this_gen; + if ((input->get_capabilities(input) & INPUT_CAP_SEEKABLE) != 0) { + input->seek(input, 0, SEEK_SET); - return demux_ts_start (this_gen, this->video_fifo, this->audio_fifo, - start_pos, start_time); -} + if (input->read(input, buf, 2069)) + got_sample = 1; -static void demux_ts_stop(demux_plugin_t *this_gen) -{ - demux_ts *this = (demux_ts *)this_gen; - void *p; + } else if ((input->get_capabilities(input) & INPUT_CAP_PREVIEW) != 0) { -#ifdef TS_READ_STATS - int i, prev_zero; - uint32_t pkt_total; + input->get_optional_data (input, buf, INPUT_OPTIONAL_DATA_PREVIEW); - pkt_total = 0; - for (i=0; i<=NPKT_PER_READ; i++) { - pkt_total += this->rstat[i]; - } - prev_zero = 1; - for (i=0; i<=NPKT_PER_READ; i++) { - if (this->rstat[i]) { - fprintf(stderr, "%3d pkts --> %6.3f%% [ %d ]\n", i, - (this->rstat[i] * 100.0 / pkt_total), this->rstat[i]); - prev_zero = 0; + got_sample = 1; } - else if (prev_zero) { - } - else { - fprintf(stderr, "...\n"); - prev_zero = 1; - } - } + if (!got_sample) + return NULL; + + ts_detected = 0; + + for (i = 0; i < 188; i++) { + try_again = 0; + if (buf[i] == 0x47) { + for (j = 1; j <= 10; j++) { + if (buf[i + j*188] != 0x47) { + try_again = 1; + break; + } + } + if (try_again == 0) { +#ifdef TS_LOG + printf ("demux_ts: found 0x47 pattern at offset %d\n", i); #endif + ts_detected = 1; + } + } + } - pthread_mutex_lock( &this->mutex ); - - if (!this->thread_running) { - printf ("demux_ts: stop...ignored\n"); - pthread_mutex_unlock( &this->mutex ); - return; + if (!ts_detected) + return NULL; } + break; - this->send_end_buffers = 0; - this->status = DEMUX_FINISHED; - - pthread_mutex_unlock( &this->mutex ); - pthread_join (this->thread, &p); + case METHOD_BY_EXTENSION: { - xine_demux_flush_engine(this->xine); + char *mrl; + char *ending; - xine_demux_control_end(this->xine, BUF_FLAG_END_USER); -} + mrl = input->get_mrl (input); + + /* + * check extension + */ + + ending = strrchr (mrl, '.'); -static int demux_ts_get_stream_length (demux_plugin_t *this_gen) { + if (ending) { + if (!strncasecmp(ending, ".ts", 3) || + !strncasecmp(ending, ".m2t", 4) || + !strncasecmp(ending, ".trp", 4)) { + break; + } + } - demux_ts *this = (demux_ts *)this_gen; + /* + * accept dvb streams + */ - return this->input->get_length (this->input) / (this->rate * 50); -} + if (!strncasecmp (mrl, "dvb://", 6)) + break; + return NULL; + } -static void *init_demuxer_plugin(xine_t *xine, void *data) { + case METHOD_EXPLICIT: + break; - demux_ts *this; - int i; + default: + return NULL; + } /* - * Initialise the generic plugin. + * if we reach this point, the input has been accepted. */ - this = xine_xmalloc(sizeof(*this)); - this->config = xine->config; - this->xine = xine; - (void*) this->config->register_string(this->config, "mrl.mrls_ts", - VALID_MRLS, - _("valid mrls for ts demuxer"), - NULL, 20, NULL, NULL); - (void*) this->config->register_string(this->config, - "mrl.ends_ts", VALID_ENDS, - _("valid mrls ending for ts demuxer"), - NULL, 20, NULL, NULL); - - this->plugin.open = demux_ts_open; - this->plugin.start = demux_ts_start; - this->plugin.seek = demux_ts_seek; - this->plugin.stop = demux_ts_stop; - this->plugin.close = demux_ts_close; - this->plugin.get_status = demux_ts_get_status; - this->plugin.get_identifier = demux_ts_get_id; - this->plugin.get_stream_length = demux_ts_get_stream_length; - this->plugin.get_mimetypes = demux_ts_get_mimetypes; + this = xine_xmalloc(sizeof(*this)); + this->stream = stream; + this->input = input; + this->blockSize = PKT_SIZE; + this->demux_plugin.send_headers = demux_ts_send_headers; + this->demux_plugin.send_chunk = demux_ts_send_chunk; + this->demux_plugin.seek = demux_ts_seek; + this->demux_plugin.dispose = demux_ts_dispose; + this->demux_plugin.get_status = demux_ts_get_status; + this->demux_plugin.get_stream_length = demux_ts_get_stream_length; + this->demux_plugin.demux_class = class_gen; + /* * Initialise our specialised data. */ @@ -1740,7 +1556,6 @@ static void *init_demuxer_plugin(xine_t *xine, void *data) { this->rate = 16000; /* FIXME */ this->status = DEMUX_FINISHED; - pthread_mutex_init( &this->mutex, NULL ); #ifdef TS_READ_STATS for (i=0; i<=NPKT_PER_READ; i++) { @@ -1748,15 +1563,61 @@ static void *init_demuxer_plugin(xine_t *xine, void *data) { } #endif - return (demux_plugin_t *)this; + return &this->demux_plugin; +} + +/* + * ts demuxer class + */ + +static char *get_description (demux_class_t *this_gen) { + return "MPEG Transport Stream demuxer"; +} + +static char *get_identifier (demux_class_t *this_gen) { + return "MPEG_TS"; +} + +static char *get_extensions (demux_class_t *this_gen) { + return "ts m2t trp"; +} + +static char *get_mimetypes (demux_class_t *this_gen) { + return NULL; +} + +static void class_dispose (demux_class_t *this_gen) { + + demux_ts_class_t *this = (demux_ts_class_t *) this_gen; + + free (this); +} + +static void *init_class (xine_t *xine, void *data) { + + demux_ts_class_t *this; + + this = xine_xmalloc (sizeof (demux_ts_class_t)); + this->config = xine->config; + this->xine = xine; + + this->demux_class.open_plugin = open_plugin; + this->demux_class.get_description = get_description; + this->demux_class.get_identifier = get_identifier; + this->demux_class.get_mimetypes = get_mimetypes; + this->demux_class.get_extensions = get_extensions; + this->demux_class.dispose = class_dispose; + + return this; } + /* * exported plugin catalog entry */ plugin_info_t xine_plugin_info[] = { /* type, API, "name", version, special_info, init_function */ - { PLUGIN_DEMUX, 10, "mpeg-ts", XINE_VERSION_CODE, NULL, init_demuxer_plugin }, + { PLUGIN_DEMUX, 15, "mpeg-ts", XINE_VERSION_CODE, NULL, init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; |