summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/demuxers/demux_asf.c3
-rw-r--r--src/demuxers/demux_avi.c4
-rw-r--r--src/demuxers/demux_elem.c3
-rw-r--r--src/demuxers/demux_mpeg.c200
-rw-r--r--src/demuxers/demux_mpeg_block.c66
-rw-r--r--src/demuxers/demux_mpgaudio.c3
-rw-r--r--src/demuxers/demux_ogg.c3
-rw-r--r--src/demuxers/demux_pes.c5
-rw-r--r--src/demuxers/demux_qt.c4
-rw-r--r--src/liba52/xine_decoder.c126
-rw-r--r--src/libdts/xine_decoder.c29
-rw-r--r--src/liblpcm/xine_decoder.c29
-rw-r--r--src/libmad/xine_decoder.c27
-rw-r--r--src/libmpeg2/decode.c7
-rw-r--r--src/libmpeg2/mpeg2.h4
-rw-r--r--src/libmpeg2/xine_decoder.c4
-rw-r--r--src/libspudec/xine_decoder.c4
-rw-r--r--src/libvorbis/xine_decoder.c16
-rw-r--r--src/libw32dll/w32codec.c60
-rw-r--r--src/xine-engine/audio_decoder.c15
-rw-r--r--src/xine-engine/audio_out.c547
-rw-r--r--src/xine-engine/audio_out.h43
-rw-r--r--src/xine-engine/buffer.h8
-rw-r--r--src/xine-engine/metronom.c232
-rw-r--r--src/xine-engine/metronom.h37
-rw-r--r--src/xine-engine/video_decoder.c44
-rw-r--r--src/xine-engine/video_out.c14
-rw-r--r--src/xine-engine/video_out.h3
28 files changed, 920 insertions, 620 deletions
diff --git a/src/demuxers/demux_asf.c b/src/demuxers/demux_asf.c
index b2da7551b..4555a03a0 100644
--- a/src/demuxers/demux_asf.c
+++ b/src/demuxers/demux_asf.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_asf.c,v 1.8 2001/11/07 19:06:15 miguelfreitas Exp $
+ * $Id: demux_asf.c,v 1.9 2001/11/10 13:48:02 guenter Exp $
*
* demultiplexer for asf streams
*
@@ -621,6 +621,7 @@ static void asf_send_buffer (demux_asf_t *this, asf_stream_t *stream,
buf->input_time = 0 ;
}
buf->PTS = timestamp * 90;
+ buf->SCR = timestamp * 90;
buf->type = stream->buf_type;
buf->size = frag_len;
diff --git a/src/demuxers/demux_avi.c b/src/demuxers/demux_avi.c
index 81afaf1f9..2e831110c 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.50 2001/11/07 19:06:15 miguelfreitas Exp $
+ * $Id: demux_avi.c,v 1.51 2001/11/10 13:48:02 guenter Exp $
*
* demultiplexer for avi streams
*
@@ -724,6 +724,7 @@ static int demux_avi_next (demux_avi_t *this) {
xprintf (VERBOSE|DEMUX|VAVI, "demux_avi: audio \n");
buf->PTS = audio_pts;
+ buf->SCR = audio_pts;
buf->size = AVI_read_audio (this, this->avi, buf->mem, 2048, &buf->decoder_info[0]);
if (buf->size<0) {
@@ -750,6 +751,7 @@ static int demux_avi_next (demux_avi_t *this) {
xprintf (VERBOSE|DEMUX|VAVI, "demux_avi: video \n");
buf->PTS = video_pts;
+ buf->SCR = video_pts;
buf->size = AVI_read_video (this, this->avi, buf->mem, 2048, &buf->decoder_info[0]);
buf->type = this->avi->video_type;
diff --git a/src/demuxers/demux_elem.c b/src/demuxers/demux_elem.c
index aae62c38b..2e019327c 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.26 2001/11/04 22:49:28 miguelfreitas Exp $
+ * $Id: demux_elem.c,v 1.27 2001/11/10 13:48:02 guenter Exp $
*
* demultiplexer for elementary mpeg streams
*
@@ -87,6 +87,7 @@ static int demux_mpeg_elem_next (demux_mpeg_elem_t *this, int preview_mode) {
buf->decoder_info[0] = 1;
buf->PTS = 0;
+ buf->SCR = 0;
buf->input_pos = this->input->get_current_pos(this->input);
buf->type = BUF_VIDEO_MPEG;
diff --git a/src/demuxers/demux_mpeg.c b/src/demuxers/demux_mpeg.c
index de52c6b48..67de987c3 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.41 2001/10/27 13:59:31 guenter Exp $
+ * $Id: demux_mpeg.c,v 1.42 2001/11/10 13:48:02 guenter Exp $
*
* demultiplexer for mpeg 1/2 program streams
* reads streams of variable blocksizes
@@ -67,6 +67,8 @@ typedef struct demux_mpeg_s {
int send_end_buffers;
+ uint32_t last_scr;
+
} demux_mpeg_t ;
static uint32_t read_bytes (demux_mpeg_t *this, int n) {
@@ -111,17 +113,17 @@ 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_mpeg_t *this, int stream_id, uint32_t scr) {
- int nLen, i;
+ int len, i;
uint32_t w, flags, header_len, pts;
buf_element_t *buf = NULL;
- nLen = read_bytes(this, 2);
+ len = read_bytes(this, 2);
- xprintf (VERBOSE|DEMUX|MPEG, " mpeg2 packet (len=%d",nLen);
+ xprintf (VERBOSE|DEMUX|MPEG, " mpeg2 packet (len=%d",len);
- if (nID==0xbd) {
+ if (stream_id==0xbd) {
int track;
@@ -131,7 +133,7 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int nID) {
flags = read_bytes(this, 1);
header_len = read_bytes(this, 1);
- nLen -= header_len + 3;
+ len -= header_len + 3;
pts=0;
@@ -159,9 +161,9 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int nID) {
/* contents */
if(this->audio_fifo)
- buf = this->input->read_block (this->input, this->audio_fifo, nLen-4);
+ buf = this->input->read_block (this->input, this->audio_fifo, len-4);
else {
- this->input->read (this->input, this->dummy_space, nLen-4);
+ this->input->read (this->input, this->dummy_space, len-4);
return;
}
@@ -171,6 +173,7 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int nID) {
}
buf->type = BUF_AUDIO_A52 + track;
buf->PTS = pts;
+ buf->SCR = scr;
if (this->preview_mode)
buf->decoder_info[0] = 0;
else
@@ -181,8 +184,8 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int nID) {
if(this->audio_fifo)
this->audio_fifo->put (this->audio_fifo, buf);
- } else if ((nID & 0xe0) == 0xc0) {
- int track = nID & 0x1f;
+ } else if ((stream_id & 0xe0) == 0xc0) {
+ int track = stream_id & 0x1f;
xprintf (VERBOSE|DEMUX|AUDIO, ", audio #%d", track);
@@ -190,7 +193,7 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int nID) {
flags = read_bytes(this, 1);
header_len = read_bytes(this, 1);
- nLen -= header_len + 3;
+ len -= header_len + 3;
pts = 0;
@@ -212,9 +215,9 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int nID) {
i = this->input->read (this->input, this->dummy_space, header_len);
if(this->audio_fifo)
- buf = this->input->read_block (this->input, this->audio_fifo, nLen);
+ buf = this->input->read_block (this->input, this->audio_fifo, len);
else {
- this->input->read (this->input, this->dummy_space, nLen);
+ this->input->read (this->input, this->dummy_space, len);
return;
}
@@ -224,6 +227,7 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int nID) {
}
buf->type = BUF_AUDIO_MPEG + track;
buf->PTS = pts;
+ buf->SCR = scr;
if (this->preview_mode)
buf->decoder_info[0] = 0;
else
@@ -233,7 +237,7 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int nID) {
if(this->audio_fifo)
this->audio_fifo->put (this->audio_fifo, buf);
- } else if ((nID >= 0xbc) && ((nID & 0xf0) == 0xe0)) {
+ } else if ((stream_id >= 0xbc) && ((stream_id & 0xf0) == 0xe0)) {
xprintf (VERBOSE|DEMUX|VIDEO, ",video");
@@ -241,7 +245,7 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int nID) {
flags = read_bytes(this, 1);
header_len = read_bytes(this, 1);
- nLen -= header_len + 3;
+ len -= header_len + 3;
pts = 0;
@@ -264,7 +268,7 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int nID) {
/* contents */
- buf = this->input->read_block (this->input, this->video_fifo, nLen);
+ buf = this->input->read_block (this->input, this->video_fifo, len);
if (buf == NULL) {
this->status = DEMUX_FINISHED;
@@ -272,6 +276,7 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int nID) {
}
buf->type = BUF_VIDEO_MPEG;
buf->PTS = pts;
+ buf->SCR = scr;
if (this->preview_mode)
buf->decoder_info[0] = 0;
else
@@ -283,17 +288,17 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int nID) {
} else {
xprintf (VERBOSE|DEMUX, ",unknown stream - skipped");
- i = this->input->read (this->input, this->dummy_space, nLen);
- /* (*this->input->seek) (nLen,SEEK_CUR); */
+ i = this->input->read (this->input, this->dummy_space, len);
+ /* (*this->input->seek) (len,SEEK_CUR); */
}
xprintf (VERBOSE|DEMUX, ")\n");
}
-static void parse_mpeg1_packet (demux_mpeg_t *this, int nID)
-{
- int nLen;
+static void parse_mpeg1_packet (demux_mpeg_t *this, int stream_id, uint32_t scr) {
+
+ int len;
uint32_t w;
int i;
int pts;
@@ -301,15 +306,15 @@ static void parse_mpeg1_packet (demux_mpeg_t *this, int nID)
xprintf (VERBOSE|DEMUX, " packet (");
- nLen = read_bytes(this, 2);
+ len = read_bytes(this, 2);
- xprintf (VERBOSE|DEMUX, "len=%d",nLen);
+ xprintf (VERBOSE|DEMUX, "len=%d",len);
pts=0;
- if (nID != 0xbf) {
+ if (stream_id != 0xbf) {
- w = read_bytes(this, 1); nLen--;
+ w = read_bytes(this, 1); len--;
while ((w & 0x80) == 0x80) {
@@ -317,7 +322,7 @@ static void parse_mpeg1_packet (demux_mpeg_t *this, int nID)
return;
/* stuffing bytes */
- w = read_bytes(this, 1); nLen--;
+ w = read_bytes(this, 1); len--;
}
if ((w & 0xC0) == 0x40) {
@@ -326,8 +331,8 @@ static void parse_mpeg1_packet (demux_mpeg_t *this, int nID)
return;
/* buffer_scale, buffer size */
- w = read_bytes(this, 1); nLen--;
- w = read_bytes(this, 1); nLen--;
+ w = read_bytes(this, 1); len--;
+ w = read_bytes(this, 1); len--;
}
if ((w & 0xF0) == 0x20) {
@@ -336,11 +341,11 @@ static void parse_mpeg1_packet (demux_mpeg_t *this, int nID)
return;
pts = (w & 0xe) << 29 ;
- w = read_bytes(this, 2); nLen -= 2;
+ w = read_bytes(this, 2); len -= 2;
pts |= (w & 0xFFFE) << 14;
- w = read_bytes(this, 2); nLen -= 2;
+ w = read_bytes(this, 2); len -= 2;
pts |= (w & 0xFFFE) >> 1;
xprintf (VERBOSE|DEMUX|VPTS, ", pts=%d",pts);
@@ -353,11 +358,11 @@ static void parse_mpeg1_packet (demux_mpeg_t *this, int nID)
return;
pts = (w & 0x0e) << 29 ;
- w = read_bytes(this, 2); nLen -= 2;
+ w = read_bytes(this, 2); len -= 2;
pts |= (w & 0xFFFE) << 14;
- w = read_bytes(this, 2); nLen -= 2;
+ w = read_bytes(this, 2); len -= 2;
pts |= (w & 0xFFFE) >> 1;
@@ -365,8 +370,8 @@ static void parse_mpeg1_packet (demux_mpeg_t *this, int nID)
xprintf (VERBOSE|DEMUX|VPTS, ", pts2=%d",pts);
/* Decoding Time Stamp */
- w = read_bytes(this, 3); nLen -= 3;
- w = read_bytes(this, 2); nLen -= 2;
+ w = read_bytes(this, 3); len -= 3;
+ w = read_bytes(this, 2); len -= 2;
} else {
xprintf (VERBOSE|DEMUX, ", w = %02x",w);
if (w != 0x0f)
@@ -375,15 +380,15 @@ static void parse_mpeg1_packet (demux_mpeg_t *this, int nID)
}
- if ((nID & 0xe0) == 0xc0) {
- int track = nID & 0x1f;
+ if ((stream_id & 0xe0) == 0xc0) {
+ int track = stream_id & 0x1f;
xprintf (VERBOSE|DEMUX|AUDIO, ", audio #%d", track);
if(this->audio_fifo) {
- buf = this->input->read_block (this->input, this->audio_fifo, nLen);
+ buf = this->input->read_block (this->input, this->audio_fifo, len);
} else {
- this->input->read (this->input, this->dummy_space, nLen);
+ this->input->read (this->input, this->dummy_space, len);
return;
}
@@ -393,6 +398,7 @@ static void parse_mpeg1_packet (demux_mpeg_t *this, int nID)
}
buf->type = BUF_AUDIO_MPEG + track ;
buf->PTS = pts;
+ buf->SCR = scr;
if (this->preview_mode)
buf->decoder_info[0] = 0;
else
@@ -404,11 +410,11 @@ static void parse_mpeg1_packet (demux_mpeg_t *this, int nID)
if(this->audio_fifo)
this->audio_fifo->put (this->audio_fifo, buf);
- } else if ((nID & 0xf0) == 0xe0) {
+ } else if ((stream_id & 0xf0) == 0xe0) {
- xprintf (VERBOSE|DEMUX|VIDEO, ", video #%d", nID & 0x0f);
+ xprintf (VERBOSE|DEMUX|VIDEO, ", video #%d", stream_id & 0x0f);
- buf = this->input->read_block (this->input, this->video_fifo, nLen);
+ buf = this->input->read_block (this->input, this->video_fifo, len);
if (buf == NULL) {
this->status = DEMUX_FINISHED;
@@ -416,6 +422,7 @@ static void parse_mpeg1_packet (demux_mpeg_t *this, int nID)
}
buf->type = BUF_VIDEO_MPEG;
buf->PTS = pts;
+ buf->SCR = scr;
if (this->preview_mode)
buf->decoder_info[0] = 0;
else
@@ -426,55 +433,91 @@ static void parse_mpeg1_packet (demux_mpeg_t *this, int nID)
this->video_fifo->put (this->video_fifo, buf);
- } else if (nID == 0xbd) {
+ } else if (stream_id == 0xbd) {
xprintf (VERBOSE|DEMUX|AC3, ", ac3");
- i = this->input->read (this->input, this->dummy_space, nLen);
+ i = this->input->read (this->input, this->dummy_space, len);
} else {
- xprintf (VERBOSE|DEMUX, ", unknown (nID = %d)",nID);
- this->input->read (this->input, this->dummy_space, nLen);
+ xprintf (VERBOSE|DEMUX, ", unknown (stream_id = %d)",stream_id);
+ this->input->read (this->input, this->dummy_space, len);
}
xprintf (VERBOSE|DEMUX, ")\n");
}
-static uint32_t parse_pack(demux_mpeg_t *this)
-{
- uint32_t buf ;
- int mpeg_version;
+static uint32_t parse_pack(demux_mpeg_t *this) {
+
+ uint32_t buf ;
+ int mpeg_version;
+ uint32_t scr;
xprintf (VERBOSE|DEMUX, "pack {\n");
- /* system_clock_reference */
buf = read_bytes (this, 1);
xprintf (VERBOSE|DEMUX|VIDEO, " mpeg version : %02x",buf>>4);
if ((buf>>4) == 4) {
- xprintf (VERBOSE|DEMUX|VIDEO, " => mpeg II \n");
- buf = read_bytes(this, 2);
- mpeg_version = 2;
- } else {
- xprintf (VERBOSE|DEMUX|VIDEO, " => mpeg I \n");
- mpeg_version = 1;
- }
- buf = read_bytes (this, 2);
- buf = read_bytes (this, 2);
-
- /* mux_rate */
-
- 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);
+ int stuffing, i;
- /* printf ("demux_mpeg: mux_rate = %d\n",this->rate); */
+ xprintf (VERBOSE|DEMUX|VIDEO, " => mpeg II \n");
+
+ mpeg_version = 2;
+
+ /* system_clock_reference */
+
+ scr = (buf & 0x08) << 27;
+ scr = (buf & 0x03) << 28;
+ buf = read_bytes (this, 1);
+ scr |= buf << 20;
+ buf = read_bytes (this, 1);
+ scr |= (buf & 0xF8) << 12 ;
+ scr |= (buf & 0x03) << 13 ;
+ buf = read_bytes (this, 1);
+ scr |= buf << 5;
+ buf = read_bytes (this, 1);
+ scr |= (buf & 0xF8) >> 3;
+ buf = read_bytes (this, 1); /* extension */
+
+ /* mux_rate */
+
+ buf = read_bytes(this,3);
+ if (!this->rate) {
+ this->rate = (buf & 0xFFFFFC) >> 2;
+ }
+
+ /* stuffing bytes */
+ buf = read_bytes(this,1);
+ stuffing = buf &0x03;
+ for (i=0; i<stuffing; i++)
+ read_bytes (this, 1);
- } else
- buf = read_bytes (this, 3) ;
+ } else {
+ xprintf (VERBOSE|DEMUX|VIDEO, " => mpeg I \n");
+ mpeg_version = 1;
+ /* system_clock_reference */
+
+ scr = (buf & 0x2) << 30;
+ buf = read_bytes (this, 2);
+ scr |= (buf & 0xFFFE) << 14;
+ buf = read_bytes (this, 2);
+ scr |= (buf & 0xFFFE) >>1;
+
+ /* mux_rate */
+
+ 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) ;
+ }
/* system header */
@@ -500,9 +543,9 @@ static uint32_t parse_pack(demux_mpeg_t *this)
return buf;
if (mpeg_version == 1)
- parse_mpeg1_packet (this, buf & 0xFF);
+ parse_mpeg1_packet (this, buf & 0xFF, scr);
else
- parse_mpeg2_packet (this, buf & 0xFF);
+ parse_mpeg2_packet (this, buf & 0xFF, scr);
buf = read_bytes (this, 4);
xprintf (VERBOSE|DEMUX, " code = %08x\n",buf);
@@ -565,9 +608,9 @@ static uint32_t parse_pack_preview (demux_mpeg_t *this, int *num_buffers)
return buf;
if (mpeg_version == 1)
- parse_mpeg1_packet (this, buf & 0xFF);
+ parse_mpeg1_packet (this, buf & 0xFF, 0);
else
- parse_mpeg2_packet (this, buf & 0xFF);
+ parse_mpeg2_packet (this, buf & 0xFF, 0);
buf = read_bytes (this, 4);
*num_buffers = *num_buffers - 1;
@@ -683,7 +726,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 */
+ this->rate = 0; /* fixme */
+ this->last_scr = 0;
buf = this->video_fifo->buffer_pool_alloc (this->video_fifo);
buf->type = BUF_CONTROL_START;
diff --git a/src/demuxers/demux_mpeg_block.c b/src/demuxers/demux_mpeg_block.c
index 5aeffe3be..fc54626e1 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.59 2001/10/25 00:46:59 miguelfreitas Exp $
+ * $Id: demux_mpeg_block.c,v 1.60 2001/11/10 13:48:02 guenter Exp $
*
* demultiplexer for mpeg 1/2 program streams
*
@@ -67,6 +67,7 @@ typedef struct demux_mpeg_block_s {
uint8_t *scratch;
+ uint32_t last_scr;
} demux_mpeg_block_t ;
@@ -79,6 +80,7 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m
uint32_t PTS;
uint32_t packet_len;
uint32_t stream_id;
+ uint32_t scr = this->last_scr;
buf = this->input->read_block (this->input, this->video_fifo, this->blocksize);
@@ -167,6 +169,18 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m
if (bMpeg1) {
+ /* system_clock_reference */
+
+ scr = (p[4] & 0x02) << 30;
+ scr |= (p[5] & 0xFF) << 22;
+ scr |= (p[5] & 0xFE) << 14;
+ scr |= (p[6] & 0xFF) << 7;
+ scr |= (p[7] & 0xFE) >> 1;
+
+ buf->SCR = scr;
+
+ /* mux_rate */
+
if (!this->rate) {
this->rate = (p[9] & 0x7F) << 15;
this->rate |= (p[10] << 7);
@@ -178,26 +192,27 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m
p += 12;
} else { /* mpeg2 */
+
+ int num_stuffing_bytes;
- int num_stuffing_bytes;
-
- /* SCR decoding code works but is not used by xine
- int scr;
+ /* system_clock_reference */
- scr = (p[4] & 0x38) << 27 ;
+ scr = (p[4] & 0x08) << 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:
-
+ /* optional - decode extension:
scr *=300;
scr += ( (p[8] & 0x03 << 7) | (p[9] & 0xFE >> 1) );
*/
+ buf->SCR = scr;
+
+ /* mux_rate */
+
if (!this->rate) {
this->rate = (p[0xA] << 14);
this->rate |= (p[0xB] << 6);
@@ -235,7 +250,29 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m
this->status = DEMUX_FINISHED;
}
- return ;
+ return;
+ }
+
+ /* discontinuity ? */
+ {
+ int32_t scr_diff = scr - this->last_scr;
+ if (abs(scr_diff) > 60000) {
+
+ buf_element_t *buf;
+
+ buf = this->video_fifo->buffer_pool_alloc (this->video_fifo);
+ buf->type = BUF_CONTROL_AVSYNC_RESET;
+ buf->SCR = scr;
+ 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_AVSYNC_RESET;
+ buf->SCR = scr;
+ this->audio_fifo->put (this->audio_fifo, buf);
+ }
+ }
+ this->last_scr = scr;
}
packet_len = p[4] << 8 | p[5];
@@ -308,7 +345,7 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m
PTS |= (p[11] & 0xFE) << 14 ;
PTS |= p[12] << 7 ;
PTS |= (p[13] & 0xFE) >> 1 ;
-
+
} else
PTS = 0;
@@ -332,6 +369,8 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m
packet_len -= header_len + 3;
}
+ PTS &= 0x7FFFFFFF ; /* 31 bit only (for signed calculations) */
+
if (stream_id == 0xbd) {
int track, spu_id;
@@ -744,6 +783,8 @@ static void demux_mpeg_block_start (demux_plugin_t *this_gen,
this->rate = demux_mpeg_block_estimate_rate (this);
+ this->last_scr = 0;
+
if((this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) != 0) {
int num_buffers = NUM_PREVIEW_BUFFERS;
@@ -792,7 +833,8 @@ static void demux_mpeg_block_start (demux_plugin_t *this_gen,
* now start demuxing
*/
- this->status = DEMUX_OK ;
+ this->status = DEMUX_OK ;
+ this->last_scr = 0;
if ((err = pthread_create (&this->thread,
NULL, demux_mpeg_block_loop, this)) != 0) {
diff --git a/src/demuxers/demux_mpgaudio.c b/src/demuxers/demux_mpgaudio.c
index 097b8344a..6ec5113be 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.26 2001/10/25 00:46:59 miguelfreitas Exp $
+ * $Id: demux_mpgaudio.c,v 1.27 2001/11/10 13:48:02 guenter Exp $
*
* demultiplexer for mpeg audio (i.e. mp3) streams
*
@@ -186,6 +186,7 @@ static int demux_mpgaudio_next (demux_mpgaudio_t *this) {
}
buf->PTS = 0;
+ buf->SCR = 0;
buf->input_pos = this->input->get_current_pos(this->input);
buf->input_time = buf->input_pos * this->stream_length /
this->input->get_length(this->input);
diff --git a/src/demuxers/demux_ogg.c b/src/demuxers/demux_ogg.c
index 8c542c00e..4842becb7 100644
--- a/src/demuxers/demux_ogg.c
+++ b/src/demuxers/demux_ogg.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_ogg.c,v 1.7 2001/11/06 21:47:30 miguelfreitas Exp $
+ * $Id: demux_ogg.c,v 1.8 2001/11/10 13:48:02 guenter Exp $
*
* demultiplexer for ogg streams
*
@@ -163,6 +163,7 @@ static void demux_ogg_send_package (demux_ogg_t *this, int is_content) {
}
buf->PTS = 0; /* FIXME */
+ buf->SCR = 0; /* FIXME */
buf->size = op.bytes;
buf->decoder_info[0] = is_content;
diff --git a/src/demuxers/demux_pes.c b/src/demuxers/demux_pes.c
index 868cec381..77defa9a7 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.11 2001/10/25 00:46:59 miguelfreitas Exp $
+ * $Id: demux_pes.c,v 1.12 2001/11/10 13:48:02 guenter Exp $
*
* demultiplexer for mpeg 2 PES (Packetized Elementary Streams)
* reads streams of variable blocksizes
@@ -168,6 +168,7 @@ static void parse_mpeg2_packet (demux_pes_t *this, int nID) {
}
buf->type = BUF_AUDIO_A52 + track;
buf->PTS = pts;
+ buf->SCR = pts; /* FIMXE! */
if (this->preview_mode)
buf->decoder_info[0] = 0;
else
@@ -217,6 +218,7 @@ static void parse_mpeg2_packet (demux_pes_t *this, int nID) {
}
buf->type = BUF_AUDIO_MPEG + track;
buf->PTS = pts;
+ buf->SCR = pts; /* FIXME ! */
if (this->preview_mode)
buf->decoder_info[0] = 0;
else
@@ -266,6 +268,7 @@ static void parse_mpeg2_packet (demux_pes_t *this, int nID) {
}
buf->type = BUF_VIDEO_MPEG;
buf->PTS = pts;
+ buf->SCR = pts; /* FIXME! */
if (this->preview_mode)
buf->decoder_info[0] = 0;
else
diff --git a/src/demuxers/demux_qt.c b/src/demuxers/demux_qt.c
index a28edafef..a214f0326 100644
--- a/src/demuxers/demux_qt.c
+++ b/src/demuxers/demux_qt.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_qt.c,v 1.10 2001/11/07 18:26:36 miguelfreitas Exp $
+ * $Id: demux_qt.c,v 1.11 2001/11/10 13:48:02 guenter Exp $
*
* demultiplexer for quicktime streams, based on:
*
@@ -3992,6 +3992,7 @@ static void *demux_qt_loop (void *this_gen) {
/* int count; */
buf->PTS = audio_pts;
+ buf->SCR = audio_pts;
buf->type = this->audio_type;
buf->decoder_info[0] = 1;
buf->input_time = 0;
@@ -4038,6 +4039,7 @@ static void *demux_qt_loop (void *this_gen) {
buf->content = buf->mem;
buf->size = copy_bytes;
buf->PTS = video_pts;
+ buf->SCR = video_pts;
buf->type = this->video_type;
buf->input_time = video_pts / 90000;
buf->input_pos = this->input->get_current_pos(this->input);
diff --git a/src/liba52/xine_decoder.c b/src/liba52/xine_decoder.c
index 0050d0fd9..cc7dcd4f9 100644
--- a/src/liba52/xine_decoder.c
+++ b/src/liba52/xine_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: xine_decoder.c,v 1.6 2001/10/22 00:40:36 matt2000 Exp $
+ * $Id: xine_decoder.c,v 1.7 2001/11/10 13:48:02 guenter Exp $
*
* stuff needed to turn liba52 into a xine decoder plugin
*/
@@ -64,7 +64,6 @@ typedef struct a52dec_decoder_s {
int a52_flags_map[11];
int ao_flags_map[11];
- int16_t int_samples [6 * 256 * 6];
sample_t *samples;
ao_instance_t *audio_out;
@@ -149,8 +148,8 @@ void a52dec_init (audio_decoder_t *this_gen, ao_instance_t *audio_out) {
this->ao_flags_map[A52_2F2R] = AO_CAP_MODE_4CHANNEL;
this->ao_flags_map[A52_3F2R] = AO_CAP_MODE_4CHANNEL;
- /* else if (this->audio_caps & AO_CAP_MODE_STEREO)
- defaults are ok */
+ /* else if (this->audio_caps & AO_CAP_MODE_STEREO)
+ defaults are ok */
} else if (!(this->audio_caps & AO_CAP_MODE_STEREO)) {
printf ("HELP! a mono-only audio driver?!\n");
@@ -175,34 +174,34 @@ void a52dec_init (audio_decoder_t *this_gen, ao_instance_t *audio_out) {
}
/*
- for (i = 0; i<8; i++)
+ for (i = 0; i<8; i++)
this->a52_flags_map[i] |= A52_ADJUST_LEVEL;
-*/
+ */
#ifdef DEBUG_A52
a52file = open ("test.a52", O_CREAT | O_WRONLY | O_TRUNC, 0644);
#endif
}
-static inline int16_t blah (int32_t i)
-{
- if (i > 0x43c07fff)
- return 32767;
- else if (i < 0x43bf8000)
- return -32768;
- else
- return i - 0x43c00000;
+static inline int16_t blah (int32_t i) {
+
+ if (i > 0x43c07fff)
+ return 32767;
+ else if (i < 0x43bf8000)
+ return -32768;
+ else
+ return i - 0x43c00000;
}
static inline void float_to_int (float * _f, int16_t * s16, int num_channels) {
- int i;
- int32_t * f = (int32_t *) _f; /* XXX assumes IEEE float format */
+ int i;
+ int32_t * f = (int32_t *) _f; /* XXX assumes IEEE float format */
- for (i = 0; i < 256; i++) {
- s16[num_channels*i] = blah (f[i]);
- }
+ for (i = 0; i < 256; i++) {
+ s16[num_channels*i] = blah (f[i]);
+ }
}
-static void a52dec_decode_frame (a52dec_decoder_t *this, uint32_t pts) {
+static void a52dec_decode_frame (a52dec_decoder_t *this, uint32_t pts, uint32_t scr) {
int output_mode = AO_CAP_MODE_STEREO;
@@ -212,8 +211,10 @@ static void a52dec_decode_frame (a52dec_decoder_t *this, uint32_t pts) {
if (!this->bypass_mode) {
- int a52_output_flags, i;
- sample_t level = this->a52_level;
+ int a52_output_flags, i;
+ sample_t level = this->a52_level;
+ audio_buffer_t *buf;
+ int16_t *int_samples;
/*
* oki, decode this frame in software
@@ -253,8 +254,8 @@ static void a52dec_decode_frame (a52dec_decoder_t *this, uint32_t pts) {
this->output_open = this->audio_out->open (this->audio_out, 16,
- this->a52_sample_rate,
- output_mode) ;
+ this->a52_sample_rate,
+ output_mode) ;
this->output_sampling_rate = this->a52_sample_rate;
this->output_mode = output_mode;
}
@@ -268,6 +269,9 @@ static void a52dec_decode_frame (a52dec_decoder_t *this, uint32_t pts) {
* decode a52 and convert/interleave samples
*/
+ buf = this->audio_out->get_buffer (this->audio_out);
+ int_samples = buf->mem;
+
for (i = 0; i < 6; i++) {
if (a52_block (&this->a52_state, this->samples)) {
printf ("liba52: a52_block error\n");
@@ -276,32 +280,32 @@ static void a52dec_decode_frame (a52dec_decoder_t *this, uint32_t pts) {
switch (output_mode) {
case AO_CAP_MODE_MONO:
- float_to_int (&this->samples[0], this->int_samples+(i*256), 1);
+ float_to_int (&this->samples[0], int_samples+(i*256), 1);
break;
case AO_CAP_MODE_STEREO:
- float_to_int (&this->samples[0*256], this->int_samples+(i*256*2), 2);
- float_to_int (&this->samples[1*256], this->int_samples+(i*256*2)+1, 2);
+ float_to_int (&this->samples[0*256], int_samples+(i*256*2), 2);
+ float_to_int (&this->samples[1*256], int_samples+(i*256*2)+1, 2);
break;
case AO_CAP_MODE_4CHANNEL:
- float_to_int (&this->samples[0*256], this->int_samples+(i*256*4), 4); /* L */
- float_to_int (&this->samples[1*256], this->int_samples+(i*256*4)+1, 4); /* R */
- float_to_int (&this->samples[2*256], this->int_samples+(i*256*4)+2, 4); /* RL */
- float_to_int (&this->samples[3*256], this->int_samples+(i*256*4)+3, 4); /* RR */
+ float_to_int (&this->samples[0*256], int_samples+(i*256*4), 4); /* L */
+ float_to_int (&this->samples[1*256], int_samples+(i*256*4)+1, 4); /* R */
+ float_to_int (&this->samples[2*256], int_samples+(i*256*4)+2, 4); /* RL */
+ float_to_int (&this->samples[3*256], int_samples+(i*256*4)+3, 4); /* RR */
break;
case AO_CAP_MODE_5CHANNEL:
- float_to_int (&this->samples[0*256], this->int_samples+(i*256*5)+0, 5); /* L */
- float_to_int (&this->samples[1*256], this->int_samples+(i*256*5)+4, 5); /* C */
- float_to_int (&this->samples[2*256], this->int_samples+(i*256*5)+1, 5); /* R */
- float_to_int (&this->samples[3*256], this->int_samples+(i*256*5)+2, 5); /* RL */
- float_to_int (&this->samples[4*256], this->int_samples+(i*256*5)+3, 5); /* RR */
+ float_to_int (&this->samples[0*256], int_samples+(i*256*5)+0, 5); /* L */
+ float_to_int (&this->samples[1*256], int_samples+(i*256*5)+4, 5); /* C */
+ float_to_int (&this->samples[2*256], int_samples+(i*256*5)+1, 5); /* R */
+ float_to_int (&this->samples[3*256], int_samples+(i*256*5)+2, 5); /* RL */
+ float_to_int (&this->samples[4*256], int_samples+(i*256*5)+3, 5); /* RR */
break;
case AO_CAP_MODE_5_1CHANNEL:
- float_to_int (&this->samples[0*256], this->int_samples+(i*256*6)+5, 6); /* lfe */
- float_to_int (&this->samples[1*256], this->int_samples+(i*256*6)+0, 6); /* L */
- float_to_int (&this->samples[2*256], this->int_samples+(i*256*6)+4, 6); /* C */
- float_to_int (&this->samples[3*256], this->int_samples+(i*256*6)+1, 6); /* R */
- float_to_int (&this->samples[4*256], this->int_samples+(i*256*6)+2, 6); /* RL */
- float_to_int (&this->samples[5*256], this->int_samples+(i*256*6)+3, 6); /* RR */
+ float_to_int (&this->samples[0*256], int_samples+(i*256*6)+5, 6); /* lfe */
+ float_to_int (&this->samples[1*256], int_samples+(i*256*6)+0, 6); /* L */
+ float_to_int (&this->samples[2*256], int_samples+(i*256*6)+4, 6); /* C */
+ float_to_int (&this->samples[3*256], int_samples+(i*256*6)+1, 6); /* R */
+ float_to_int (&this->samples[4*256], int_samples+(i*256*6)+2, 6); /* RL */
+ float_to_int (&this->samples[5*256], int_samples+(i*256*6)+3, 6); /* RR */
break;
default:
printf ("liba52: help - unsupported mode %08x\n", output_mode);
@@ -310,10 +314,12 @@ static void a52dec_decode_frame (a52dec_decoder_t *this, uint32_t pts) {
/* output decoded samples */
- this->audio_out->write (this->audio_out,
- this->int_samples,
- 256*6,
- pts);
+ buf->num_frames = 256*6;
+ buf->vpts = pts;
+ buf->scr = scr;
+
+ this->audio_out->put_buffer (this->audio_out, buf);
+
pts = 0;
} else {
@@ -329,16 +335,24 @@ static void a52dec_decode_frame (a52dec_decoder_t *this, uint32_t pts) {
a52_syncinfo (this->frame_buffer, &flags, &sample_rate, &bit_rate);
this->output_open = this->audio_out->open (this->audio_out, 16,
- sample_rate,
- AO_CAP_MODE_A52) ;
+ sample_rate,
+ AO_CAP_MODE_A52) ;
this->output_mode = AO_CAP_MODE_A52;
}
if (this->output_open) {
- this->audio_out->write (this->audio_out,
- (int16_t*)this->frame_buffer,
- this->frame_length,
- pts);
+
+ audio_buffer_t *buf = this->audio_out->get_buffer (this->audio_out);
+
+ memcpy (buf->mem, this->frame_buffer, this->frame_length);
+
+ buf->num_frames = this->frame_length;
+ buf->vpts = pts;
+ buf->scr = scr;
+
+ this->audio_out->put_buffer (this->audio_out, buf);
+
+ pts = 0;
}
}
}
@@ -354,10 +368,10 @@ void a52dec_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) {
return;
/*
- printf ("liba52: got buffer, pts =%d, pts - last_pts=%d\n",
- buf->PTS, buf->PTS - this->last_pts);
+ printf ("liba52: got buffer, pts =%d, pts - last_pts=%d\n",
+ buf->PTS, buf->PTS - this->last_pts);
- this->last_pts = buf->PTS;
+ this->last_pts = buf->PTS;
*/
if (buf->PTS)
@@ -367,7 +381,7 @@ void a52dec_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) {
while (current != end) {
if ( (this->sync_todo == 0) && (this->frame_todo == 0) ) {
- a52dec_decode_frame (this, this->pts);
+ a52dec_decode_frame (this, this->pts, buf->SCR);
#ifdef DEBUG_A52
write (a52file, this->frame_buffer, this->frame_length);
#endif
diff --git a/src/libdts/xine_decoder.c b/src/libdts/xine_decoder.c
index e0d3d0520..b831c15f6 100644
--- a/src/libdts/xine_decoder.c
+++ b/src/libdts/xine_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: xine_decoder.c,v 1.1 2001/09/06 15:23:14 joachim_koenig Exp $
+ * $Id: xine_decoder.c,v 1.2 2001/11/10 13:48:02 guenter Exp $
*
* 04-09-2001 DTS passtrough (C) Joachim Koenig
*
@@ -39,13 +39,12 @@
typedef struct dts_decoder_s {
audio_decoder_t audio_decoder;
- uint32_t pts;
uint32_t rate;
uint32_t bits_per_sample;
uint32_t number_of_channels;
uint32_t audio_caps;
- ao_instance_t *audio_out;
+ ao_instance_t *audio_out;
int output_open;
} dts_decoder_t;
@@ -62,7 +61,6 @@ void dts_init (audio_decoder_t *this_gen, ao_instance_t *audio_out) {
this->audio_out = audio_out;
this->output_open = 0;
- this->pts = 0;
this->rate = 48000;
this->bits_per_sample=16;
this->number_of_channels=2;
@@ -72,31 +70,30 @@ void dts_init (audio_decoder_t *this_gen, ao_instance_t *audio_out) {
void dts_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) {
- dts_decoder_t *this = (dts_decoder_t *) this_gen;
- int16_t *sample_buffer=(int16_t *)buf->content;
+ dts_decoder_t *this = (dts_decoder_t *) this_gen;
+ int16_t *sample_buffer=(int16_t *)buf->content;
+ audio_buffer_t *audio_buffer;
if ((this->audio_caps & AO_CAP_MODE_AC5) == 0) {
return;
}
- this->pts = buf->PTS;
-
-
if (!this->output_open) {
this->output_open = (this->audio_out->open (this->audio_out, this->bits_per_sample,
this->rate,
AO_CAP_MODE_AC5));
}
- if (!this->output_open) {
+ if (!this->output_open)
return;
- }
-
- this->audio_out->write (this->audio_out,
- sample_buffer,
- 1536,
- this->pts);
+
+ audio_buffer = this->audio_out->get_buffer (this->audio_out);
+ audio_buffer->vpts = buf->PTS;
+ audio_buffer->scr = buf->SCR;
+ audio_buffer->num_frames = 1536;
+ this->audio_out->put_buffer (this->audio_out, audio_buffer);
+
}
void dts_close (audio_decoder_t *this_gen) {
diff --git a/src/liblpcm/xine_decoder.c b/src/liblpcm/xine_decoder.c
index 25d0d4362..fa45cd7bd 100644
--- a/src/liblpcm/xine_decoder.c
+++ b/src/liblpcm/xine_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: xine_decoder.c,v 1.12 2001/10/18 14:32:28 jkeil Exp $
+ * $Id: xine_decoder.c,v 1.13 2001/11/10 13:48:02 guenter Exp $
*
* 31-8-2001 Added LPCM rate sensing.
* (c) 2001 James Courtier-Dutton James@superbug.demon.co.uk
@@ -41,13 +41,12 @@
typedef struct lpcm_decoder_s {
audio_decoder_t audio_decoder;
- uint32_t pts;
uint32_t rate;
uint32_t bits_per_sample;
uint32_t number_of_channels;
uint32_t ao_cap_mode;
- ao_instance_t *audio_out;
+ ao_instance_t *audio_out;
int output_open;
int cpu_be; /* TRUE, if we're a Big endian CPU */
} lpcm_decoder_t;
@@ -66,7 +65,6 @@ void lpcm_init (audio_decoder_t *this_gen, ao_instance_t *audio_out) {
this->audio_out = audio_out;
this->output_open = 0;
- this->pts = 0;
this->rate = 0;
this->bits_per_sample=0;
this->number_of_channels=0;
@@ -79,10 +77,10 @@ void lpcm_init (audio_decoder_t *this_gen, ao_instance_t *audio_out) {
void lpcm_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) {
lpcm_decoder_t *this = (lpcm_decoder_t *) this_gen;
- int16_t *sample_buffer=(int16_t *)buf->content;
- int stream_be;
+ int16_t *sample_buffer=(int16_t *)buf->content;
+ int stream_be;
+ audio_buffer_t *audio_buffer;
- this->pts = buf->PTS;
if (buf->decoder_info[0] == 0) {
this->rate=buf->decoder_info[1];
this->bits_per_sample=buf->decoder_info[2] ;
@@ -113,17 +111,22 @@ void lpcm_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) {
if (!this->output_open)
return;
+ audio_buffer = this->audio_out->get_buffer (this->audio_out);
+
/* Swap LPCM samples into native byte order, if necessary */
+
stream_be = ( buf->type == BUF_AUDIO_LPCM_BE );
if (stream_be != this->cpu_be)
- swab(sample_buffer, sample_buffer, buf->size);
+ swab (audio_buffer->mem, sample_buffer, buf->size);
+ else
+ memcpy (audio_buffer->mem, sample_buffer, buf->size);
+
+ audio_buffer->vpts = buf->PTS;
+ audio_buffer->scr = buf->SCR;
+ audio_buffer->num_frames = (((buf->size*8)/this->number_of_channels)/this->bits_per_sample);
- this->audio_out->write (this->audio_out,
- sample_buffer,
- (((buf->size*8)/this->number_of_channels)/this->bits_per_sample),
- this->pts);
+ this->audio_out->put_buffer (this->audio_out, audio_buffer);
-
}
void lpcm_close (audio_decoder_t *this_gen) {
diff --git a/src/libmad/xine_decoder.c b/src/libmad/xine_decoder.c
index ed537fc30..dd775740c 100644
--- a/src/libmad/xine_decoder.c
+++ b/src/libmad/xine_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: xine_decoder.c,v 1.7 2001/09/12 17:33:34 guenter Exp $
+ * $Id: xine_decoder.c,v 1.8 2001/11/10 13:48:02 guenter Exp $
*
* stuff needed to turn libmad into a xine decoder plugin
*/
@@ -31,7 +31,6 @@
#include "frame.h"
#include "synth.h"
-#define MAX_NUM_SAMPLES 8192
#define INPUT_BUF_SIZE 16384
typedef struct mad_decoder_s {
@@ -48,8 +47,6 @@ typedef struct mad_decoder_s {
int output_open;
int output_mode;
- int16_t samples[MAX_NUM_SAMPLES];
-
uint8_t buffer[INPUT_BUF_SIZE];
int bytes_in_buffer;
@@ -189,10 +186,14 @@ static void mad_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) {
mad_synth_frame (&this->synth, &this->frame);
{
- unsigned int nchannels, nsamples;
- mad_fixed_t const *left_ch, *right_ch;
- struct mad_pcm *pcm = &this->synth.pcm;
- uint16_t *output = this->samples;
+ unsigned int nchannels, nsamples;
+ mad_fixed_t const *left_ch, *right_ch;
+ struct mad_pcm *pcm = &this->synth.pcm;
+ audio_buffer_t *audio_buffer;
+ uint16_t *output;
+
+ audio_buffer = this->audio_out->get_buffer (this->audio_out);
+ output = audio_buffer->mem;
nchannels = pcm->channels;
nsamples = pcm->length;
@@ -209,10 +210,12 @@ static void mad_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) {
}
- this->audio_out->write (this->audio_out,
- this->samples,
- pcm->length,
- buf->PTS);
+ audio_buffer->num_frames = pcm->length;
+ audio_buffer->vpts = buf->PTS;
+ audio_buffer->scr = buf->SCR;
+
+ this->audio_out->put_buffer (this->audio_out, audio_buffer);
+
buf->PTS = 0;
}
diff --git a/src/libmpeg2/decode.c b/src/libmpeg2/decode.c
index 1b0432472..e0ceacb97 100644
--- a/src/libmpeg2/decode.c
+++ b/src/libmpeg2/decode.c
@@ -257,6 +257,7 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code,
}
picture->current_frame->bad_frame = 0;
picture->current_frame->PTS = mpeg2dec->pts;
+ picture->current_frame->SCR = mpeg2dec->scr;
mpeg2dec->pts = 0;
}
}
@@ -323,7 +324,7 @@ static inline uint8_t * copy_chunk (mpeg2dec_t * mpeg2dec,
}
int mpeg2_decode_data (mpeg2dec_t * mpeg2dec, uint8_t * current, uint8_t * end,
- uint32_t pts)
+ uint32_t pts, uint32_t scr)
{
int ret;
uint8_t code;
@@ -340,6 +341,8 @@ int mpeg2_decode_data (mpeg2dec_t * mpeg2dec, uint8_t * current, uint8_t * end,
if (pts)
mpeg2dec->pts = pts;
+ mpeg2dec->scr = scr;
+
while (current != end) {
code = mpeg2dec->code;
current = copy_chunk (mpeg2dec, current, end);
@@ -380,6 +383,7 @@ void mpeg2_close (mpeg2dec_t * mpeg2dec)
if (picture->throwaway_frame) {
printf ("libmpeg2: blasting out throwaway frame on close\n");
picture->throwaway_frame->PTS = 0;
+ picture->throwaway_frame->SCR = mpeg2dec->scr;
picture->throwaway_frame->bad_frame = 0;
picture->throwaway_frame->draw (picture->throwaway_frame);
picture->throwaway_frame->free (picture->throwaway_frame);
@@ -388,6 +392,7 @@ void mpeg2_close (mpeg2dec_t * mpeg2dec)
if (picture->backward_reference_frame) {
printf ("libmpeg2: blasting out backward reference frame on close\n");
picture->backward_reference_frame->PTS = 0;
+ picture->backward_reference_frame->SCR = mpeg2dec->scr;
picture->backward_reference_frame->bad_frame = 0;
picture->backward_reference_frame->draw (picture->backward_reference_frame);
picture->backward_reference_frame->free (picture->backward_reference_frame);
diff --git a/src/libmpeg2/mpeg2.h b/src/libmpeg2/mpeg2.h
index 5ff2165bf..c4f250f6d 100644
--- a/src/libmpeg2/mpeg2.h
+++ b/src/libmpeg2/mpeg2.h
@@ -43,7 +43,7 @@ typedef struct mpeg2dec_s {
/* last start code ? */
uint8_t code;
- uint32_t pts;
+ uint32_t pts, scr;
} mpeg2dec_t ;
@@ -60,7 +60,7 @@ void mpeg2_close (mpeg2dec_t * mpeg2dec);
int mpeg2_decode_data (mpeg2dec_t * mpeg2dec,
uint8_t * data_start, uint8_t * data_end,
- uint32_t pts);
+ uint32_t pts, uint32_t scr);
void mpeg2_find_sequence_header (mpeg2dec_t * mpeg2dec,
uint8_t * data_start, uint8_t * data_end);
diff --git a/src/libmpeg2/xine_decoder.c b/src/libmpeg2/xine_decoder.c
index 012e24a5f..5c4885237 100644
--- a/src/libmpeg2/xine_decoder.c
+++ b/src/libmpeg2/xine_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: xine_decoder.c,v 1.15 2001/10/03 17:17:06 jkeil Exp $
+ * $Id: xine_decoder.c,v 1.16 2001/11/10 13:48:03 guenter Exp $
*
* stuff needed to turn libmpeg2 into a xine decoder plugin
*/
@@ -72,7 +72,7 @@ static void mpeg2dec_decode_data (video_decoder_t *this_gen, buf_element_t *buf)
/* write (this->mpeg_file, buf->content, buf->size); */
mpeg2_decode_data (&this->mpeg2, buf->content, buf->content + buf->size,
- buf->PTS);
+ buf->PTS, buf->SCR);
}
diff --git a/src/libspudec/xine_decoder.c b/src/libspudec/xine_decoder.c
index 338ece46b..6346f4849 100644
--- a/src/libspudec/xine_decoder.c
+++ b/src/libspudec/xine_decoder.c
@@ -19,7 +19,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_decoder.c,v 1.31 2001/10/26 20:18:54 jcdutton Exp $
+ * $Id: xine_decoder.c,v 1.32 2001/11/10 13:48:03 guenter Exp $
*
* stuff needed to turn libspu into a xine decoder plugin
*/
@@ -476,7 +476,7 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) {
if (buf->PTS) {
metronom_t *metronom = this->ovl_src.metronom;
- uint32_t vpts = metronom->got_spu_packet(metronom, buf->PTS, 0);
+ uint32_t vpts = metronom->got_spu_packet(metronom, buf->PTS, 0, buf->SCR);
if (vpts < this->buf_pts) {
/* FIXME: Don't do this yet,
because it will cause all sorts of
diff --git a/src/libvorbis/xine_decoder.c b/src/libvorbis/xine_decoder.c
index 53d90c55c..6d2ee9a7e 100644
--- a/src/libvorbis/xine_decoder.c
+++ b/src/libvorbis/xine_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: xine_decoder.c,v 1.1 2001/10/07 03:53:11 heikos Exp $
+ * $Id: xine_decoder.c,v 1.2 2001/11/10 13:48:03 guenter Exp $
*
* (ogg/)vorbis audio decoder plugin (libvorbis wrapper) for xine
*/
@@ -171,11 +171,14 @@ static void vorbis_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) {
int i,j;
int clipflag=0;
int bout=(samples<this->convsize?samples:this->convsize);
+ audio_buffer_t *audio_buffer;
+
+ audio_buffer = this->audio_out->get_buffer (this->audio_out);
/* convert floats to 16 bit signed ints (host order) and
interleave */
for(i=0;i<this->vi.channels;i++){
- ogg_int16_t *ptr=this->convbuffer+i;
+ ogg_int16_t *ptr=audio_buffer->mem+i;
float *mono=pcm[i];
for(j=0;j<bout;j++){
int val=mono[j]*32767.f;
@@ -193,10 +196,11 @@ static void vorbis_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) {
}
}
- this->audio_out->write (this->audio_out,
- this->convbuffer,
- bout,
- buf->PTS);
+ audio_buffer->vpts = buf->PTS;
+ audio_buffer->num_frames = bout;
+
+ this->audio_out->put_buffer (this->audio_out, audio_buffer);
+
buf->PTS=0;
vorbis_synthesis_read(&this->vd,bout);
}
diff --git a/src/libw32dll/w32codec.c b/src/libw32dll/w32codec.c
index 1e02a83dd..c49971680 100644
--- a/src/libw32dll/w32codec.c
+++ b/src/libw32dll/w32codec.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: w32codec.c,v 1.39 2001/11/08 21:39:03 miguelfreitas Exp $
+ * $Id: w32codec.c,v 1.40 2001/11/10 13:48:03 guenter Exp $
*
* routines for using w32 codecs
*
@@ -75,10 +75,8 @@ typedef struct w32a_decoder_s {
int output_open;
int decoder_ok;
- unsigned char *buf;
+ unsigned char *buf;
int size;
- unsigned char *sample_buf;
- int sample_buf_size;
HACMSTREAM srcstream;
int rec_audio_src_size;
int num_channels;
@@ -505,6 +503,7 @@ static void w32v_decode_data (video_decoder_t *this_gen, buf_element_t *buf) {
}
img->PTS = buf->PTS;
+ img->SCR = buf->SCR;
if(ret) {
printf("w32codec: Error decompressing frame, err=%ld\n", (long)ret);
img->bad_frame = 1;
@@ -596,7 +595,7 @@ static void w32a_init (audio_decoder_t *this_gen, ao_instance_t *audio_out) {
this->output_open = 0;
this->decoder_ok = 0;
- this->buf = this->sample_buf = NULL;
+ this->buf = NULL;
}
static int w32a_init_audio (w32a_decoder_t *this,
@@ -663,8 +662,6 @@ static int w32a_init_audio (w32a_decoder_t *this,
if( this->buf )
free(this->buf);
- if( this->sample_buf )
- free(this->sample_buf);
if( this->rec_audio_src_size < 2 * in_fmt->nBlockAlign ) {
this->rec_audio_src_size = 2 * in_fmt->nBlockAlign;
@@ -672,8 +669,6 @@ static int w32a_init_audio (w32a_decoder_t *this,
printf("w32codec: adjusting source buffer size to %d\n", this->rec_audio_src_size);
}
this->buf = malloc( 2 * this->rec_audio_src_size );
- this->sample_buf = malloc( srcsize );
- this->sample_buf_size = srcsize;
this->size = 0;
@@ -682,32 +677,41 @@ static int w32a_init_audio (w32a_decoder_t *this,
static void w32a_decode_audio (w32a_decoder_t *this,
- unsigned char *data, uint32_t nSize,
- int bFrameEnd, uint32_t nPTS) {
+ unsigned char *data,
+ uint32_t size,
+ int frame_end,
+ uint32_t pts,
+ uint32_t scr) {
static ACMSTREAMHEADER ash;
HRESULT hr;
/* DWORD srcsize=0; */
- fast_memcpy (&this->buf[this->size], data, nSize);
+ fast_memcpy (&this->buf[this->size], data, size);
- this->size += nSize;
+ this->size += size;
if( this->size > 2 * this->rec_audio_src_size )
printf("w32codec: buffer overflow on w32a_decode_audio\n");
while (this->size >= this->rec_audio_src_size) {
+ audio_buffer_t *audio_buffer = this->audio_out->get_buffer (this->audio_out);
+
memset(&ash, 0, sizeof(ash));
ash.cbStruct=sizeof(ash);
ash.fdwStatus=0;
ash.dwUser=0;
ash.pbSrc=this->buf;
ash.cbSrcLength=this->rec_audio_src_size;
- ash.pbDst=this->sample_buf;
- ash.cbDstLength=this->sample_buf_size;
+ ash.pbDst=(uint8_t *)audio_buffer->mem;
+ ash.cbDstLength=audio_buffer->mem_size;
hr=acmStreamPrepareHeader(this->srcstream,&ash,0);
if(hr){
printf("w32codec: (ACM_Decoder) acmStreamPrepareHeader error %d\n",(int)hr);
+
+ audio_buffer->num_frames = 0;
+ this->audio_out->put_buffer (this->audio_out, audio_buffer);
+
return;
}
@@ -722,21 +726,23 @@ static void w32a_decode_audio (w32a_decoder_t *this,
if(hr){
printf("w32codec: acmStreamConvert error %d, used %d bytes\n",(int)hr,(int)ash.cbSrcLengthUsed);
ash.cbSrcLengthUsed = this->rec_audio_src_size;
+
+ audio_buffer->num_frames = 0;
+ this->audio_out->put_buffer (this->audio_out, audio_buffer);
+
} else {
/*
printf ("acmStreamConvert worked, used %d bytes, generated %d bytes\n",
ash.cbSrcLengthUsed, ash.cbDstLengthUsed);
*/
if (ash.cbDstLengthUsed>0) {
- /*
- printf ("decoded : %02x %02x %02x %02x ... %02x %02x \n",
- this->sample_buf[0], this->sample_buf[1], this->sample_buf[2], this->sample_buf[3],
- this->sample_buf[ash.cbDstLengthUsed-2], this->sample_buf[ash.cbDstLengthUsed-1]);
- */
- this->audio_out->write (this->audio_out,
- (int16_t*) this->sample_buf,
- ash.cbDstLengthUsed / (this->num_channels*2),
- nPTS);
+
+ audio_buffer->num_frames = ash.cbDstLengthUsed / (this->num_channels*2);
+ audio_buffer->vpts = pts;
+ audio_buffer->scr = scr;
+
+ this->audio_out->put_buffer (this->audio_out, audio_buffer);
+
}
}
if(ash.cbSrcLengthUsed>=this->size){
@@ -765,7 +771,7 @@ static void w32a_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) {
w32a_decode_audio (this, buf->content, buf->size,
buf->decoder_info[0]==2,
- buf->PTS);
+ buf->PTS, buf->SCR);
}
}
@@ -787,10 +793,6 @@ static void w32a_close (audio_decoder_t *this_gen) {
free(this->buf);
this->buf = NULL;
}
- if( this->sample_buf ) {
- free(this->sample_buf);
- this->sample_buf = NULL;
- }
}
static char *w32a_get_id(void) {
diff --git a/src/xine-engine/audio_decoder.c b/src/xine-engine/audio_decoder.c
index 9a7a6015a..0e920f477 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.50 2001/10/22 01:23:08 jcdutton Exp $
+ * $Id: audio_decoder.c,v 1.51 2001/11/10 13:48:03 guenter Exp $
*
*
* functions that implement audio decoding
@@ -124,13 +124,24 @@ void *audio_decoder_loop (void *this_gen) {
break;
case BUF_VIDEO_FILL:
- this->metronom->got_audio_still (this->metronom);
break;
case BUF_CONTROL_NOP:
break;
case BUF_CONTROL_DISCONTINUITY:
+ printf ("audio_decoder: BUF_CONTROL_DISCONTINUITY is deprecated\n");
+ break;
+
+ case BUF_CONTROL_AVSYNC_RESET:
+ printf ("audio_decoder: discontinuity ahead\n");
+
+ /* fixme ? */
+ if (this->cur_audio_decoder_plugin) {
+ this->cur_audio_decoder_plugin->close (this->cur_audio_decoder_plugin);
+ this->cur_audio_decoder_plugin = NULL;
+ }
+
this->metronom->expect_audio_discontinuity (this->metronom);
break;
diff --git a/src/xine-engine/audio_out.c b/src/xine-engine/audio_out.c
index ab5cb40f4..b56b8b0b4 100644
--- a/src/xine-engine/audio_out.c
+++ b/src/xine-engine/audio_out.c
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2000, 2001 the xine project
*
- * This file is part of xine, a unix video player.
+ * This file is part of xine, a free video player.
*
* xine is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,7 +17,7 @@
* along with self program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: audio_out.c,v 1.23 2001/11/04 22:49:38 guenter Exp $
+ * $Id: audio_out.c,v 1.24 2001/11/10 13:48:03 guenter Exp $
*
* 22-8-2001 James imported some useful AC3 sections from the previous alsa driver.
* (c) 2001 Andy Lo A Foe <andy@alsaplayer.org>
@@ -66,9 +66,14 @@
#include "metronom.h"
#include "utils.h"
-#define ZERO_BUF_SIZE 5000
+/*
+#define AUDIO_OUT_LOG
+*/
-#define MAX_GAP 90000
+#define NUM_AUDIO_BUFFERS 32
+#define AUDIO_BUF_SIZE 32768
+
+#define ZERO_BUF_SIZE 5000
struct frmsize_s
{
@@ -119,57 +124,90 @@ static const struct frmsize_s frmsizecod_tbl[64] =
{ 640 ,{1280 ,1394 ,1920 } }
};
-/*
- * open the audio device for writing to
- */
-static int ao_open(ao_instance_t *this,
- uint32_t bits, uint32_t rate, int mode)
-{
- int output_sample_rate;
- if ((output_sample_rate=this->driver->open(this->driver,bits,(this->force_rate ? this->force_rate : rate),mode)) == 0) {
- printf("audio_out: open failed!\n");
- return 0;
- };
+struct audio_fifo_s {
+ audio_buffer_t *first;
+ audio_buffer_t *last;
+ int num_buffers;
- printf("audio_out: output sample rate %d\n", output_sample_rate);
+ pthread_mutex_t mutex;
+ pthread_cond_t not_empty;
+};
- this->mode = mode;
- this->input_frame_rate = rate;
- this->bits = bits;
- this->audio_started = 0;
- this->last_audio_vpts = 0;
- this->output_frame_rate = output_sample_rate;
+static audio_fifo_t *fifo_new () {
- switch (this->resample_conf) {
- case 1: /* force off */
- this->do_resample = 0;
- break;
- case 2: /* force on */
- this->do_resample = 1;
- break;
- default: /* AUTO */
- this->do_resample = this->output_frame_rate != this->input_frame_rate;
+ audio_fifo_t *fifo;
+
+ fifo = (audio_fifo_t *) xmalloc (sizeof (audio_fifo_t));
+
+ if (!fifo) {
+ printf ("audio_out: out of memory!\n");
+ return NULL;
}
- /* HACK: we do not have resample functions for 8-bit audio */
- if (this->bits==8)
- this->do_resample = 0;
+ fifo->first = NULL;
+ fifo->last = NULL;
+ fifo->num_buffers = 0;
+ pthread_mutex_init (&fifo->mutex, NULL);
+ pthread_cond_init (&fifo->not_empty, NULL);
- if (this->do_resample)
- printf("audio_out: will resample audio from %d to %d\n",
- this->input_frame_rate, this->output_frame_rate);
+ return fifo;
+}
- this->num_channels = this->driver->num_channels(this->driver);
+static void fifo_append (audio_fifo_t *fifo,
+ audio_buffer_t *buf) {
- this->frame_rate_factor = (double) this->output_frame_rate / (double) this->input_frame_rate;
- this->audio_step = (uint32_t) 90000 * (uint32_t) 32768 / this->input_frame_rate;
- this->frames_per_kpts = this->output_frame_rate * 1024 / 90000;
- xprintf (VERBOSE|AUDIO, "audio_out : audio_step %d pts per 32768 frames\n", this->audio_step);
+ pthread_mutex_lock (&fifo->mutex);
- this->metronom->set_audio_rate(this->metronom, this->audio_step);
+ buf->next = NULL;
- return this->output_frame_rate;
+ if (!fifo->first) {
+
+ fifo->first = buf;
+ fifo->last = buf;
+ fifo->num_buffers = 1;
+
+ } else {
+
+ fifo->last->next = buf;
+ fifo->last = buf;
+ fifo->num_buffers++;
+
+ }
+
+ pthread_cond_signal (&fifo->not_empty);
+ pthread_mutex_unlock (&fifo->mutex);
+}
+
+static audio_buffer_t *fifo_remove (audio_fifo_t *fifo) {
+
+ audio_buffer_t *buf;
+
+ pthread_mutex_lock (&fifo->mutex);
+
+ while (!fifo->first) {
+ pthread_cond_wait (&fifo->not_empty, &fifo->mutex);
+ }
+
+ buf = fifo->first;
+
+ if (buf) {
+ fifo->first = buf->next;
+
+ if (!fifo->first) {
+
+ fifo->last = NULL;
+ fifo->num_buffers = 0;
+ pthread_cond_init (&fifo->not_empty, NULL);
+
+ } else
+ fifo->num_buffers--;
+
+ }
+
+ pthread_mutex_unlock (&fifo->mutex);
+
+ return buf;
}
/*
@@ -216,10 +254,6 @@ void write_pause_burst(ao_instance_t *this, uint32_t num_frames)
static void ao_fill_gap (ao_instance_t *this, uint32_t pts_len) {
int num_frames ;
- xprintf (VERBOSE|AUDIO, "audio_out : fill_gap\n");
-
- if (pts_len > MAX_GAP)
- pts_len = MAX_GAP;
num_frames = pts_len * this->frames_per_kpts / 1024;
@@ -243,177 +277,297 @@ static void ao_fill_gap (ao_instance_t *this, uint32_t pts_len) {
}
-static int ao_write(ao_instance_t *this,
- int16_t* output_frames, uint32_t num_frames,
- uint32_t pts)
-{
- uint32_t vpts, buffer_vpts;
- int32_t gap;
- int bDropPackage;
- int delay;
- int frame_size;
- int fscod;
- int frmsizecod;
- uint8_t *data;
- uint32_t cur_time;
-
- vpts = this->metronom->got_audio_samples (this->metronom, pts, num_frames);
+static void *ao_loop (void *this_gen) {
- xprintf (VERBOSE|AUDIO, "audio_out: got %d frames, vpts=%d pts=%d\n",
- num_frames, vpts, pts);
+ ao_instance_t *this = (ao_instance_t *) this_gen;
+ uint32_t hw_vpts;
+ audio_buffer_t *buf;
+ int32_t gap;
+ int delay;
+ int frame_size;
+ int fscod;
+ int frmsizecod;
+ uint8_t *data;
+ uint32_t cur_time;
+ int num_output_frames ;
- if (vpts<this->last_audio_vpts) {
- /* reject this */
- xprintf (VERBOSE|AUDIO, "audio_out: rejected frame vpts=%d, last_audio_vpts=%d\n", vpts,this->last_audio_vpts)
+ this->audio_loop_running = 1;
+
+ while ((this->audio_loop_running) ||
+ (!this->audio_loop_running && this->out_fifo->first)) {
- return 1;
- }
- this->last_audio_vpts = vpts;
+#ifdef AUDIO_OUT_LOG
+ printf ("audio_out: fifo_remove\n");
+#endif
+
+ buf = fifo_remove (this->out_fifo);
- bDropPackage = 0;
+ if (!buf->num_frames)
+ break;
- if (this->audio_started)
delay = this->driver->delay(this->driver);
- else
- delay = 0;
- /*
- * where, in the timeline is the "end" of the audio buffer at the moment?
- */
+ /*
+ * where, in the timeline is the "end" of the
+ * hardware audio buffer at the moment?
+ */
- cur_time = this->metronom->get_current_time (this->metronom);
- buffer_vpts = cur_time;
-
- /* External A52 decoder delay correction */
- if ((this->mode==AO_CAP_MODE_A52) || (this->mode==AO_CAP_MODE_AC5))
- delay+=10;
-
- buffer_vpts += delay * 1024 / this->frames_per_kpts;
-
- /*
- * calculate gap:
- */
+ cur_time = this->metronom->get_current_time (this->metronom);
+ hw_vpts = cur_time;
- gap = vpts - buffer_vpts;
+#ifdef AUDIO_OUT_LOG
+ printf ("audio_out: current delay is %d, current time is %d\n",
+ delay, cur_time);
+#endif
+
+ /* External A52 decoder delay correction */
+ if ((this->mode==AO_CAP_MODE_A52) || (this->mode==AO_CAP_MODE_AC5))
+ delay+=10;
- /*
- printf ("vpts : %d buffer_vpts : %d gap %d\n",
- vpts, buffer_vpts, gap);
- */
+ hw_vpts += delay * 1024 / this->frames_per_kpts;
- if (gap>this->gap_tolerance) {
-
-
- if (gap>15000)
- ao_fill_gap (this, gap);
- else {
- printf ("audio_out: adjusting master clock %d -> %d\n",
- cur_time, cur_time + gap);
- this->metronom->adjust_clock (this->metronom,
- cur_time + gap);
- }
+ /*
+ * calculate gap:
+ */
- /* keep xine responsive */
+ gap = buf->vpts - hw_vpts;
- if (gap>MAX_GAP)
- return 0;
+ /*
+ printf ("vpts : %d buffer_vpts : %d gap %d\n",
+ vpts, buffer_vpts, gap);
+ */
+
+ /*
+ * output audio data synced to master clock
+ */
+
+ if (gap < (-1 * this->gap_tolerance)) {
+
+ /* drop package */
+
+ xprintf (VERBOSE|AUDIO, "audio_out: audio package (vpts = %d %d) dropped\n",
+ vpts, gap);
+
+ } else {
+
+ if (gap>this->gap_tolerance) {
- } else if (gap < (-1 * this->gap_tolerance)) {
- bDropPackage = 1;
- xprintf (VERBOSE|AUDIO, "audio_out: audio package (vpts = %d %d)"
- "dropped\n", vpts, gap);
- }
+ if (gap>15000)
+ ao_fill_gap (this, gap);
+ else {
+ printf ("audio_out: adjusting master clock %d -> %d\n",
+ cur_time, cur_time + gap);
+ this->metronom->adjust_clock (this->metronom,
+ cur_time + gap);
+ }
+
+ }
+ /*
+ * resample and output audio data
+ */
+
+ num_output_frames = (double) buf->num_frames * this->frame_rate_factor;
+
+ if ((!this->do_resample)
+ && (this->mode != AO_CAP_MODE_A52)
+ && (this->mode != AO_CAP_MODE_AC5)) {
+
+ this->driver->write (this->driver, buf->mem,
+ buf->num_frames );
+ } else switch (this->mode) {
+ case AO_CAP_MODE_MONO:
+ audio_out_resample_mono (buf->mem, buf->num_frames,
+ this->frame_buffer, num_output_frames);
+ this->driver->write(this->driver, this->frame_buffer, num_output_frames);
+ break;
+ case AO_CAP_MODE_STEREO:
+ audio_out_resample_stereo (buf->mem, buf->num_frames,
+ this->frame_buffer, num_output_frames);
+ this->driver->write(this->driver, this->frame_buffer, num_output_frames);
+ break;
+ case AO_CAP_MODE_4CHANNEL:
+ audio_out_resample_4channel (buf->mem, buf->num_frames,
+ this->frame_buffer, num_output_frames);
+ this->driver->write(this->driver, this->frame_buffer, num_output_frames);
+ break;
+ case AO_CAP_MODE_5CHANNEL:
+ audio_out_resample_5channel (buf->mem, buf->num_frames,
+ this->frame_buffer, num_output_frames);
+ this->driver->write(this->driver, this->frame_buffer, num_output_frames);
+ break;
+ case AO_CAP_MODE_5_1CHANNEL:
+ audio_out_resample_6channel (buf->mem, buf->num_frames,
+ this->frame_buffer, num_output_frames);
+ this->driver->write(this->driver, this->frame_buffer, num_output_frames);
+ break;
+ case AO_CAP_MODE_A52:
+
+ this->frame_buffer[0] = 0xf872; /* spdif syncword */
+ this->frame_buffer[1] = 0x4e1f; /* ............. */
+ this->frame_buffer[2] = 0x0001; /* AC3 data */
+
+ data = (uint8_t *)&buf->mem[1]; /* skip AC3 sync */
+ fscod = (data[2] >> 6) & 0x3;
+ frmsizecod = data[2] & 0x3f;
+ frame_size = frmsizecod_tbl[frmsizecod].frm_size[fscod] << 4;
+ this->frame_buffer[3] = frame_size;
+
+ /* ac3 seems to be swabbed data */
+ swab(buf->mem,this->frame_buffer+4, buf->num_frames );
+ this->driver->write(this->driver, this->frame_buffer, 1536);
+
+ break;
+ case AO_CAP_MODE_AC5:
+ memset(this->frame_buffer,0xff,6144);
+ this->frame_buffer[0] = 0xf872; /* spdif syncword */
+ this->frame_buffer[1] = 0x4e1f; /* ............. */
+ this->frame_buffer[2] = 0x0001; /* */
+
+ this->frame_buffer[3] = 0x3ee0;
+
+ /* ac3 seems to be swabbed data */
+ swab(buf->mem,this->frame_buffer+4, 2014 );
+
+ this->driver->write(this->driver, this->frame_buffer, 1024);
+
+ break;
+
+ }
+
+ }
+
+ fifo_append (this->free_fifo, buf);
+
+ }
+
+ pthread_exit(NULL);
+
+ return NULL;
+}
+
+/*
+ * open the audio device for writing to, start audio output thread
+ */
+
+static int ao_open(ao_instance_t *this,
+ uint32_t bits, uint32_t rate, int mode) {
+
+ int output_sample_rate, err;
+
+ if ((output_sample_rate=this->driver->open(this->driver,bits,(this->force_rate ? this->force_rate : rate),mode)) == 0) {
+ printf("audio_out: open failed!\n");
+ return 0;
+ };
+
+ printf("audio_out: output sample rate %d\n", output_sample_rate);
+
+ this->mode = mode;
+ this->input_frame_rate = rate;
+ this->bits = bits;
+ this->last_audio_vpts = 0;
+ this->output_frame_rate = output_sample_rate;
+
+ switch (this->resample_conf) {
+ case 1: /* force off */
+ this->do_resample = 0;
+ break;
+ case 2: /* force on */
+ this->do_resample = 1;
+ break;
+ default: /* AUTO */
+ this->do_resample = this->output_frame_rate != this->input_frame_rate;
+ }
+
+ /* HACK: we do not have resample functions for 8-bit audio */
+ if (this->bits==8)
+ this->do_resample = 0;
+
+ if (this->do_resample)
+ printf("audio_out: will resample audio from %d to %d\n",
+ this->input_frame_rate, this->output_frame_rate);
+
+ this->num_channels = this->driver->num_channels(this->driver);
+
+ this->frame_rate_factor = (double) this->output_frame_rate / (double) this->input_frame_rate;
+ this->audio_step = (uint32_t) 90000 * (uint32_t) 32768 / this->input_frame_rate;
+ this->frames_per_kpts = this->output_frame_rate * 1024 / 90000;
+ xprintf (VERBOSE|AUDIO, "audio_out : audio_step %d pts per 32768 frames\n", this->audio_step);
+
+ this->metronom->set_audio_rate(this->metronom, this->audio_step);
+
/*
- * resample and output frames
+ * start output thread
*/
- if (!bDropPackage) {
- int num_output_frames = (double) num_frames * this->frame_rate_factor;
-
- if ((!this->do_resample)
- && (this->mode != AO_CAP_MODE_A52)
- && (this->mode != AO_CAP_MODE_AC5)) {
- xprintf (VERBOSE|AUDIO, "audio_out: writing without resampling\n");
- this->driver->write (this->driver, output_frames,
- num_frames );
- } else switch (this->mode) {
- case AO_CAP_MODE_MONO:
- audio_out_resample_mono (output_frames, num_frames,
- this->frame_buffer, num_output_frames);
- this->driver->write(this->driver, this->frame_buffer, num_output_frames);
- break;
- case AO_CAP_MODE_STEREO:
- audio_out_resample_stereo (output_frames, num_frames,
- this->frame_buffer, num_output_frames);
- this->driver->write(this->driver, this->frame_buffer, num_output_frames);
- break;
- case AO_CAP_MODE_4CHANNEL:
- audio_out_resample_4channel (output_frames, num_frames,
- this->frame_buffer, num_output_frames);
- this->driver->write(this->driver, this->frame_buffer, num_output_frames);
- break;
- case AO_CAP_MODE_5CHANNEL:
- audio_out_resample_5channel (output_frames, num_frames,
- this->frame_buffer, num_output_frames);
- this->driver->write(this->driver, this->frame_buffer, num_output_frames);
- break;
- case AO_CAP_MODE_5_1CHANNEL:
- audio_out_resample_6channel (output_frames, num_frames,
- this->frame_buffer, num_output_frames);
- this->driver->write(this->driver, this->frame_buffer, num_output_frames);
- break;
- case AO_CAP_MODE_A52:
-
- this->frame_buffer[0] = 0xf872; /* spdif syncword */
- this->frame_buffer[1] = 0x4e1f; /* ............. */
- this->frame_buffer[2] = 0x0001; /* AC3 data */
+ if ((err = pthread_create (&this->audio_thread,
+ NULL, ao_loop, this)) != 0) {
- data = (uint8_t *)&output_frames[1]; /* skip AC3 sync */
- fscod = (data[2] >> 6) & 0x3;
- frmsizecod = data[2] & 0x3f;
- frame_size = frmsizecod_tbl[frmsizecod].frm_size[fscod] << 4;
- this->frame_buffer[3] = frame_size;
+ /* FIXME: how does this happen ? */
- /* ac3 seems to be swabbed data */
- swab(output_frames,this->frame_buffer+4, num_frames );
- this->driver->write(this->driver, this->frame_buffer, 1536);
+ printf ("audio_out: can't create thread (%s)\n", strerror(err));
+ printf ("audio_out: sorry, this should not happen. please restart xine.\n");
+ exit(1);
- break;
- case AO_CAP_MODE_AC5:
- memset(this->frame_buffer,0xff,6144);
- this->frame_buffer[0] = 0xf872; /* spdif syncword */
- this->frame_buffer[1] = 0x4e1f; /* ............. */
- this->frame_buffer[2] = 0x0001; /* */
+ } else
+ printf ("audio_out: thread created\n");
- this->frame_buffer[3] = 0x3ee0;
- /* ac3 seems to be swabbed data */
- swab(output_frames,this->frame_buffer+4, 2014 );
-
- this->driver->write(this->driver, this->frame_buffer, 1024);
-
- break;
- }
+ return this->output_frame_rate;
+}
- xprintf (AUDIO|VERBOSE, "audio_out :audio package written\n");
+static audio_buffer_t *ao_get_buffer (ao_instance_t *this) {
+ return fifo_remove (this->free_fifo);
+}
- /*
- * step values
- */
+static void ao_put_buffer (ao_instance_t *this, audio_buffer_t *buf) {
- this->audio_started = 1;
+ if (buf->num_frames == 0) {
+ fifo_append (this->free_fifo, buf);
+ return;
}
- return 1;
+ buf->vpts = this->metronom->got_audio_samples (this->metronom, buf->vpts,
+ buf->num_frames, buf->scr);
+ if ( buf->vpts<this->last_audio_vpts) {
+
+ /* reject buffer */
+ printf ("audio_out: rejected buffer vpts=%d, last_audio_vpts=%d\n",
+ buf->vpts, this->last_audio_vpts);
+
+ fifo_append (this->free_fifo, buf);
+
+ } else {
+
+ fifo_append (this->out_fifo, buf);
+ this->last_audio_vpts = buf->vpts;
+
+ }
}
+static void ao_close(ao_instance_t *this) {
+
+ audio_buffer_t *audio_buffer;
+
+ printf ("audio_out: stopping thread...\n");
+
+ if (this->audio_loop_running) {
+ void *p;
+
+ this->audio_loop_running = 0;
+
+ audio_buffer = fifo_remove(this->free_fifo);
+ audio_buffer->num_frames = 0;
+ fifo_append (this->out_fifo, audio_buffer);
+
+ pthread_join (this->audio_thread, &p);
+ }
+
+ printf ("audio_out: thread stopped, closing driver\n");
-static void ao_close(ao_instance_t *this)
-{
this->driver->close(this->driver);
}
@@ -441,6 +595,7 @@ ao_instance_t *ao_new_instance (ao_driver_t *driver, metronom_t *metronom,
config_values_t *config) {
ao_instance_t *this;
+ int i;
this = xmalloc (sizeof (ao_instance_t)) ;
@@ -448,7 +603,8 @@ ao_instance_t *ao_new_instance (ao_driver_t *driver, metronom_t *metronom,
this->metronom = metronom;
this->open = ao_open;
- this->write = ao_write;
+ this->get_buffer = ao_get_buffer;
+ this->put_buffer = ao_put_buffer;
this->close = ao_close;
this->exit = ao_exit;
this->get_capabilities = ao_get_capabilities;
@@ -462,6 +618,25 @@ ao_instance_t *ao_new_instance (ao_driver_t *driver, metronom_t *metronom,
this->resample_conf = config->lookup_int (config, "audio_resample_mode", 0);
this->force_rate = config->lookup_int (config, "audio_force_rate", 0);
+ /*
+ * pre-allocate memory for samples
+ */
+
+ this->free_fifo = fifo_new ();
+ this->out_fifo = fifo_new ();
+
+ for (i=0; i<NUM_AUDIO_BUFFERS; i++) {
+
+ audio_buffer_t *buf;
+
+ buf = (audio_buffer_t *) malloc (sizeof (audio_buffer_t));
+ buf->mem = malloc (AUDIO_BUF_SIZE);
+ buf->mem_size = AUDIO_BUF_SIZE;
+
+ fifo_append (this->free_fifo, buf);
+ }
+
+
return this;
}
diff --git a/src/xine-engine/audio_out.h b/src/xine-engine/audio_out.h
index b167f1563..86ae13484 100644
--- a/src/xine-engine/audio_out.h
+++ b/src/xine-engine/audio_out.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: audio_out.h,v 1.19 2001/11/04 22:49:38 guenter Exp $
+ * $Id: audio_out.h,v 1.20 2001/11/10 13:48:03 guenter Exp $
*/
#ifndef HAVE_AUDIO_OUT_H
#define HAVE_AUDIO_OUT_H
@@ -34,7 +34,7 @@ extern "C" {
#endif
-#define AUDIO_OUT_IFACE_VERSION 2
+#define AUDIO_OUT_IFACE_VERSION 3
/*
* ao_driver_s contains the driver every audio output
@@ -90,7 +90,7 @@ struct ao_driver_s {
* call write_audio_data with the _same_ samples again
*/
int (*write)(ao_driver_t *this,
- int16_t* audio_data, uint32_t num_samples);
+ int16_t* audio_data, uint32_t num_samples);
/*
* this is called when the decoder no longer uses the audio
@@ -121,6 +121,22 @@ struct ao_driver_s {
/*
* ao_instance_s contains the instance every audio decoder talks to
*/
+typedef struct audio_fifo_s audio_fifo_t;
+
+typedef struct audio_buffer_s audio_buffer_t;
+
+struct audio_buffer_s {
+
+ audio_buffer_t *next;
+
+ int16_t *mem;
+ int mem_size;
+ int num_frames;
+
+ uint32_t vpts;
+ uint32_t scr;
+};
+
typedef struct ao_instance_s ao_instance_t;
struct ao_instance_s {
@@ -141,17 +157,17 @@ struct ao_instance_s {
uint32_t bits, uint32_t rate, int mode);
/*
- * write audio data to output buffer
- * audio driver must sync sample playback with metronom
- * return value:
- * 1 => audio samples were processed ok
- * 0 => audio samples were not yet processed,
- * call write_audio_data with the _same_ samples again
+ * get a piece of memory for audio data
+ */
+
+ audio_buffer_t * (*get_buffer) (ao_instance_t *this);
+
+ /*
+ * append a buffer filled with audio data to the audio fifo
+ * for output
*/
- int (*write)(ao_instance_t *this,
- int16_t* audio_data, uint32_t num_frames,
- uint32_t pts);
+ void (*put_buffer) (ao_instance_t *this, audio_buffer_t *buf);
/* audio driver is no longer used by decoder => close */
void (*close) (ao_instance_t *self);
@@ -172,7 +188,6 @@ struct ao_instance_s {
int32_t output_frame_rate, input_frame_rate;
double frame_rate_factor;
uint32_t num_channels;
- int audio_started;
uint32_t last_audio_vpts;
int resample_conf;
int force_rate; /* force audio output rate to this value if non-zero */
@@ -180,6 +195,8 @@ struct ao_instance_s {
int mode;
int bits;
int gap_tolerance;
+ audio_fifo_t *free_fifo;
+ audio_fifo_t *out_fifo;
uint16_t *frame_buffer;
int16_t *zero_space;
};
diff --git a/src/xine-engine/buffer.h b/src/xine-engine/buffer.h
index 7977822e8..6e4a6de08 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.23 2001/11/07 19:41:26 miguelfreitas Exp $
+ * $Id: buffer.h,v 1.24 2001/11/10 13:48:03 guenter Exp $
*
*
* contents:
@@ -65,10 +65,11 @@ extern "C" {
#define BUF_CONTROL_START 0x01000000
#define BUF_CONTROL_END 0x01010000
#define BUF_CONTROL_QUIT 0x01020000
-#define BUF_CONTROL_DISCONTINUITY 0x01030000
+#define BUF_CONTROL_DISCONTINUITY 0x01030000 /* deprecated */
#define BUF_CONTROL_NOP 0x01040000
#define BUF_CONTROL_AUDIO_CHANNEL 0x01050000
#define BUF_CONTROL_SPU_CHANNEL 0x01060000
+#define BUF_CONTROL_AVSYNC_RESET 0x01070000
/* video buffer types: (please keep in sync with buffer_types.c) */
@@ -136,7 +137,8 @@ struct buf_element_s {
uint32_t size ; /* size of _content_ */
uint32_t max_size;
uint32_t type;
- uint32_t PTS;
+ uint32_t PTS; /* presentation time stamp, used for a/v sync */
+ uint32_t SCR; /* system clock reference, used for discont. detection */
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 */
diff --git a/src/xine-engine/metronom.c b/src/xine-engine/metronom.c
index 6b3effcc6..e2ce2fda0 100644
--- a/src/xine-engine/metronom.c
+++ b/src/xine-engine/metronom.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: metronom.c,v 1.32 2001/10/24 22:23:10 guenter Exp $
+ * $Id: metronom.c,v 1.33 2001/11/10 13:48:03 guenter Exp $
*/
#ifdef HAVE_CONFIG_H
@@ -39,16 +39,16 @@
#include "metronom.h"
#include "utils.h"
-#define MAX_PTS_TOLERANCE 5000
-#define MAX_VIDEO_DELTA 1600
-#define MAX_AUDIO_DELTA 1600
-#define AUDIO_SAMPLE_NUM 32768
-#define WRAP_START_TIME 100000
-#define WRAP_TRESHOLD 30000
-#define MAX_NUM_WRAP_DIFF 100
-#define MAX_SCR_PROVIDERS 10
-#define REALTIME_PTS 90000.0
-#define PREBUFFER_PTS_OFFSET 30000
+#define MAX_PTS_TOLERANCE 5000
+#define MAX_VIDEO_DELTA 1600
+#define MAX_AUDIO_DELTA 1600
+#define AUDIO_SAMPLE_NUM 32768
+#define WRAP_START_TIME 100000
+#define WRAP_TRESHOLD 30000
+#define SCR_DISCONTINUITY 60000
+#define MAX_NUM_WRAP_DIFF 100
+#define MAX_SCR_PROVIDERS 10
+#define PREBUFFER_PTS_OFFSET 30000
/*
#define METRONOM_LOG
@@ -228,7 +228,7 @@ static int metronom_set_speed (metronom_t *this, int speed) {
/*
* virtual pts calculation
-*/
+ */
static void metronom_video_stream_start (metronom_t *this) {
@@ -249,14 +249,18 @@ static void metronom_video_stream_start (metronom_t *this) {
this->video_pts_delta = 0;
this->last_video_pts = 0;
+ this->last_video_scr = 0;
this->num_video_vpts_guessed = 1;
- this->video_wrap_offset = 0;
+ this->video_wrap_offset = PREBUFFER_PTS_OFFSET;
this->wrap_diff_counter = 0;
this->video_stream_running = 1;
this->video_stream_starting = 1;
+ this->video_discontinuity = 0;
+ this->video_discontinuity_count = 0;
+
if (this->have_audio) {
/*while (!this->audio_stream_running) {*/
if (!this->audio_stream_running) {
@@ -317,13 +321,17 @@ static void metronom_audio_stream_start (metronom_t *this) {
this->num_audio_samples_guessed = 1;
this->last_audio_pts = 0;
+ this->last_audio_scr = 0;
- this->audio_wrap_offset = 0;
+ this->audio_wrap_offset = PREBUFFER_PTS_OFFSET;
this->wrap_diff_counter = 0;
this->audio_stream_running = 1;
this->audio_stream_starting = 1;
+ this->audio_discontinuity = 0;
+ this->audio_discontinuity_count = 0;
+
/*while (!this->video_stream_running) { */
if (!this->video_stream_running) {
printf ("metronom: waiting for video to start...\n");
@@ -385,7 +393,8 @@ static void metronom_set_audio_rate (metronom_t *this, uint32_t pts_per_smpls) {
}
-static uint32_t metronom_got_spu_packet (metronom_t *this, uint32_t pts,uint32_t duration) {
+static uint32_t metronom_got_spu_packet (metronom_t *this, uint32_t pts,
+ uint32_t duration, uint32_t scr) {
if (pts) {
this->spu_vpts=pts;
} else {
@@ -402,21 +411,37 @@ static uint32_t metronom_got_spu_packet (metronom_t *this, uint32_t pts,uint32_t
return pts + this->video_wrap_offset;
}
-static void metronom_expect_audio_discontinuity (metronom_t *this) {
-
- printf ("metronom: expecting audio discontinuity\n");
-
- this->audio_discontinuity = 10;
-}
-
static void metronom_expect_video_discontinuity (metronom_t *this) {
- printf ("metronom: expecting video discontinuity\n");
+ pthread_mutex_lock (&this->lock);
+ printf ("metronom: video discontinuity\n");
+
this->video_discontinuity = 10;
+
+ this->video_discontinuity_count++;
+ pthread_cond_signal (&this->video_discontinuity_reached);
+
+ while ( this->audio_discontinuity_count <
+ this->video_discontinuity_count ) {
+ pthread_cond_wait (&this->audio_discontinuity_reached, &this->lock);
+ }
+
+ if ( this->video_vpts < this->audio_vpts ) {
+ this->video_vpts = this->audio_vpts;
+ printf("metronom: video vpts adjusted to %d\n", this->video_vpts);
+ }
+
+ this->num_video_vpts_guessed = 1;
+ this->last_video_pts = this->video_vpts - this->video_wrap_offset;
+
+ printf ("metronom: video discontinuity => last_video_pts=%d, wrap_offset=%d, video_vpts=%d\n",
+ this->last_video_pts, this->video_wrap_offset, this->video_vpts);
+
+ pthread_mutex_unlock (&this->lock);
}
-static uint32_t metronom_got_video_frame (metronom_t *this, uint32_t pts) {
+static uint32_t metronom_got_video_frame (metronom_t *this, uint32_t pts, uint32_t scr) {
uint32_t vpts;
@@ -425,44 +450,27 @@ static uint32_t metronom_got_video_frame (metronom_t *this, uint32_t pts) {
if (pts) {
/*
- * first video pts ?
+ * first video pts ?
*/
- if (this->video_stream_starting) {
+ if (this->video_stream_starting)
this->video_stream_starting = 0;
- this->video_wrap_offset = this->video_vpts + this->pts_per_frame - pts;
- assert (this->video_pts_delta == 0);
-
- if (this->audio_wrap_offset) {
- if (this->audio_wrap_offset>this->video_wrap_offset)
- this->video_wrap_offset = this->audio_wrap_offset;
- else
- this->audio_wrap_offset = this->video_wrap_offset;
- }
-
- printf ("metronom: first video pts => offset = %d\n", this->video_wrap_offset);
-
- }
-
/*
- * did a wrap-around occur?
+ * discontinuity ?
*/
- if ( ( (pts + WRAP_TRESHOLD) <this->last_video_pts)
- && (this->video_discontinuity || (pts<WRAP_START_TIME)) ) {
-
+ if ( this->video_discontinuity ) {
+
this->video_discontinuity = 0;
this->video_wrap_offset += this->last_video_pts - pts
- + this->num_video_vpts_guessed *(this->pts_per_frame + this->video_pts_delta);
+ + this->num_video_vpts_guessed
+ * (this->pts_per_frame + this->video_pts_delta);
- printf ("metronom: video pts wraparound detected, wrap_offset = %d\n",
- this->video_wrap_offset);
- }
+ printf ("metronom: video pts discontinuity, pts is %d, last_pts is %d, wrap_offset = %d\n",
+ pts, this->last_video_pts, this->video_wrap_offset);
- /* don't expect discontinuities forever */
- if (this->video_discontinuity)
- this->video_discontinuity--;
+ }
/*
* audio and video wrap are not allowed to differ
@@ -492,22 +500,6 @@ static uint32_t metronom_got_video_frame (metronom_t *this, uint32_t pts) {
vpts = pts + this->video_wrap_offset;
/*
- * jump into the future?
- */
- if (this->video_discontinuity
- && (vpts > (this->video_vpts + 10000))) {
-
- printf ("metronom: video jump into the future\n");
-
- this->video_discontinuity = 0;
-
- this->video_wrap_offset += this->last_video_pts - pts
- + this->num_video_vpts_guessed *(this->pts_per_frame + this->video_pts_delta);
-
- vpts = pts + this->video_wrap_offset;
- }
-
- /*
* calc delta to compensate wrong framerates
*/
@@ -540,24 +532,38 @@ static uint32_t metronom_got_video_frame (metronom_t *this, uint32_t pts) {
return vpts + this->av_offset;
}
-static void metronom_got_audio_still (metronom_t *this) {
+static void metronom_expect_audio_discontinuity (metronom_t *this) {
pthread_mutex_lock (&this->lock);
-
- this->audio_vpts += this->pts_per_frame + this->video_pts_delta;
- this->audio_wrap_offset = this->video_wrap_offset;
- this->last_audio_pts = this->audio_vpts - this->audio_wrap_offset;
- this->audio_stream_starting = 0;
-
-#ifdef METRONOM_LOG
- printf ("metronom: got audio still, vpts = %d, wrap = %d\n",
- this->audio_vpts, this->audio_wrap_offset);
-#endif
+
+ printf ("metronom: audio discontinuity\n");
+
+ this->audio_discontinuity = 10;
+ this->audio_discontinuity_count++;
+ pthread_cond_signal (&this->audio_discontinuity_reached);
+
+ while ( this->audio_discontinuity_count >
+ this->video_discontinuity_count ) {
+ pthread_cond_wait (&this->video_discontinuity_reached, &this->lock);
+ }
+
+ if ( this->audio_vpts < this->video_vpts ) {
+ this->audio_vpts = this->video_vpts;
+ printf("metronom: audio vpts adjusted to %d\n", this->audio_vpts);
+ }
+
+ this->num_audio_samples_guessed = 1;
+ this->last_audio_pts = this->audio_vpts - this->audio_wrap_offset;
+
+ printf ("metronom: audio discontinuity => last_audio_pts=%d, wrap_offset=%d, audio_vpts=%d\n",
+ this->last_audio_pts, this->audio_wrap_offset, this->audio_vpts);
pthread_mutex_unlock (&this->lock);
}
-static uint32_t metronom_got_audio_samples (metronom_t *this, uint32_t pts, uint32_t nsamples) {
+
+static uint32_t metronom_got_audio_samples (metronom_t *this, uint32_t pts,
+ uint32_t nsamples, uint32_t scr) {
uint32_t vpts;
@@ -566,53 +572,40 @@ static uint32_t metronom_got_audio_samples (metronom_t *this, uint32_t pts, uint
pthread_mutex_lock (&this->lock);
+
+ this->last_audio_scr = scr;
+
if (pts) {
/*
* first audio pts ?
*/
- if (this->audio_stream_starting) {
+ if (this->audio_stream_starting)
this->audio_stream_starting = 0;
- this->audio_wrap_offset = this->audio_vpts + (nsamples * this->pts_per_smpls) / AUDIO_SAMPLE_NUM - pts;
- assert (this->audio_pts_delta == 0);
-
- if (this->video_wrap_offset) {
- if (this->audio_wrap_offset>this->video_wrap_offset)
- this->video_wrap_offset = this->audio_wrap_offset;
- else
- this->audio_wrap_offset = this->video_wrap_offset;
- }
-
- printf ("metronom: first audio pts => offset = %d\n", this->audio_wrap_offset);
- }
-
/*
- * did a wrap-around occur?
+ * discontinuity ?
*/
- if ( ( (pts + WRAP_TRESHOLD) < this->last_audio_pts )
- && (this->audio_discontinuity || (pts<WRAP_START_TIME)) ) {
+
+ if ( this->audio_discontinuity ) {
this->audio_discontinuity = 0;
this->audio_wrap_offset += this->last_audio_pts - pts
- + this->num_audio_samples_guessed *(this->audio_pts_delta + this->pts_per_smpls) / AUDIO_SAMPLE_NUM ;
+ + this->num_audio_samples_guessed
+ * (this->audio_pts_delta + this->pts_per_smpls) / AUDIO_SAMPLE_NUM ;
- printf ("metronom: audio pts wraparound detected, wrap_offset = %d\n",
- this->audio_wrap_offset);
- }
+ printf ("metronom: audio pts discontinuity, pts is %d, last_pts is %d, wrap_offset = %d\n",
+ pts, this->last_audio_pts, this->audio_wrap_offset);
- /* don't expect discontinuities forever */
- if (this->audio_discontinuity)
- this->audio_discontinuity--;
+ }
/*
* audio and video wrap are not allowed to differ
* for too long
*/
- if ( !this->video_stream_starting
- && this->video_wrap_offset != this->audio_wrap_offset) {
+ if ( this->video_wrap_offset != this->audio_wrap_offset ) {
this->wrap_diff_counter++;
if (this->wrap_diff_counter > MAX_NUM_WRAP_DIFF) {
@@ -634,22 +627,6 @@ static uint32_t metronom_got_audio_samples (metronom_t *this, uint32_t pts, uint
vpts = pts + this->audio_wrap_offset;
/*
- * jump into the future?
- */
- if (this->audio_discontinuity
- && (vpts > (this->audio_vpts + 10000))) {
-
- printf ("metronom: video jump into the future\n");
-
- this->audio_discontinuity = 0;
-
- this->audio_wrap_offset += this->last_audio_pts - pts
- + this->num_audio_samples_guessed *(this->audio_pts_delta + this->pts_per_smpls) / AUDIO_SAMPLE_NUM ;
-
- vpts = pts + this->audio_wrap_offset;
- }
-
- /*
* calc delta to compensate wrong samplerates
*/
@@ -710,7 +687,7 @@ static scr_plugin_t* get_master_scr(metronom_t *this) {
}
}
if (select < 0) {
- printf("panic: No scr provider found!\n");
+ printf("metronom: panic - no scr provider found!\n");
return NULL;
}
return this->scr_list[select];
@@ -776,10 +753,10 @@ metronom_t * metronom_init (int have_audio) {
this->got_video_frame = metronom_got_video_frame;
this->got_audio_samples = metronom_got_audio_samples;
this->got_spu_packet = metronom_got_spu_packet;
+ this->expect_audio_discontinuity = metronom_expect_audio_discontinuity;
+ this->expect_video_discontinuity = metronom_expect_video_discontinuity;
this->set_av_offset = metronom_set_av_offset;
this->get_av_offset = metronom_get_av_offset;
- this->expect_video_discontinuity = metronom_expect_video_discontinuity;
- this->expect_audio_discontinuity = metronom_expect_audio_discontinuity;
this->start_clock = metronom_start_clock;
this->stop_clock = metronom_stop_clock;
this->resume_clock = metronom_resume_clock;
@@ -788,21 +765,22 @@ metronom_t * metronom_init (int have_audio) {
this->register_scr = metronom_register_scr;
this->unregister_scr = metronom_unregister_scr;
this->set_speed = metronom_set_speed;
- this->got_audio_still = metronom_got_audio_still;
this->scr_list = calloc(MAX_SCR_PROVIDERS, sizeof(void*));
this->register_scr(this, unixscr_init());
if ((err = pthread_create(&this->sync_thread, NULL,
(void*(*)(void*)) metronom_sync_loop, this)) != 0)
- fprintf(stderr, "metronom: cannot create sync thread (%s)\n",
- strerror(err));
+ printf("metronom: cannot create sync thread (%s)\n",
+ strerror(err));
pthread_mutex_init (&this->lock, NULL);
pthread_cond_init (&this->video_started, NULL);
pthread_cond_init (&this->audio_started, NULL);
pthread_cond_init (&this->video_ended, NULL);
pthread_cond_init (&this->audio_ended, NULL);
+ pthread_cond_init (&this->video_discontinuity_reached, NULL);
+ pthread_cond_init (&this->audio_discontinuity_reached, NULL);
this->av_offset = 0;
this->have_audio = have_audio;
diff --git a/src/xine-engine/metronom.h b/src/xine-engine/metronom.h
index 0452ab889..097983f09 100644
--- a/src/xine-engine/metronom.h
+++ b/src/xine-engine/metronom.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: metronom.h,v 1.12 2001/10/18 18:50:53 guenter Exp $
+ * $Id: metronom.h,v 1.13 2001/11/10 13:48:03 guenter Exp $
*
* metronom: general pts => virtual calculation/assoc
*
@@ -83,55 +83,52 @@ struct metronom_s {
* called by video output driver for *every* frame
*
* parameter pts: pts for frame if known, 0 otherwise
+ * scr: system clock reference, may be 0 or == pts if unknown
*
* return value: virtual pts for frame
*
*/
- uint32_t (*got_video_frame) (metronom_t *this, uint32_t pts);
+ uint32_t (*got_video_frame) (metronom_t *this, uint32_t pts, uint32_t scr);
/*
* called by audio output driver whenever audio samples are delivered to it
*
* parameter pts : pts for audio data if known, 0 otherwise
* nsamples : number of samples delivered
+ * scr : system clock reference, may be 0 or == pts if unknown
*
* return value: virtual pts for audio data
*
*/
- uint32_t (*got_audio_samples) (metronom_t *this, uint32_t pts, uint32_t nsamples);
-
- /*
- * inform metronom that there was a still image with no audio
- */
-
- void (*got_audio_still) (metronom_t *this);
+ uint32_t (*got_audio_samples) (metronom_t *this, uint32_t pts, uint32_t nsamples, uint32_t scr);
/*
* called by SPU decoder whenever a packet is delivered to it
*
* parameter pts : pts for SPU packet if known, 0 otherwise
+ * scr : system clock reference, may be 0 or == pts if unknown
*
* return value: virtual pts for SPU packet
*
*/
- uint32_t (*got_spu_packet) (metronom_t *this, uint32_t pts, uint32_t duration);
+ uint32_t (*got_spu_packet) (metronom_t *this, uint32_t pts, uint32_t duration,
+ uint32_t scr);
/*
- * manually correct audio <-> video sync
+ * tell metronom about discontinuities
*/
- void (*set_av_offset) (metronom_t *this, int32_t pts);
-
- int32_t (*get_av_offset) (metronom_t *this);
+ void (*expect_audio_discontinuity) (metronom_t *this);
+ void (*expect_video_discontinuity) (metronom_t *this);
/*
- * tell metronom to expect a pts discontinuity
+ * manually correct audio <-> video sync
*/
+ void (*set_av_offset) (metronom_t *this, int32_t pts);
- void (*expect_audio_discontinuity) (metronom_t *this);
- void (*expect_video_discontinuity) (metronom_t *this);
+ int32_t (*get_av_offset) (metronom_t *this);
/*
* system clock reference (SCR) functions
@@ -199,10 +196,12 @@ struct metronom_s {
int wrap_diff_counter;
uint32_t last_video_pts;
+ uint32_t last_video_scr;
int num_video_vpts_guessed;
int32_t video_pts_delta;
uint32_t last_audio_pts;
+ uint32_t last_audio_scr;
int num_audio_samples_guessed;
int32_t av_offset;
@@ -219,7 +218,11 @@ struct metronom_s {
int audio_stream_starting;
int audio_stream_running;
int video_discontinuity;
+ int video_discontinuity_count;
int audio_discontinuity;
+ int audio_discontinuity_count;
+ pthread_cond_t video_discontinuity_reached;
+ pthread_cond_t audio_discontinuity_reached;
pthread_cond_t video_started;
pthread_cond_t audio_started;
pthread_cond_t video_ended;
diff --git a/src/xine-engine/video_decoder.c b/src/xine-engine/video_decoder.c
index 83f40227d..bd4a53caf 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.61 2001/11/06 21:46:05 miguelfreitas Exp $
+ * $Id: video_decoder.c,v 1.62 2001/11/10 13:48:03 guenter Exp $
*
*/
@@ -101,18 +101,9 @@ void *video_decoder_loop (void *this_gen) {
break;
- case BUF_SPU_CLUT:
- profiler_start_count (prof_spu_decode);
-
- spu_decoder = update_spu_decoder(this, buf->type);
-
- if (spu_decoder)
- spu_decoder->decode_data (spu_decoder, buf);
-
- profiler_stop_count (prof_spu_decode);
- break;
-
case BUF_SPU_SUBP_CONTROL:
+ case BUF_SPU_CLUT:
+ case BUF_SPU_PACKAGE:
profiler_start_count (prof_spu_decode);
spu_decoder = update_spu_decoder(this, buf->type);
@@ -127,22 +118,6 @@ void *video_decoder_loop (void *this_gen) {
this->spu_channel = buf->decoder_info[0];
break;
- case BUF_SPU_PACKAGE:
- profiler_start_count (prof_spu_decode);
-
- /* now, decode this buffer if it's the right track */
-// if ( (buf->type & 0xFFFF)== this->spu_channel) {
-
- spu_decoder = update_spu_decoder (this, buf->type);
-
- if (spu_decoder)
- spu_decoder->decode_data (spu_decoder, buf);
-
-// }
-
- profiler_stop_count (prof_spu_decode);
- break;
-
case BUF_CONTROL_END:
this->metronom->video_stream_end (this->metronom);
@@ -185,9 +160,22 @@ void *video_decoder_loop (void *this_gen) {
break;
case BUF_CONTROL_DISCONTINUITY:
+ printf ("video_decoder: BUF_CONTROL_DISCONTINUITY is deprecated\n");
+ break;
+
+ case BUF_CONTROL_AVSYNC_RESET:
+ printf ("video_decoder: discontinuity ahead\n");
+
+ /* fixme ? */
+ if (this->cur_video_decoder_plugin) {
+ this->cur_video_decoder_plugin->close (this->cur_video_decoder_plugin);
+ this->cur_video_decoder_plugin = NULL;
+ }
+
this->metronom->expect_video_discontinuity (this->metronom);
break;
+ case BUF_CONTROL_AUDIO_CHANNEL:
case BUF_CONTROL_NOP:
break;
diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c
index 07ca06f91..cd274d291 100644
--- a/src/xine-engine/video_out.c
+++ b/src/xine-engine/video_out.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_out.c,v 1.51 2001/10/21 13:14:08 jcdutton Exp $
+ * $Id: video_out.c,v 1.52 2001/11/10 13:48:03 guenter Exp $
*
*/
@@ -346,11 +346,11 @@ static void vo_open (vo_instance_t *this) {
pthread_attr_setscope(&pth_attrs, PTHREAD_SCOPE_SYSTEM);
if((err = pthread_create (&this->video_thread,
- &pth_attrs, video_out_loop, this)) != 0)
- {
- fprintf (stderr, "video_out: can't create thread (%s)\n", strerror(err));
- /* FIXME: why pthread_create fails? */
- fprintf (stderr, "Sorry, this should not happen. Please restart Xine.\n");
+ &pth_attrs, video_out_loop, this)) != 0) {
+
+ printf ("video_out: can't create thread (%s)\n", strerror(err));
+ /* FIXME: how does this happen ? */
+ printf ("video_out: sorry, this should not happen. please restart xine.\n");
exit(1);
}
else
@@ -469,7 +469,7 @@ static int vo_frame_draw (vo_frame_t *img) {
uint32_t pic_vpts ;
int frames_to_skip;
- pic_vpts = this->metronom->got_video_frame (this->metronom, img->PTS);
+ pic_vpts = this->metronom->got_video_frame (this->metronom, img->PTS, img->SCR);
/*
printf ("video_out: got image %d. vpts for picture is %d (pts was %d)\n",
diff --git a/src/xine-engine/video_out.h b/src/xine-engine/video_out.h
index eb6b1f84e..26ed87b8a 100644
--- a/src/xine-engine/video_out.h
+++ b/src/xine-engine/video_out.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: video_out.h,v 1.26 2001/11/10 06:20:39 mlampard Exp $
+ * $Id: video_out.h,v 1.27 2001/11/10 13:48:03 guenter Exp $
*
*
* xine version of video_out.h
@@ -60,6 +60,7 @@ struct vo_frame_s {
struct vo_frame_s *next;
uint32_t PTS;
+ uint32_t SCR;
int bad_frame; /* e.g. frame skipped or based on skipped frame */
uint8_t *base[3];