summaryrefslogtreecommitdiff
path: root/src/demuxers/demux_mpeg.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/demuxers/demux_mpeg.c')
-rw-r--r--src/demuxers/demux_mpeg.c185
1 files changed, 127 insertions, 58 deletions
diff --git a/src/demuxers/demux_mpeg.c b/src/demuxers/demux_mpeg.c
index 80ae1a34f..60fc67b60 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.52 2002/03/12 03:03:18 miguelfreitas Exp $
+ * $Id: demux_mpeg.c,v 1.53 2002/04/09 03:38:00 miguelfreitas Exp $
*
* demultiplexer for mpeg 1/2 program streams
* reads streams of variable blocksizes
@@ -61,6 +61,7 @@ typedef struct demux_mpeg_s {
input_plugin_t *input;
pthread_t thread;
+ pthread_mutex_t mutex;
unsigned char dummy_space[100000];
@@ -72,7 +73,8 @@ typedef struct demux_mpeg_s {
int send_end_buffers;
int64_t last_scr;
-
+ int send_newpts;
+
} demux_mpeg_t;
static uint32_t read_bytes (demux_mpeg_t *this, int n) {
@@ -113,6 +115,28 @@ static uint32_t read_bytes (demux_mpeg_t *this, int n) {
return res;
}
+
+static void check_newpts( demux_mpeg_t *this, int64_t pts )
+{
+ if( this->send_newpts && !this->preview_mode && pts ) {
+
+ buf_element_t *buf;
+
+ buf = this->video_fifo->buffer_pool_alloc (this->video_fifo);
+ buf->type = BUF_CONTROL_NEWPTS;
+ buf->disc_off = pts;
+ this->video_fifo->put (this->video_fifo, buf);
+
+ if (this->audio_fifo) {
+ buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo);
+ buf->type = BUF_CONTROL_NEWPTS;
+ buf->disc_off = pts;
+ this->audio_fifo->put (this->audio_fifo, buf);
+ }
+ this->send_newpts = 0;
+ }
+}
+
static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr) {
int len, i;
@@ -143,7 +167,9 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr)
w = read_bytes(this, 2);
pts |= (w & 0xFFFE) >> 1;
- header_len -= 5 ;
+ header_len -= 5 ;
+
+ check_newpts( this, pts );
}
/* read rest of header */
@@ -198,6 +224,8 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr)
pts |= (w & 0xFFFE) >> 1;
header_len -= 5 ;
+
+ check_newpts( this, pts );
}
/* read rest of header */
@@ -245,6 +273,8 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr)
pts |= (w & 0xFFFE) >> 1;
header_len -= 5 ;
+
+ check_newpts( this, pts );
}
/* read rest of header */
@@ -354,6 +384,7 @@ static void parse_mpeg1_packet (demux_mpeg_t *this, int stream_id, int64_t scr)
}
}
+ check_newpts( this, pts );
if ((stream_id & 0xe0) == 0xc0) {
int track = stream_id & 0x1f;
@@ -384,7 +415,6 @@ static void parse_mpeg1_packet (demux_mpeg_t *this, int stream_id, int64_t scr)
} else if ((stream_id & 0xf0) == 0xe0) {
-
buf = this->input->read_block (this->input, this->video_fifo, len);
if (buf == NULL) {
@@ -485,11 +515,12 @@ static uint32_t parse_pack(demux_mpeg_t *this) {
}
/* discontinuity ? */
- if( scr )
+ if( scr && !this->preview_mode )
{
int64_t scr_diff = scr - this->last_scr;
- if (abs(scr_diff) > 60000 && !this->preview_mode) {
-
+
+ if (abs(scr_diff) > 60000 && !this->send_newpts) {
+
buf_element_t *buf;
buf = this->video_fifo->buffer_pool_alloc (this->video_fifo);
@@ -617,15 +648,23 @@ static void *demux_mpeg_loop (void *this_gen) {
demux_mpeg_t *this = (demux_mpeg_t *) this_gen;
buf_element_t *buf;
- uint32_t w;
+ uint32_t w=0;
- do {
+ while(1) {
+
+ pthread_mutex_lock( &this->mutex );
+
+ if( this->status != DEMUX_OK)
+ break;
+
w = parse_pack (this);
if (w != 0x000001ba)
demux_mpeg_resync (this, w);
- } while (this->status == DEMUX_OK) ;
+ pthread_mutex_unlock( &this->mutex );
+
+ }
if (this->send_end_buffers) {
buf = this->video_fifo->buffer_pool_alloc (this->video_fifo);
@@ -644,6 +683,8 @@ static void *demux_mpeg_loop (void *this_gen) {
printf ("demux_mpeg: demux loop finished (status: %d, buf:%x)\n",
this->status, w);
+ pthread_mutex_unlock( &this->mutex );
+
pthread_exit(NULL);
return NULL;
@@ -655,26 +696,21 @@ static void demux_mpeg_stop (demux_plugin_t *this_gen) {
buf_element_t *buf;
void *p;
- printf ("demux_mpeg: stop...\n");
-
+ pthread_mutex_lock( &this->mutex );
+
if (this->status != DEMUX_OK) {
-
- this->video_fifo->clear(this->video_fifo);
- if(this->audio_fifo)
- this->audio_fifo->clear(this->audio_fifo);
-
+ printf ("demux_mpeg: stop...ignored\n");
+ pthread_mutex_unlock( &this->mutex );
return;
}
-
+
this->send_end_buffers = 0;
this->status = DEMUX_FINISHED;
-
- pthread_cancel (this->thread);
+
+ pthread_mutex_unlock( &this->mutex );
pthread_join (this->thread, &p);
- this->video_fifo->clear(this->video_fifo);
- if(this->audio_fifo)
- this->audio_fifo->clear(this->audio_fifo);
+ xine_flush_engine(this->xine);
buf = this->video_fifo->buffer_pool_alloc (this->video_fifo);
buf->type = BUF_CONTROL_END;
@@ -704,64 +740,93 @@ static void demux_mpeg_start (demux_plugin_t *this_gen,
buf_element_t *buf;
int err;
- this->video_fifo = video_fifo;
- this->audio_fifo = audio_fifo;
+ pthread_mutex_lock( &this->mutex );
- this->rate = 0; /* fixme */
- this->last_scr = 0;
-
- buf = this->video_fifo->buffer_pool_alloc (this->video_fifo);
- buf->type = BUF_CONTROL_START;
- this->video_fifo->put (this->video_fifo, buf);
+ if( this->status != DEMUX_OK ) {
+
+ this->video_fifo = video_fifo;
+ this->audio_fifo = audio_fifo;
+
+ this->rate = 0; /* fixme */
+ this->last_scr = 0;
- if(this->audio_fifo) {
- buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo);
+ buf = this->video_fifo->buffer_pool_alloc (this->video_fifo);
buf->type = BUF_CONTROL_START;
- this->audio_fifo->put (this->audio_fifo, buf);
- }
+ this->video_fifo->put (this->video_fifo, buf);
- if ((this->input->get_capabilities (this->input) & INPUT_CAP_SEEKABLE) != 0 ) {
+ if(this->audio_fifo) {
+ buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo);
+ buf->type = BUF_CONTROL_START;
+ this->audio_fifo->put (this->audio_fifo, buf);
+ }
- uint32_t w;
- int num_buffers = NUM_PREVIEW_BUFFERS;
+ if ((this->input->get_capabilities (this->input) & INPUT_CAP_SEEKABLE) != 0 ) {
- this->preview_mode = 1;
+ uint32_t w;
+ int num_buffers = NUM_PREVIEW_BUFFERS;
- this->input->seek (this->input, 4, SEEK_SET);
+ this->preview_mode = 1;
- this->status = DEMUX_OK ;
+ this->input->seek (this->input, 4, SEEK_SET);
- do {
+ this->status = DEMUX_OK ;
- w = parse_pack_preview (this, &num_buffers);
+ do {
+
+ w = parse_pack_preview (this, &num_buffers);
- if (w != 0x000001ba)
- demux_mpeg_resync (this, w);
+ if (w != 0x000001ba)
+ demux_mpeg_resync (this, w);
- num_buffers --;
-
- } while ( (this->status == DEMUX_OK) && (num_buffers>0)) ;
+ num_buffers --;
- /* printf ("demux_mpeg: rate %d\n", this->rate); */
+ } while ( (this->status == DEMUX_OK) && (num_buffers>0)) ;
+ /* printf ("demux_mpeg: rate %d\n", this->rate); */
+ this->status = DEMUX_FINISHED;
+ }
+ }
+
+ if ((this->input->get_capabilities (this->input) & INPUT_CAP_SEEKABLE) != 0 ) {
+
if ( (!start_pos) && (start_time))
start_pos = start_time * this->rate * 50;
this->input->seek (this->input, start_pos+4, SEEK_SET);
+ if( start_pos )
+ demux_mpeg_resync (this, read_bytes(this, 4) );
+
} else
read_bytes(this, 4);
+
+ this->send_newpts = 1;
+
+ if( this->status != DEMUX_OK ) {
+ this->preview_mode = 0;
+ this->send_end_buffers = 1;
+ this->status = DEMUX_OK ;
- this->preview_mode = 0;
- this->send_end_buffers = 1;
- this->status = DEMUX_OK ;
-
- if ((err = pthread_create (&this->thread,
+ if ((err = pthread_create (&this->thread,
NULL, demux_mpeg_loop, this)) != 0) {
- printf ("demux_mpeg: can't create new thread (%s)\n",
- strerror(err));
- exit (1);
+ printf ("demux_mpeg: can't create new thread (%s)\n",
+ strerror(err));
+ exit (1);
+ }
+ }
+ else {
+ xine_flush_engine(this->xine);
}
+ pthread_mutex_unlock( &this->mutex );
+
+}
+
+static void demux_mpeg_seek (demux_plugin_t *this_gen,
+ off_t start_pos, int start_time) {
+ demux_mpeg_t *this = (demux_mpeg_t *) this_gen;
+
+ demux_mpeg_start (this_gen, this->video_fifo, this->audio_fifo,
+ start_pos, start_time);
}
static int demux_mpeg_open(demux_plugin_t *this_gen,
@@ -910,7 +975,7 @@ demux_plugin_t *init_demuxer_plugin(int iface, xine_t *xine) {
demux_mpeg_t *this;
- if (iface != 6) {
+ if (iface != 7) {
printf ("demux_mpeg: plugin doesn't support plugin API version %d.\n"
" this means there's a version mismatch between xine and this "
" demuxer plugin.\nInstalling current demux plugins should help.\n",
@@ -934,6 +999,7 @@ demux_plugin_t *init_demuxer_plugin(int iface, xine_t *xine) {
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.seek = demux_mpeg_seek;
this->demux_plugin.stop = demux_mpeg_stop;
this->demux_plugin.close = demux_mpeg_close;
this->demux_plugin.get_status = demux_mpeg_get_status;
@@ -941,6 +1007,9 @@ demux_plugin_t *init_demuxer_plugin(int iface, xine_t *xine) {
this->demux_plugin.get_stream_length = demux_mpeg_get_stream_length;
this->demux_plugin.get_mimetypes = demux_mpeg_get_mimetypes;
+ this->status = DEMUX_FINISHED;
+ pthread_mutex_init( &this->mutex, NULL );
+
return (demux_plugin_t *) this;
}