summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/demuxers/demux.h32
-rw-r--r--src/demuxers/demux_avi.c84
-rw-r--r--src/demuxers/demux_elem.c43
-rw-r--r--src/demuxers/demux_mpeg.c57
-rw-r--r--src/demuxers/demux_mpeg_block.c379
-rw-r--r--src/demuxers/demux_mpgaudio.c29
-rw-r--r--src/demuxers/demux_pes.c96
-rw-r--r--src/demuxers/demux_ts.c1693
-rw-r--r--src/libmpeg2/decode.c6
-rw-r--r--src/xine-engine/audio_decoder.c5
-rw-r--r--src/xine-engine/buffer.h5
-rw-r--r--src/xine-engine/video_decoder.c6
-rw-r--r--src/xine-engine/xine.c196
-rw-r--r--src/xine-engine/xine_internal.h42
14 files changed, 1352 insertions, 1321 deletions
diff --git a/src/demuxers/demux.h b/src/demuxers/demux.h
index 017af8f0f..3bdcae1b1 100644
--- a/src/demuxers/demux.h
+++ b/src/demuxers/demux.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000 the xine project
+ * Copyright (C) 2000, 2001 the xine project
*
* This file is part of xine, a unix video player.
*
@@ -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.h,v 1.8 2001/07/18 21:38:16 f1rmb Exp $
+ * $Id: demux.h,v 1.9 2001/09/01 14:32:59 guenter Exp $
*/
#ifndef HAVE_DEMUX_H
@@ -35,7 +35,7 @@ extern "C" {
#include "input_plugin.h"
#endif
-#define DEMUXER_PLUGIN_IFACE_VERSION 2
+#define DEMUXER_PLUGIN_IFACE_VERSION 3
#define DEMUX_OK 0
#define DEMUX_FINISHED 1
@@ -57,8 +57,7 @@ typedef char* (*gui_get_next_mrl_cb_t) (void);
typedef void (*gui_branched_cb_t) (void);
/*
- * a demux plugin (no matter if it's staically built into xine
- * or dynamically loaded at run-time) must implement these functions
+ * a demux plugin must implement these functions
*/
typedef struct demux_plugin_s demux_plugin_t;
@@ -84,12 +83,20 @@ struct demux_plugin_s
/*
* start demux thread
- * pos : 0..65535
+ *
+ * for seekable streams, a start position can be specified
+ *
+ * start_pos : position in input source
+ * start_time : position measured in seconds from stream start
+ *
+ * if both parameters are !=0 start_pos will be used
+ * for non-seekable streams both values will be ignored
*/
void (*start) (demux_plugin_t *this, fifo_buffer_t *video_fifo,
fifo_buffer_t *audio_fifo,
- off_t pos, gui_get_next_mrl_cb_t next_mrl_cb,
+ off_t start_pos, int start_time,
+ gui_get_next_mrl_cb_t next_mrl_cb,
gui_branched_cb_t branched_cb) ;
/*
@@ -117,15 +124,18 @@ struct demux_plugin_s
char* (*get_identifier) (void);
+ /*
+ * estimate stream length in seconds
+ * may return 0 for non-seekable streams
+ */
+
+ int (*get_stream_length) (demux_plugin_t *this);
} ;
/*
- * for dynamic demux plugins:
- *
- * make sure you provide this (and only this!) function call:
+ * demuxer plugins should provide this (and only this!) function call:
*
* demux_plugin_t *init_demux_plugin (int iface_version, config_values_t *cfg);
- *
*/
#ifdef __cplusplus
diff --git a/src/demuxers/demux_avi.c b/src/demuxers/demux_avi.c
index 8e7c96044..2bdc9f64c 100644
--- a/src/demuxers/demux_avi.c
+++ b/src/demuxers/demux_avi.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_avi.c,v 1.30 2001/09/01 01:51:50 jcdutton Exp $
+ * $Id: demux_avi.c,v 1.31 2001/09/01 14:32:59 guenter Exp $
*
* demultiplexer for avi streams
*
@@ -705,7 +705,6 @@ static int demux_avi_next (demux_avi_t *this) {
buf = this->video_fifo->buffer_pool_alloc (this->video_fifo);
buf->content = buf->mem;
- buf->DTS = 0 ; /* FIXME */
audio_pts = get_audio_pts (this, this->avi->audio_posc, this->avi->audio_posb);
video_pts = get_video_pts (this, this->avi->video_posf);
@@ -723,7 +722,8 @@ static int demux_avi_next (demux_avi_t *this) {
return 0;
}
- buf->input_pos = this->input->get_current_pos(this->input);
+ buf->input_pos = 0;
+ buf->input_time = 0;
buf->type = this->avi->audio_type;
buf->decoder_info[1] = this->avi->a_rate; /* Audio Rate */
@@ -740,9 +740,12 @@ static int demux_avi_next (demux_avi_t *this) {
/* read video */
xprintf (VERBOSE|DEMUX|VAVI, "demux_avi: video \n");
- buf->PTS = video_pts;
- buf->size = AVI_read_video (this, this->avi, buf->mem, 2048, &buf->decoder_info[0]);
- buf->type = this->avi->video_type;
+ buf->PTS = video_pts;
+ buf->size = AVI_read_video (this, this->avi, buf->mem, 2048, &buf->decoder_info[0]);
+ buf->type = this->avi->video_type;
+
+ buf->input_time = video_pts / 90000;
+ buf->input_pos = this->input->get_current_pos(this->input);
if (buf->size<0) {
buf->free_buffer (buf);
@@ -849,13 +852,13 @@ static int demux_avi_get_status (demux_plugin_t *this_gen) {
static void demux_avi_start (demux_plugin_t *this_gen,
fifo_buffer_t *video_fifo,
fifo_buffer_t *audio_fifo,
- off_t pos,
+ off_t start_pos, int start_time,
gui_get_next_mrl_cb_t next_mrl_cb,
gui_branched_cb_t branched_cb)
{
buf_element_t *buf;
demux_avi_t *this = (demux_avi_t *) this_gen;
- uint32_t video_pts;
+ uint32_t video_pts = 0;
this->audio_fifo = audio_fifo;
this->video_fifo = video_fifo;
@@ -889,24 +892,39 @@ static void demux_avi_start (demux_plugin_t *this_gen,
AVI_seek_start (this->avi);
/*
- * seek
+ * seek to start pos / time
*/
/* seek video */
-
- while ( (this->avi->video_index[this->avi->video_posf].pos < pos)
- || !(this->avi->video_index[this->avi->video_posf].flags & AVIIF_KEYFRAME) ) {
- this->avi->video_posf++;
- if (this->avi->video_posf>this->avi->video_frames) {
- this->status = DEMUX_FINISHED;
- return;
+ if (start_pos) {
+ while ( (this->avi->video_index[this->avi->video_posf].pos < start_pos)
+ || !(this->avi->video_index[this->avi->video_posf].flags & AVIIF_KEYFRAME) ) {
+ this->avi->video_posf++;
+ if (this->avi->video_posf>this->avi->video_frames) {
+ this->status = DEMUX_FINISHED;
+ return;
+ }
}
- }
+
+ video_pts = get_video_pts (this, this->avi->video_posf);
+
+ } else if (start_time) {
- video_pts = get_video_pts (this, this->avi->video_posf);
+ video_pts = start_time * 90000;
+
+ while ( (get_video_pts (this, this->avi->video_posf) < video_pts)
+ || !(this->avi->video_index[this->avi->video_posf].flags & AVIIF_KEYFRAME) ) {
+ this->avi->video_posf++;
+ if (this->avi->video_posf>this->avi->video_frames) {
+ this->status = DEMUX_FINISHED;
+ return;
+ }
+ }
+ }
+ /* seek audio */
if (!this->no_audio) {
- /* seek audio */
+
while (get_audio_pts (this, this->avi->audio_posc, 0) < video_pts) {
this->avi->audio_posc++;
if (this->avi->audio_posc>this->avi->audio_chunks) {
@@ -916,6 +934,7 @@ static void demux_avi_start (demux_plugin_t *this_gen,
}
}
+
/*
* send start buffers
*/
@@ -1028,8 +1047,6 @@ static int demux_avi_open(demux_plugin_t *this_gen,
demux_avi_t *this = (demux_avi_t *) this_gen;
- printf ("avi_open...\n"); fflush (stdout);
-
switch(stage) {
case STAGE_BY_CONTENT: {
@@ -1043,13 +1060,8 @@ static int demux_avi_open(demux_plugin_t *this_gen,
this->input = input;
- printf ("avi_init...\n"); fflush (stdout);
-
this->avi = AVI_init (this);
- printf ("avi_init...done\n");
-
-
if (this->avi) {
printf ("demux_avi: %ld frames\n", this->avi->video_frames);
@@ -1100,14 +1112,25 @@ static char *demux_avi_get_id(void) {
return "AVI";
}
+static int demux_avi_get_stream_length (demux_plugin_t *this_gen) {
+
+ demux_avi_t *this = (demux_avi_t *) this_gen;
+
+ if (this->avi) {
+ return get_video_pts(this, this->avi->video_frames) / 90000 ;
+ }
+
+ return 0;
+}
+
demux_plugin_t *init_demuxer_plugin(int iface, config_values_t *config) {
demux_avi_t *this;
- if (iface != 2) {
- printf( "demux_mpeg: plugin doesn't support plugin API version %d.\n"
- "demux_mpeg: this means there's a version mismatch between xine and this "
- "demux_mpeg: demuxer plugin.\nInstalling current input plugins should help.\n",
+ if (iface != 3) {
+ printf( "demux_avi: this plugin doesn't support plugin API version %d.\n"
+ "demux_avi: this means there's a version mismatch between xine and this "
+ "demux_avi: demuxer plugin.\nInstalling current demuxer plugins should help.\n",
iface);
return NULL;
}
@@ -1122,6 +1145,7 @@ demux_plugin_t *init_demuxer_plugin(int iface, config_values_t *config) {
this->demux_plugin.close = demux_avi_close;
this->demux_plugin.get_status = demux_avi_get_status;
this->demux_plugin.get_identifier = demux_avi_get_id;
+ this->demux_plugin.get_stream_length = demux_avi_get_stream_length;
return (demux_plugin_t *) this;
}
diff --git a/src/demuxers/demux_elem.c b/src/demuxers/demux_elem.c
index 159623e9f..ddf0f4290 100644
--- a/src/demuxers/demux_elem.c
+++ b/src/demuxers/demux_elem.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_elem.c,v 1.16 2001/08/25 08:40:08 guenter Exp $
+ * $Id: demux_elem.c,v 1.17 2001/09/01 14:33:00 guenter Exp $
*
* demultiplexer for elementary mpeg streams
*
@@ -82,7 +82,6 @@ static int demux_mpeg_elem_next (demux_mpeg_elem_t *this, int preview_mode) {
else
buf->decoder_info[0] = 1;
- buf->DTS = 0;
buf->PTS = 0;
buf->input_pos = this->input->get_current_pos(this->input);
buf->type = BUF_VIDEO_MPEG;
@@ -174,11 +173,12 @@ static int demux_mpeg_elem_get_status (demux_plugin_t *this_gen) {
*
*/
static void demux_mpeg_elem_start (demux_plugin_t *this_gen,
- fifo_buffer_t *video_fifo,
- fifo_buffer_t *audio_fifo,
- off_t pos,
- gui_get_next_mrl_cb_t next_mrl_cb,
- gui_branched_cb_t branched_cb) {
+ fifo_buffer_t *video_fifo,
+ fifo_buffer_t *audio_fifo,
+ off_t start_pos, int start_time,
+ gui_get_next_mrl_cb_t next_mrl_cb,
+ gui_branched_cb_t branched_cb) {
+
demux_mpeg_elem_t *this = (demux_mpeg_elem_t *) this_gen;
buf_element_t *buf;
@@ -187,12 +187,9 @@ static void demux_mpeg_elem_start (demux_plugin_t *this_gen,
this->status = DEMUX_OK;
- if((this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) != 0) {
- xprintf (VERBOSE|DEMUX, "=>seek to %Ld\n",pos);
- this->input->seek (this->input, pos, SEEK_SET);
- }
-
- this->blocksize = 2048;
+ this->blocksize = this->input->get_blocksize(this->input);
+ if (!this->blocksize)
+ this->blocksize = 2048;
buf = this->video_fifo->buffer_pool_alloc (this->video_fifo);
buf->type = BUF_CONTROL_START;
@@ -215,8 +212,10 @@ static void demux_mpeg_elem_start (demux_plugin_t *this_gen,
num_buffers--;
}
- xprintf (VERBOSE|DEMUX, "=>seek to %Ld\n",pos);
- this->input->seek (this->input, pos, SEEK_SET);
+ /* FIXME: implement time seek */
+
+ xprintf (VERBOSE|DEMUX, "=>seek to %Ld\n",start_pos);
+ this->input->seek (this->input, start_pos, SEEK_SET);
}
/*
@@ -230,7 +229,7 @@ static void demux_mpeg_elem_start (demux_plugin_t *this_gen,
*
*/
static int demux_mpeg_elem_open(demux_plugin_t *this_gen,
- input_plugin_t *input, int stage) {
+ input_plugin_t *input, int stage) {
demux_mpeg_elem_t *this = (demux_mpeg_elem_t *) this_gen;
@@ -245,8 +244,7 @@ static int demux_mpeg_elem_open(demux_plugin_t *this_gen,
if((input->get_capabilities(input) & INPUT_CAP_SEEKABLE) != 0) {
input->seek(input, 0, SEEK_SET);
- if(input->get_blocksize)
- bs = input->get_blocksize(input);
+ bs = input->get_blocksize(input);
if (bs<4)
bs = 4;
@@ -308,6 +306,10 @@ static void demux_mpeg_elem_close (demux_plugin_t *this) {
/* nothing */
}
+static int demux_mpeg_elem_get_stream_length(demux_plugin_t *this_gen,
+ input_plugin_t *input, int stage) {
+ return 0 ; /*FIXME: implement */
+}
/*
*
*/
@@ -315,10 +317,10 @@ demux_plugin_t *init_demuxer_plugin(int iface, config_values_t *config) {
demux_mpeg_elem_t *this;
- if (iface != 2) {
+ if (iface != 3) {
printf( "demux_elem: plugin doesn't support plugin API version %d.\n"
"demux_elem: this means there's a version mismatch between xine and this "
- "demux_elem: demuxer plugin.\nInstalling current input plugins should help.\n",
+ "demux_elem: demuxer plugin.\nInstalling current demux plugins should help.\n",
iface);
return NULL;
}
@@ -333,6 +335,7 @@ demux_plugin_t *init_demuxer_plugin(int iface, config_values_t *config) {
this->demux_plugin.close = demux_mpeg_elem_close;
this->demux_plugin.get_status = demux_mpeg_elem_get_status;
this->demux_plugin.get_identifier = demux_mpeg_elem_get_id;
+ this->demux_plugin.get_stream_length = demux_mpeg_elem_get_stream_length;
return &this->demux_plugin;
}
diff --git a/src/demuxers/demux_mpeg.c b/src/demuxers/demux_mpeg.c
index 1096f310c..5eeb28f81 100644
--- a/src/demuxers/demux_mpeg.c
+++ b/src/demuxers/demux_mpeg.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_mpeg.c,v 1.31 2001/08/28 19:16:19 guenter Exp $
+ * $Id: demux_mpeg.c,v 1.32 2001/09/01 14:33:00 guenter Exp $
*
* demultiplexer for mpeg 1/2 program streams
* reads streams of variable blocksizes
@@ -62,6 +62,8 @@ typedef struct demux_mpeg_s {
int status;
int preview_mode;
+ int rate;
+
int send_end_buffers;
} demux_mpeg_t ;
@@ -168,7 +170,6 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int nID) {
}
buf->type = BUF_AUDIO_A52 + track;
buf->PTS = pts;
- buf->DTS = 0 ; /* FIXME */
if (this->preview_mode)
buf->decoder_info[0] = 0;
else
@@ -218,7 +219,6 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int nID) {
}
buf->type = BUF_AUDIO_MPEG + track;
buf->PTS = pts;
- buf->DTS = 0; /* FIXME */
if (this->preview_mode)
buf->decoder_info[0] = 0;
else
@@ -268,7 +268,6 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int nID) {
}
buf->type = BUF_VIDEO_MPEG;
buf->PTS = pts;
- buf->DTS = 0;
if (this->preview_mode)
buf->decoder_info[0] = 0;
else
@@ -390,12 +389,13 @@ static void parse_mpeg1_packet (demux_mpeg_t *this, int nID)
}
buf->type = BUF_AUDIO_MPEG + track ;
buf->PTS = pts;
- buf->DTS = 0; /* FIXME */
if (this->preview_mode)
buf->decoder_info[0] = 0;
else
buf->decoder_info[0] = 1;
buf->input_pos = this->input->get_current_pos(this->input);
+ if (this->rate)
+ buf->input_time = buf->input_pos / (this->rate * 50);
if(this->audio_fifo)
this->audio_fifo->put (this->audio_fifo, buf);
@@ -404,8 +404,7 @@ static void parse_mpeg1_packet (demux_mpeg_t *this, int nID)
xprintf (VERBOSE|DEMUX|VIDEO, ", video #%d", nID & 0x0f);
- if(this->input->read_block)
- buf = this->input->read_block (this->input, this->video_fifo, nLen);
+ buf = this->input->read_block (this->input, this->video_fifo, nLen);
if (buf == NULL) {
this->status = DEMUX_FINISHED;
@@ -413,12 +412,13 @@ static void parse_mpeg1_packet (demux_mpeg_t *this, int nID)
}
buf->type = BUF_VIDEO_MPEG;
buf->PTS = pts;
- buf->DTS = 0; /* FIXME */
if (this->preview_mode)
buf->decoder_info[0] = 0;
else
buf->decoder_info[0] = 1;
buf->input_pos = this->input->get_current_pos(this->input);
+ if (this->rate)
+ buf->input_time = buf->input_pos / (this->rate * 50);
this->video_fifo->put (this->video_fifo, buf);
@@ -459,9 +459,19 @@ static uint32_t parse_pack(demux_mpeg_t *this)
/* mux_rate */
- buf = read_bytes (this, 3) ;
+ if (!this->rate) {
+ buf = read_bytes (this,1);
+ this->rate = (buf & 0x7F) << 15;
+ buf = read_bytes (this,1);
+ this->rate |= (buf << 7);
+ buf = read_bytes (this,1);
+ this->rate |= (buf >> 1);
+
+ /* printf ("demux_mpeg: mux_rate = %d\n",this->rate); */
+
+ } else
+ buf = read_bytes (this, 3) ;
- /* printf (" mux_rate = %06x\n",buf); */
/* system header */
@@ -595,7 +605,7 @@ static int demux_mpeg_get_status (demux_plugin_t *this_gen) {
static void demux_mpeg_start (demux_plugin_t *this_gen,
fifo_buffer_t *video_fifo,
fifo_buffer_t *audio_fifo,
- off_t pos,
+ off_t start_pos, int start_time,
gui_get_next_mrl_cb_t next_mrl_cb,
gui_branched_cb_t branched_cb)
{
@@ -605,6 +615,8 @@ static void demux_mpeg_start (demux_plugin_t *this_gen,
this->video_fifo = video_fifo;
this->audio_fifo = audio_fifo;
+ this->rate = 0; /* fixme */
+
buf = this->video_fifo->buffer_pool_alloc (this->video_fifo);
buf->type = BUF_CONTROL_START;
this->video_fifo->put (this->video_fifo, buf);
@@ -636,8 +648,11 @@ static void demux_mpeg_start (demux_plugin_t *this_gen,
} while ( (this->status == DEMUX_OK) && (num_buffers>0)) ;
- xprintf (VERBOSE|DEMUX, "=>seek to %Ld\n",pos);
- this->input->seek (this->input, pos+4, SEEK_SET);
+ if ( (!start_pos) && (start_time))
+ start_pos = start_time * this->rate * 50;
+
+ this->input->seek (this->input, start_pos+4, SEEK_SET);
+
} else
read_bytes(this, 4);
@@ -759,14 +774,25 @@ static void demux_mpeg_close (demux_plugin_t *this) {
/* nothing */
}
+static int demux_mpeg_get_stream_length (demux_plugin_t *this_gen) {
+
+ demux_mpeg_t *this = (demux_mpeg_t *) this_gen;
+
+ if (this->rate)
+ return this->input->get_length (this->input) / (this->rate * 50);
+ else
+ return 0;
+
+}
+
demux_plugin_t *init_demuxer_plugin(int iface, config_values_t *config) {
demux_mpeg_t *this;
- if (iface != 2) {
+ if (iface != 3) {
printf( "demux_mpeg: plugin doesn't support plugin API version %d.\n"
"demux_mpeg: this means there's a version mismatch between xine and this "
- "demux_mpeg: demuxer plugin.\nInstalling current input plugins should help.\n",
+ "demux_mpeg: demuxer plugin.\nInstalling current demux plugins should help.\n",
iface);
return NULL;
}
@@ -781,6 +807,7 @@ demux_plugin_t *init_demuxer_plugin(int iface, config_values_t *config) {
this->demux_plugin.close = demux_mpeg_close;
this->demux_plugin.get_status = demux_mpeg_get_status;
this->demux_plugin.get_identifier = demux_mpeg_get_id;
+ this->demux_plugin.get_stream_length = demux_mpeg_get_stream_length;
return (demux_plugin_t *) this;
}
diff --git a/src/demuxers/demux_mpeg_block.c b/src/demuxers/demux_mpeg_block.c
index ee6ebdf40..a7c602262 100644
--- a/src/demuxers/demux_mpeg_block.c
+++ b/src/demuxers/demux_mpeg_block.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_mpeg_block.c,v 1.34 2001/08/31 17:57:54 jkeil Exp $
+ * $Id: demux_mpeg_block.c,v 1.35 2001/09/01 14:33:00 guenter Exp $
*
* demultiplexer for mpeg 1/2 program streams
*
@@ -56,6 +56,7 @@ typedef struct demux_mpeg_block_s {
int status;
int blocksize;
+ int rate;
int send_end_buffers;
@@ -72,12 +73,10 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m
buf_element_t *buf = NULL;
unsigned char *p;
int bMpeg1=0;
- uint32_t nHeaderLen;
- uint32_t nPTS;
- uint32_t nDTS;
- uint32_t nPacketLen;
- uint32_t nStreamID;
-
+ uint32_t header_len;
+ uint32_t PTS;
+ uint32_t packet_len;
+ uint32_t stream_id;
buf = this->input->read_block (this->input, this->video_fifo, this->blocksize);
@@ -127,9 +126,13 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m
else
buf->decoder_info[0] = 1;
+ buf->input_pos = this->input->get_current_pos (this->input);
+
+ if (this->rate)
+ buf->input_time = buf->input_pos / (this->rate * 50);
+
if (p[3] == 0xBA) { /* program stream pack header */
- int nStuffingBytes;
xprintf (VERBOSE|DEMUX, "program stream pack header\n");
@@ -137,28 +140,59 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m
if (bMpeg1) {
+ if (!this->rate) {
+ this->rate = (p[9] & 0x7F) << 15;
+ this->rate |= (p[10] << 7);
+ this->rate |= (p[11] >> 1);
+ }
+
+ buf->input_time = buf->input_pos / (this->rate * 50);
+
p += 12;
} else { /* mpeg2 */
- nStuffingBytes = p[0xD] & 0x07;
+ int num_stuffing_bytes;
+
+ /* SCR decoding code works but is not used by xine
+ int scr;
+
+ scr = (p[4] & 0x38) << 27 ;
+ scr |= (p[4] & 0x03) << 28 ;
+ scr |= p[5] << 20;
+ scr |= (p[6] & 0xF8) << 12 ;
+ scr |= (p[6] & 0x03) << 13 ;
+ scr |= p[7] << 5;
+ scr |= (p[8] & 0xF8) >> 3;
+
+ optional - decode extension:
+
+ scr *=300;
+ scr += ( (p[8] & 0x03 << 7) | (p[9] & 0xFE >> 1) );
+ */
- xprintf (VERBOSE|DEMUX, "%d stuffing bytes\n",nStuffingBytes);
+ if (!this->rate) {
+ this->rate = (p[0xA] << 14);
+ this->rate |= (p[0xB] << 6);
+ this->rate |= (p[0xB] >> 2);
+ }
+
+ num_stuffing_bytes = p[0xD] & 0x07;
- p += 14 + nStuffingBytes;
+ p += 14 + num_stuffing_bytes;
}
}
if (p[3] == 0xbb) { /* program stream system header */
- int nHeaderLen;
+ int header_len;
xprintf (VERBOSE|DEMUX, "program stream system header\n");
- nHeaderLen = (p[4] << 8) | p[5];
+ header_len = (p[4] << 8) | p[5];
- p += 6 + nHeaderLen;
+ p += 6 + header_len;
}
/* we should now have a PES packet here */
@@ -169,109 +203,109 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m
return ;
}
- nPacketLen = p[4] << 8 | p[5];
- nStreamID = p[3];
+ packet_len = p[4] << 8 | p[5];
+ stream_id = p[3];
- xprintf (VERBOSE|DEMUX, "packet id = %02x len = %d\n",nStreamID, nPacketLen);
+ xprintf (VERBOSE|DEMUX, "packet id = %02x len = %d\n",stream_id, packet_len);
if (bMpeg1) {
- if (nStreamID == 0xBF) {
+ if (stream_id == 0xBF) {
buf->free_buffer (buf);
return ;
}
- p += 6; /* nPacketLen -= 6; */
+ p += 6; /* packet_len -= 6; */
while ((p[0] & 0x80) == 0x80) {
p++;
- nPacketLen--;
+ packet_len--;
/* printf ("stuffing\n");*/
}
if ((p[0] & 0xc0) == 0x40) {
/* STD_buffer_scale, STD_buffer_size */
p += 2;
- nPacketLen -=2;
+ packet_len -=2;
}
- nPTS = 0;
- nDTS = 0;
+ PTS = 0;
if ((p[0] & 0xf0) == 0x20) {
- nPTS = (p[ 0] & 0x0E) << 29 ;
- nPTS |= p[ 1] << 22 ;
- nPTS |= (p[ 2] & 0xFE) << 14 ;
- nPTS |= p[ 3] << 7 ;
- nPTS |= (p[ 4] & 0xFE) >> 1 ;
+ PTS = (p[ 0] & 0x0E) << 29 ;
+ PTS |= p[ 1] << 22 ;
+ PTS |= (p[ 2] & 0xFE) << 14 ;
+ PTS |= p[ 3] << 7 ;
+ PTS |= (p[ 4] & 0xFE) >> 1 ;
p += 5;
- nPacketLen -=5;
+ packet_len -=5;
} else if ((p[0] & 0xf0) == 0x30) {
- nPTS = (p[ 0] & 0x0E) << 29 ;
- nPTS |= p[ 1] << 22 ;
- nPTS |= (p[ 2] & 0xFE) << 14 ;
- nPTS |= p[ 3] << 7 ;
- nPTS |= (p[ 4] & 0xFE) >> 1 ;
- nDTS = (p[ 5] & 0x0E) << 29 ;
- nDTS |= p[ 6] << 22 ;
- nDTS |= (p[ 7] & 0xFE) << 14 ;
- nDTS |= p[ 8] << 7 ;
- nDTS |= (p[ 9] & 0xFE) >> 1 ;
+ PTS = (p[ 0] & 0x0E) << 29 ;
+ PTS |= p[ 1] << 22 ;
+ PTS |= (p[ 2] & 0xFE) << 14 ;
+ PTS |= p[ 3] << 7 ;
+ PTS |= (p[ 4] & 0xFE) >> 1 ;
+ /* DTS decoding code is working, but not used in xine
+ DTS = (p[ 5] & 0x0E) << 29 ;
+ DTS |= p[ 6] << 22 ;
+ DTS |= (p[ 7] & 0xFE) << 14 ;
+ DTS |= p[ 8] << 7 ;
+ DTS |= (p[ 9] & 0xFE) >> 1 ;
+ */
p += 10;
- nPacketLen -= 10;
+ packet_len -= 10;
} else {
p++;
- nPacketLen --;
+ packet_len --;
}
} else { /* mpeg 2 */
if (p[7] & 0x80) { /* PTS avail */
- nPTS = (p[ 9] & 0x0E) << 29 ;
- nPTS |= p[10] << 22 ;
- nPTS |= (p[11] & 0xFE) << 14 ;
- nPTS |= p[12] << 7 ;
- nPTS |= (p[13] & 0xFE) >> 1 ;
+ PTS = (p[ 9] & 0x0E) << 29 ;
+ PTS |= p[10] << 22 ;
+ PTS |= (p[11] & 0xFE) << 14 ;
+ PTS |= p[12] << 7 ;
+ PTS |= (p[13] & 0xFE) >> 1 ;
} else
- nPTS = 0;
-
- if (p[7] & 0x40) { /* PTS avail */
+ PTS = 0;
+
+ /* code is working but not used in xine
+ if (p[7] & 0x40) {
- nDTS = (p[14] & 0x0E) << 29 ;
- nDTS |= p[15] << 22 ;
- nDTS |= (p[16] & 0xFE) << 14 ;
- nDTS |= p[17] << 7 ;
- nDTS |= (p[18] & 0xFE) >> 1 ;
+ DTS = (p[14] & 0x0E) << 29 ;
+ DTS |= p[15] << 22 ;
+ DTS |= (p[16] & 0xFE) << 14 ;
+ DTS |= p[17] << 7 ;
+ DTS |= (p[18] & 0xFE) >> 1 ;
} else
- nDTS = 0;
+ DTS = 0;
+ */
- nHeaderLen = p[8];
+ header_len = p[8];
- p += nHeaderLen + 9;
- nPacketLen -= nHeaderLen + 3;
+ p += header_len + 9;
+ packet_len -= header_len + 3;
}
- xprintf (VERBOSE|DEMUX, "stream_id=%x len=%d pts=%d dts=%d\n", nStreamID, nPacketLen, nPTS, nDTS);
-
- if (nStreamID == 0xbd) {
+ if (stream_id == 0xbd) {
- int nTrack, nSPUID;
+ int track, spu_id;
- nTrack = p[0] & 0x0F; /* hack : ac3 track */
+ track = p[0] & 0x0F; /* hack : ac3 track */
if((p[0] & 0xE0) == 0x20) {
- nSPUID = (p[0] & 0x1f);
+ spu_id = (p[0] & 0x1f);
xprintf(VERBOSE|DEMUX, "SPU PES packet, id 0x%03x\n",p[0] & 0x1f);
buf->content = p+1;
- buf->size = nPacketLen-1;
- buf->type = BUF_SPU_PACKAGE + nSPUID;
- buf->PTS = nPTS;
- buf->DTS = nDTS ;
+ buf->size = packet_len-1;
+ buf->type = BUF_SPU_PACKAGE + spu_id;
+ buf->PTS = PTS;
buf->input_pos = this->input->get_current_pos(this->input);
this->video_fifo->put (this->video_fifo, buf);
@@ -281,14 +315,14 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m
if ((p[0]&0xF0) == 0x80) {
- xprintf (VERBOSE|DEMUX|AC3, "ac3 PES packet, track %02x\n",nTrack);
- /* printf ( "ac3 PES packet, track %02x\n",nTrack); */
+ xprintf (VERBOSE|DEMUX|AC3, "ac3 PES packet, track %02x\n",track);
+ /* printf ( "ac3 PES packet, track %02x\n",track); */
buf->content = p+4;
- buf->size = nPacketLen-4;
- buf->type = BUF_AUDIO_A52 + nTrack;
- buf->PTS = nPTS;
- buf->DTS = nDTS ;
+ buf->size = packet_len-4;
+ buf->type = BUF_AUDIO_A52 + track;
+ buf->PTS = PTS;
+
buf->input_pos = this->input->get_current_pos(this->input);
if(this->audio_fifo)
@@ -301,9 +335,9 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m
int pcm_offset;
- xprintf (VERBOSE|DEMUX,"LPCMacket, len : %d %02x\n",nPacketLen-4, p[0]);
+ xprintf (VERBOSE|DEMUX,"LPCMacket, len : %d %02x\n",packet_len-4, p[0]);
- for( pcm_offset=0; ++pcm_offset < nPacketLen-1 ; ){
+ for( pcm_offset=0; ++pcm_offset < packet_len-1 ; ){
if ( p[pcm_offset] == 0x01 && p[pcm_offset+1] == 0x80 ) { /* START */
pcm_offset += 2;
break;
@@ -311,10 +345,10 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m
}
buf->content = p+pcm_offset;
- buf->size = nPacketLen-pcm_offset;
- buf->type = BUF_AUDIO_LPCM_BE + nTrack;
- buf->PTS = nPTS;
- buf->DTS = nDTS ;
+ buf->size = packet_len-pcm_offset;
+ buf->type = BUF_AUDIO_LPCM_BE + track;
+ buf->PTS = PTS;
+
buf->input_pos = this->input->get_current_pos(this->input);
if(this->audio_fifo)
@@ -325,33 +359,33 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m
return ;
}
- } else if ((nStreamID >= 0xbc) && ((nStreamID & 0xf0) == 0xe0)) {
+ } else if ((stream_id >= 0xbc) && ((stream_id & 0xf0) == 0xe0)) {
- xprintf (VERBOSE|DEMUX, "video %d\n", nStreamID);
+ xprintf (VERBOSE|DEMUX, "video %d\n", stream_id);
buf->content = p;
- buf->size = nPacketLen;
+ buf->size = packet_len;
buf->type = BUF_VIDEO_MPEG;
- buf->PTS = nPTS;
- buf->DTS = nDTS;
+ buf->PTS = PTS;
+
buf->input_pos = this->input->get_current_pos(this->input);
this->video_fifo->put (this->video_fifo, buf);
return ;
- } else if ((nStreamID & 0xe0) == 0xc0) {
- int nTrack;
+ } else if ((stream_id & 0xe0) == 0xc0) {
+ int track;
- nTrack = nStreamID & 0x1f;
+ track = stream_id & 0x1f;
- xprintf (VERBOSE|DEMUX|MPEG, "mpg audio #%d", nTrack);
+ xprintf (VERBOSE|DEMUX|MPEG, "mpg audio #%d", track);
buf->content = p;
- buf->size = nPacketLen;
- buf->type = BUF_AUDIO_MPEG + nTrack;
- buf->PTS = nPTS;
- buf->DTS = nDTS;
+ buf->size = packet_len;
+ buf->type = BUF_AUDIO_MPEG + track;
+ buf->PTS = PTS;
+
buf->input_pos = this->input->get_current_pos(this->input);
if(this->audio_fifo)
@@ -362,7 +396,7 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m
return ;
} else {
- xprintf (VERBOSE | DEMUX, "unknown packet, id = %x\n",nStreamID);
+ xprintf (VERBOSE | DEMUX, "unknown packet, id = %x\n",stream_id);
}
buf->free_buffer (buf);
@@ -413,6 +447,126 @@ static void *demux_mpeg_block_loop (void *this_gen) {
return NULL;
}
+/* estimate bitrate */
+
+static int demux_mpeg_block_estimate_rate (demux_mpeg_block_t *this) {
+
+ buf_element_t *buf = NULL;
+ unsigned char *p;
+ int is_mpeg1=0;
+ off_t pos, last_pos;
+ off_t step;
+ uint32_t PTS, last_PTS;
+ int rate;
+ int count;
+
+ if (!(this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE))
+ return 0;
+
+ pos = 0;
+ last_pos = 0;
+ last_PTS = 0;
+ rate = 0;
+ step = this->input->get_length (this->input) / 10;
+ step = (step / this->blocksize) * this->blocksize;
+ count = 0;
+
+ this->input->seek (this->input, 0, SEEK_SET);
+
+ while ((buf = this->input->read_block (this->input, this->video_fifo, this->blocksize)) ) {
+
+ p = buf->content; /* len = this->mnBlocksize; */
+
+ if (p[3] == 0xBA) { /* program stream pack header */
+
+ is_mpeg1 = (p[4] & 0x40) == 0;
+
+ if (is_mpeg1)
+ p += 12;
+ else
+ p += 14 + (p[0xD] & 0x07);
+ }
+
+ if (p[3] == 0xbb) /* program stream system header */
+ p += 6 + ((p[4] << 8) | p[5]);
+
+ /* we should now have a PES packet here */
+
+ if (p[0] || p[1] || (p[2] != 1)) {
+ printf ("demux_mpeg_block: error %02x %02x %02x (should be 0x000001) \n",p[0],p[1],p[2]);
+ buf->free_buffer (buf);
+ return rate;
+ }
+
+ PTS = 0;
+
+ if (is_mpeg1) {
+
+ if (p[3] != 0xBF) { /* stream_id */
+
+ p += 6; /* packet_len -= 6; */
+
+ while ((p[0] & 0x80) == 0x80) {
+ p++; /* stuffing */
+ }
+
+ if ((p[0] & 0xc0) == 0x40) {
+ /* STD_buffer_scale, STD_buffer_size */
+ p += 2;
+ }
+
+ if ( ((p[0] & 0xf0) == 0x20) || ((p[0] & 0xf0) == 0x30) ) {
+ PTS = (p[ 0] & 0x0E) << 29 ;
+ PTS |= p[ 1] << 22 ;
+ PTS |= (p[ 2] & 0xFE) << 14 ;
+ PTS |= p[ 3] << 7 ;
+ PTS |= (p[ 4] & 0xFE) >> 1 ;
+ }
+ }
+ } else { /* mpeg 2 */
+
+ if (p[7] & 0x80) { /* PTS avail */
+
+ PTS = (p[ 9] & 0x0E) << 29 ;
+ PTS |= p[10] << 22 ;
+ PTS |= (p[11] & 0xFE) << 14 ;
+ PTS |= p[12] << 7 ;
+ PTS |= (p[13] & 0xFE) >> 1 ;
+
+ } else
+ PTS = 0;
+ }
+
+ if (PTS) {
+
+ if ( (pos>last_pos) && (PTS>last_PTS) ) {
+ int cur_rate;
+
+ cur_rate = ((pos - last_pos)*90000) / ((PTS - last_PTS) * 50);
+
+ rate = (count * rate + cur_rate) / (count+1);
+
+ count ++;
+
+ /* printf ("demux_mpeg_block: cur_rate = %d, overall rate : %d\n", cur_rate, rate); */
+ }
+
+ last_pos = pos;
+ last_PTS = PTS;
+ pos += step;
+ } else
+ pos += (off_t) this->blocksize;
+
+ buf->free_buffer (buf);
+
+ if (this->input->seek (this->input, pos, SEEK_SET) == (off_t)-1)
+ break;
+ }
+
+ return rate;
+
+}
+
static void demux_mpeg_block_close (demux_plugin_t *this_gen) {
demux_mpeg_block_t *this = (demux_mpeg_block_t *) this_gen;
@@ -462,7 +616,7 @@ static int demux_mpeg_block_get_status (demux_plugin_t *this_gen) {
static void demux_mpeg_block_start (demux_plugin_t *this_gen,
fifo_buffer_t *video_fifo,
fifo_buffer_t *audio_fifo,
- off_t pos,
+ off_t start_pos, int start_time,
gui_get_next_mrl_cb_t next_mrl_cb,
gui_branched_cb_t branched_cb)
{
@@ -475,9 +629,6 @@ static void demux_mpeg_block_start (demux_plugin_t *this_gen,
this->next_mrl_cb = next_mrl_cb;
this->branched_cb = branched_cb;
- pos /= (off_t) this->blocksize;
- pos *= (off_t) this->blocksize;
-
/*
* send start buffer
*/
@@ -492,6 +643,8 @@ static void demux_mpeg_block_start (demux_plugin_t *this_gen,
this->audio_fifo->put (this->audio_fifo, buf);
}
+ this->rate = demux_mpeg_block_estimate_rate (this);
+
if((this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) != 0) {
int num_buffers = NUM_PREVIEW_BUFFERS;
@@ -505,8 +658,18 @@ static void demux_mpeg_block_start (demux_plugin_t *this_gen,
num_buffers --;
}
- xprintf (VERBOSE|DEMUX, "=>seek to %Ld\n",pos);
- this->input->seek (this->input, pos, SEEK_SET);
+ if (start_pos) {
+ start_pos /= (off_t) this->blocksize;
+ start_pos *= (off_t) this->blocksize;
+
+ this->input->seek (this->input, start_pos, SEEK_SET);
+ } else if (start_time) {
+ start_pos = start_time * this->rate * 50;
+ start_pos /= (off_t) this->blocksize;
+ start_pos *= (off_t) this->blocksize;
+
+ this->input->seek (this->input, start_pos, SEEK_SET);
+ }
}
/*
@@ -645,14 +808,25 @@ static char *demux_mpeg_block_get_id(void) {
return "MPEG_BLOCK";
}
+static int demux_mpeg_block_get_stream_length (demux_plugin_t *this_gen) {
+
+ demux_mpeg_block_t *this = (demux_mpeg_block_t *) this_gen;
+
+ if (this->rate)
+ return this->input->get_length (this->input) / (this->rate * 50);
+ else
+ return 0;
+
+}
+
demux_plugin_t *init_demuxer_plugin(int iface, config_values_t *config) {
demux_mpeg_block_t *this;
- if (iface != 2) {
+ if (iface != 3) {
printf( "demux_mpeg: plugin doesn't support plugin API version %d.\n"
"demux_mpeg: this means there's a version mismatch between xine and this "
- "demux_mpeg: demuxer plugin.\nInstalling current input plugins should help.\n",
+ "demux_mpeg: demuxer plugin.\nInstalling current demux plugins should help.\n",
iface);
return NULL;
}
@@ -667,6 +841,7 @@ demux_plugin_t *init_demuxer_plugin(int iface, config_values_t *config) {
this->demux_plugin.close = demux_mpeg_block_close;
this->demux_plugin.get_status = demux_mpeg_block_get_status;
this->demux_plugin.get_identifier = demux_mpeg_block_get_id;
+ this->demux_plugin.get_stream_length = demux_mpeg_block_get_stream_length;
this->scratch = xmalloc_aligned (512, 4096);
diff --git a/src/demuxers/demux_mpgaudio.c b/src/demuxers/demux_mpgaudio.c
index 9f2a8c9c9..fb967cb89 100644
--- a/src/demuxers/demux_mpgaudio.c
+++ b/src/demuxers/demux_mpgaudio.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_mpgaudio.c,v 1.16 2001/08/12 15:12:54 guenter Exp $
+ * $Id: demux_mpgaudio.c,v 1.17 2001/09/01 14:33:00 guenter Exp $
*
* demultiplexer for mpeg audio (i.e. mp3) streams
*
@@ -38,7 +38,7 @@
#include "monitor.h"
#include "demux.h"
-#define DEMUX_MPGAUDIO_IFACE_VERSION 1
+#define DEMUX_MPGAUDIO_IFACE_VERSION 3
typedef struct {
@@ -92,7 +92,6 @@ static int demux_mpgaudio_next (demux_mpgaudio_t *this) {
return 0;
}
- buf->DTS = 0;
buf->PTS = 0;
buf->input_pos = this->input->get_current_pos(this->input);
buf->type = BUF_AUDIO_MPEG;
@@ -179,7 +178,7 @@ static int demux_mpgaudio_get_status (demux_plugin_t *this_gen) {
static void demux_mpgaudio_start (demux_plugin_t *this_gen,
fifo_buffer_t *video_fifo,
fifo_buffer_t *audio_fifo,
- off_t pos,
+ off_t start_pos, int start_time,
gui_get_next_mrl_cb_t next_mrl_cb,
gui_branched_cb_t branched_cb) {
demux_mpgaudio_t *this = (demux_mpgaudio_t *) this_gen;
@@ -191,8 +190,11 @@ static void demux_mpgaudio_start (demux_plugin_t *this_gen,
this->status = DEMUX_OK;
if((this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) != 0) {
- xprintf (VERBOSE|DEMUX, "=>seek to %Ld\n",pos);
- this->input->seek (this->input, pos, SEEK_SET);
+ xprintf (VERBOSE|DEMUX, "=>seek to %Ld\n",start_pos);
+ this->input->seek (this->input, start_pos, SEEK_SET);
+
+ /* FIMXE: implement seeking to start_time */
+
}
buf = this->video_fifo->buffer_pool_alloc (this->video_fifo);
@@ -277,9 +279,6 @@ static int demux_mpgaudio_open(demux_plugin_t *this_gen,
return DEMUX_CANNOT_HANDLE;
}
-/*
- *
- */
static char *demux_mpgaudio_get_id(void) {
return "MPGAUDIO";
}
@@ -288,14 +287,21 @@ static void demux_mpgaudio_close (demux_plugin_t *this) {
/* nothing */
}
+static int demux_mpgaudio_get_stream_length (demux_plugin_t *this) {
+ /* FIXME: implement */
+
+ return 0;
+}
+
+
demux_plugin_t *init_demuxer_plugin(int iface, config_values_t *config) {
demux_mpgaudio_t *this;
- if (iface != 2) {
+ if (iface != 3) {
printf( "demux_mpeg: plugin doesn't support plugin API version %d.\n"
"demux_mpeg: this means there's a version mismatch between xine and this "
- "demux_mpeg: demuxer plugin.\nInstalling current input plugins should help.\n",
+ "demux_mpeg: demuxer plugin.\nInstalling current demux plugins should help.\n",
iface);
return NULL;
}
@@ -310,6 +316,7 @@ demux_plugin_t *init_demuxer_plugin(int iface, config_values_t *config) {
this->demux_plugin.close = demux_mpgaudio_close;
this->demux_plugin.get_status = demux_mpgaudio_get_status;
this->demux_plugin.get_identifier = demux_mpgaudio_get_id;
+ this->demux_plugin.get_stream_length = demux_mpgaudio_get_stream_length;
return &this->demux_plugin;
}
diff --git a/src/demuxers/demux_pes.c b/src/demuxers/demux_pes.c
index 419b0a3fa..4f746eb0c 100644
--- a/src/demuxers/demux_pes.c
+++ b/src/demuxers/demux_pes.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_pes.c,v 1.5 2001/08/28 19:16:19 guenter Exp $
+ * $Id: demux_pes.c,v 1.6 2001/09/01 14:33:00 guenter Exp $
*
* demultiplexer for mpeg 2 PES (Packetized Elementary Streams)
* reads streams of variable blocksizes
@@ -45,7 +45,7 @@
static uint32_t xine_debug;
-typedef struct demux_mpeg_s {
+typedef struct demux_pes_s {
demux_plugin_t demux_plugin;
@@ -63,9 +63,9 @@ typedef struct demux_mpeg_s {
int send_end_buffers;
-} demux_mpeg_t ;
+} demux_pes_t ;
-static uint32_t read_bytes (demux_mpeg_t *this, int n) {
+static uint32_t read_bytes (demux_pes_t *this, int n) {
uint32_t res;
uint32_t i;
@@ -107,7 +107,7 @@ static uint32_t read_bytes (demux_mpeg_t *this, int n) {
return res;
}
-static void parse_mpeg2_packet (demux_mpeg_t *this, int nID) {
+static void parse_mpeg2_packet (demux_pes_t *this, int nID) {
int nLen, i;
uint32_t w, flags, header_len, pts;
@@ -167,7 +167,6 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int nID) {
}
buf->type = BUF_AUDIO_A52 + track;
buf->PTS = pts;
- buf->DTS = 0 ; /* FIXME */
if (this->preview_mode)
buf->decoder_info[0] = 0;
else
@@ -217,7 +216,6 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int nID) {
}
buf->type = BUF_AUDIO_MPEG + track;
buf->PTS = pts;
- buf->DTS = 0; /* FIXME */
if (this->preview_mode)
buf->decoder_info[0] = 0;
else
@@ -267,7 +265,6 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int nID) {
}
buf->type = BUF_VIDEO_MPEG;
buf->PTS = pts;
- buf->DTS = 0;
if (this->preview_mode)
buf->decoder_info[0] = 0;
else
@@ -288,7 +285,7 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int nID) {
}
-static uint32_t parse_pack(demux_mpeg_t *this)
+static uint32_t parse_pack(demux_pes_t *this)
{
uint32_t buf ;
@@ -307,7 +304,7 @@ static uint32_t parse_pack(demux_mpeg_t *this)
}
-static void demux_mpeg_resync (demux_mpeg_t *this, uint32_t buf) {
+static void demux_pes_resync (demux_pes_t *this, uint32_t buf) {
while ((buf !=0x000001) && (this->status == DEMUX_OK)) {
xprintf (VERBOSE|DEMUX, "resync : %08x\n",buf);
@@ -315,9 +312,9 @@ static void demux_mpeg_resync (demux_mpeg_t *this, uint32_t buf) {
}
}
-static void *demux_mpeg_loop (void *this_gen) {
+static void *demux_pes_loop (void *this_gen) {
- demux_mpeg_t *this = (demux_mpeg_t *) this_gen;
+ demux_pes_t *this = (demux_pes_t *) this_gen;
buf_element_t *buf;
uint32_t w;
@@ -325,7 +322,7 @@ static void *demux_mpeg_loop (void *this_gen) {
w = parse_pack (this);
if (w != 0x000001)
- demux_mpeg_resync (this, w);
+ demux_pes_resync (this, w);
} while (this->status == DEMUX_OK) ;
@@ -353,12 +350,12 @@ static void *demux_mpeg_loop (void *this_gen) {
return NULL;
}
-static void demux_mpeg_stop (demux_plugin_t *this_gen) {
+static void demux_pes_stop (demux_plugin_t *this_gen) {
- demux_mpeg_t *this = (demux_mpeg_t *) this_gen;
+ demux_pes_t *this = (demux_pes_t *) this_gen;
buf_element_t *buf;
- printf ("demux_mpeg: stop...\n");
+ printf ("demux_pes: stop...\n");
if (this->status != DEMUX_OK) {
@@ -392,19 +389,19 @@ static void demux_mpeg_stop (demux_plugin_t *this_gen) {
}
-static int demux_mpeg_get_status (demux_plugin_t *this_gen) {
- demux_mpeg_t *this = (demux_mpeg_t *) this_gen;
+static int demux_pes_get_status (demux_plugin_t *this_gen) {
+ demux_pes_t *this = (demux_pes_t *) this_gen;
return this->status;
}
-static void demux_mpeg_start (demux_plugin_t *this_gen,
- fifo_buffer_t *video_fifo,
- fifo_buffer_t *audio_fifo,
- off_t pos,
- gui_get_next_mrl_cb_t next_mrl_cb,
- gui_branched_cb_t branched_cb)
+static void demux_pes_start (demux_plugin_t *this_gen,
+ fifo_buffer_t *video_fifo,
+ fifo_buffer_t *audio_fifo,
+ off_t start_pos, int start_time,
+ gui_get_next_mrl_cb_t next_mrl_cb,
+ gui_branched_cb_t branched_cb)
{
- demux_mpeg_t *this = (demux_mpeg_t *) this_gen;
+ demux_pes_t *this = (demux_pes_t *) this_gen;
buf_element_t *buf;
this->video_fifo = video_fifo;
@@ -435,14 +432,17 @@ static void demux_mpeg_start (demux_plugin_t *this_gen,
w = parse_pack (this);
if (w != 0x000001)
- demux_mpeg_resync (this, w);
+ demux_pes_resync (this, w);
num_buffers --;
} while ( (this->status == DEMUX_OK) && (num_buffers>0)) ;
- xprintf (VERBOSE|DEMUX, "=>seek to %Ld\n",pos);
- this->input->seek (this->input, pos+3, SEEK_SET);
+ xprintf (VERBOSE|DEMUX, "=>seek to %Ld\n",start_pos);
+ this->input->seek (this->input, start_pos+3, SEEK_SET);
+
+ /* FIXME: implement time seek */
+
} else
read_bytes(this, 3);
@@ -450,13 +450,13 @@ static void demux_mpeg_start (demux_plugin_t *this_gen,
this->send_end_buffers = 1;
this->status = DEMUX_OK ;
- pthread_create (&this->thread, NULL, demux_mpeg_loop, this) ;
+ pthread_create (&this->thread, NULL, demux_pes_loop, this) ;
}
-static int demux_mpeg_open(demux_plugin_t *this_gen,
+static int demux_pes_open(demux_plugin_t *this_gen,
input_plugin_t *input, int stage) {
- demux_mpeg_t *this = (demux_mpeg_t *) this_gen;
+ demux_pes_t *this = (demux_pes_t *) this_gen;
this->input = input;
@@ -535,36 +535,44 @@ static int demux_mpeg_open(demux_plugin_t *this_gen,
return DEMUX_CANNOT_HANDLE;
}
-static char *demux_mpeg_get_id(void) {
+static char *demux_pes_get_id(void) {
return "MPEG_PES";
}
-static void demux_mpeg_close (demux_plugin_t *this) {
+static void demux_pes_close (demux_plugin_t *this) {
/* nothing */
}
+static int demux_pes_get_stream_length (demux_plugin_t *this_gen) {
+
+ /* demux_pes_t *this = (demux_pes_t *) this_gen; */
+
+ return 0; /* FIXME: implement */
+}
+
demux_plugin_t *init_demuxer_plugin(int iface, config_values_t *config) {
- demux_mpeg_t *this;
+ demux_pes_t *this;
- if (iface != 2) {
+ if (iface != 3) {
printf( "demux_pes: plugin doesn't support plugin API version %d.\n"
"demux_pes: this means there's a version mismatch between xine and this "
- "demux_pes: demuxer plugin.\nInstalling current input plugins should help.\n",
+ "demux_pes: demuxer plugin.\nInstalling current demux plugins should help.\n",
iface);
return NULL;
}
- this = xmalloc (sizeof (demux_mpeg_t));
+ this = xmalloc (sizeof (demux_pes_t));
xine_debug = config->lookup_int (config, "xine_debug", 0);
- this->demux_plugin.interface_version = DEMUXER_PLUGIN_IFACE_VERSION;
- this->demux_plugin.open = demux_mpeg_open;
- this->demux_plugin.start = demux_mpeg_start;
- this->demux_plugin.stop = demux_mpeg_stop;
- this->demux_plugin.close = demux_mpeg_close;
- this->demux_plugin.get_status = demux_mpeg_get_status;
- this->demux_plugin.get_identifier = demux_mpeg_get_id;
+ this->demux_plugin.interface_version = 3;
+ this->demux_plugin.open = demux_pes_open;
+ this->demux_plugin.start = demux_pes_start;
+ this->demux_plugin.stop = demux_pes_stop;
+ this->demux_plugin.close = demux_pes_close;
+ this->demux_plugin.get_status = demux_pes_get_status;
+ this->demux_plugin.get_identifier = demux_pes_get_id;
+ this->demux_plugin.get_stream_length = demux_pes_get_stream_length;
return (demux_plugin_t *) this;
}
diff --git a/src/demuxers/demux_ts.c b/src/demuxers/demux_ts.c
index 335ca5502..1b022d54a 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.10 2001/08/31 17:57:54 jkeil Exp $
+ * $Id: demux_ts.c,v 1.11 2001/09/01 14:33:00 guenter Exp $
*
* Demultiplexer for MPEG2 Transport Streams.
*
@@ -46,6 +46,9 @@
*
* 29-Jul-2001 shaheedhaque Reviewed by: n/a
* Compiles!
+
+ *
+ * TODO: do without memcpys, seeking (if possible), preview buffers
*/
#ifdef HAVE_CONFIG_H
@@ -85,244 +88,286 @@
* Describe a single elementary stream.
*/
typedef struct {
- unsigned int pid;
- fifo_buffer_t *fifo;
- int type;
- buf_element_t *buf;
- int pes_buf_next;
- int pes_len;
- int pes_len_zero;
- unsigned int counter;
+ unsigned int pid;
+ fifo_buffer_t *fifo;
+ int type;
+ buf_element_t *buf;
+ int pes_buf_next;
+ int pes_len;
+ int pes_len_zero;
+ unsigned int counter;
+
} demux_ts_media;
typedef struct {
+ /*
+ * The first field must be the "base class" for the plugin!
+ */
+ demux_plugin_t plugin;
+
+ fifo_buffer_t *fifoAudio;
+ fifo_buffer_t *fifoVideo;
+
+ input_plugin_t *input;
+
+ pthread_t thread;
+
+ int status;
+
+ int broken_pes;
+ int buf_type;
+
+ int blockSize;
+ int rate;
+ demux_ts_media media[MAX_PIDS];
+ /*
+ * Stuff to do with the transport header. As well as the video
+ * and audio PIDs, we keep the index of the corresponding entry
+ * inthe media[] array.
+ */
+ unsigned int programNumber;
+ unsigned int pmtPid;
+ unsigned int pcrPid;
+ unsigned int videoPid;
+ unsigned int audioPid;
+ unsigned int videoMedia;
+ unsigned int audioMedia;
+} demux_ts;
+
+static uint32_t xine_debug;
+
+
+/*
+ * demux_ts_parse_pat
+ *
+ * Parse a program association table (PAT).
+ * The PAT is expected to be exactly one section long,
+ * and that section is expected to be contained in a single TS packet.
+ *
+ * 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 *originalPkt,
+ unsigned char *pkt, unsigned int pus) {
+
+ unsigned int length;
+ unsigned char *program;
+ unsigned int programNumber;
+ unsigned int pmtPid;
+ unsigned int programCount;
+
+ /*
+ * A PAT in a single section should start with a payload unit start
+ * indicator set.
+ */
+ if (!pus) {
+ printf ("demux_ts: demux error! PAT without payload unit start\n");
+ return;
+ }
+
+ /*
+ * PAT packets with a pus start with a pointer. Skip it!
+ */
+ pkt += pkt[4];
+ if (pkt - originalPkt > PKT_SIZE) {
+ printf ("demux_ts: demux error! PAT with invalid pointer\n");
+ return;
+ }
+ if (!(pkt[10] & 0x01)) {
+ /*
+ * Not current!
+ */
+ return;
+ }
+ length = (((unsigned int)pkt[6] & 0x3) << 8) | pkt[7];
+ if (pkt - originalPkt > BODY_SIZE - 1 - 3 - (int)length) {
+ printf ("demux_ts: demux error! PAT with invalid section length\n");
+ return;
+ }
+ if ((pkt[11]) || (pkt[12])) {
+ printf ("demux_ts: demux error! PAT with invalid section %02x of %02x\n", pkt[11], pkt[12]);
+ return;
+ }
+
+ /*
+ * TBD: at this point, we should check the CRC. Its not that expensive, and
+ * the consequences of getting it wrong are dire!
+ */
+
+ /*
+ * Process all programs in the program loop.
+ */
+ programCount = 0;
+ for (program = pkt + 13; program < pkt + 13 + length - 9; program += 4) {
+ programNumber = ((unsigned int)program[0] << 8) | program[1];
+
/*
- * The first field must be the "base class" for the plugin!
+ * Skip NITs completely.
*/
- demux_plugin_t plugin;
+ if (!programNumber)
+ continue;
+ programCount++;
+ pmtPid = (((unsigned int)program[2] & 0x1f) << 8) | program[3];
+
+ /*
+ * If we have yet to learn our program number, then learn it.
+ */
+ if (this->programNumber == INVALID_PROGRAM) {
+ xprintf(VERBOSE|DEMUX, "acquiring programNumber=%u pmtPid=%04x\n", programNumber, pmtPid);
+ this->programNumber = programNumber;
+ this->pmtPid = pmtPid;
+ } else {
+ if (this->programNumber != programNumber) {
+ fprintf(stderr, "demux error! MPTS: programNumber=%u pmtPid=%04x\n", programNumber, pmtPid);
+ } else {
+ if (this->pmtPid != pmtPid) {
+ xprintf(VERBOSE|DEMUX, "pmtPid changed %04x\n", pmtPid);
+ this->pmtPid = pmtPid;
+ }
+ }
+ }
+ }
+}
- fifo_buffer_t *fifoAudio;
- fifo_buffer_t *fifoVideo;
- fifo_buffer_t *fifoSPU;
+static int demux_ts_parse_pes_header (demux_ts *this, buf_element_t *buf, int packet_len) {
- input_plugin_t *input;
+ unsigned char *p;
+ uint32_t header_len;
+ uint32_t PTS;
+ uint32_t stream_id;
- pthread_t thread;
+ p = buf->mem;
- int mnAudioChannel;
- int mnSPUChannel;
- int status;
+ /* we should have a PES packet here */
- int blockSize;
- demux_ts_media media[MAX_PIDS];
- /*
- * Stuff to do with the transport header. As well as the video
- * and audio PIDs, we keep the index of the corresponding entry
- * inthe media[] array.
- */
- unsigned int programNumber;
- unsigned int pmtPid;
- unsigned int pcrPid;
- unsigned int videoPid;
- unsigned int audioPid;
- unsigned int videoMedia;
- unsigned int audioMedia;
-} demux_ts;
+ 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]);
+ return 0 ;
+ }
-/*
-**
-** PRIVATE FUNCTIONS
-**
-*/
-static void *demux_ts_loop(
- void *gen_this);
-static void demux_ts_pat_parse(
- demux_ts *this,
- unsigned char *originalPkt,
- unsigned char *pkt,
- unsigned int pus);
-static void demux_ts_pes_buffer(
- demux_ts *this,
- unsigned char *ts,
- unsigned int mediaIndex,
- unsigned int pus,
- unsigned int cc,
- unsigned int len);
-static void demux_ts_pes_new(
- demux_ts *this,
- unsigned int mediaIndex,
- unsigned int pid,
- fifo_buffer_t *fifo);
-static void demux_ts_pmt_parse(
- demux_ts *this,
- unsigned char *originalPkt,
- unsigned char *pkt,
- unsigned int pus);
-static void demux_ts_parse_ts(
- demux_ts *this);
-static void demux_ts_queue_pes(
- demux_ts *this,
- buf_element_t *buf);
-static void demux_ts_close(
- demux_plugin_t *gen_this);
-static char *demux_ts_get_id(
- void);
-static int demux_ts_get_status(
- demux_plugin_t *this_gen);
-static int demux_ts_open(
- demux_plugin_t *this_gen,
- input_plugin_t *input,
- int stage);
-static void demux_ts_start(
- demux_plugin_t *this_gen,
- fifo_buffer_t *fifoVideo,
- fifo_buffer_t *fifoAudio,
- off_t pos,
- gui_get_next_mrl_cb_t next_mrl_cb,
- gui_branched_cb_t branched_cb);
-static void demux_ts_stop(
- demux_plugin_t *this_gen);
+ packet_len -= 6;
+ /* packet_len = p[4] << 8 | p[5]; */
+ stream_id = p[3];
-/*
-**
-** DATA
-**
-*/
-static uint32_t xine_debug;
+ if (packet_len==0)
+ return 0;
-/*
- * Sit in a loop eating data.
- */
-static void *demux_ts_loop(
- void *gen_this)
-{
- demux_ts *this = (demux_ts *)gen_this;
- buf_element_t *buf;
+ xprintf(VERBOSE|DEMUX, "packet stream id = %02x len = %d\n",
+ stream_id, packet_len);
- /*
- * TBD: why do we not appear at the beginning of the file?
- */
-this->input->seek(this->input, 0, SEEK_SET);
-fprintf (stderr, "demux %u demux_ts_loop seeking back to start of file! \n", __LINE__);
- do {
- demux_ts_parse_ts(this);
- } while (this->status == DEMUX_OK) ;
+ if (p[7] & 0x80) { /* PTS avail */
- xprintf(VERBOSE|DEMUX, "demux loop finished (status: %d)\n", this->status);
+ PTS = (p[ 9] & 0x0E) << 29 ;
+ PTS |= p[10] << 22 ;
+ PTS |= (p[11] & 0xFE) << 14 ;
+ PTS |= p[12] << 7 ;
+ PTS |= (p[13] & 0xFE) >> 1 ;
+
+ } else
+ PTS = 0;
- this->status = DEMUX_FINISHED;
- buf = this->fifoVideo->buffer_pool_alloc(this->fifoVideo);
- buf->type = BUF_CONTROL_END;
- buf->decoder_info[0] = 0; /* stream finished */
- this->fifoVideo->put(this->fifoVideo, buf);
+ /* code works but not used in xine
+ if (p[7] & 0x40) {
+
+ DTS = (p[14] & 0x0E) << 29 ;
+ DTS |= p[15] << 22 ;
+ DTS |= (p[16] & 0xFE) << 14 ;
+ DTS |= p[17] << 7 ;
+ DTS |= (p[18] & 0xFE) >> 1 ;
+
+ } else
+ DTS = 0;
+ */
+
+ buf->PTS = PTS;
+ buf->input_pos = this->input->get_current_pos(this->input);
+ /* FIXME: not working correctly */
+ buf->input_time = buf->input_pos / (this->rate * 50);
+
+ header_len = p[8];
- if (this->fifoAudio) {
- buf = this->fifoAudio->buffer_pool_alloc(this->fifoAudio);
- buf->type = BUF_CONTROL_END;
- buf->decoder_info[0] = 0; /* stream finished */
- this->fifoAudio->put(this->fifoAudio, buf);
- }
- pthread_exit(NULL);
- return NULL;
-}
+ p += header_len + 9;
+ packet_len -= header_len + 3;
-/*
- * NAME demux_ts_pat_parse
- *
- * Parse a PAT. The PAT is expected to be exactly one section long,
- * and that section is expected to be contained in a single TS packet.
- *
- * 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_pat_parse(
- demux_ts *this,
- unsigned char *originalPkt,
- unsigned char *pkt,
- unsigned int pus)
-{
- unsigned int length;
- unsigned char *program;
- unsigned int programNumber;
- unsigned int pmtPid;
- unsigned int programCount;
+ if (stream_id == 0xbd) {
- /*
- * A PAT in a single section should start with a payload unit start
- * indicator set.
- */
- if (!pus) {
- fprintf (stderr, "demux error! PAT without payload unit start\n");
- return;
- }
+ int track, spu_id;
- /*
- * PAT packets with a pus start with a pointer. Skip it!
- */
- pkt += pkt[4];
- if (pkt - originalPkt > PKT_SIZE) {
- fprintf (stderr, "demux error! PAT with invalid pointer\n");
- return;
- }
- if (!(pkt[10] & 0x01)) {
- /*
- * Not current!
- */
- return;
- }
- length = (((unsigned int)pkt[6] & 0x3) << 8) | pkt[7];
- if (pkt - originalPkt > BODY_SIZE - 1 - 3 - (int)length) {
- fprintf (stderr, "demux error! PAT with invalid section length\n");
- return;
- }
- if ((pkt[11]) || (pkt[12])) {
- fprintf (stderr, "demux error! PAT with invalid section %02x of %02x\n", pkt[11], pkt[12]);
- return;
- }
+ track = p[0] & 0x0F; /* hack : ac3 track */
- /*
- * TBD: at this point, we should check the CRC. Its not that expensive, and
- * the consequences of getting it wrong are dire!
- */
+ if ((p[0] & 0xE0) == 0x20) {
- /*
- * Process all programs in the program loop.
- */
- programCount = 0;
- for (program = pkt + 13; program < pkt + 13 + length - 9; program += 4) {
- programNumber = ((unsigned int)program[0] << 8) | program[1];
-
- /*
- * Skip NITs completely.
- */
- if (!programNumber)
- continue;
- programCount++;
- pmtPid = (((unsigned int)program[2] & 0x1f) << 8) | program[3];
-
- /*
- * If we have yet to learn our program number, then learn it.
- */
- if (this->programNumber == INVALID_PROGRAM) {
- xprintf(VERBOSE|DEMUX, "acquiring programNumber=%u pmtPid=%04x\n", programNumber, pmtPid);
- this->programNumber = programNumber;
- this->pmtPid = pmtPid;
- } else {
- if (this->programNumber != programNumber) {
- fprintf(stderr, "demux error! MPTS: programNumber=%u pmtPid=%04x\n", programNumber, pmtPid);
- } else {
- if (this->pmtPid != pmtPid) {
- xprintf(VERBOSE|DEMUX, "pmtPid changed %04x\n", pmtPid);
- this->pmtPid = pmtPid;
- }
- }
- }
+ spu_id = (p[0] & 0x1f);
+
+ buf->content = p+1;
+ buf->size = packet_len-1;
+ buf->type = BUF_SPU_PACKAGE + spu_id;
+
+ this->buf_type = BUF_SPU_PACKAGE + spu_id;
+
+ return 1;
+ } else if ((p[0] & 0xF0) == 0x80) {
+
+ buf->content = p+4;
+ buf->size = packet_len - 4;
+ buf->type = BUF_AUDIO_A52 + track;
+
+ this->buf_type = BUF_AUDIO_A52 + track;
+
+ return 1;
+
+ } else if ((p[0]&0xf0) == 0xa0) {
+
+ int pcm_offset;
+
+ for (pcm_offset=0; ++pcm_offset < packet_len-1 ; ){
+ if (p[pcm_offset] == 0x01 && p[pcm_offset+1] == 0x80 ) { /* START */
+ pcm_offset += 2;
+ break;
+ }
+ }
+
+ buf->content = p+pcm_offset;
+ buf->size = packet_len-pcm_offset;
+ buf->type = BUF_AUDIO_LPCM_BE + track;
+
+ this->buf_type = BUF_AUDIO_LPCM_BE + track;
+
+ return 1;
}
+
+ } else if ((stream_id >= 0xbc) && ((stream_id & 0xf0) == 0xe0)) {
+
+ buf->content = p;
+ buf->size = packet_len;
+ buf->type = BUF_VIDEO_MPEG;
+ this->buf_type = BUF_VIDEO_MPEG;
+
+ return 1;
+
+ } else if ((stream_id & 0xe0) == 0xc0) {
+
+ int track;
+
+ track = stream_id & 0x1f;
+
+ buf->content = p;
+ buf->size = packet_len;
+ buf->type = BUF_AUDIO_MPEG + track;
+ this->buf_type = BUF_AUDIO_MPEG + track;
+
+ return 1;
+
+ } else {
+ xprintf(VERBOSE | DEMUX, "unknown packet, id = %x\n",stream_id);
+ }
+
+ return 0 ;
}
/*
- * Manage a buffer for a PES stream.
+ * buffer arriving pes data
* Input is 188 bytes of Transport stream
* Build a PES packet. PES packets can get as big as 65536
* If PES packet length was empty(zero) work it out based on seeing the next PUS.
@@ -330,126 +375,96 @@ static void demux_ts_pat_parse(
* then queue it. The queuing routine might have to cut it up to make bits < 4096. FIXME: implement cut up.
* Currently if PES packets are >4096, corruption occurs.
*/
-static void demux_ts_pes_buffer(
- demux_ts *this,
- unsigned char *ts,
- unsigned int mediaIndex,
- unsigned int pus,
- unsigned int cc,
- unsigned int len)
-{
- demux_ts_media *m = &this->media[mediaIndex];
- if (!m->fifo) return; /* To avoid segfault if Video out or Audio out plugin not loaded */
- /*
- * By checking the CC here, we avoid the need to check for the no-payload
- * case (i.e. adaptation field only) when it does not get bumped.
- */
- if (m->counter != INVALID_CC) {
- if ((m->counter & 0x0f) != cc) {
- fprintf(stderr, "dropped input packet cc = %d expected = %d\n", cc, m->counter);
- }
+
+static void demux_ts_buffer_pes(demux_ts *this, unsigned char *ts,
+ unsigned int mediaIndex,
+ unsigned int pus,
+ unsigned int cc,
+ unsigned int len) {
+
+ buf_element_t *buf;
+
+ demux_ts_media *m = &this->media[mediaIndex];
+ if (!m->fifo) {
+
+ printf ("fifo unavailable (%d)\n", mediaIndex);
+
+ return; /* To avoid segfault if video out or audio out plugin not loaded */
+
+ }
+
+ /*
+ * By checking the CC here, we avoid the need to check for the no-payload
+ * case (i.e. adaptation field only) when it does not get bumped.
+ */
+ if (m->counter != INVALID_CC) {
+ if ((m->counter & 0x0f) != cc) {
+ printf("demux_ts: dropped input packet cc = %d expected = %d\n", cc, m->counter);
}
- m->counter = cc;
- m->counter++;
- if (pus) {
- /* new PES packet */
- if (ts[0] || ts[1] || ts[2] != 1) {
- fprintf(stderr, "PUS set but no PES header (corrupt stream?)\n");
- m->buf->free_buffer(m->buf);
- m->buf = 0;
- m->pes_len_zero=0;
- return;
- }
- if (m->buf) {
- if(m->pes_len_zero) {
-/*
- fprintf(stderr,"Queuing ZERO PES %02X %02X %02X %02X %02X\n", m->buf->mem[3], m->buf->mem[4], m->buf->mem[5],
- (m->pes_buf_next-6) & 0xff,
- (m->pes_buf_next-6) >> 8 );
- */
- m->buf->mem[5]=(m->pes_buf_next - 6 ) & 0xff;
- m->buf->mem[4]=(m->pes_buf_next - 6 ) >> 8;
- demux_ts_queue_pes(this, m->buf);
- m->buf = 0;
- m->pes_len_zero=0;
- } else {
-
- fprintf(stderr, "PUS set but last PES not complete (corrupt stream?) %d %d %d\n",
- m->pes_buf_next, m->pes_len, m->pes_len_zero);
-
- m->buf->free_buffer(m->buf);
- m->buf = 0;
- /* return; */
- }
- }
- m->pes_len = ((ts[4] << 8) | ts[5]) ;
- if (m->pes_len) {
- m->pes_len+=6;
- m->pes_len_zero=0;
- } else {
- m->pes_len_zero=1;
- }
-/*
- fprintf(stderr,"starting new pes, len = %d %d %02X\n", m->pes_len, m->pes_len_zero,ts[3]);
- */
- if (m->fifo) { /* allow running without sound card */
- m->buf = m->fifo->buffer_pool_alloc(m->fifo);
- memcpy(m->buf->mem, ts, len);
- m->pes_buf_next = len;
- }
- return;
- } else if (m->buf) {
- if( m->pes_buf_next+len <= m->buf->max_size) {
- memcpy(m->buf->mem+m->pes_buf_next, ts, len);
- m->pes_buf_next += len;
- if( !m->pes_len_zero) {
- if (m->pes_buf_next == m->pes_len ) {
-/*
- fprintf(stderr,"Queuing PES - len = %d\n", m->pes_len);
- fprintf(stderr,"Queuing PES %02X\n", m->buf->mem[3]);
- */
- demux_ts_queue_pes(this, m->buf);
- m->buf = 0;
- } else if ( m->pes_buf_next > m->pes_len) {
- fprintf(stderr, "too much data read for PES (corrupt stream?)\n");
- m->buf->free_buffer(m->buf);
- m->buf = 0;
- m->pes_len_zero=0;
- }
- }
- } else {
- fprintf(stderr, "Buffer overflow on data read for PES (discontinuity ?)\n");
- /* FIXME: Implement discontinuity sensing */
- m->buf->free_buffer(m->buf);
- m->buf = 0;
- m->pes_len_zero=0;
- }
-
+ }
+
+ m->counter = cc;
+ m->counter++;
+
+ if (pus) {
+
+ /* new PES packet */
+
+ if (ts[0] || ts[1] || ts[2] != 1) {
+ fprintf(stderr, "PUS set but no PES header (corrupt stream?)\n");
+ return;
+ }
+
+ buf = m->fifo->buffer_pool_alloc(m->fifo);
+
+ memcpy (buf->mem, ts, len); /* FIXME: reconstruct parser to do without memcpys */
+
+ if (!demux_ts_parse_pes_header(this, buf, len)) {
+ buf->free_buffer(buf);
+ this->broken_pes = 1;
+ printf ("demux_ts: broken pes encountered\n");
} else {
- /*
- fprintf(stderr, "nowhere to buffer input. Waiting for PUS. \n");
- */
+ this->broken_pes = 0;
+
+ buf->decoder_info[0] = 1;
+
+ m->fifo->put (m->fifo, buf);
}
+
+ } else if (!this->broken_pes) {
+
+ buf = m->fifo->buffer_pool_alloc(m->fifo);
+
+ memcpy (buf->mem, ts, len); /* FIXME: reconstruct parser to do without memcpys */
+
+ buf->content = buf->mem;
+ buf->size = len;
+ buf->type = this->buf_type;
+ buf->PTS = 0;
+ buf->input_pos = this->input->get_current_pos(this->input);
+ buf->decoder_info[0] = 1;
+
+ m->fifo->put (m->fifo, buf);
+ }
}
/*
* Create a buffer for a PES stream.
*/
-static void demux_ts_pes_new(
- demux_ts *this,
- unsigned int mediaIndex,
- unsigned int pid,
- fifo_buffer_t *fifo)
-{
- demux_ts_media *m = &this->media[mediaIndex];
-
- /* new PID seen - initialise stuff */
- m->pid = pid;
- m->fifo = fifo;
- m->buf = 0;
- m->pes_buf_next = 0;
- m->pes_len = 0;
- m->counter = INVALID_CC;
+static void demux_ts_pes_new(demux_ts *this,
+ unsigned int mediaIndex,
+ unsigned int pid,
+ fifo_buffer_t *fifo) {
+
+ demux_ts_media *m = &this->media[mediaIndex];
+
+ /* new PID seen - initialise stuff */
+ m->pid = pid;
+ m->fifo = fifo;
+ m->buf = 0;
+ m->pes_buf_next = 0;
+ m->pes_len = 0;
+ m->counter = INVALID_CC;
}
/*
@@ -461,147 +476,145 @@ static void demux_ts_pes_new(
* In other words, the PMT is assumed to describe a reasonable number of
* video, audio and other streams (with descriptors).
*/
-static void demux_ts_pmt_parse(
- demux_ts *this,
- unsigned char *originalPkt,
- unsigned char *pkt,
- unsigned int pus)
-{
- typedef enum
+static void demux_ts_parse_pmt(demux_ts *this,
+ unsigned char *originalPkt,
+ unsigned char *pkt,
+ unsigned int pus) {
+ 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_13818_AUX = 14
+ 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
} streamType;
- unsigned int length;
- unsigned int programInfoLength;
- unsigned int codedLength;
- unsigned int mediaIndex;
- unsigned int pid;
- unsigned char *stream;
-
- /*
- * A PMT in a single section should start with a payload unit start
- * indicator set.
- */
- if (!pus) {
- fprintf (stderr, "demux error! PMT without payload unit start\n");
- return;
- }
-
- /*
- * PMT packets with a pus start with a pointer. Skip it!
- */
- pkt += pkt[4];
- if (pkt - originalPkt > PKT_SIZE) {
- fprintf (stderr, "demux error! PMT with invalid pointer\n");
- return;
- }
- if (!(pkt[10] & 0x01)) {
- /*
- * Not current!
- */
- return;
- }
- length = (((unsigned int)pkt[6] & 0x3) << 8) | pkt[7];
- if (pkt - originalPkt > BODY_SIZE - 1 - 3 - (int)length) {
- fprintf (stderr, "demux error! PMT with invalid section length\n");
- return;
- }
- if ((pkt[11]) || (pkt[12])) {
- fprintf (stderr, "demux error! PMT with invalid section %02x of %02x\n", pkt[11], pkt[12]);
- return;
- }
-
- /*
- * TBD: at this point, we should check the CRC. Its not that expensive, and
- * the consequences of getting it wrong are dire!
- */
-
+ unsigned int length;
+ unsigned int programInfoLength;
+ unsigned int codedLength;
+ unsigned int mediaIndex;
+ unsigned int pid;
+ unsigned char *stream;
+
+ /*
+ * A PMT in a single section should start with a payload unit start
+ * indicator set.
+ */
+ if (!pus) {
+ fprintf (stderr, "demux error! PMT without payload unit start\n");
+ return;
+ }
+
+ /*
+ * PMT packets with a pus start with a pointer. Skip it!
+ */
+ pkt += pkt[4];
+ if (pkt - originalPkt > PKT_SIZE) {
+ fprintf (stderr, "demux error! PMT with invalid pointer\n");
+ return;
+ }
+ if (!(pkt[10] & 0x01)) {
/*
- * ES definitions start here...we are going to learn upto one video
- * PID and one audio PID.
+ * Not current!
*/
-
- programInfoLength = (((unsigned int)pkt[15] & 0x0f) << 8) | pkt[16];
- stream = &pkt[17] + programInfoLength;
- codedLength = 13 + programInfoLength;
+ return;
+ }
+ length = (((unsigned int)pkt[6] & 0x3) << 8) | pkt[7];
+ if (pkt - originalPkt > BODY_SIZE - 1 - 3 - (int)length) {
+ fprintf (stderr, "demux error! PMT with invalid section length\n");
+ return;
+ }
+ if ((pkt[11]) || (pkt[12])) {
+ fprintf (stderr, "demux error! PMT with invalid section %02x of %02x\n", pkt[11], pkt[12]);
+ return;
+ }
+
+ /*
+ * TBD: at this point, we should check the CRC. Its not that expensive, and
+ * the consequences of getting it wrong are dire!
+ */
+
+ /*
+ * ES definitions start here...we are going to learn upto one video
+ * PID and one audio PID.
+ */
+
+ programInfoLength = (((unsigned int)pkt[15] & 0x0f) << 8) | pkt[16];
+ stream = &pkt[17] + programInfoLength;
+ codedLength = 13 + programInfoLength;
+ if (codedLength > length) {
+ fprintf (stderr, "demux error! PMT with inconsistent progInfo length\n");
+ return;
+ }
+ length -= codedLength;
+
+ /*
+ * Extract the elementary streams.
+ */
+ mediaIndex = 0;
+ while (length > 0) {
+ unsigned int streamInfoLength;
+
+ pid = (((unsigned int)stream[1] & 0x1f) << 8) | stream[2];
+ streamInfoLength = (((unsigned int)stream[3] & 0xf) << 8) | stream[4];
+ codedLength = 5 + streamInfoLength;
if (codedLength > length) {
- fprintf (stderr, "demux error! PMT with inconsistent progInfo length\n");
- return;
+ fprintf (stderr, "demux error! PMT with inconsistent streamInfo length\n");
+ return;
}
- length -= codedLength;
-
+
/*
- * Extract the elementary streams.
+ * Squirrel away the first audio and the first video stream. TBD: there
+ * should really be a way to select the stream of interest.
*/
- mediaIndex = 0;
- while (length > 0) {
- unsigned int streamInfoLength;
-
- pid = (((unsigned int)stream[1] & 0x1f) << 8) | stream[2];
- streamInfoLength = (((unsigned int)stream[3] & 0xf) << 8) | stream[4];
- codedLength = 5 + streamInfoLength;
- if (codedLength > length) {
- fprintf (stderr, "demux error! PMT with inconsistent streamInfo length\n");
- return;
- }
-
- /*
- * Squirrel away the first audio and the first video stream. TBD: there
- * should really be a way to select the stream of interest.
- */
- switch (stream[0]) {
- case ISO_11172_VIDEO:
- case ISO_13818_VIDEO:
- if (this->videoPid == INVALID_PID) {
- xprintf(VERBOSE|DEMUX, "video pid %04x\n", pid);
- demux_ts_pes_new(this, mediaIndex, pid, this->fifoVideo);
- }
- this->videoPid = pid;
- this->videoMedia = mediaIndex;
- break;
- case ISO_11172_AUDIO:
- case ISO_13818_AUDIO:
- if (this->audioPid == INVALID_PID) {
- xprintf(VERBOSE|DEMUX, "audio pid %04x\n", pid);
- demux_ts_pes_new(this, mediaIndex, pid, this->fifoAudio);
- }
- this->audioPid = pid;
- this->audioMedia = mediaIndex;
- break;
- default:
- break;
- }
- mediaIndex++;
- stream += codedLength;
- length -= codedLength;
+ switch (stream[0]) {
+ case ISO_11172_VIDEO:
+ case ISO_13818_VIDEO:
+ if (this->videoPid == INVALID_PID) {
+ xprintf(VERBOSE|DEMUX, "video pid %04x\n", pid);
+ demux_ts_pes_new(this, mediaIndex, pid, this->fifoVideo);
+ }
+ this->videoPid = pid;
+ this->videoMedia = mediaIndex;
+ break;
+ case ISO_11172_AUDIO:
+ case ISO_13818_AUDIO:
+ if (this->audioPid == INVALID_PID) {
+ xprintf(VERBOSE|DEMUX, "audio pid %04x\n", pid);
+ demux_ts_pes_new(this, mediaIndex, pid, this->fifoAudio);
+ }
+ this->audioPid = pid;
+ this->audioMedia = mediaIndex;
+ break;
+ default:
+ break;
}
-
- /*
- * Get the current PCR PID.
- */
- pid = (((unsigned int)pkt[13] & 0x1f) << 8) |
- pkt[14];
- if (this->pcrPid != pid) {
- if (this->pcrPid == INVALID_PID) {
- xprintf(VERBOSE|DEMUX, "pcr pid %04x\n", pid);
- } else {
- xprintf(VERBOSE|DEMUX, "pcr pid changed %04x\n", pid);
- }
- this->pcrPid = pid;
+ mediaIndex++;
+ stream += codedLength;
+ length -= codedLength;
+ }
+
+ /*
+ * Get the current PCR PID.
+ */
+ pid = (((unsigned int)pkt[13] & 0x1f) << 8) |
+ pkt[14];
+ if (this->pcrPid != pid) {
+ if (this->pcrPid == INVALID_PID) {
+ xprintf(VERBOSE|DEMUX, "pcr pid %04x\n", pid);
+ } else {
+ xprintf(VERBOSE|DEMUX, "pcr pid changed %04x\n", pid);
}
+ this->pcrPid = pid;
+ }
}
/*********************************************************************
@@ -632,26 +645,24 @@ static void demux_ts_pmt_parse(
/* When we've acquired sync, we need to set all of the continuity
* counters to an invalid value to disable the sequence checking */
-static void resetAllCCs(demux_ts * this)
-{
- int i;
- for (i = 0; i != MAX_PIDS; ++i)
- this->media[i].counter = INVALID_CC;
+static void resetAllCCs(demux_ts * this) {
+ int i;
+ for (i = 0; i != MAX_PIDS; ++i)
+ this->media[i].counter = INVALID_CC;
}
/* Find the first sync byte in the packet pointed to by p */
-static int searchForSyncByte(const unsigned char * p)
-{
- const unsigned char * start = p, * end = p + PKT_SIZE;
-
- while (p != end && *p != SYNC_BYTE)
- p++;
-
- if (p == end)
- return -1;
- else
- return p - start;
+static int searchForSyncByte(const unsigned char * p) {
+ const unsigned char * start = p, * end = p + PKT_SIZE;
+
+ while (p != end && *p != SYNC_BYTE)
+ p++;
+
+ if (p == end)
+ return -1;
+ else
+ return p - start;
}
/* Main synchronisation routine.
@@ -660,52 +671,51 @@ static int searchForSyncByte(const unsigned char * p)
* loop, so its harmless and easier than doing the packet looping internally.
*/
-static unsigned char * demux_synchronise(demux_ts * this)
-{
- static int in, out, count; /* statics are zeroed */
- static unsigned char buf[BUF_SIZE];
-
- int syncByte, syncBytePosn;
- unsigned char * retPtr = NULL;
-
- if (this->input->read(this->input, &buf[in], PKT_SIZE) != PKT_SIZE) {
- if (count > 0) {
- int oldOut = out; /* drain pipeline on end of stream */
- BUMP(out);
- count--;
- retPtr = &buf[oldOut];
- } else {
- this->status = DEMUX_FINISHED;
- }
- return retPtr;
- }
-
- syncBytePosn = out;
- WRAP_ADD(syncBytePosn, count * PKT_SIZE, BUF_SIZE - PKT_SIZE);
- syncByte = buf[syncBytePosn];
-
- if (syncByte != SYNC_BYTE) { /* new packet not in sync */
- int syncPosn = searchForSyncByte(&buf[in]);
- if (syncPosn > 0) {
- memmove(&buf[0], &buf[in + syncPosn], PKT_SIZE - syncPosn);
- in = PKT_SIZE - syncPosn;
- } else {
- in = 0; /* no sync byte in packet, so start again */
- }
- out = count = 0;
- } else { /* this packet extends the sync run */
- BUMP(in);
- count++;
- if (count > MIN_SYNCS) { /* sync acquired */
- int oldOut = out;
- resetAllCCs(this);
- BUMP(out);
- count--;
- retPtr = &buf[oldOut];
- }
+static unsigned char * demux_synchronise(demux_ts * this) {
+ static int in, out, count; /* statics are zeroed */
+ static unsigned char buf[BUF_SIZE];
+
+ int syncByte, syncBytePosn;
+ unsigned char * retPtr = NULL;
+
+ if (this->input->read(this->input, &buf[in], PKT_SIZE) != PKT_SIZE) {
+ if (count > 0) {
+ int oldOut = out; /* drain pipeline on end of stream */
+ BUMP(out);
+ count--;
+ retPtr = &buf[oldOut];
+ } else {
+ this->status = DEMUX_FINISHED;
}
-
return retPtr;
+ }
+
+ syncBytePosn = out;
+ WRAP_ADD(syncBytePosn, count * PKT_SIZE, BUF_SIZE - PKT_SIZE);
+ syncByte = buf[syncBytePosn];
+
+ if (syncByte != SYNC_BYTE) { /* new packet not in sync */
+ int syncPosn = searchForSyncByte(&buf[in]);
+ if (syncPosn > 0) {
+ memmove(&buf[0], &buf[in + syncPosn], PKT_SIZE - syncPosn);
+ in = PKT_SIZE - syncPosn;
+ } else {
+ in = 0; /* no sync byte in packet, so start again */
+ }
+ out = count = 0;
+ } else { /* this packet extends the sync run */
+ BUMP(in);
+ count++;
+ if (count > MIN_SYNCS) { /* sync acquired */
+ int oldOut = out;
+ resetAllCCs(this);
+ BUMP(out);
+ count--;
+ retPtr = &buf[oldOut];
+ }
+ }
+
+ return retPtr;
}
#undef BUMP
@@ -714,423 +724,223 @@ static unsigned char * demux_synchronise(demux_ts * this)
#undef BUF_SIZE
#undef SYNC_BYTE
-/***************************************************************************/
-
-static void demux_ts_parse_ts(
- demux_ts *this)
-{
- /* unsigned char originalPkt[PKT_SIZE]; */
- unsigned char * originalPkt;
- unsigned int sync_byte;
- unsigned int transport_error_indicator;
- unsigned int payload_unit_start_indicator;
- unsigned int transport_priority;
- unsigned int pid;
- unsigned int transport_scrambling_control;
- unsigned int adaption_field_control;
- unsigned int continuity_counter;
- unsigned int data_offset;
- unsigned int data_len;
-
- /* get next synchronised packet, or NULL */
- originalPkt = demux_synchronise(this);
- if (originalPkt == NULL)
- return;
-
- sync_byte=originalPkt[0];
- transport_error_indicator = (originalPkt[1] >> 7) & 0x01;
- payload_unit_start_indicator = (originalPkt[1] >> 6) & 0x01;
- transport_priority = (originalPkt[1] >> 5) & 0x01;
- pid = ((originalPkt[1] << 8) | originalPkt[2]) & 0x1fff;
- transport_scrambling_control = (originalPkt[3] >> 6) & 0x03;
- adaption_field_control = (originalPkt[3] >> 4) & 0x03;
- continuity_counter = originalPkt[3] & 0x0f;
+/* transport stream packet layer */
+
+static void demux_ts_parse_packet (demux_ts *this) {
+
+ unsigned char *originalPkt;
+ unsigned int sync_byte;
+ unsigned int transport_error_indicator;
+ unsigned int payload_unit_start_indicator;
+ unsigned int transport_priority;
+ unsigned int pid;
+ unsigned int transport_scrambling_control;
+ unsigned int adaption_field_control;
+ unsigned int continuity_counter;
+ unsigned int data_offset;
+ unsigned int data_len;
+
+ /* get next synchronised packet, or NULL */
+ originalPkt = demux_synchronise(this);
+ if (originalPkt == NULL)
+ return;
+
+ sync_byte = originalPkt[0];
+ transport_error_indicator = (originalPkt[1] >> 7) & 0x01;
+ payload_unit_start_indicator = (originalPkt[1] >> 6) & 0x01;
+ transport_priority = (originalPkt[1] >> 5) & 0x01;
+ pid = ((originalPkt[1] << 8) | originalPkt[2]) & 0x1fff;
+ transport_scrambling_control = (originalPkt[3] >> 6) & 0x03;
+ adaption_field_control = (originalPkt[3] >> 4) & 0x03;
+ continuity_counter = originalPkt[3] & 0x0f;
+
+ /*
+ * Discard packets that are obviously bad.
+ * FIXME: maybe search for 0x47 is the first 188 bytes[packet size] of stream.
+ */
+ if (sync_byte != 0x47) {
+ fprintf (stderr, "demux error! invalid ts sync byte %02x\n",originalPkt[0]);
+ return;
+ }
+ if (transport_error_indicator) {
+ fprintf (stderr, "demux error! transport error\n");
+ return;
+ }
+
+ data_offset=4;
+ if (adaption_field_control & 0x1) {
/*
- * Discard packets that are obviously bad.
- * FIXME: maybe search for 0x47 is the first 188 bytes[packet size] of stream.
+ * Has a payload! Calculate & check payload length.
*/
- if (sync_byte != 0x47) {
- fprintf (stderr, "demux error! invalid ts sync byte %02x\n",originalPkt[0]);
- return;
- }
- if (transport_error_indicator) {
- fprintf (stderr, "demux error! transport error\n");
- return;
+ if (adaption_field_control & 0x2) {
+ /*
+ * Skip adaptation header.
+ */
+ data_offset+=originalPkt[4]+1;
}
-/*
- for(n=0;n<4;n++) {fprintf(stderr,"%02X ",originalPkt[n]);}
- fprintf(stderr," sync:%02X TE:%02X PUS:%02X TP:%02X PID:%04X TSC:%02X AFC:%02X CC:%02X\n",
- sync_byte,
- transport_error_indicator,
- payload_unit_start_indicator,
- transport_priority,
- pid,
- transport_scrambling_control,
- adaption_field_control,
- continuity_counter );
- */
-
- data_offset=4;
- if (adaption_field_control & 0x1) {
- /*
- * Has a payload! Calculate & check payload length.
- */
- if (adaption_field_control & 0x2) {
- /*
- * Skip adaptation header.
- */
- data_offset+=originalPkt[4]+1;
- }
- data_len = PKT_SIZE - data_offset;
- if (data_len > PKT_SIZE) {
- fprintf (stderr, "demux error! invalid payload size %d\n",data_len);
- } else {
-
- /*
- * Do the demuxing in descending order of packet frequency!
- */
- if (pid == this->videoPid ) {
- demux_ts_pes_buffer(this, originalPkt+data_offset, this->videoMedia, payload_unit_start_indicator, continuity_counter, data_len);
- } else if (pid == this->audioPid) {
- demux_ts_pes_buffer(this, originalPkt+data_offset, this->audioMedia, payload_unit_start_indicator, continuity_counter, data_len);
- } else if (pid == this->pmtPid) {
- demux_ts_pmt_parse(this, originalPkt, originalPkt+data_offset-4, payload_unit_start_indicator);
- } else if (pid == 0) {
- demux_ts_pat_parse(this, originalPkt, originalPkt+data_offset-4, payload_unit_start_indicator);
- } else if (pid == 0x1fff) {
- /* fprintf(stderr,"Null Packet\n"); */
- }
- }
- }
-
- /*
- * Now check for PCRs. First test for an adaptation header, since
- * that is the most likely test to fail.
- */
-}
-
-static void demux_ts_queue_pes(
- demux_ts *this,
- buf_element_t *buf)
-{
- unsigned char *p;
- int bMpeg1=0;
- uint32_t nHeaderLen;
- uint32_t nPTS;
- uint32_t nDTS;
- uint32_t nPacketLen;
- uint32_t nStreamID;
-
- p = buf->mem; /* len = this->blockSize; */
- /* FIXME: HACK to get the decoders working */
- buf->decoder_info[0] = 1;
- /* we should have a PES packet here */
-
- if (p[0] || p[1] || (p[2] != 1)) {
- fprintf (stderr, "demux error! %02x %02x %02x (should be 0x000001) \n",p[0],p[1],p[2]);
- buf->free_buffer(buf);
- return ;
- }
- nPacketLen = p[4] << 8 | p[5];
- nStreamID = p[3];
+ data_len = PKT_SIZE - data_offset;
- xprintf(VERBOSE|DEMUX, "packet stream id = %02x len = %d\n",nStreamID, nPacketLen);
+ if (data_len > PKT_SIZE) {
- if (bMpeg1) {
+ printf ("demux_ts: demux error! invalid payload size %d\n",data_len);
- if (nStreamID == 0xBF) {
- buf->free_buffer(buf);
- return ;
- }
-
- p += 6; /* nPacketLen -= 6; */
-
- while ((p[0] & 0x80) == 0x80) {
- p++;
- nPacketLen--;
- /* printf ("stuffing\n");*/
- }
-
- if ((p[0] & 0xc0) == 0x40) {
- /* STD_buffer_scale, STD_buffer_size */
- p += 2;
- nPacketLen -=2;
- }
-
- nPTS = 0;
- nDTS = 0;
- if ((p[0] & 0xf0) == 0x20) {
- nPTS = (p[ 0] & 0x0E) << 29 ;
- nPTS |= p[ 1] << 22 ;
- nPTS |= (p[ 2] & 0xFE) << 14 ;
- nPTS |= p[ 3] << 7 ;
- nPTS |= (p[ 4] & 0xFE) >> 1 ;
- p += 5;
- nPacketLen -=5;
- } else if ((p[0] & 0xf0) == 0x30) {
- nPTS = (p[ 0] & 0x0E) << 29 ;
- nPTS |= p[ 1] << 22 ;
- nPTS |= (p[ 2] & 0xFE) << 14 ;
- nPTS |= p[ 3] << 7 ;
- nPTS |= (p[ 4] & 0xFE) >> 1 ;
- nDTS = (p[ 5] & 0x0E) << 29 ;
- nDTS |= p[ 6] << 22 ;
- nDTS |= (p[ 7] & 0xFE) << 14 ;
- nDTS |= p[ 8] << 7 ;
- nDTS |= (p[ 9] & 0xFE) >> 1 ;
- p += 10;
- nPacketLen -= 10;
} else {
- p++;
- nPacketLen --;
+
+ /*
+ * Do the demuxing in descending order of packet frequency!
+ */
+ if (pid == this->videoPid ) {
+ demux_ts_buffer_pes (this, originalPkt+data_offset, this->videoMedia,
+ payload_unit_start_indicator, continuity_counter, data_len);
+ } else if (pid == this->audioPid) {
+ demux_ts_buffer_pes (this, originalPkt+data_offset, this->audioMedia,
+ payload_unit_start_indicator, continuity_counter, data_len);
+ } else if (pid == this->pmtPid) {
+ demux_ts_parse_pmt (this, originalPkt, originalPkt+data_offset-4, payload_unit_start_indicator);
+ } else if (pid == 0) {
+ demux_ts_parse_pat (this, originalPkt, originalPkt+data_offset-4, payload_unit_start_indicator);
+ } else if (pid == 0x1fff) {
+ /* fprintf(stderr,"Null Packet\n"); */
+ }
}
+ }
+
+}
- } else { /* mpeg 2 */
-
- if (p[7] & 0x80) { /* PTS avail */
-
- nPTS = (p[ 9] & 0x0E) << 29 ;
- nPTS |= p[10] << 22 ;
- nPTS |= (p[11] & 0xFE) << 14 ;
- nPTS |= p[12] << 7 ;
- nPTS |= (p[13] & 0xFE) >> 1 ;
-
- } else
- nPTS = 0;
-
- if (p[7] & 0x40) { /* PTS avail */
-
- nDTS = (p[14] & 0x0E) << 29 ;
- nDTS |= p[15] << 22 ;
- nDTS |= (p[16] & 0xFE) << 14 ;
- nDTS |= p[17] << 7 ;
- nDTS |= (p[18] & 0xFE) >> 1 ;
-
- } else
- nDTS = 0;
-
-
- nHeaderLen = p[8];
+/*
+ * Sit in a loop eating data.
+ */
+static void *demux_ts_loop(void *gen_this) {
- p += nHeaderLen + 9;
- nPacketLen -= nHeaderLen + 3;
+ demux_ts *this = (demux_ts *)gen_this;
+ buf_element_t *buf;
+
+ do {
+ demux_ts_parse_packet(this);
+ } while (this->status == DEMUX_OK) ;
+
+ xprintf(VERBOSE|DEMUX, "demux loop finished (status: %d)\n", this->status);
+
+ this->status = DEMUX_FINISHED;
+ buf = this->fifoVideo->buffer_pool_alloc(this->fifoVideo);
+ buf->type = BUF_CONTROL_END;
+ buf->decoder_info[0] = 0; /* stream finished */
+ this->fifoVideo->put(this->fifoVideo, buf);
+
+ if (this->fifoAudio) {
+ buf = this->fifoAudio->buffer_pool_alloc(this->fifoAudio);
+ buf->type = BUF_CONTROL_END;
+ buf->decoder_info[0] = 0; /* stream finished */
+ this->fifoAudio->put(this->fifoAudio, buf);
}
+ pthread_exit(NULL);
+ return NULL;
+}
- xprintf(VERBOSE|DEMUX, "stream_id=%x len=%d pts=%d dts=%d\n", nStreamID, nPacketLen, nPTS, nDTS);
-
- if (nStreamID == 0xbd) {
+static void demux_ts_close(demux_plugin_t *gen_this) {
- int nTrack,nSPUID;
+ /* nothing */
+}
- nTrack = p[0] & 0x0F; /* hack : ac3 track */
+static char *demux_ts_get_id(void) {
+ return "MPEG_TS";
+}
- if((p[0] & 0xE0) == 0x20) {
- nSPUID = (p[0] & 0x1f);
+static int demux_ts_get_status(demux_plugin_t *this_gen) {
- xprintf(VERBOSE|DEMUX, "SPU PES packet, id 0x%03x\n",p[0] & 0x1f);
+ demux_ts *this = (demux_ts *)this_gen;
- if((this->mnSPUChannel >= 0)
- && (this->fifoSPU != NULL)
- && (nSPUID == this->mnSPUChannel)) {
- buf->content = p+1;
- buf->size = nPacketLen-1;
- buf->type = BUF_SPU_PACKAGE;
- buf->PTS = nPTS;
- buf->DTS = nDTS ;
- buf->input_pos = this->input->seek(this->input, 0, SEEK_CUR);
+ return this->status;
+}
- this->fifoSPU->put(this->fifoSPU, buf);
- return;
+static int demux_ts_open(demux_plugin_t *this_gen, input_plugin_t *input,
+ int stage) {
+
+ demux_ts *this = (demux_ts *) this_gen;
+ char *mrl;
+ char *media;
+ char *ending;
+
+ switch (stage) {
+ case STAGE_BY_EXTENSION:
+ mrl = input->get_mrl(input);
+ media = strstr(mrl, "://");
+ if (media) {
+ fprintf (stderr, "demux %u ts_open! \n", __LINE__);
+ if ((!(strncasecmp(mrl, "stdin", 5))) || (!(strncasecmp(mrl, "fifo", 4)))) {
+ if(!(strncasecmp(media+3, "ts", 3))) {
+ break;
+ }
+ return DEMUX_CANNOT_HANDLE;
+ }
+ else if (strncasecmp(mrl, "file", 4)) {
+ return DEMUX_CANNOT_HANDLE;
}
}
-
- if (((p[0]&0xF0) == 0x80) && (nTrack == this->mnAudioChannel)) {
-
- xprintf(VERBOSE|DEMUX|AC3, "ac3 PES packet, track %02x\n",nTrack);
- /* printf ( "ac3 PES packet, track %02x\n",nTrack); */
-
- buf->content = p+4;
- buf->size = nPacketLen-4;
- buf->type = BUF_AUDIO_A52;
- buf->PTS = nPTS;
- buf->DTS = nDTS ;
- buf->input_pos = this->input->seek(this->input, 0, SEEK_CUR);
-
- this->fifoAudio->put(this->fifoAudio, buf);
- return ;
- } else if (((p[0]&0xf0) == 0xa0) || (nTrack == (this->mnAudioChannel-16))) {
-
- int pcm_offset;
-
- xprintf(VERBOSE|DEMUX,"LPCMacket, len : %d %02x\n",nPacketLen-4, p[0]);
-
- /* printf ("PCM!!!!!!!!!!!!!!!!!!!!!!!\n"); */
-
- for( pcm_offset=0; ++pcm_offset < nPacketLen-1 ; ){
- if ( p[pcm_offset] == 0x01 && p[pcm_offset+1] == 0x80 ) { /* START */
- pcm_offset += 2;
- break;
- }
+ ending = strrchr(mrl, '.');
+ if (ending) {
+ xprintf(VERBOSE|DEMUX, "demux_ts_open: ending %s of %s\n", ending, mrl);
+ if ((!strcasecmp(ending, ".m2t")) || (!strcasecmp(ending, ".ts"))) {
+ break;
}
-
- buf->content = p+pcm_offset;
- buf->size = nPacketLen-pcm_offset;
- buf->type = BUF_AUDIO_LPCM_BE;
- buf->PTS = nPTS;
- buf->DTS = nDTS ;
- buf->input_pos = this->input->seek(this->input, 0, SEEK_CUR);
-
- this->fifoAudio->put(this->fifoAudio, buf);
- return ;
}
-
- } else if ((nStreamID >= 0xbc) && ((nStreamID & 0xf0) == 0xe0)) {
-
- xprintf(VERBOSE|DEMUX, "video %X\n", nStreamID);
-
- buf->content = p;
- buf->size = nPacketLen;
- buf->type = BUF_VIDEO_MPEG;
- buf->PTS = nPTS;
- buf->DTS = nDTS;
-
- this->fifoVideo->put(this->fifoVideo, buf);
- return ;
-
- } else if ((nStreamID & 0xe0) == 0xc0) {
- int nTrack;
-
- nTrack = nStreamID & 0x1f;
-
- xprintf(VERBOSE|DEMUX|MPEG, "mpg audio #%d\n", nTrack);
- xprintf(VERBOSE|DEMUX|MPEG, "bMpeg1=%d this->mnAudioChannel %d\n", bMpeg1, this->mnAudioChannel);
-
-// if ((bMpeg1 && (nTrack == this->mnAudioChannel))
-// || (!bMpeg1 && (nTrack == (this->mnAudioChannel-8)))) {
-
- buf->content = p;
- buf->size = nPacketLen;
- buf->type = BUF_AUDIO_MPEG;
- buf->PTS = nPTS;
- buf->DTS = nDTS;
- buf->input_pos = this->input->seek(this->input, 0, SEEK_CUR);
-
- this->fifoAudio->put(this->fifoAudio, buf);
- return ;
-// }
-
- } else {
- xprintf(VERBOSE | DEMUX, "unknown packet, id = %x\n",nStreamID);
+ return DEMUX_CANNOT_HANDLE;
+ default:
+ return DEMUX_CANNOT_HANDLE;
}
-
- buf->free_buffer(buf);
- return ;
-}
-
-static void demux_ts_close(
- demux_plugin_t *gen_this)
-{
- /* nothing */
+
+ this->input = input;
+ this->blockSize = PKT_SIZE;
+ return DEMUX_CAN_HANDLE;
}
-static char *demux_ts_get_id(
- void)
-{
- return "MPEG_TS";
-}
+static void demux_ts_start(demux_plugin_t *this_gen,
+ fifo_buffer_t *fifoVideo,
+ fifo_buffer_t *fifoAudio,
+ off_t start_pos, int start_time,
+ gui_get_next_mrl_cb_t next_mrl_cb,
+ gui_branched_cb_t branched_cb) {
-static int demux_ts_get_status(
- demux_plugin_t *this_gen)
-{
- demux_ts *this = (demux_ts *)this_gen;
- return this->status;
-}
-
-static int demux_ts_open(
- demux_plugin_t *this_gen,
- input_plugin_t *input,
- int stage)
-{
- demux_ts *this = (demux_ts *) this_gen;
- char *mrl;
- char *media;
- char *ending;
-
- switch (stage) {
- case STAGE_BY_EXTENSION:
- mrl = input->get_mrl(input);
- media = strstr(mrl, "://");
- if (media) {
-fprintf (stderr, "demux %u ts_open! \n", __LINE__);
- if ((!(strncasecmp(mrl, "stdin", 5))) || (!(strncasecmp(mrl, "fifo", 4)))) {
- if(!(strncasecmp(media+3, "ts", 3))) {
- break;
- }
- return DEMUX_CANNOT_HANDLE;
- }
- else if (strncasecmp(mrl, "file", 4)) {
- return DEMUX_CANNOT_HANDLE;
- }
- }
- ending = strrchr(mrl, '.');
- if (ending) {
- xprintf(VERBOSE|DEMUX, "demux_ts_open: ending %s of %s\n", ending, mrl);
- if ((!strcasecmp(ending, ".m2t")) || (!strcasecmp(ending, ".ts"))) {
- break;
- }
- }
- return DEMUX_CANNOT_HANDLE;
- default:
- return DEMUX_CANNOT_HANDLE;
- }
+ demux_ts *this = (demux_ts *)this_gen;
+ buf_element_t *buf;
+
+ this->fifoVideo = fifoVideo;
+ this->fifoAudio = fifoAudio;
+
+ /*
+ * send start buffers
+ */
+ buf = this->fifoVideo->buffer_pool_alloc(this->fifoVideo);
+ buf->type = BUF_CONTROL_START;
+ this->fifoVideo->put(this->fifoVideo, buf);
+ if (this->fifoAudio) {
+ buf = this->fifoAudio->buffer_pool_alloc(this->fifoAudio);
+ buf->type = BUF_CONTROL_START;
+ this->fifoAudio->put(this->fifoAudio, buf);
+ }
+
+ this->status = DEMUX_OK ;
+ this->broken_pes = 1;
- this->input = input;
- this->blockSize = PKT_SIZE;
- return DEMUX_CAN_HANDLE;
-}
+
+ if ((this->input->get_capabilities (this->input) & INPUT_CAP_SEEKABLE) != 0 ) {
-static void demux_ts_start(
- demux_plugin_t *this_gen,
- fifo_buffer_t *fifoVideo,
- fifo_buffer_t *fifoAudio,
- off_t pos,
- gui_get_next_mrl_cb_t next_mrl_cb,
- gui_branched_cb_t branched_cb)
-{
- demux_ts *this = (demux_ts *)this_gen;
- buf_element_t *buf;
+ if ( (!start_pos) && (start_time))
+ start_pos = start_time * this->rate * 50;
- this->fifoVideo = fifoVideo;
- this->fifoAudio = fifoAudio;
+ this->input->seek (this->input, start_pos, SEEK_SET);
- /*
- * Send reset buffer.
- */
- buf = this->fifoVideo->buffer_pool_alloc(this->fifoVideo);
- buf->type = BUF_CONTROL_START;
- this->fifoVideo->put(this->fifoVideo, buf);
- if (this->fifoAudio) {
- buf = this->fifoAudio->buffer_pool_alloc(this->fifoAudio);
- buf->type = BUF_CONTROL_START;
- this->fifoAudio->put(this->fifoAudio, buf);
- }
+ }
- this->status = DEMUX_OK ;
- if (this->input->get_blocksize(this->input))
- this->blockSize = this->input->get_blocksize(this->input);
- pos /= (off_t)this->blockSize;
- pos *= (off_t)this->blockSize;
-
- /*
- * Now start demuxing.
- */
- pthread_create(&this->thread, NULL, demux_ts_loop, this);
+ /*
+ * Now start demuxing.
+ */
+ pthread_create(&this->thread, NULL, demux_ts_loop, this);
}
-static void demux_ts_stop(
- demux_plugin_t *this_gen)
+static void demux_ts_stop(demux_plugin_t *this_gen)
{
demux_ts *this = (demux_ts *)this_gen;
buf_element_t *buf;
@@ -1166,45 +976,56 @@ static void demux_ts_stop(
}
}
-demux_plugin_t *init_demuxer_plugin(
- int iface,
- config_values_t *config)
-{
- demux_ts *this;
- int i;
-
- if (iface != 2) {
- printf(
- "demux_ts: plugin doesn't support plugin API version %d.\n"
- "demux_ts: this means there's a version mismatch between xine and this "
- "demux_ts: demuxer plugin.\nInstalling current input plugins should help.\n",
- iface);
- return NULL;
- }
+static int demux_ts_get_stream_length (demux_plugin_t *this_gen) {
- /*
- * Initialise the generic plugin.
- */
- this = xmalloc(sizeof(*this));
- xine_debug = config->lookup_int(config, "xine_debug", 0);
- this->plugin.interface_version = DEMUXER_PLUGIN_IFACE_VERSION;
- this->plugin.open = demux_ts_open;
- this->plugin.start = demux_ts_start;
- 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;
+ demux_ts *this = (demux_ts *)this_gen;
- /*
- * Initialise our specialised data.
- */
- this->mnSPUChannel = -1; /* Turn off SPU by default */
- for (i = 0; i < MAX_PIDS; i++)
- this->media[i].pid = INVALID_PID;
- this->programNumber = INVALID_PROGRAM;
- this->pmtPid = INVALID_PID;
- this->pcrPid = INVALID_PID;
- this->videoPid = INVALID_PID;
- this->audioPid = INVALID_PID;
- return (demux_plugin_t *)this;
+ return this->input->get_length (this->input) / (this->rate * 50);
}
+
+
+demux_plugin_t *init_demuxer_plugin(int iface, config_values_t *config) {
+
+ demux_ts *this;
+ int i;
+
+ if (iface != 3) {
+ printf("demux_ts: plugin doesn't support plugin API version %d.\n"
+ "demux_ts: this means there's a version mismatch between xine and this "
+ "demux_ts: demuxer plugin.\nInstalling current demux plugins should help.\n",
+ iface);
+ return NULL;
+ }
+
+ /*
+ * Initialise the generic plugin.
+ */
+ this = xmalloc(sizeof(*this));
+ xine_debug = config->lookup_int(config, "xine_debug", 0);
+ this->plugin.interface_version = DEMUXER_PLUGIN_IFACE_VERSION;
+ this->plugin.open = demux_ts_open;
+ this->plugin.start = demux_ts_start;
+ 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;
+
+ /*
+ * Initialise our specialised data.
+ */
+ for (i = 0; i < MAX_PIDS; i++)
+ this->media[i].pid = INVALID_PID;
+ this->programNumber = INVALID_PROGRAM;
+ this->pmtPid = INVALID_PID;
+ this->pcrPid = INVALID_PID;
+ this->videoPid = INVALID_PID;
+ this->audioPid = INVALID_PID;
+
+ this->rate = 16000; /* FIXME */
+
+ return (demux_plugin_t *)this;
+}
+
+
+
diff --git a/src/libmpeg2/decode.c b/src/libmpeg2/decode.c
index c08dc3ed2..58a9d4e32 100644
--- a/src/libmpeg2/decode.c
+++ b/src/libmpeg2/decode.c
@@ -300,7 +300,13 @@ static inline uint8_t * copy_chunk (mpeg2dec_t * mpeg2dec,
if (limit > end)
limit = end;
+ /*
+ printf ("copy chunk current %08x\n", current );
+ printf ("copy chunk end %08x\n", end); fflush(stdout);
+ */
+
while (1) {
+
byte = *current++;
if (shift != 0x00000100) {
shift = (shift | byte) << 8;
diff --git a/src/xine-engine/audio_decoder.c b/src/xine-engine/audio_decoder.c
index 0a98a15d8..707160c58 100644
--- a/src/xine-engine/audio_decoder.c
+++ b/src/xine-engine/audio_decoder.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: audio_decoder.c,v 1.31 2001/08/25 08:48:12 guenter Exp $
+ * $Id: audio_decoder.c,v 1.32 2001/09/01 14:33:00 guenter Exp $
*
*
* functions that implement audio decoding
@@ -54,6 +54,9 @@ void *audio_decoder_loop (void *this_gen) {
if (buf->input_pos)
this->cur_input_pos = buf->input_pos;
+ if (buf->input_time)
+ this->cur_input_time = buf->input_time;
+
/*
* Call update status callback function if
* there is no video decoder initialized, like
diff --git a/src/xine-engine/buffer.h b/src/xine-engine/buffer.h
index de98971f5..9cd17add0 100644
--- a/src/xine-engine/buffer.h
+++ b/src/xine-engine/buffer.h
@@ -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: buffer.h,v 1.7 2001/08/31 17:57:54 jkeil Exp $
+ * $Id: buffer.h,v 1.8 2001/09/01 14:33:00 guenter Exp $
*
*
* contents:
@@ -109,8 +109,9 @@ struct buf_element_s {
uint32_t size ; /* size of _content_ */
uint32_t max_size;
uint32_t type;
- uint32_t PTS, DTS;
+ uint32_t PTS;
off_t input_pos; /* remember where this buf came from in the input source */
+ int input_time;/* time offset in seconds from beginning of stream */
uint32_t decoder_info[4]; /* additional decoder flags and other dec-spec. stuff */
void (*free_buffer) (buf_element_t *buf);
diff --git a/src/xine-engine/video_decoder.c b/src/xine-engine/video_decoder.c
index 64d9748e4..83e716cae 100644
--- a/src/xine-engine/video_decoder.c
+++ b/src/xine-engine/video_decoder.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: video_decoder.c,v 1.44 2001/08/28 19:16:20 guenter Exp $
+ * $Id: video_decoder.c,v 1.45 2001/09/01 14:33:00 guenter Exp $
*
*/
@@ -66,6 +66,8 @@ void *video_decoder_loop (void *this_gen) {
buf = this->video_fifo->get (this->video_fifo);
if (buf->input_pos)
this->cur_input_pos = buf->input_pos;
+ if (buf->input_time)
+ this->cur_input_time = buf->input_time;
/* printf ("video_decoder: got buffer %d\n", buf->type); */
@@ -182,7 +184,7 @@ void *video_decoder_loop (void *this_gen) {
decoder->get_identifier());
}
-
+
decoder->decode_data (this->cur_video_decoder_plugin, buf);
}
} else
diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c
index a4878d7b9..b2abd26a0 100644
--- a/src/xine-engine/xine.c
+++ b/src/xine-engine/xine.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: xine.c,v 1.52 2001/08/29 11:14:12 guenter Exp $
+ * $Id: xine.c,v 1.53 2001/09/01 14:33:00 guenter Exp $
*
* top-level xine functions
*
@@ -75,11 +75,11 @@ void xine_stop (xine_t *this) {
pthread_mutex_unlock (&this->xine_lock);
return;
}
- else if(this->status == XINE_PAUSE) {
- this->metronom->set_speed (this->metronom, SPEED_NORMAL);
- this->paused = 0;
- this->audio_mute = 0;
- }
+
+
+ this->metronom->set_speed (this->metronom, SPEED_NORMAL);
+ this->speed = SPEED_NORMAL;
+ this->audio_mute = 0;
this->status = XINE_STOP;
printf ("xine_stop: stopping demuxer\n");
@@ -89,8 +89,6 @@ void xine_stop (xine_t *this) {
this->cur_demuxer_plugin = NULL;
}
- printf ("xine_stop: closing input\n");
-
if(this->cur_input_plugin) {
this->cur_input_plugin->close(this->cur_input_plugin);
/*
@@ -174,20 +172,38 @@ static int find_demuxer(xine_t *this, const char *MRL) {
return 0;
}
-static void xine_play_internal (xine_t *this, char *mrl,
- int spos, off_t pos) {
+void xine_play (xine_t *this, char *mrl,
+ int start_pos, int start_time) {
double share ;
- off_t len;
+ off_t pos, len;
int i;
- xprintf (VERBOSE|LOOP, "xine open %s, start pos = %d\n", mrl, spos);
+ xprintf (VERBOSE|LOOP, "xine open %s, start pos = %d\n", mrl, start_pos);
- printf ("xine_play_internal: open %s, start pos = %d\n", mrl, spos);
+ pthread_mutex_lock (&this->xine_lock);
- if (this->status != XINE_STOP) {
- printf ("xine_play_internal: error: xine is not stopped\n");
- return;
+ printf ("xine_play: open %s, start pos = %d\n", mrl, start_pos);
+
+ /*
+ * stop engine?
+ */
+
+ if (this->status == XINE_PLAY) {
+
+ if(this->cur_demuxer_plugin) {
+ this->cur_demuxer_plugin->stop (this->cur_demuxer_plugin);
+ }
+
+ if(this->cur_input_plugin) {
+
+ if (strcmp (mrl, this->cur_mrl))
+ this->cur_input_plugin->close(this->cur_input_plugin);
+ else
+ this->cur_input_plugin->stop(this->cur_input_plugin);
+ }
+
+ this->status = XINE_STOP;
}
/*
@@ -204,8 +220,9 @@ static void xine_play_internal (xine_t *this, char *mrl,
}
if (!this->cur_input_plugin) {
- perror ("open input source");
+ printf ("xine: cannot find input plugin for this MRL\n");
this->cur_demuxer_plugin = NULL;
+ pthread_mutex_unlock (&this->xine_lock);
return;
}
@@ -224,6 +241,7 @@ static void xine_play_internal (xine_t *this, char *mrl,
if(!find_demuxer(this, mrl)) {
printf ("xine: couldn't find demuxer for >%s<\n", mrl);
+ pthread_mutex_unlock (&this->xine_lock);
return;
}
@@ -234,94 +252,32 @@ static void xine_play_internal (xine_t *this, char *mrl,
* start demuxer
*/
- if (spos) {
+ if (start_pos) {
len = this->cur_input_plugin->get_length (this->cur_input_plugin);
- share = (double) spos / 65535;
+ share = (double) start_pos / 65535;
pos = (off_t) (share * len) ;
- }
+ } else
+ pos = 0;
this->cur_demuxer_plugin->start (this->cur_demuxer_plugin,
this->video_fifo,
this->audio_fifo,
- pos,
+ pos, start_time,
this->get_next_mrl_cb,
this->branched_cb);
this->status = XINE_PLAY;
strncpy (this->cur_mrl, mrl, 1024);
- printf ("xine: demuxer started\n");
-
-}
+ this->metronom->set_speed (this->metronom, SPEED_NORMAL);
+ this->audio_mute = 0;
+ this->speed = SPEED_NORMAL;
-void xine_play (xine_t *this, char *MRL, int spos) {
-
- pthread_mutex_lock (&this->xine_lock);
-
- if(this->status == XINE_PAUSE) {
-
- this->metronom->set_speed (this->metronom, SPEED_NORMAL);
- this->paused = 0;
- this->audio_mute = 0;
-
- if(this->cur_demuxer_plugin) {
- this->cur_demuxer_plugin->stop (this->cur_demuxer_plugin);
- this->cur_demuxer_plugin = NULL;
- }
-
- printf ("xine_stop: closing input\n");
-
- if(this->cur_input_plugin) {
- this->cur_input_plugin->close(this->cur_input_plugin);
- }
-
- this->status = XINE_STOP;
-
- }
- else if (this->status != XINE_STOP) {
-
- this->metronom->set_speed (this->metronom, SPEED_NORMAL);
- this->audio_mute = 0;
-
- pthread_mutex_unlock (&this->xine_lock);
- return;
- }
-
- xine_play_internal (this, MRL, spos, (off_t) 0);
+ printf ("xine_play: demuxer started\n");
pthread_mutex_unlock (&this->xine_lock);
}
-void xine_seek (xine_t *this, char *mrl, int pos) {
-
- pthread_mutex_lock (&this->xine_lock);
-
- printf ("xine_seek\n");
-
- if (this->status == XINE_PLAY || this->status == XINE_PAUSE) {
-
- if(this->status == XINE_PAUSE) {
- this->metronom->set_speed (this->metronom, SPEED_NORMAL);
- this->paused = 0;
- this->audio_mute = 0;
- }
-
- if(this->cur_demuxer_plugin) {
- this->cur_demuxer_plugin->stop (this->cur_demuxer_plugin);
- }
-
- if(this->cur_input_plugin) {
- this->cur_input_plugin->stop(this->cur_input_plugin);
- }
-
- this->status = XINE_STOP;
- }
-
- xine_play_internal (this, mrl, pos, (off_t)0);
-
- pthread_mutex_unlock (&this->xine_lock);
-}
-
int xine_eject (xine_t *this) {
if(this->cur_input_plugin == NULL)
@@ -347,11 +303,9 @@ void xine_exit (xine_t *this) {
pthread_mutex_lock (&this->xine_lock);
- if(this->status == XINE_PAUSE) {
- this->metronom->set_speed (this->metronom, SPEED_NORMAL);
- this->paused = 0;
- this->status = XINE_STOP;
- }
+ this->metronom->set_speed (this->metronom, SPEED_NORMAL);
+ this->speed = SPEED_NORMAL;
+ this->status = XINE_STOP;
/*
* stop decoder threads
@@ -391,37 +345,6 @@ void xine_exit (xine_t *this) {
}
-void xine_pause (xine_t *this) {
-
- pthread_mutex_lock (&this->xine_lock);
-
- printf ("xine_pause\n");
-
- if (this->status != XINE_PLAY && this->status != XINE_PAUSE ) {
- printf ("xine: error, pause called when not in playback mode\n");
- pthread_mutex_unlock (&this->xine_lock);
- return;
- }
-
- if (this->paused) {
-
- this->metronom->set_speed (this->metronom, SPEED_NORMAL);
- this->audio_mute = 0;
- this->paused = 0;
- this->status = XINE_PLAY;
-
- } else {
-
- this->metronom->set_speed (this->metronom, SPEED_PAUSE);
- this->paused = 1;
- this->audio_mute = 2;
- this->status = XINE_PAUSE;
-
- }
-
- pthread_mutex_unlock (&this->xine_lock);
-}
-
static void event_handler(xine_t *xine, event_t *event, void *data) {
/* Check Xine handle/current input plugin is not NULL */
if((xine == NULL) || (xine->cur_input_plugin == NULL)) {
@@ -658,8 +581,11 @@ void xine_set_speed (xine_t *this, int speed) {
this->metronom->set_speed (this->metronom, speed);
- this->audio_mute = speed != SPEED_NORMAL;
- this->paused = speed == SPEED_PAUSE;
+ if (speed == SPEED_PAUSE)
+ this->audio_mute = 2;
+ else
+ this->audio_mute = speed != SPEED_NORMAL;
+
this->speed = speed;
pthread_mutex_unlock (&this->xine_lock);
@@ -669,3 +595,21 @@ void xine_set_speed (xine_t *this, int speed) {
int xine_get_speed (xine_t *this) {
return this->speed;
}
+
+/*
+ * time measurement / seek
+ */
+
+int xine_get_current_time (xine_t *this) {
+ return this->cur_input_time;
+}
+
+int xine_get_stream_length (xine_t *this) {
+
+ if(this->cur_demuxer_plugin)
+ return this->cur_demuxer_plugin->get_stream_length (this->cur_demuxer_plugin);
+
+ return 0;
+}
+
+
diff --git a/src/xine-engine/xine_internal.h b/src/xine-engine/xine_internal.h
index 56290bb79..33af5169d 100644
--- a/src/xine-engine/xine_internal.h
+++ b/src/xine-engine/xine_internal.h
@@ -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: xine_internal.h,v 1.42 2001/08/28 22:52:57 f1rmb Exp $
+ * $Id: xine_internal.h,v 1.43 2001/09/01 14:33:00 guenter Exp $
*
*/
@@ -120,7 +120,6 @@ typedef void (*gui_stream_end_cb_t)(int nStatus);
#define XINE_STOP 0
#define XINE_PLAY 1
#define XINE_QUIT 2
-#define XINE_PAUSE 3
typedef struct xine_s xine_t;
@@ -146,6 +145,7 @@ struct xine_s {
int status;
int speed;
off_t cur_input_pos;
+ int cur_input_time;
char cur_mrl[1024];
spu_functions_t *spu_out;
@@ -166,7 +166,6 @@ struct xine_s {
video_decoder_t *video_decoder_plugins[DECODER_PLUGIN_MAX];
video_decoder_t *cur_video_decoder_plugin;
int video_finished;
- int paused;
ao_instance_t *audio_out;
fifo_buffer_t *audio_fifo;
@@ -211,29 +210,18 @@ xine_t *xine_init (vo_driver_t *vo,
gui_branched_cb_t branched_cb);
/*
- * open a stream and play it
+ * open a stream sekk to a given position and play it
*
- * name : mrl to open
- * pos : start position 0..65535
+ * name : mrl to open
+ * start_pos : position in input source (0..65535)
+ * start_time : position measured in seconds from stream start
*
- */
-void xine_play (xine_t *this, char *MRL, int pos);
-
-
-/*
- * seek the stream to pos, and play it
- *
- * name : mrl to open
- * pos : start position 0..65535
+ * if both parameters are !=0 start_pos will be used
+ * for non-seekable streams both values will be ignored
*
*/
-void xine_seek (xine_t *this, char *MRL, int pos);
-
+void xine_play (xine_t *this, char *MRL, int start_pos, int start_time);
-/*
- * toggle pause mode
- */
-void xine_pause (xine_t *this);
/*
* set/get playback speed
@@ -280,6 +268,18 @@ int xine_get_status (xine_t *this);
int xine_get_current_position (xine_t *this);
/*
+ * get current position measured in seconds from
+ * the beginning of the stream
+ */
+int xine_get_current_time (xine_t *this);
+
+/*
+ * estimate length of input stream in seconds
+ * may return 0 if stream is not seekable
+ */
+int xine_get_stream_length (xine_t *this);
+
+/*
* return the current audio channel
*/
int xine_get_audio_channel (xine_t *this);