From b602849ad7cd8ce3b9c99da97bc3b4138cf8159d Mon Sep 17 00:00:00 2001 From: Guenter Bartsch Date: Sat, 10 Nov 2001 13:48:02 +0000 Subject: very unfinished scr discontinuity detection stuff, new software audio out buffer and thread CVS patchset: 1010 CVS date: 2001/11/10 13:48:02 --- src/demuxers/demux_asf.c | 3 +- src/demuxers/demux_avi.c | 4 +- src/demuxers/demux_elem.c | 3 +- src/demuxers/demux_mpeg.c | 200 +++++++++------ src/demuxers/demux_mpeg_block.c | 66 ++++- src/demuxers/demux_mpgaudio.c | 3 +- src/demuxers/demux_ogg.c | 3 +- src/demuxers/demux_pes.c | 5 +- src/demuxers/demux_qt.c | 4 +- src/liba52/xine_decoder.c | 126 +++++---- src/libdts/xine_decoder.c | 29 +-- src/liblpcm/xine_decoder.c | 29 ++- src/libmad/xine_decoder.c | 27 +- src/libmpeg2/decode.c | 7 +- src/libmpeg2/mpeg2.h | 4 +- src/libmpeg2/xine_decoder.c | 4 +- src/libspudec/xine_decoder.c | 4 +- src/libvorbis/xine_decoder.c | 16 +- src/libw32dll/w32codec.c | 60 ++--- src/xine-engine/audio_decoder.c | 15 +- src/xine-engine/audio_out.c | 547 ++++++++++++++++++++++++++-------------- src/xine-engine/audio_out.h | 43 +++- src/xine-engine/buffer.h | 8 +- src/xine-engine/metronom.c | 232 ++++++++--------- src/xine-engine/metronom.h | 37 +-- src/xine-engine/video_decoder.c | 44 ++-- src/xine-engine/video_out.c | 14 +- src/xine-engine/video_out.h | 3 +- 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 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=(samplesconvsize?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;ivi.channels;i++){ - ogg_int16_t *ptr=this->convbuffer+i; + ogg_int16_t *ptr=audio_buffer->mem+i; float *mono=pcm[i]; for(j=0;jaudio_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 @@ -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 (vptslast_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->vptslast_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; imem = 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) last_video_pts) - && (this->video_discontinuity || (ptsvideo_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 @@ -491,22 +499,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 || (ptsaudio_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) { @@ -633,22 +626,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]; -- cgit v1.2.3