diff options
36 files changed, 1051 insertions, 1260 deletions
diff --git a/src/demuxers/demux_asf.c b/src/demuxers/demux_asf.c index a61102349..770aa36c7 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.23 2002/02/17 17:32:49 guenter Exp $ + * $Id: demux_asf.c,v 1.24 2002/03/11 12:31:24 guenter Exp $ * * demultiplexer for asf streams * @@ -345,7 +345,7 @@ static void asf_send_audio_header (demux_asf_t *this, int stream_id) { buf->size = this->wavex_size; buf->type = this->streams[this->num_streams].buf_type; - buf->decoder_info[0] = 0; /* first package, containing wavex */ + buf->decoder_flags = BUF_FLAG_HEADER; buf->decoder_info[1] = wavex->nSamplesPerSec; buf->decoder_info[2] = wavex->wBitsPerSample; buf->decoder_info[3] = wavex->nChannels; @@ -390,7 +390,7 @@ static void asf_send_video_header (demux_asf_t *this, int stream_id) { buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->content = buf->mem; - buf->decoder_info[0] = 0; /* first package, containing bih */ + buf->decoder_flags = BUF_FLAG_HEADER; buf->decoder_info[1] = 3000; /* FIXME ? */ memcpy (buf->content, &this->bih, this->bih_size); buf->size = this->bih_size; @@ -591,12 +591,16 @@ static int asf_get_packet(demux_asf_t *this) { this->packet_flags = get_byte(this); this->segtype = get_byte(this); this->packet_padsize = 0; - - if (this->packet_flags & 0x40) { - get_le16(this); - printf ("demux_asf: absolute size ignored\n"); - hdr_size += 2; + + /* FIXME: really not necessary? + patch submitted by Andrei Lahun <Uman@editec-lotteries.com> + + if (this->packet_flags & 0x40) { + get_le16(this); + printf ("demux_asf: absolute size ignored\n"); + hdr_size += 2; } + */ if (this->packet_flags & 0x10) { this->packet_padsize = get_le16(this); @@ -684,7 +688,6 @@ static void asf_send_buffer_nodefrag (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 = bufsize; timestamp = 0; @@ -694,10 +697,10 @@ static void asf_send_buffer_nodefrag (demux_asf_t *this, asf_stream_t *stream, /* test if whole packet read */ if (stream->frag_offset == payload_size) { - buf->decoder_info[0] = 2; + buf->decoder_flags = BUF_FLAG_FRAME_END; stream->frag_offset = 0; } else - buf->decoder_info[0] = 1; + buf->decoder_flags = 0; stream->fifo->put (stream->fifo, buf); } @@ -758,7 +761,6 @@ static void asf_send_buffer_defrag (demux_asf_t *this, asf_stream_t *stream, buf->pts = stream->timestamp * 90 + stream->ts_per_kbyte * (p-stream->buffer) / 1024; - buf->scr = buf->pts; buf->type = stream->buf_type; buf->size = bufsize; @@ -767,10 +769,10 @@ static void asf_send_buffer_defrag (demux_asf_t *this, asf_stream_t *stream, /* test if whole packet read */ if ( !stream->frag_offset ) - buf->decoder_info[0] = 2; + buf->decoder_flags = BUF_FLAG_FRAME_END ; else - buf->decoder_info[0] = 1; - + buf->decoder_flags = 0; + stream->fifo->put (stream->fifo, buf); } } @@ -1009,13 +1011,13 @@ static void *demux_asf_loop (void *this_gen) { if (this->send_end_buffers) { buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = BUF_CONTROL_END; - buf->decoder_info[0] = 0; /* stream finished */ + buf->decoder_flags = BUF_FLAG_END_STREAM; /* stream finished */ 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_END; - buf->decoder_info[0] = 0; /* stream finished */ + buf->decoder_flags = BUF_FLAG_END_STREAM; /* stream finished */ this->audio_fifo->put (this->audio_fifo, buf); } @@ -1057,14 +1059,13 @@ static void demux_asf_stop (demux_plugin_t *this_gen) { buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = BUF_CONTROL_END; - buf->decoder_info[0] = 1; /* forced */ - + buf->decoder_flags = BUF_FLAG_END_USER; 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_END; - buf->decoder_info[0] = 1; /* forced */ + buf->decoder_flags = BUF_FLAG_END_USER; this->audio_fifo->put (this->audio_fifo, buf); } diff --git a/src/demuxers/demux_avi.c b/src/demuxers/demux_avi.c index eb31c2245..3abe24e1b 100644 --- a/src/demuxers/demux_avi.c +++ b/src/demuxers/demux_avi.c @@ -1,7 +1,7 @@ /* - * Copyright (C) 2000, 2001 the xine project + * Copyright (C) 2000-2002 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 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.64 2002/02/17 17:32:49 guenter Exp $ + * $Id: demux_avi.c,v 1.65 2002/03/11 12:31:24 guenter Exp $ * * demultiplexer for avi streams * @@ -614,64 +614,66 @@ static void AVI_seek_start(avi_t *AVI) } static long AVI_read_audio(demux_avi_t *this, avi_t *AVI, char *audbuf, - long bytes, int *bFrameDone) -{ + long bytes, int *buf_flags) { + long nr, pos, left, todo; - if(!AVI->audio_index) { this->AVI_errno = AVI_ERR_NO_IDX; return -1; } + if(!AVI->audio_index) { + this->AVI_errno = AVI_ERR_NO_IDX; return -1; + } nr = 0; /* total number of bytes read */ /* printf ("avi audio package len: %d\n", AVI->audio_index[AVI->audio_posc].len); */ - while(bytes>0) - { + while(bytes>0) { + left = AVI->audio_index[AVI->audio_posc].len - AVI->audio_posb; + if(left==0) { + AVI->audio_posc++; + AVI->audio_posb = 0; + if (nr>0) { + *buf_flags = BUF_FLAG_FRAME_END; + return nr; + } left = AVI->audio_index[AVI->audio_posc].len - AVI->audio_posb; - if(left==0) - { - AVI->audio_posc++; - AVI->audio_posb = 0; - if (nr>0) { - *bFrameDone = 2; - return nr; - } - left = AVI->audio_index[AVI->audio_posc].len - AVI->audio_posb; - } - if(bytes<left) - todo = bytes; - else - todo = left; - pos = AVI->audio_index[AVI->audio_posc].pos + AVI->audio_posb; - /* printf ("demux_avi: read audio from %d\n", pos); */ - if (this->input->seek (this->input, pos, SEEK_SET)<0) - return -1; - if (this->input->read(this->input, audbuf+nr,todo) != todo) - { - this->AVI_errno = AVI_ERR_READ; - *bFrameDone = 1; - return -1; - } - bytes -= todo; - nr += todo; - AVI->audio_posb += todo; } + if(bytes<left) + todo = bytes; + else + todo = left; + pos = AVI->audio_index[AVI->audio_posc].pos + AVI->audio_posb; + /* printf ("demux_avi: read audio from %d\n", pos); */ + if (this->input->seek (this->input, pos, SEEK_SET)<0) + return -1; + if (this->input->read(this->input, audbuf+nr,todo) != todo) { + this->AVI_errno = AVI_ERR_READ; + *buf_flags = 0; + return -1; + } + bytes -= todo; + nr += todo; + AVI->audio_posb += todo; + } left = AVI->audio_index[AVI->audio_posc].len - AVI->audio_posb; if (left==0) - *bFrameDone = 2; + *buf_flags = BUF_FLAG_FRAME_END; else - *bFrameDone = 1; + *buf_flags = 0; return nr; } static long AVI_read_video(demux_avi_t *this, avi_t *AVI, char *vidbuf, - long bytes, int *frame_done) { + long bytes, int *buf_flags) { long nr, pos, left, todo; - if(!AVI->video_index) { this->AVI_errno = AVI_ERR_NO_IDX; return -1; } + if (!AVI->video_index) { + this->AVI_errno = AVI_ERR_NO_IDX; + return -1; + } nr = 0; /* total number of bytes read */ @@ -683,7 +685,7 @@ static long AVI_read_video(demux_avi_t *this, avi_t *AVI, char *vidbuf, AVI->video_posf++; AVI->video_posb = 0; if (nr>0) { - *frame_done = 2; + *buf_flags = BUF_FLAG_FRAME_END; return nr; } left = AVI->video_index[AVI->video_posf].len - AVI->video_posb; @@ -698,7 +700,7 @@ static long AVI_read_video(demux_avi_t *this, avi_t *AVI, char *vidbuf, return -1; if (this->input->read(this->input, vidbuf+nr,todo) != todo) { this->AVI_errno = AVI_ERR_READ; - *frame_done = 1; + *buf_flags = 0; return -1; } bytes -= todo; @@ -708,9 +710,9 @@ static long AVI_read_video(demux_avi_t *this, avi_t *AVI, char *vidbuf, left = AVI->video_index[AVI->video_posf].len - AVI->video_posb; if (left==0) - *frame_done = 2; + *buf_flags = BUF_FLAG_FRAME_END; else - *frame_done = 1; + *buf_flags = 0; return nr; } @@ -752,8 +754,7 @@ static int demux_avi_next (demux_avi_t *this) { /* read audio */ buf->pts = audio_pts; - buf->scr = audio_pts; - buf->size = AVI_read_audio (this, this->avi, buf->mem, 2048, &buf->decoder_info[0]); + buf->size = AVI_read_audio (this, this->avi, buf->mem, 2048, &buf->decoder_flags); if (buf->size<0) { buf->free_buffer (buf); @@ -764,9 +765,9 @@ static int demux_avi_next (demux_avi_t *this) { buf->input_time = 0; buf->type = this->avi->audio_type; - buf->decoder_info[1] = this->avi->a_rate; /* Audio Rate */ - buf->decoder_info[2] = this->avi->a_bits; /* Audio bits */ - buf->decoder_info[3] = this->avi->a_chans; /* Audio channels */ + buf->decoder_info[1] = this->avi->a_rate; /* audio rate */ + buf->decoder_info[2] = this->avi->a_bits; /* audio bits */ + buf->decoder_info[3] = this->avi->a_chans; /* audio channels */ if(this->audio_fifo) { this->audio_fifo->put (this->audio_fifo, buf); @@ -779,8 +780,7 @@ static int demux_avi_next (demux_avi_t *this) { /* read video */ buf->pts = video_pts; - buf->scr = video_pts; - buf->size = AVI_read_video (this, this->avi, buf->mem, 2048, &buf->decoder_info[0]); + buf->size = AVI_read_video (this, this->avi, buf->mem, 2048, &buf->decoder_flags); buf->type = this->avi->video_type; buf->input_time = video_pts / 90000; @@ -999,18 +999,32 @@ static void demux_avi_start (demux_plugin_t *this_gen, */ buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); - buf->type = BUF_CONTROL_START; + buf->type = BUF_CONTROL_START; + buf->decoder_flags = 0; + 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_START; + buf->decoder_flags = 0; + this->audio_fifo->put (this->audio_fifo, buf); + } + + buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); + buf->type = BUF_CONTROL_DISCONTINUITY; + buf->disc_off = video_pts; this->video_fifo->put (this->video_fifo, buf); if(this->audio_fifo) { buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); - buf->type = BUF_CONTROL_START; + buf->type = BUF_CONTROL_DISCONTINUITY; + buf->disc_off = video_pts; this->audio_fifo->put (this->audio_fifo, buf); } buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->content = buf->mem; - buf->decoder_info[0] = 0; /* first package, containing bih */ + buf->decoder_flags = BUF_FLAG_HEADER; buf->decoder_info[1] = this->video_step; memcpy (buf->content, &this->avi->bih, sizeof (this->avi->bih)); buf->size = sizeof (this->avi->bih); @@ -1032,6 +1046,7 @@ static void demux_avi_start (demux_plugin_t *this_gen, if(this->audio_fifo) { buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); buf->content = buf->mem; + buf->decoder_flags = BUF_FLAG_HEADER; memcpy (buf->content, &this->avi->wavex, sizeof (this->avi->wavex)); buf->size = sizeof (this->avi->wavex); @@ -1054,7 +1069,7 @@ static void demux_avi_start (demux_plugin_t *this_gen, buf->type = BUF_SPU_TEXT; - buf->decoder_info[0] = 0; + buf->decoder_flags = BUF_FLAG_HEADER; buf->decoder_info[1] = this->avi->width; buf->decoder_info[2] = this->avi->height; diff --git a/src/demuxers/demux_cda.c b/src/demuxers/demux_cda.c index 55e8b5be5..94d5098da 100644 --- a/src/demuxers/demux_cda.c +++ b/src/demuxers/demux_cda.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_cda.c,v 1.8 2002/02/17 17:32:49 guenter Exp $ + * $Id: demux_cda.c,v 1.9 2002/03/11 12:31:24 guenter Exp $ */ #ifdef HAVE_CONFIG_H @@ -74,7 +74,6 @@ static int demux_cda_next (demux_cda_t *this) { len = this->input->get_length(this->input); buf->pts = 0; - buf->scr = 0; buf->input_pos = pos; buf->input_time = buf->input_pos / this->blocksize; buf->type = BUF_CONTROL_NOP; /* Fake */ diff --git a/src/demuxers/demux_elem.c b/src/demuxers/demux_elem.c index e48182520..5c3cf35c0 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.34 2002/02/17 17:32:50 guenter Exp $ + * $Id: demux_elem.c,v 1.35 2002/03/11 12:31:24 guenter Exp $ * * demultiplexer for elementary mpeg streams * @@ -89,7 +89,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->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 6a4bfd4a1..197828ef1 100644 --- a/src/demuxers/demux_mpeg.c +++ b/src/demuxers/demux_mpeg.c @@ -1,7 +1,7 @@ /* - * Copyright (C) 2000, 2001 the xine project + * Copyright (C) 2000-2002 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 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.50 2002/02/17 17:32:50 guenter Exp $ + * $Id: demux_mpeg.c,v 1.51 2002/03/11 12:31:24 guenter Exp $ * * demultiplexer for mpeg 1/2 program streams * reads streams of variable blocksizes @@ -71,9 +71,9 @@ typedef struct demux_mpeg_s { int send_end_buffers; - uint32_t last_scr; + int64_t last_scr; -} demux_mpeg_t ; +} demux_mpeg_t; static uint32_t read_bytes (demux_mpeg_t *this, int n) { @@ -113,10 +113,11 @@ static uint32_t read_bytes (demux_mpeg_t *this, int n) { return res; } -static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, uint32_t scr) { +static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr) { int len, i; - uint32_t w, flags, header_len, pts; + uint32_t w, flags, header_len; + int64_t pts; buf_element_t *buf = NULL; len = read_bytes(this, 2); @@ -165,11 +166,11 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, uint32_t scr) } buf->type = BUF_AUDIO_A52 + track; buf->pts = pts; - buf->scr = scr; + /* buf->scr = scr;*/ if (this->preview_mode) - buf->decoder_info[0] = 0; + buf->decoder_flags = BUF_FLAG_PREVIEW; else - buf->decoder_info[0] = 1; + buf->decoder_flags = 0; buf->input_pos = this->input->get_current_pos (this->input); @@ -215,11 +216,10 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, uint32_t scr) } buf->type = BUF_AUDIO_MPEG + track; buf->pts = pts; - buf->scr = scr; if (this->preview_mode) - buf->decoder_info[0] = 0; + buf->decoder_flags = BUF_FLAG_PREVIEW; else - buf->decoder_info[0] = 1; + buf->decoder_flags = 0; buf->input_pos = this->input->get_current_pos(this->input); if(this->audio_fifo) @@ -260,11 +260,10 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, uint32_t scr) } buf->type = BUF_VIDEO_MPEG; buf->pts = pts; - buf->scr = scr; if (this->preview_mode) - buf->decoder_info[0] = 0; + buf->decoder_flags = BUF_FLAG_PREVIEW; else - buf->decoder_info[0] = 1; + buf->decoder_flags = 0; buf->input_pos = this->input->get_current_pos(this->input); this->video_fifo->put (this->video_fifo, buf); @@ -277,12 +276,12 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, uint32_t scr) } -static void parse_mpeg1_packet (demux_mpeg_t *this, int stream_id, uint32_t scr) { +static void parse_mpeg1_packet (demux_mpeg_t *this, int stream_id, int64_t scr) { int len; uint32_t w; int i; - int pts; + int64_t pts; buf_element_t *buf = NULL; len = read_bytes(this, 2); @@ -372,11 +371,10 @@ static void parse_mpeg1_packet (demux_mpeg_t *this, int stream_id, uint32_t scr) } buf->type = BUF_AUDIO_MPEG + track ; buf->pts = pts; - buf->scr = scr; if (this->preview_mode) - buf->decoder_info[0] = 0; + buf->decoder_flags = BUF_FLAG_PREVIEW; else - buf->decoder_info[0] = 1; + buf->decoder_flags = 0; buf->input_pos = this->input->get_current_pos(this->input); if (this->rate) buf->input_time = buf->input_pos / (this->rate * 50); @@ -395,11 +393,10 @@ static void parse_mpeg1_packet (demux_mpeg_t *this, int stream_id, uint32_t scr) } buf->type = BUF_VIDEO_MPEG; buf->pts = pts; - buf->scr = scr; if (this->preview_mode) - buf->decoder_info[0] = 0; + buf->decoder_flags = BUF_FLAG_PREVIEW; else - buf->decoder_info[0] = 1; + buf->decoder_flags = 0; buf->input_pos = this->input->get_current_pos(this->input); if (this->rate) buf->input_time = buf->input_pos / (this->rate * 50); @@ -420,7 +417,7 @@ static uint32_t parse_pack(demux_mpeg_t *this) { uint32_t buf ; int mpeg_version; - uint32_t scr; + int64_t scr; buf = read_bytes (this, 1); @@ -489,20 +486,20 @@ static uint32_t parse_pack(demux_mpeg_t *this) { /* discontinuity ? */ { - int32_t scr_diff = scr - this->last_scr; + int64_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_DISCONTINUITY; - buf->scr = scr; + buf->disc_off = scr_diff; 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_DISCONTINUITY; - buf->scr = scr; + buf->disc_off = scr_diff; this->audio_fifo->put (this->audio_fifo, buf); } } @@ -632,13 +629,13 @@ static void *demux_mpeg_loop (void *this_gen) { if (this->send_end_buffers) { buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = BUF_CONTROL_END; - buf->decoder_info[0] = 0; /* stream finished */ + buf->decoder_flags = BUF_FLAG_END_STREAM; 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_END; - buf->decoder_info[0] = 0; /* stream finished */ + buf->decoder_flags = BUF_FLAG_END_STREAM; this->audio_fifo->put (this->audio_fifo, buf); } } @@ -680,13 +677,13 @@ static void demux_mpeg_stop (demux_plugin_t *this_gen) { buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = BUF_CONTROL_END; - buf->decoder_info[0] = 1; /* forced */ + buf->decoder_flags = BUF_FLAG_END_USER; /* user finished */ 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_END; - buf->decoder_info[0] = 1; /* forced */ + buf->decoder_flags = BUF_FLAG_END_USER; /* user finished */ this->audio_fifo->put (this->audio_fifo, buf); } diff --git a/src/demuxers/demux_mpeg_block.c b/src/demuxers/demux_mpeg_block.c index a3519c6aa..9bebd56ba 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.77 2002/02/17 17:32:50 guenter Exp $ + * $Id: demux_mpeg_block.c,v 1.78 2002/03/11 12:31:24 guenter Exp $ * * demultiplexer for mpeg 1/2 program streams * @@ -74,7 +74,7 @@ typedef struct demux_mpeg_block_s { uint8_t *scratch; - uint32_t last_scr; + int64_t last_scr; } demux_mpeg_block_t ; @@ -84,10 +84,10 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m uint8_t *p; int bMpeg1=0; uint32_t header_len; - uint32_t PTS; + int64_t PTS; uint32_t packet_len; uint32_t stream_id; - uint32_t scr = this->last_scr; + int64_t scr = this->last_scr; buf = this->input->read_block (this->input, this->video_fifo, this->blocksize); @@ -149,7 +149,7 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m if (this->audio_fifo) { cbuf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); cbuf->type = buf->type; - cbuf->decoder_info[0] = buf->decoder_info[0]; + cbuf->decoder_flags = buf->decoder_flags; this->audio_fifo->put (this->audio_fifo, cbuf); } @@ -158,9 +158,9 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m p = buf->content; /* len = this->mnBlocksize; */ if (preview_mode) - buf->decoder_info[0] = 0; + buf->decoder_flags = BUF_FLAG_PREVIEW; else - buf->decoder_info[0] = 1; + buf->decoder_flags = 0; buf->input_pos = this->input->get_current_pos (this->input); @@ -182,7 +182,7 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m scr |= (p[6] & 0xFF) << 7; scr |= (p[7] & 0xFE) >> 1; - buf->scr = scr; + /* buf->scr = scr; */ /* mux_rate */ @@ -214,7 +214,7 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m scr += ( (p[8] & 0x03 << 7) | (p[9] & 0xFE >> 1) ); */ - buf->scr = scr; + /* buf->scr = scr; */ /* mux_rate */ @@ -259,7 +259,7 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m /* discontinuity ? */ { - int32_t scr_diff = scr - this->last_scr; + int64_t scr_diff = scr - this->last_scr; #ifdef LOG printf ("demux_mpeg_block: scr %d last_scr %d diff %d\n", @@ -276,13 +276,13 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = BUF_CONTROL_DISCONTINUITY; - buf->scr = scr; + buf->disc_off = scr_diff; 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_DISCONTINUITY; - buf->scr = scr; + buf->disc_off = scr_diff; this->audio_fifo->put (this->audio_fifo, buf); } } @@ -565,13 +565,13 @@ static void *demux_mpeg_block_loop (void *this_gen) { if (this->send_end_buffers) { buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = BUF_CONTROL_END; - buf->decoder_info[0] = 0; /* stream finished */ + buf->decoder_flags = BUF_FLAG_END_STREAM; 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_END; - buf->decoder_info[0] = 0; /* stream finished */ + buf->decoder_flags = BUF_FLAG_END_STREAM; this->audio_fifo->put (this->audio_fifo, buf); } @@ -591,7 +591,7 @@ static int demux_mpeg_block_estimate_rate (demux_mpeg_block_t *this) { int is_mpeg1=0; off_t pos, last_pos; off_t step; - uint32_t PTS, last_PTS; + int64_t PTS, last_PTS; int rate; int count; int stream_id; @@ -748,14 +748,14 @@ static void demux_mpeg_block_stop (demux_plugin_t *this_gen) { buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = BUF_CONTROL_END; - buf->decoder_info[0] = 1; /* forced */ + buf->decoder_flags = BUF_FLAG_END_USER; 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_END; - buf->decoder_info[0] = 1; /* forced */ + buf->decoder_flags = BUF_FLAG_END_USER; this->audio_fifo->put (this->audio_fifo, buf); } } diff --git a/src/demuxers/demux_mpgaudio.c b/src/demuxers/demux_mpgaudio.c index f5860a87b..bd609df4d 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.35 2002/02/17 17:32:50 guenter Exp $ + * $Id: demux_mpgaudio.c,v 1.36 2002/03/11 12:31:24 guenter Exp $ * * demultiplexer for mpeg audio (i.e. mp3) streams * @@ -189,7 +189,7 @@ static int demux_mpgaudio_next (demux_mpgaudio_t *this) { } buf->pts = 0; - buf->scr = 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 941c4512b..f5aeb8487 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.15 2002/02/17 17:32:50 guenter Exp $ + * $Id: demux_ogg.c,v 1.16 2002/03/11 12:31:24 guenter Exp $ * * demultiplexer for ogg streams * @@ -174,7 +174,6 @@ 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 b8dc3cd55..ef20f8b33 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.19 2002/02/17 17:32:50 guenter Exp $ + * $Id: demux_pes.c,v 1.20 2002/03/11 12:31:24 guenter Exp $ * * demultiplexer for mpeg 2 PES (Packetized Elementary Streams) * reads streams of variable blocksizes @@ -163,7 +163,6 @@ 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 @@ -209,7 +208,6 @@ 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 @@ -255,7 +253,6 @@ 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 a18fd831a..3e815d5c5 100644 --- a/src/demuxers/demux_qt.c +++ b/src/demuxers/demux_qt.c @@ -17,9 +17,9 @@ * 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.22 2002/03/01 09:29:50 guenter Exp $ + * $Id: demux_qt.c,v 1.23 2002/03/11 12:31:24 guenter Exp $ * - * demultiplexer for quicktime streams, based on: + * demultiplexer for mpeg-4 system (aka quicktime) streams, based on: * * openquicktime.c * @@ -54,7 +54,14 @@ #include "libw32dll/wine/vfw.h" #include "libw32dll/wine/mmreg.h" -#define VALID_ENDS "mov" + +#define LOG + + +#define DBG_QT + + +#define VALID_ENDS "mov,mp4" /* OpenQuicktime Codec Parameter Types */ #define QUICKTIME_UNKNOWN_PARAMETER -1 @@ -70,6 +77,10 @@ typedef int64_t longest; typedef uint64_t ulongest; +#ifdef DBG_QT +int debug_fh; +#endif + /* typedef __s64 longest; typedef __u64 ulongest; @@ -191,6 +202,7 @@ typedef struct { typedef struct { long sample_count; long sample_duration; + int64_t pts; } quicktime_stts_table_t; typedef struct { @@ -513,6 +525,17 @@ typedef struct quicktime_struc { } quicktime_t; +typedef struct { + int64_t pts; + off_t offset; + int first_sample; + int last_sample; + int32_t type; + quicktime_trak_t *track; +} qt_idx_t; + +#define MAX_QT_INDEX 200000 + typedef struct demux_qt_s { demux_plugin_t demux_plugin; @@ -531,6 +554,8 @@ typedef struct demux_qt_s { int send_end_buffers; quicktime_t *qt; + qt_idx_t index[MAX_QT_INDEX]; + int num_index_entries; int has_audio; /* 1 if this qt stream has audio */ @@ -555,171 +580,163 @@ typedef struct demux_qt_s { /* Disk I/O */ -static longest quicktime_ftell(quicktime_t *file) -{ +static longest quicktime_ftell(quicktime_t *file) { return file->ftell_position; } -static int quicktime_fseek(quicktime_t *file, longest offset) -{ +static int quicktime_fseek(quicktime_t *file, longest offset) { file->ftell_position = offset; - if(offset > file->total_length || offset < 0) return 1; - if (file->input->seek(file->input, file->ftell_position, SEEK_SET)) - { - // perror("quicktime_read_data FSEEK"); - return 1; - } + if(offset > file->total_length || offset < 0) + return 1; + if (file->input->seek(file->input, file->ftell_position, SEEK_SET)) { + /* perror("quicktime_read_data FSEEK"); */ + return 1; + } return 0; } /* Read entire buffer from the preload buffer */ -static int quicktime_read_preload(quicktime_t *file, char *data, longest size) -{ +static int quicktime_read_preload(quicktime_t *file, char *data, longest size) { longest selection_start = file->file_position; longest selection_end = file->file_position + size; longest fragment_start, fragment_len; fragment_start = file->preload_ptr + (selection_start - file->preload_start); - while(fragment_start < 0) fragment_start += file->preload_size; - while(fragment_start >= file->preload_size) fragment_start -= file->preload_size; + while(fragment_start < 0) + fragment_start += file->preload_size; + while(fragment_start >= file->preload_size) + fragment_start -= file->preload_size; // gcc 2.96 fails here - while(selection_start < selection_end) - { - fragment_len = selection_end - selection_start; - if(fragment_start + fragment_len > file->preload_size) - fragment_len = file->preload_size - fragment_start; - - memcpy(data, file->preload_buffer + fragment_start, fragment_len); - fragment_start += fragment_len; - data = data + fragment_len; - - if(fragment_start >= file->preload_size) fragment_start = (longest)0; - selection_start += fragment_len; - } + while (selection_start < selection_end) { + fragment_len = selection_end - selection_start; + if (fragment_start + fragment_len > file->preload_size) + fragment_len = file->preload_size - fragment_start; + + memcpy (data, file->preload_buffer + fragment_start, fragment_len); + fragment_start += fragment_len; + data = data + fragment_len; + + if (fragment_start >= file->preload_size) + fragment_start = (longest)0; + selection_start += fragment_len; + } return 0; } -static int quicktime_read_data(quicktime_t *file, char *data, longest size) -{ +static int quicktime_read_data(quicktime_t *file, char *data, longest size) { + int result = 1; - if(file->decompressed_buffer) - { - if(file->decompressed_position < file->decompressed_buffer_size) - { - memcpy(data, - file->decompressed_buffer+file->decompressed_position, - size); - file->decompressed_position+=size; - return result; - } - else - { - //printf("Deleting Decompressed buffer\n"); - file->decompressed_position = 0; - file->decompressed_buffer_size=0; - free(file->decompressed_buffer); - file->decompressed_buffer = NULL; - } + + if (file->decompressed_buffer) { + + if (file->decompressed_position < file->decompressed_buffer_size) { + memcpy(data, + file->decompressed_buffer+file->decompressed_position, + size); + file->decompressed_position+=size; + return result; + + } else { + + //printf("Deleting Decompressed buffer\n"); + file->decompressed_position = 0; + file->decompressed_buffer_size=0; + free(file->decompressed_buffer); + file->decompressed_buffer = NULL; } + } - if(!file->preload_size) - { - //printf("quicktime_read_data 0x%llx\n", file->file_position); + if (!file->preload_size) { + //printf("quicktime_read_data 0x%llx\n", file->file_position); + file->quicktime_fseek(file, file->file_position); + /* result = fread(data, size, 1, (FILE*)file->stream); */ + result = file->input->read(file->input, data, size); + file->ftell_position += size; + + } else { + + longest selection_start = file->file_position; + longest selection_end = file->file_position + size; + longest fragment_start, fragment_len; + + if(selection_end - selection_start > file->preload_size) { + /* Size is larger than preload size. Should never happen. */ + //printf("read data 1\n"); file->quicktime_fseek(file, file->file_position); /* result = fread(data, size, 1, (FILE*)file->stream); */ result = file->input->read(file->input, data, size); file->ftell_position += size; - } - else - { - longest selection_start = file->file_position; - longest selection_end = file->file_position + size; - longest fragment_start, fragment_len; - if(selection_end - selection_start > file->preload_size) - { - /* Size is larger than preload size. Should never happen. */ - //printf("read data 1\n"); - file->quicktime_fseek(file, file->file_position); - /* result = fread(data, size, 1, (FILE*)file->stream); */ - result = file->input->read(file->input, data, size); - file->ftell_position += size; - } - else - if(selection_start >= file->preload_start && - selection_start < file->preload_end && - selection_end <= file->preload_end && - selection_end > file->preload_start) - { - /* Entire range is in buffer */ - //printf("read data 2\n"); - quicktime_read_preload(file, data, size); - } - else - if(selection_end > file->preload_end && - selection_end - file->preload_size < file->preload_end) - { - /* Range is after buffer */ - /* Move the preload start to within one preload length of the selection_end */ - //printf("read data 3\n"); - while(selection_end - file->preload_start > file->preload_size) - { - fragment_len = selection_end - file->preload_start - file->preload_size; - if(file->preload_ptr + fragment_len > file->preload_size) - fragment_len = file->preload_size - file->preload_ptr; - file->preload_start += fragment_len; - file->preload_ptr += fragment_len; - if(file->preload_ptr >= file->preload_size) file->preload_ptr = 0; - } - - /* Append sequential data after the preload end to the new end */ - fragment_start = file->preload_ptr + file->preload_end - file->preload_start; - while(fragment_start >= file->preload_size) fragment_start -= file->preload_size; - - while(file->preload_end < selection_end) - { - fragment_len = selection_end - file->preload_end; - if(fragment_start + fragment_len > file->preload_size) fragment_len = file->preload_size - fragment_start; - file->quicktime_fseek(file, file->preload_end); - /* result = fread(&(file->preload_buffer[fragment_start]), fragment_len, 1, (FILE*)file->stream); */ - result = file->input->read (file->input, - &(file->preload_buffer[fragment_start]), - fragment_len); - file->ftell_position += fragment_len; - file->preload_end += fragment_len; - fragment_start += fragment_len; - if(fragment_start >= file->preload_size) fragment_start = 0; - } - - quicktime_read_preload(file, data, size); - } - else - { - //printf("quicktime_read_data 4 selection_start %lld selection_end %lld preload_start %lld\n", selection_start, selection_end, file->preload_start); - /* Range is before buffer or over a preload_size away from the end of the buffer. */ - /* Replace entire preload buffer with range. */ - file->quicktime_fseek(file, file->file_position); - /* result = fread(file->preload_buffer, size, 1, (FILE*)file->stream); */ - result = file->input->read(file->input, file->preload_buffer, size); - file->ftell_position += size; - file->preload_start = file->file_position; - file->preload_end = file->file_position + size; - file->preload_ptr = 0; - //printf("quicktime_read_data 5\n"); - quicktime_read_preload(file, data, size); - //printf("quicktime_read_data 6\n"); - } + } else if (selection_start >= file->preload_start + && selection_start < file->preload_end + && selection_end <= file->preload_end + && selection_end > file->preload_start) { + /* Entire range is in buffer */ + //printf("read data 2\n"); + quicktime_read_preload(file, data, size); + + } else if (selection_end > file->preload_end + && selection_end - file->preload_size < file->preload_end) { + /* Range is after buffer */ + /* Move the preload start to within one preload length of the selection_end */ + //printf("read data 3\n"); + while (selection_end - file->preload_start > file->preload_size) { + fragment_len = selection_end - file->preload_start - file->preload_size; + if (file->preload_ptr + fragment_len > file->preload_size) + fragment_len = file->preload_size - file->preload_ptr; + file->preload_start += fragment_len; + file->preload_ptr += fragment_len; + if (file->preload_ptr >= file->preload_size) + file->preload_ptr = 0; + } + + /* Append sequential data after the preload end to the new end */ + fragment_start = file->preload_ptr + file->preload_end - file->preload_start; + while (fragment_start >= file->preload_size) + fragment_start -= file->preload_size; + + while (file->preload_end < selection_end) { + fragment_len = selection_end - file->preload_end; + if (fragment_start + fragment_len > file->preload_size) + fragment_len = file->preload_size - fragment_start; + file->quicktime_fseek(file, file->preload_end); + /* result = fread(&(file->preload_buffer[fragment_start]), fragment_len, 1, (FILE*)file->stream); */ + result = file->input->read (file->input, + &(file->preload_buffer[fragment_start]), + fragment_len); + file->ftell_position += fragment_len; + file->preload_end += fragment_len; + fragment_start += fragment_len; + if (fragment_start >= file->preload_size) + fragment_start = 0; + } + + quicktime_read_preload(file, data, size); + } else { + //printf("quicktime_read_data 4 selection_start %lld selection_end %lld preload_start %lld\n", selection_start, selection_end, file->preload_start); + /* Range is before buffer or over a preload_size away from the end of the buffer. */ + /* Replace entire preload buffer with range. */ + file->quicktime_fseek(file, file->file_position); + /* result = fread(file->preload_buffer, size, 1, (FILE*)file->stream); */ + result = file->input->read(file->input, file->preload_buffer, size); + file->ftell_position += size; + file->preload_start = file->file_position; + file->preload_end = file->file_position + size; + file->preload_ptr = 0; + //printf("quicktime_read_data 5\n"); + quicktime_read_preload(file, data, size); + //printf("quicktime_read_data 6\n"); } + } //printf("quicktime_read_data 1 %lld %lld\n", file->file_position, size); file->file_position += size; return result; } -static longest quicktime_position(quicktime_t *file) -{ +static longest quicktime_position(quicktime_t *file) { if (file->decompressed_buffer) { return file->decompressed_position; @@ -866,10 +883,9 @@ static void quicktime_read_char32(quicktime_t *file, char *string) file->quicktime_read_data(file, string, 4); } -static int quicktime_set_position(quicktime_t *file, longest position) -{ +static int quicktime_set_position(quicktime_t *file, longest position) { //if(file->wr) printf("quicktime_set_position 0x%llx\n", position); - if(file->decompressed_buffer) + if (file->decompressed_buffer) file->decompressed_position = position; else file->file_position = position; @@ -877,8 +893,8 @@ static int quicktime_set_position(quicktime_t *file, longest position) return 0; } -static void quicktime_copy_char32(char *output, char *input) -{ +static void quicktime_copy_char32(char *output, char *input) { + *output++ = *input++; *output++ = *input++; *output++ = *input++; @@ -886,15 +902,15 @@ static void quicktime_copy_char32(char *output, char *input) } -static unsigned long quicktime_current_time(void) -{ +static unsigned long quicktime_current_time(void) { + time_t t; time (&t); return (t+(66*31536000)+1468800); } -static int quicktime_match_32(char *input, char *output) -{ +static int quicktime_match_32(char *input, char *output) { + if(input[0] == output[0] && input[1] == output[1] && input[2] == output[2] && @@ -904,8 +920,8 @@ static int quicktime_match_32(char *input, char *output) return 0; } -static void quicktime_read_pascal(quicktime_t *file, char *data) -{ +static void quicktime_read_pascal(quicktime_t *file, char *data) { + char len = quicktime_read_char(file); file->quicktime_read_data(file, data, len); data[(int) len] = 0; @@ -913,29 +929,28 @@ static void quicktime_read_pascal(quicktime_t *file, char *data) /* matrix.c */ -static void quicktime_matrix_init(quicktime_matrix_t *matrix) -{ +static void quicktime_matrix_init(quicktime_matrix_t *matrix) { + int i; - for(i = 0; i < 9; i++) matrix->values[i] = 0; + for (i = 0; i < 9; i++) + matrix->values[i] = 0; + matrix->values[0] = matrix->values[4] = 1; matrix->values[8] = 16384; } -static void quicktime_matrix_delete(quicktime_matrix_t *matrix) -{ +static void quicktime_matrix_delete(quicktime_matrix_t *matrix) { } -static void quicktime_read_matrix(quicktime_t *file, quicktime_matrix_t *matrix) -{ +static void quicktime_read_matrix(quicktime_t *file, + quicktime_matrix_t *matrix) { int i = 0; - for(i = 0; i < 9; i++) - { - matrix->values[i] = quicktime_read_fixed32(file); - } + for(i = 0; i < 9; i++) { + matrix->values[i] = quicktime_read_fixed32(file); + } } -static int quicktime_get_timescale(float frame_rate) -{ +static int quicktime_get_timescale(float frame_rate) { int timescale = 600; /* Encode the 29.97, 23.976, 59.94 framerates */ if(frame_rate - (int)frame_rate != 0) @@ -950,9 +965,10 @@ static int quicktime_get_timescale(float frame_rate) /* mvhd.c */ -static int quicktime_mvhd_init(quicktime_mvhd_t *mvhd) -{ +static int quicktime_mvhd_init(quicktime_mvhd_t *mvhd) { + int i; + mvhd->version = 0; mvhd->flags = 0; mvhd->creation_time = quicktime_current_time(); @@ -961,7 +977,8 @@ static int quicktime_mvhd_init(quicktime_mvhd_t *mvhd) mvhd->duration = 0; mvhd->preferred_rate = 1.0; mvhd->preferred_volume = 0.996094; - for(i = 0; i < 10; i++) mvhd->reserved[i] = 0; + for(i = 0; i < 10; i++) + mvhd->reserved[i] = 0; quicktime_matrix_init(&(mvhd->matrix)); mvhd->preview_time = 0; mvhd->preview_duration = 0; @@ -973,13 +990,11 @@ static int quicktime_mvhd_init(quicktime_mvhd_t *mvhd) return 0; } -static int quicktime_mvhd_delete(quicktime_mvhd_t *mvhd) -{ +static int quicktime_mvhd_delete(quicktime_mvhd_t *mvhd) { return 0; } -static void quicktime_read_mvhd(quicktime_t *file, quicktime_mvhd_t *mvhd) -{ +static void quicktime_read_mvhd(quicktime_t *file, quicktime_mvhd_t *mvhd) { mvhd->version = quicktime_read_char(file); mvhd->flags = quicktime_read_int24(file); mvhd->creation_time = quicktime_read_int32(file); @@ -2009,24 +2024,20 @@ static void quicktime_read_stsd(quicktime_t *file, quicktime_minf_t *minf, quick /* stts.c */ -static void quicktime_stts_init(quicktime_stts_t *stts) -{ +static void quicktime_stts_init(quicktime_stts_t *stts) { stts->version = 0; stts->flags = 0; stts->total_entries = 0; } -static void quicktime_stts_init_table(quicktime_stts_t *stts) -{ - if(!stts->total_entries) - { - stts->total_entries = 1; - stts->table = (quicktime_stts_table_t*)malloc(sizeof(quicktime_stts_table_t) * stts->total_entries); - } +static void quicktime_stts_init_table(quicktime_stts_t *stts) { + if(!stts->total_entries) { + stts->total_entries = 1; + stts->table = (quicktime_stts_table_t*)malloc(sizeof(quicktime_stts_table_t) * stts->total_entries); + } } -static void quicktime_stts_init_video(quicktime_t *file, quicktime_stts_t *stts, int time_scale, float frame_rate) -{ +static void quicktime_stts_init_video(quicktime_t *file, quicktime_stts_t *stts, int time_scale, float frame_rate) { quicktime_stts_table_t *table; quicktime_stts_init_table(stts); table = &(stts->table[0]); @@ -2036,8 +2047,7 @@ static void quicktime_stts_init_video(quicktime_t *file, quicktime_stts_t *stts, //printf("quicktime_stts_init_video %ld %f\n", time_scale, (double)frame_rate); } -static void quicktime_stts_init_audio(quicktime_t *file, quicktime_stts_t *stts, int sample_rate) -{ +static void quicktime_stts_init_audio(quicktime_t *file, quicktime_stts_t *stts, int sample_rate) { quicktime_stts_table_t *table; quicktime_stts_init_table(stts); table = &(stts->table[0]); @@ -2046,49 +2056,47 @@ static void quicktime_stts_init_audio(quicktime_t *file, quicktime_stts_t *stts, table->sample_duration = 1; } -static void quicktime_stts_delete(quicktime_stts_t *stts) -{ +static void quicktime_stts_delete(quicktime_stts_t *stts) { if(stts->total_entries) free(stts->table); stts->total_entries = 0; } -static void quicktime_read_stts(quicktime_t *file, quicktime_stts_t *stts) -{ +static void quicktime_read_stts(quicktime_t *file, + quicktime_stts_t *stts, + long time_scale) { int i; + stts->version = quicktime_read_char(file); stts->flags = quicktime_read_int24(file); stts->total_entries = quicktime_read_int32(file); stts->table = (quicktime_stts_table_t*)malloc(sizeof(quicktime_stts_table_t) * stts->total_entries); - for(i = 0; i < stts->total_entries; i++) - { - stts->table[i].sample_count = quicktime_read_int32(file); - stts->table[i].sample_duration = quicktime_read_int32(file); - } + printf ("demux_qt: reading stts... (time scale is %ld units/sec)\n", + time_scale); + for(i = 0; i < stts->total_entries; i++) { + stts->table[i].sample_count = quicktime_read_int32(file); + stts->table[i].sample_duration = quicktime_read_int32(file); + } } /* stsc.c */ -static void quicktime_stsc_init(quicktime_stsc_t *stsc) -{ +static void quicktime_stsc_init(quicktime_stsc_t *stsc) { stsc->version = 0; stsc->flags = 0; stsc->total_entries = 0; stsc->entries_allocated = 0; } -static void quicktime_stsc_init_table(quicktime_t *file, quicktime_stsc_t *stsc) -{ - if(!stsc->entries_allocated) - { - stsc->total_entries = 0; - stsc->entries_allocated = 2000; - stsc->table = (quicktime_stsc_table_t*)calloc(1, sizeof(quicktime_stsc_table_t) * stsc->entries_allocated); - } +static void quicktime_stsc_init_table(quicktime_t *file, quicktime_stsc_t *stsc) { + if(!stsc->entries_allocated) { + stsc->total_entries = 0; + stsc->entries_allocated = 2000; + stsc->table = (quicktime_stsc_table_t*)calloc(1, sizeof(quicktime_stsc_table_t) * stsc->entries_allocated); + } } -static void quicktime_stsc_init_video(quicktime_t *file, quicktime_stsc_t *stsc) -{ +static void quicktime_stsc_init_video(quicktime_t *file, quicktime_stsc_t *stsc) { quicktime_stsc_table_t *table; quicktime_stsc_init_table(file, stsc); table = &(stsc->table[0]); @@ -2097,8 +2105,7 @@ static void quicktime_stsc_init_video(quicktime_t *file, quicktime_stsc_t *stsc) table->id = 1; } -static void quicktime_stsc_init_audio(quicktime_t *file, quicktime_stsc_t *stsc, int sample_rate) -{ +static void quicktime_stsc_init_audio(quicktime_t *file, quicktime_stsc_t *stsc, int sample_rate) { quicktime_stsc_table_t *table; quicktime_stsc_init_table(file, stsc); table = &(stsc->table[0]); @@ -2107,9 +2114,9 @@ static void quicktime_stsc_init_audio(quicktime_t *file, quicktime_stsc_t *stsc, table->id = 1; } -static void quicktime_stsc_delete(quicktime_stsc_t *stsc) -{ - if(stsc->total_entries) free(stsc->table); +static void quicktime_stsc_delete(quicktime_stsc_t *stsc) { + if(stsc->total_entries) + free(stsc->table); stsc->total_entries = 0; } @@ -2122,29 +2129,27 @@ static void quicktime_read_stsc(quicktime_t *file, quicktime_stsc_t *stsc) stsc->entries_allocated = stsc->total_entries; stsc->table = (quicktime_stsc_table_t*)malloc(sizeof(quicktime_stsc_table_t) * stsc->total_entries); - for(i = 0; i < stsc->total_entries; i++) - { - stsc->table[i].chunk = quicktime_read_int32(file); - stsc->table[i].samples = quicktime_read_int32(file); - stsc->table[i].id = quicktime_read_int32(file); - } + for(i = 0; i < stsc->total_entries; i++) { + stsc->table[i].chunk = quicktime_read_int32(file); + stsc->table[i].samples = quicktime_read_int32(file); + stsc->table[i].id = quicktime_read_int32(file); + } } -static int quicktime_update_stsc(quicktime_stsc_t *stsc, long chunk, long samples) -{ +static int quicktime_update_stsc(quicktime_stsc_t *stsc, long chunk, long samples) { /* long i; */ - if(chunk > stsc->entries_allocated) - { - stsc->entries_allocated = chunk * 2; - stsc->table =(quicktime_stsc_table_t*)realloc(stsc->table, sizeof(quicktime_stsc_table_t) * stsc->entries_allocated); - } + if (chunk > stsc->entries_allocated) { + stsc->entries_allocated = chunk * 2; + stsc->table =(quicktime_stsc_table_t*)realloc(stsc->table, sizeof(quicktime_stsc_table_t) * stsc->entries_allocated); + } stsc->table[chunk - 1].samples = samples; stsc->table[chunk - 1].chunk = chunk; stsc->table[chunk - 1].id = 1; - if(chunk > stsc->total_entries) stsc->total_entries = chunk; + if (chunk > stsc->total_entries) + stsc->total_entries = chunk; return 0; } @@ -2158,8 +2163,7 @@ static int quicktime_update_stsc(quicktime_stsc_t *stsc, long chunk, long sample /* stsz.c */ -static void quicktime_stsz_init(quicktime_stsz_t *stsz) -{ +static void quicktime_stsz_init(quicktime_stsz_t *stsz) { stsz->version = 0; stsz->flags = 0; stsz->sample_size = 0; @@ -2167,48 +2171,42 @@ static void quicktime_stsz_init(quicktime_stsz_t *stsz) stsz->entries_allocated = 0; } -static void quicktime_stsz_init_video(quicktime_t *file, quicktime_stsz_t *stsz) -{ +static void quicktime_stsz_init_video(quicktime_t *file, quicktime_stsz_t *stsz) { stsz->sample_size = 0; - if(!stsz->entries_allocated) - { - stsz->entries_allocated = 2000; - stsz->total_entries = 0; - stsz->table = (quicktime_stsz_table_t*)malloc(sizeof(quicktime_stsz_table_t) * stsz->entries_allocated); - } + if(!stsz->entries_allocated) { + stsz->entries_allocated = 2000; + stsz->total_entries = 0; + stsz->table = (quicktime_stsz_table_t*)malloc(sizeof(quicktime_stsz_table_t) * stsz->entries_allocated); + } } -static void quicktime_stsz_init_audio(quicktime_t *file, quicktime_stsz_t *stsz, int channels, int bits) -{ +static void quicktime_stsz_init_audio(quicktime_t *file, quicktime_stsz_t *stsz, int channels, int bits) { /*stsz->sample_size = channels * bits / 8; */ stsz->sample_size = 1; /* ? */ stsz->total_entries = 0; /* set this when closing */ stsz->entries_allocated = 0; } -static void quicktime_stsz_delete(quicktime_stsz_t *stsz) -{ - if(!stsz->sample_size && stsz->total_entries) free(stsz->table); +static void quicktime_stsz_delete(quicktime_stsz_t *stsz) { + if(!stsz->sample_size && stsz->total_entries) + free(stsz->table); stsz->total_entries = 0; stsz->entries_allocated = 0; } -static void quicktime_read_stsz(quicktime_t *file, quicktime_stsz_t *stsz) -{ +static void quicktime_read_stsz(quicktime_t *file, quicktime_stsz_t *stsz) { long i; stsz->version = quicktime_read_char(file); stsz->flags = quicktime_read_int24(file); stsz->sample_size = quicktime_read_int32(file); stsz->total_entries = quicktime_read_int32(file); stsz->entries_allocated = stsz->total_entries; - if(!stsz->sample_size) - { - stsz->table = (quicktime_stsz_table_t*)malloc(sizeof(quicktime_stsz_table_t) * stsz->entries_allocated); - for(i = 0; i < stsz->total_entries; i++) - { - stsz->table[i].size = quicktime_read_int32(file); - } + if(!stsz->sample_size) { + stsz->table = (quicktime_stsz_table_t*)malloc(sizeof(quicktime_stsz_table_t) * stsz->entries_allocated); + for(i = 0; i < stsz->total_entries; i++) { + stsz->table[i].size = quicktime_read_int32(file); } + } } static void quicktime_update_stsz(quicktime_stsz_t *stsz, long sample, long sample_size) @@ -2390,44 +2388,35 @@ static void quicktime_stbl_delete(quicktime_stbl_t *stbl) quicktime_stco_delete(&(stbl->stco)); } -static int quicktime_read_stbl(quicktime_t *file, quicktime_minf_t *minf, quicktime_stbl_t *stbl, quicktime_atom_t *parent_atom) -{ +static int quicktime_read_stbl(quicktime_t *file, quicktime_minf_t *minf, long time_scale, + quicktime_stbl_t *stbl, quicktime_atom_t *parent_atom) { quicktime_atom_t leaf_atom; - do - { - quicktime_atom_read_header(file, &leaf_atom); + do { + quicktime_atom_read_header(file, &leaf_atom); - //printf("quicktime_read_stbl 1\n"); - /* mandatory */ - if(quicktime_atom_is(&leaf_atom, "stsd")) - { - //printf("STSD start %lld end %lld", leaf_atom.start, leaf_atom.end); - quicktime_read_stsd(file, minf, &(stbl->stsd)); - /* Some codecs store extra information at the end of this */ - quicktime_atom_skip(file, &leaf_atom); - } - else - if(quicktime_atom_is(&leaf_atom, "stts")) - { quicktime_read_stts(file, &(stbl->stts)); } - else - if(quicktime_atom_is(&leaf_atom, "stss")) - { quicktime_read_stss(file, &(stbl->stss)); } - else - if(quicktime_atom_is(&leaf_atom, "stsc")) - { quicktime_read_stsc(file, &(stbl->stsc)); } - else - if(quicktime_atom_is(&leaf_atom, "stsz")) - { quicktime_read_stsz(file, &(stbl->stsz)); } - else - if(quicktime_atom_is(&leaf_atom, "co64")) - { quicktime_read_stco64(file, &(stbl->stco)); } - else - if(quicktime_atom_is(&leaf_atom, "stco")) - { quicktime_read_stco(file, &(stbl->stco)); } - else - quicktime_atom_skip(file, &leaf_atom); - }while(quicktime_position(file) < parent_atom->end); + //printf("quicktime_read_stbl 1\n"); + /* mandatory */ + if(quicktime_atom_is(&leaf_atom, "stsd")) { + //printf("STSD start %lld end %lld", leaf_atom.start, leaf_atom.end); + quicktime_read_stsd(file, minf, &(stbl->stsd)); + /* Some codecs store extra information at the end of this */ + quicktime_atom_skip(file, &leaf_atom); + } else if(quicktime_atom_is(&leaf_atom, "stts")) { + quicktime_read_stts(file, &(stbl->stts), time_scale); + } else if(quicktime_atom_is(&leaf_atom, "stss")) { + quicktime_read_stss(file, &(stbl->stss)); + } else if(quicktime_atom_is(&leaf_atom, "stsc")) { + quicktime_read_stsc(file, &(stbl->stsc)); + } else if(quicktime_atom_is(&leaf_atom, "stsz")) { + quicktime_read_stsz(file, &(stbl->stsz)); + } else if(quicktime_atom_is(&leaf_atom, "co64")) { + quicktime_read_stco64(file, &(stbl->stco)); + } else if(quicktime_atom_is(&leaf_atom, "stco")) { + quicktime_read_stco(file, &(stbl->stco)); + } else + quicktime_atom_skip(file, &leaf_atom); + } while (quicktime_position(file) < parent_atom->end); return 0; } @@ -2488,37 +2477,30 @@ static void quicktime_minf_delete(quicktime_minf_t *minf) quicktime_hdlr_delete(&(minf->hdlr)); } -static int quicktime_read_minf(quicktime_t *file, quicktime_minf_t *minf, quicktime_atom_t *parent_atom) -{ +static int quicktime_read_minf(quicktime_t *file, quicktime_minf_t *minf, + long time_scale, + quicktime_atom_t *parent_atom) { quicktime_atom_t leaf_atom; - do - { - quicktime_atom_read_header(file, &leaf_atom); - //printf("quicktime_read_minf 1\n"); - - /* mandatory */ - if(quicktime_atom_is(&leaf_atom, "vmhd")) - { minf->is_video = 1; quicktime_read_vmhd(file, &(minf->vmhd)); } - else - if(quicktime_atom_is(&leaf_atom, "smhd")) - { minf->is_audio = 1; quicktime_read_smhd(file, &(minf->smhd)); } - else - if(quicktime_atom_is(&leaf_atom, "hdlr")) - { - quicktime_read_hdlr(file, &(minf->hdlr)); - /* Main Actor doesn't write component name */ - quicktime_atom_skip(file, &leaf_atom); - } - else - if(quicktime_atom_is(&leaf_atom, "dinf")) - { quicktime_read_dinf(file, &(minf->dinf), &leaf_atom); } - else - if(quicktime_atom_is(&leaf_atom, "stbl")) - { quicktime_read_stbl(file, minf, &(minf->stbl), &leaf_atom); } - else - quicktime_atom_skip(file, &leaf_atom); - }while(quicktime_position(file) < parent_atom->end); + do { + quicktime_atom_read_header(file, &leaf_atom); + //printf("quicktime_read_minf 1\n"); + + /* mandatory */ + if (quicktime_atom_is(&leaf_atom, "vmhd")) { + minf->is_video = 1; quicktime_read_vmhd(file, &(minf->vmhd)); + } else if (quicktime_atom_is(&leaf_atom, "smhd")) { + minf->is_audio = 1; quicktime_read_smhd(file, &(minf->smhd)); + } else if (quicktime_atom_is(&leaf_atom, "hdlr")) { + quicktime_read_hdlr(file, &(minf->hdlr)); + /* Main Actor doesn't write component name */ + quicktime_atom_skip(file, &leaf_atom); + } else if (quicktime_atom_is(&leaf_atom, "dinf")) { quicktime_read_dinf(file, &(minf->dinf), &leaf_atom); + } else if (quicktime_atom_is(&leaf_atom, "stbl")){ + quicktime_read_stbl(file, minf, time_scale, &(minf->stbl), &leaf_atom); + } else + quicktime_atom_skip(file, &leaf_atom); + } while (quicktime_position(file) < parent_atom->end); return 0; } @@ -2568,31 +2550,27 @@ static void quicktime_mdia_delete(quicktime_mdia_t *mdia) quicktime_minf_delete(&(mdia->minf)); } -static int quicktime_read_mdia(quicktime_t *file, quicktime_mdia_t *mdia, quicktime_atom_t *trak_atom) -{ +static int quicktime_read_mdia(quicktime_t *file, quicktime_mdia_t *mdia, + quicktime_atom_t *trak_atom) { + quicktime_atom_t leaf_atom; - do - { - quicktime_atom_read_header(file, &leaf_atom); - //printf("quicktime_read_mdia 0x%llx\n", quicktime_position(file)); - - /* mandatory */ - if(quicktime_atom_is(&leaf_atom, "mdhd")) - { quicktime_read_mdhd(file, &(mdia->mdhd)); } - else - if(quicktime_atom_is(&leaf_atom, "hdlr")) - { - quicktime_read_hdlr(file, &(mdia->hdlr)); - /* Main Actor doesn't write component name */ - quicktime_atom_skip(file, &leaf_atom); - } - else - if(quicktime_atom_is(&leaf_atom, "minf")) - { quicktime_read_minf(file, &(mdia->minf), &leaf_atom); } - else - quicktime_atom_skip(file, &leaf_atom); - }while(quicktime_position(file) < trak_atom->end); + do { + quicktime_atom_read_header(file, &leaf_atom); + //printf("quicktime_read_mdia 0x%llx\n", quicktime_position(file)); + + /* mandatory */ + if(quicktime_atom_is(&leaf_atom, "mdhd")) { + quicktime_read_mdhd(file, &(mdia->mdhd)); + } else if(quicktime_atom_is(&leaf_atom, "hdlr")) { + quicktime_read_hdlr(file, &(mdia->hdlr)); + /* Main Actor doesn't write component name */ + quicktime_atom_skip(file, &leaf_atom); + } else if(quicktime_atom_is(&leaf_atom, "minf")) { + quicktime_read_minf(file, &(mdia->minf), mdia->mdhd.time_scale, &leaf_atom); + } else + quicktime_atom_skip(file, &leaf_atom); + } while (quicktime_position(file) < trak_atom->end); return 0; @@ -2817,9 +2795,9 @@ static long quicktime_track_samples(quicktime_t *file, quicktime_trak_t *trak) } static int quicktime_chunk_of_sample(longest *chunk_sample, - longest *chunk, - quicktime_trak_t *trak, - long sample) + longest *chunk, + quicktime_trak_t *trak, + long sample) { quicktime_stsc_table_t *table = trak->mdia.minf.stbl.stsc.table; long total_entries = trak->mdia.minf.stbl.stsc.total_entries; @@ -2831,12 +2809,11 @@ static int quicktime_chunk_of_sample(longest *chunk_sample, chunk1samples = 0; chunk2entry = 0; - if(!total_entries) - { - *chunk_sample = 0; - *chunk = 0; - return 0; - } + if(!total_entries) { + *chunk_sample = 0; + *chunk = 0; + return 0; + } do { @@ -2864,7 +2841,7 @@ static int quicktime_chunk_of_sample(longest *chunk_sample, else sample_duration = 1; // this way nothing is broken ... I hope - chunk1samples = table[chunk2entry].samples * sample_duration; + chunk1samples = table[chunk2entry].samples * sample_duration; chunk1 = chunk2; if(chunk2entry < total_entries) @@ -2986,18 +2963,15 @@ static longest quicktime_sample_range_size(quicktime_trak_t *trak, return total; } -static longest quicktime_sample_to_offset(quicktime_trak_t *trak, long sample) -{ +static longest quicktime_sample_to_offset(quicktime_trak_t *trak, long sample) { longest chunk, chunk_sample, chunk_offset1, chunk_offset2; quicktime_chunk_of_sample(&chunk_sample, &chunk, trak, sample); - // printf("\tBEFORE quicktime_chunk_to_offset chunk %lld, chunk_sample %lld\n", chunk, chunk_sample); + printf("demux_qt: quicktime_sample_to_offset chunk %lld, chunk_sample %lld, sample %ld\n", + chunk, chunk_sample, sample); + chunk_offset1 = quicktime_chunk_to_offset(trak, chunk); - // printf("\tAFTER quicktime_chunk_to_offset %lld\n", chunk_offset1); chunk_offset2 = chunk_offset1 + quicktime_sample_range_size(trak, chunk_sample, sample); - // printf("\tAFTER AFTER %lld\n", chunk_offset2); - //printf("quicktime_sample_to_offset chunk %lld sample %lld chunk_offset %lld chunk_sample %lld chunk_offset + samples %lld\n", - // chunk, sample, chunk_offset1, chunk_sample, chunk_offset2); return chunk_offset2; } @@ -3044,17 +3018,15 @@ static int quicktime_update_tables(quicktime_t *file, #endif static int quicktime_trak_duration(quicktime_trak_t *trak, - long *duration, - long *timescale) -{ + long *duration, + long *timescale) { quicktime_stts_t *stts = &(trak->mdia.minf.stbl.stts); int i; *duration = 0; - for(i = 0; i < stts->total_entries; i++) - { - *duration += stts->table[i].sample_duration * stts->table[i].sample_count; - } + for(i = 0; i < stts->total_entries; i++) { + *duration += stts->table[i].sample_duration * stts->table[i].sample_count; + } *timescale = trak->mdia.mdhd.time_scale; return 0; @@ -3377,76 +3349,68 @@ static int quicktime_set_audio_position(quicktime_t *file, longest sample, int t longest offset, chunk_sample, chunk; quicktime_trak_t *trak; - if(file->total_atracks) - { - trak = file->atracks[track].track; - file->atracks[track].current_position = sample; - // printf("BEFORE quicktime_chunk_of_sample track %d sample %li\n", track, sample); - quicktime_chunk_of_sample(&chunk_sample, &chunk, trak, sample); - file->atracks[track].current_chunk = chunk; - // printf("AFTER quicktime_chunk_of_sample chunk %d chunk_sample %d\n", chunk, chunk_sample); - offset = quicktime_sample_to_offset(trak, sample); - // printf("AFTER quicktime_sample_to_offset offset %li\n", offset); - quicktime_set_position(file, offset); - } + if(file->total_atracks) { + trak = file->atracks[track].track; + file->atracks[track].current_position = sample; + // printf("BEFORE quicktime_chunk_of_sample track %d sample %li\n", track, sample); + quicktime_chunk_of_sample(&chunk_sample, &chunk, trak, sample); + file->atracks[track].current_chunk = chunk; + // printf("AFTER quicktime_chunk_of_sample chunk %d chunk_sample %d\n", chunk, chunk_sample); + offset = quicktime_sample_to_offset(trak, sample); + // printf("AFTER quicktime_sample_to_offset offset %li\n", offset); + quicktime_set_position(file, offset); + } return 0; } -static int quicktime_set_video_position(quicktime_t *file, longest frame, int track) -{ +static int quicktime_set_video_position(quicktime_t *file, longest frame, + int track) { longest offset, chunk_sample, chunk; quicktime_trak_t *trak; - if(file->total_vtracks) - { - trak = file->vtracks[track].track; - file->vtracks[track].current_position = frame; - quicktime_chunk_of_sample(&chunk_sample, &chunk, trak, frame); - file->vtracks[track].current_chunk = chunk; - offset = quicktime_sample_to_offset(trak, frame); - quicktime_set_position(file, offset); - } + if(file->total_vtracks) { + trak = file->vtracks[track].track; + file->vtracks[track].current_position = frame; + quicktime_chunk_of_sample(&chunk_sample, &chunk, trak, frame); + file->vtracks[track].current_chunk = chunk; + offset = quicktime_sample_to_offset(trak, frame); + quicktime_set_position(file, offset); + } return 0; } -static int quicktime_audio_tracks(quicktime_t *file) -{ +static int quicktime_audio_tracks(quicktime_t *file) { int i, result = 0; quicktime_minf_t *minf; - for(i = 0; i < file->moov.total_tracks; i++) - { - minf = &(file->moov.trak[i]->mdia.minf); - if(minf->is_audio) - result++; - } + for(i = 0; i < file->moov.total_tracks; i++) { + minf = &(file->moov.trak[i]->mdia.minf); + if(minf->is_audio) + result++; + } return result; } -static int quicktime_has_audio(quicktime_t *file) -{ - if(quicktime_audio_tracks(file)) return 1; +static int quicktime_has_audio(quicktime_t *file) { + if(quicktime_audio_tracks(file)) + return 1; return 0; } -static long quicktime_sample_rate(quicktime_t *file, int track) -{ -/* return 8000;*/ +static long quicktime_sample_rate(quicktime_t *file, int track) { if(file->total_atracks) return file->atracks[track].track->mdia.minf.stbl.stsd.table[0].sample_rate; return 0; } -static int quicktime_audio_bits(quicktime_t *file, int track) -{ +static int quicktime_audio_bits(quicktime_t *file, int track) { if(file->total_atracks) return file->atracks[track].track->mdia.minf.stbl.stsd.table[0].sample_size; return 0; } -static char* quicktime_audio_compressor(quicktime_t *file, int track) -{ +static char* quicktime_audio_compressor(quicktime_t *file, int track) { if (track < file->total_atracks) return file->atracks[track].track->mdia.minf.stbl.stsd.table[0].format; /* @@ -3456,74 +3420,66 @@ static char* quicktime_audio_compressor(quicktime_t *file, int track) return "NONE"; } -static int quicktime_track_channels(quicktime_t *file, int track) -{ +static int quicktime_track_channels(quicktime_t *file, int track) { if(track < file->total_atracks) return file->atracks[track].channels; return 0; } -static int quicktime_channel_location(quicktime_t *file, int *quicktime_track, int *quicktime_channel, int channel) -{ +static int quicktime_channel_location(quicktime_t *file, int *quicktime_track, + int *quicktime_channel, int channel) { int current_channel = 0, current_track = 0; *quicktime_channel = 0; *quicktime_track = 0; - for(current_channel = 0, current_track = 0; current_track < file->total_atracks; ) - { - if(channel >= current_channel) - { - *quicktime_channel = channel - current_channel; - *quicktime_track = current_track; - } - - current_channel += file->atracks[current_track].channels; - current_track++; + for(current_channel = 0, current_track = 0; current_track < file->total_atracks; ) { + if(channel >= current_channel) { + *quicktime_channel = channel - current_channel; + *quicktime_track = current_track; } + + current_channel += file->atracks[current_track].channels; + current_track++; + } return 0; } -static int quicktime_video_tracks(quicktime_t *file) -{ +static int quicktime_video_tracks(quicktime_t *file) { int i, result = 0; - for(i = 0; i < file->moov.total_tracks; i++) - { - if(file->moov.trak[i]->mdia.minf.is_video) result++; - } + for(i = 0; i < file->moov.total_tracks; i++) { + if(file->moov.trak[i]->mdia.minf.is_video) + result++; + } return result; } -static int quicktime_has_video(quicktime_t *file) -{ - if(quicktime_video_tracks(file)) return 1; +static int quicktime_has_video(quicktime_t *file) { + if (quicktime_video_tracks(file)) + return 1; return 0; } -static int quicktime_video_width(quicktime_t *file, int track) -{ +static int quicktime_video_width(quicktime_t *file, int track) { if(file->total_vtracks) return file->vtracks[track].track->tkhd.track_width; return 0; } -static int quicktime_video_height(quicktime_t *file, int track) -{ +static int quicktime_video_height(quicktime_t *file, int track) { if(file->total_vtracks) return file->vtracks[track].track->tkhd.track_height; return 0; } -static int quicktime_video_depth(quicktime_t *file, int track) -{ +static int quicktime_video_depth(quicktime_t *file, int track) { if(file->total_vtracks) return file->vtracks[track].track->mdia.minf.stbl.stsd.table[0].depth; return 0; } -static float quicktime_frame_rate(quicktime_t *file, int track) -{ +static float quicktime_frame_rate(quicktime_t *file, int track) { if(file->total_vtracks > track) return (float)file->vtracks[track].track->mdia.mdhd.time_scale / file->vtracks[track].track->mdia.minf.stbl.stts.table[0].sample_duration; @@ -3531,209 +3487,21 @@ static float quicktime_frame_rate(quicktime_t *file, int track) return 0; } -static char* quicktime_video_compressor(quicktime_t *file, int track) -{ +static char* quicktime_video_compressor(quicktime_t *file, int track) { return file->vtracks[track].track->mdia.minf.stbl.stsd.table[0].format; } -static long quicktime_read_audio(quicktime_t *file, char *audio_buffer, long samples, int track) -{ - longest chunk_sample, chunk; - int result = 1; - quicktime_trak_t *trak = file->atracks[track].track; - longest fragment_len, chunk_end; - longest position = file->atracks[track].current_position; - longest end = position + samples; - longest bytes, total_bytes = 0; - longest buffer_offset; - - quicktime_chunk_of_sample(&chunk_sample, &chunk, trak, position); - buffer_offset = 0; - - while(position < end && result) - { - quicktime_set_audio_position(file, position, track); - fragment_len = quicktime_chunk_samples(trak, chunk); - chunk_end = chunk_sample + fragment_len; - fragment_len -= position - chunk_sample; - if(position + fragment_len > chunk_end) fragment_len = chunk_end - position; - if(position + fragment_len > end) fragment_len = end - position; - - bytes = quicktime_samples_to_bytes(trak, fragment_len); - result = file->quicktime_read_data(file, &audio_buffer[buffer_offset], bytes); - - total_bytes += bytes; - position += fragment_len; - chunk_sample = position; - buffer_offset += bytes; - chunk++; - } - - file->atracks[track].current_position = position; - if(!result) return 0; - return total_bytes; -} - -static int quicktime_read_chunk(quicktime_t *file, char *output, int track, longest chunk, longest byte_start, longest byte_len) -{ - quicktime_set_position(file, quicktime_chunk_to_offset(file->atracks[track].track, chunk) + byte_start); - if(file->quicktime_read_data(file, output, byte_len)) return 0; - else - return 1; -} - -static long quicktime_frame_size(quicktime_t *file, long frame, int track) -{ - long bytes = 0; - quicktime_trak_t *trak = file->vtracks[track].track; - - if(trak->mdia.minf.stbl.stsz.sample_size) - { - bytes = trak->mdia.minf.stbl.stsz.sample_size; - } - else - { - long total_frames = quicktime_track_samples(file, trak); - if(frame < 0) frame = 0; - else - if(frame > total_frames - 1) frame = total_frames - 1; - bytes = trak->mdia.minf.stbl.stsz.table[frame].size; - } - - - return bytes; -} - -#if 0 -static longest quicktime_read_next_packet(quicktime_t *file, unsigned char *outbuf, int *isVideo, int *thetrak) -{ - longest packet_start; - longest min_video_delta = 100000000000; - longest min_audio_delta = 100000000000; - longest min_video_start=0; - longest min_audio_start=0; - longest current_position = quicktime_position(file); - long packet = 0; - long min_audio_packet=0; - long min_video_packet=0; - int trak = 0; - int min_audio_trak=0; - int min_video_trak=0; - - - for(trak = 0; trak < file->total_vtracks; trak++) { - packet = quicktime_offset_to_chunk(&packet_start, file->vtracks[trak].track, current_position); - /* printf("video_packet %d, video position %li\n", packet, packet_start); */ - if(current_position - packet_start < min_video_delta) { - min_video_delta = current_position - packet_start; - min_video_trak = trak; - min_video_packet = packet; - min_video_start = packet_start; - } - } - - for(trak = 0; trak < file->total_atracks; trak++) { - packet = quicktime_offset_to_chunk(&packet_start, file->atracks[trak].track, current_position); - /* printf("audio packet %d, audio position %li ", packet, packet_start); */ - if(current_position - packet_start < min_audio_delta) { - min_audio_delta = current_position - packet_start; - min_audio_trak = trak; - min_audio_packet = packet; - min_audio_start = packet_start; - } - } - if(min_audio_delta < min_video_delta) { - longest chunksize = file->atracks[min_audio_trak].track->mdia.minf.stbl.stsz.table[min_audio_packet-1].size; - /* printf("audio chunksize %li min_audio_start %li\n", chunksize, min_audio_start); */ - *thetrak = min_audio_trak; - *isVideo = 0; - file->quicktime_fseek(file, min_audio_start); - file->quicktime_read_data(file,(char*)outbuf, chunksize); - return chunksize; - } else { - longest chunksize = file->vtracks[min_video_trak].track->mdia.minf.stbl.stsz.table[min_video_packet-1].size; - /* printf("video chunksize %li\n", chunksize); */ - *thetrak = min_video_trak; - *isVideo = 1; - file->quicktime_fseek(file, min_video_start); - file->quicktime_read_data(file,(char*)outbuf, chunksize); - return chunksize; - - } - - return 0; -} -#endif - -static long quicktime_read_frame(quicktime_t *file, unsigned char *video_buffer, int track) -{ - longest bytes; - int result = 0; - - /* quicktime_trak_t *trak = file->vtracks[track].track; */ - bytes = quicktime_frame_size(file, file->vtracks[track].current_position, track); - - quicktime_set_video_position(file, file->vtracks[track].current_position, track); - result = file->quicktime_read_data(file, (char*)video_buffer, bytes); - file->vtracks[track].current_position++; - - if(!result) return 0; - return bytes; -} - -/* return -1 if there is NO keyframe after */ -static long quicktime_get_keyframe_after(quicktime_t *file, long frame, int track) -{ - quicktime_trak_t *trak = file->vtracks[track].track; - quicktime_stss_t *stss = &trak->mdia.minf.stbl.stss; - int lo, hi; - - lo = 0; - hi = stss->total_entries-1; - if (stss->table[lo].sample-1>=frame) return stss->table[lo].sample-1; - if (stss->table[hi].sample-1< frame) return -1; - while (hi>lo+1) { - /* here: stss->table[lo].sample-1<frame - stss->table[hi].sample-1>=frame */ - int med = (lo+hi)/2; - if (stss->table[med].sample-1<frame) lo = med; else hi = med; - } - /* here: hi=lo+1 */ - return stss->table[hi].sample-1; -} - - -static int quicktime_read_frame_init(quicktime_t *file, int track) -{ - /* quicktime_trak_t *trak = file->vtracks[track].track; */ - quicktime_set_video_position(file, file->vtracks[track].current_position, track); - if(quicktime_ftell(file) != file->file_position) - { - file->input->seek (file->input, file->file_position, SEEK_SET); - file->ftell_position = file->file_position; - } - return 0; -} - -static int quicktime_read_frame_end(quicktime_t *file, int track) -{ - file->file_position = quicktime_ftell(file); - file->vtracks[track].current_position++; - return 0; -} - -static int quicktime_init_video_map(quicktime_t *file, quicktime_video_map_t *vtrack, quicktime_trak_t *trak) -{ +static int quicktime_init_video_map(quicktime_t *file, quicktime_video_map_t *vtrack, + quicktime_trak_t *trak) { vtrack->track = trak; vtrack->current_position = 0; vtrack->current_chunk = 1; return 0; } -static int quicktime_delete_video_map(quicktime_t *file, quicktime_video_map_t *vtrack) -{ +static int quicktime_delete_video_map(quicktime_t *file, quicktime_video_map_t *vtrack) { return 0; } @@ -3746,17 +3514,15 @@ static int quicktime_init_audio_map(quicktime_t *file, quicktime_audio_map_t *at return 0; } -static int quicktime_delete_audio_map(quicktime_t *file, quicktime_audio_map_t *atrack) -{ +static int quicktime_delete_audio_map(quicktime_t *file, quicktime_audio_map_t *atrack) { return 0; } -static void quicktime_mdat_delete(quicktime_mdat_t *mdat) -{ +static void quicktime_mdat_delete(quicktime_mdat_t *mdat) { } -static void quicktime_read_mdat(quicktime_t *file, quicktime_mdat_t *mdat, quicktime_atom_t *parent_atom, xine_t *xine) -{ +static void quicktime_read_mdat(quicktime_t *file, quicktime_mdat_t *mdat, + quicktime_atom_t *parent_atom, xine_t *xine) { mdat->atom.size = parent_atom->size; mdat->atom.start = parent_atom->start; quicktime_atom_skip(file, parent_atom); @@ -3824,8 +3590,7 @@ static int quicktime_read_info(quicktime_t *file, xine_t *xine) { /* ============================= Initialization functions */ -static int quicktime_init(quicktime_t *file) -{ +static int quicktime_init(quicktime_t *file) { memset(file, sizeof(quicktime_t), 0); @@ -3836,8 +3601,7 @@ static int quicktime_init(quicktime_t *file) return 0; } -static int quicktime_delete(quicktime_t *file) -{ +static int quicktime_delete(quicktime_t *file) { int i; if(file->total_atracks) { @@ -3922,8 +3686,7 @@ static void quicktime_close(quicktime_t *file) free(file); } -static quicktime_t* quicktime_open(input_plugin_t *input, xine_t *xine) -{ +static quicktime_t* quicktime_open(input_plugin_t *input, xine_t *xine) { quicktime_t *new_file = calloc(1, sizeof(quicktime_t)); quicktime_init(new_file); @@ -3952,131 +3715,112 @@ static quicktime_t* quicktime_open(input_plugin_t *input, xine_t *xine) return new_file; } - /* * now for the xine-specific demuxer stuff */ -static void *demux_qt_loop (void *this_gen) { +static off_t demux_qt_get_sample_size (quicktime_trak_t *trak, int sample_num) { - buf_element_t *buf = NULL; - demux_qt_t *this = (demux_qt_t *) this_gen; - uint32_t audio_pts, video_pts, frame_num, audio_pos; + quicktime_stsz_t *stsz; - /* printf ("demux_qt: demux loop starting...\n"); */ + stsz = &trak->mdia.minf.stbl.stsz; - do { + if (stsz->sample_size) + return stsz->sample_size; + + return stsz->table[sample_num].size; +} - if (this->has_audio) { - audio_pos = quicktime_audio_position (this->qt, 0); +static void *demux_qt_loop (void *this_gen) { - if ( (audio_pos + 256) > quicktime_audio_length (this->qt, 0)) { - this->status = DEMUX_FINISHED; - break; - } - } + buf_element_t *buf = NULL; + demux_qt_t *this = (demux_qt_t *) this_gen; + int idx; + off_t offset, size, todo; + fifo_buffer_t *fifo; + int64_t pts; + uint32_t flags; + +#ifdef LOG + printf ("demux_qt: demux loop starting...\n"); +#endif - /* - printf ("audio pos:%d < %d\n", - audio_pos, quicktime_audio_length (this->qt, 0)); - */ + idx = 0; + + do { - audio_pts = quicktime_audio_position (this->qt, 0) * this->audio_factor ; + int is_audio, sample_num; - frame_num = quicktime_video_position (this->qt, 0); - if ( frame_num == quicktime_video_length (this->qt, 0) ) { - this->status = DEMUX_FINISHED; + if (idx >= this->num_index_entries) break; - } - /* - printf ("video pos:%d < %d\n", - frame_num, quicktime_video_length (this->qt, 0)); - */ + is_audio = (this->index[idx].type & BUF_MAJOR_MASK) == BUF_AUDIO_BASE; - video_pts = frame_num * this->video_step ; + if (is_audio) + fifo = this->audio_fifo; + else + fifo = this->video_fifo; - if ( this->has_audio && this->audio_fifo && (audio_pts < video_pts)) { + offset = this->index[idx].offset; + pts = this->index[idx].pts; - buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); - - buf->content = buf->mem; - - if ( !(buf->size = quicktime_read_audio (this->qt, buf->content, 256, 0)) ) { - this->status = DEMUX_FINISHED; - buf->free_buffer (buf); - } else { + for (sample_num = this->index[idx].first_sample; sample_num <= this->index[idx].last_sample; sample_num++) { - /* int count; */ - - buf->pts = audio_pts; - buf->scr = audio_pts; - buf->type = this->audio_type; - buf->decoder_info[0] = 1; - buf->input_time = 0; - buf->input_pos = 0; - - /* - for (count=0; count<buf->size; count++){ - - printf ("%02x ", buf->content[count]); - if ( !(count % 8) ) - printf (" "); - if ( !(count % 16) ) - printf ("\n"); - } - */ + todo = demux_qt_get_sample_size (this->index[idx].track, sample_num); - this->audio_fifo->put (this->audio_fifo, buf); - } +#ifdef LOG + printf ("demux_qt: [idx:%04d type:%08x len:%08lld ] ---------------------------\n", + idx, this->index[idx].type, todo); +#endif - } else { + flags = BUF_FLAG_FRAME_START; + while (todo) { - int size;/* = quicktime_frame_size (this->qt, frame_num, 0); */ + buf = fifo->buffer_pool_alloc (fifo); - if (! (size=quicktime_read_frame (this->qt, this->scratch, 0))) - this->status = DEMUX_FINISHED; - else { - int pos=0; + if (todo>buf->max_size) + size = buf->max_size; + else + size = todo; + todo -= size; - while (size>0) { - int copy_bytes; + quicktime_set_position (this->qt, offset); + + buf->size = this->qt->quicktime_read_data (this->qt, buf->mem, size); +#ifdef LOG + printf ("demux_qt: generated buffer of %d bytes \n", buf->size); +#endif + + buf->content = buf->mem; - buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); +#ifdef DBG_QT + if (is_audio) + write (debug_fh, buf->mem, buf->size); +#endif - if (size>buf->max_size) { - copy_bytes = buf->max_size; - buf->decoder_info[0] = 1; - } else { - copy_bytes = size; - buf->decoder_info[0] = 2; - } + buf->type = this->index[idx].type; + buf->pts = pts; + buf->input_pos = this->qt->file_position; + if (todo) + buf->decoder_flags = flags; + else + buf->decoder_flags = flags | BUF_FLAG_FRAME_END; - memcpy (buf->mem, &this->scratch[pos], copy_bytes); - 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); - - this->video_fifo->put (this->video_fifo, buf); + fifo->put (fifo, buf); - pos += copy_bytes; - size -= copy_bytes; - } + pts = 0; + flags = 0; + offset += size; } + } + idx++; } while (this->status == DEMUX_OK) ; - - /* printf ("demux_qt: demux loop finished (status: %d)\n", this->status); - */ this->status = DEMUX_FINISHED; @@ -4104,7 +3848,11 @@ static void demux_qt_close (demux_plugin_t *this_gen) { demux_qt_t *this = (demux_qt_t *) this_gen; free (this); - + +#ifdef DBG_QT + close (debug_fh); +#endif + } static void demux_qt_stop (demux_plugin_t *this_gen) { @@ -4203,6 +3951,8 @@ static int demux_qt_detect_compressors (demux_qt_t *this) { this->wavex.wFormatTag = WAVE_FORMAT_ADPCM; } else if (!strncasecmp (audio, ".mp3", 4)) { this->audio_type = BUF_AUDIO_MPEG; + } else if (!strncasecmp (audio, "mp4a", 4)) { + this->audio_type = BUF_AUDIO_AAC; } else { printf ("demux_qt: unknown audio codec >%s<\n", audio); @@ -4212,6 +3962,180 @@ static int demux_qt_detect_compressors (demux_qt_t *this) { return 1; } +static void demux_qt_add_index_entry (demux_qt_t *this, off_t offset, + int first_sample, int last_sample, + int64_t pts, int32_t type, + quicktime_trak_t *track) { + + int i,j; + + /* + * insertion sort + */ + + for (i=0; i<this->num_index_entries; i++) { + if (this->index[i].pts >= pts) + break; + } + + for (j=this->num_index_entries; j>i; j--) + this->index[j] = this->index[j-1]; + + this->index[i].pts = pts; + this->index[i].offset = offset; + this->index[i].first_sample = first_sample; + this->index[i].last_sample = last_sample; + this->index[i].type = type; + this->index[i].track = track; + + this->num_index_entries++; +} + +static void demux_qt_index_trak (demux_qt_t *this, quicktime_trak_t *trak, uint32_t type) { + + quicktime_stsz_t *stsz; + quicktime_stsc_t *stsc; + quicktime_stco_t *stco; + quicktime_stts_t *stts; + long time_scale; + int stsc_entry, stsc_first, stsc_cur, stsc_next; + int stsc_samples, stsc_last_sample, stsc_first_sample; + int stts_entry, stts_first_sample, stts_last_sample; + int64_t stts_duration, stts_pts, pts; + off_t chunk_offset; + + stts = &trak->mdia.minf.stbl.stts; + stsz = &trak->mdia.minf.stbl.stsz; + stsc = &trak->mdia.minf.stbl.stsc; + stco = &trak->mdia.minf.stbl.stco; + time_scale = trak->mdia.mdhd.time_scale; + pts = 0; + + /* + * generate one entry per chunk + */ + + /* chunk-tracking */ + + stsc_entry = 0; + stsc_first = stsc->table[stsc_entry].chunk; + stsc_cur = stsc_first; + + if (stsc->total_entries>(stsc_entry+1)) + stsc_next = stsc->table[stsc_entry+1].chunk; + else + stsc_next = 1000000; + + stsc_samples = stsc->table[stsc_entry].samples; + stsc_last_sample = stsc_samples-1; + stsc_first_sample = 0; + + /* time-to-sample tracking */ + + stts_entry = 0; + stts_first_sample = 0; + stts_last_sample = stts->table[stts_entry].sample_count-1; + stts_duration = stts->table[stts_entry].sample_duration * 90000 / time_scale; + stts_pts = 0; + + while (stsc_cur < stco->total_entries) { + + printf ("demux_qt: chunk # is %d...\n", stsc_cur); + + chunk_offset = stco->table[stsc_cur-1].offset; + + /* + * add index entry + */ + +#ifdef LOG + printf ("demux_qt: index entry, sample_num=%d, offset = %lld, sample %d-%d, pts = %lld\n", + stsc_first_sample, chunk_offset, stsc_first_sample, stsc_last_sample, pts); +#endif + + demux_qt_add_index_entry (this, chunk_offset, stsc_first_sample, stsc_last_sample, pts, type, + trak); + + /* + * next chunk + */ + + stsc_cur ++; + + /* + * offset of chunk / sample + */ + + while (stsc_cur >= stsc_next) { + + stsc_entry++; + + stsc_first = stsc->table[stsc_entry].chunk; + + if (stsc->total_entries>(stsc_entry+1)) + stsc_next = stsc->table[stsc_entry+1].chunk; + else + stsc_next = 1000000; + + stsc_samples = stsc->table[stsc_entry].samples; + } + + stsc_first_sample = stsc_last_sample + 1; + stsc_last_sample = stsc_first_sample + stsc_samples - 1; + + printf ("demux_qt: chunk offset is %lld...\n", chunk_offset); + + + /* + * find out about pts of sample + */ + + while (stsc_first_sample > stts_last_sample) { + + stts_pts += stts_duration * stts->table[stts_entry].sample_count; + stts_entry++; + stts_first_sample = stts_last_sample+1; + stts_last_sample += stts->table[stts_entry].sample_count; + stts_duration = stts->table[stts_entry].sample_duration * 90000 / time_scale; + } + + pts = stts_pts + (stsc_first_sample - stts_first_sample) * stts_duration; + + } + +} + +static void demux_qt_create_index (demux_qt_t *this) { + + int track_num; + quicktime_trak_t *trak; + + this->num_index_entries = 0; + + /* video */ + + printf ("demux_qt: generating index, video entries...\n"); + + for (track_num = 0; track_num<this->qt->total_vtracks; track_num++) { + + trak = this->qt->vtracks[track_num].track; + + demux_qt_index_trak (this, trak, this->video_type | track_num); + } + + /* audio */ + + printf ("demux_qt: generating index, audio entries...\n"); + + for (track_num = 0; track_num<this->qt->total_atracks; track_num++) { + + trak = this->qt->atracks[track_num].track; + + demux_qt_index_trak (this, trak, this->audio_type | track_num); + } + printf ("demux_qt: index generation done.\n"); +} + static void demux_qt_start (demux_plugin_t *this_gen, fifo_buffer_t *video_fifo, fifo_buffer_t *audio_fifo, @@ -4225,6 +4149,10 @@ static void demux_qt_start (demux_plugin_t *this_gen, this->audio_fifo = audio_fifo; this->send_end_buffers = 1; +#ifdef DBG_QT + debug_fh = open ("/tmp/t.mp3", O_CREAT | O_WRONLY | O_TRUNC, 0644); +#endif + /* * init quicktime parser */ @@ -4249,6 +4177,12 @@ static void demux_qt_start (demux_plugin_t *this_gen, return; } + /* + * generate index + */ + + demux_qt_create_index (this); + /* * send start buffer */ @@ -4286,6 +4220,7 @@ static void demux_qt_start (demux_plugin_t *this_gen, buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->content = buf->mem; + buf->decoder_flags = BUF_FLAG_HEADER; buf->decoder_info[0] = 0; /* first package, containing bih */ buf->decoder_info[1] = this->video_step; memcpy (buf->content, &this->bih, sizeof (this->bih)); @@ -4295,6 +4230,8 @@ static void demux_qt_start (demux_plugin_t *this_gen, this->video_fifo->put (this->video_fifo, buf); + printf ("demux_qt: sent buffer %08x\n", buf); + if(this->audio_fifo) { buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); buf->content = buf->mem; @@ -4302,6 +4239,7 @@ static void demux_qt_start (demux_plugin_t *this_gen, sizeof (this->wavex)); buf->size = sizeof (this->wavex); buf->type = this->audio_type; + buf->decoder_flags = BUF_FLAG_HEADER; buf->decoder_info[0] = 0; /* first package, containing wavex */ buf->decoder_info[1] = quicktime_sample_rate (this->qt, 0); buf->decoder_info[2] = quicktime_audio_bits (this->qt, 0); diff --git a/src/demuxers/demux_ts.c b/src/demuxers/demux_ts.c index 6fea5bdac..ad8d31e39 100644 --- a/src/demuxers/demux_ts.c +++ b/src/demuxers/demux_ts.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: demux_ts.c,v 1.37 2002/02/17 17:32:50 guenter Exp $ + * $Id: demux_ts.c,v 1.38 2002/03/11 12:31:24 guenter Exp $ * * Demultiplexer for MPEG2 Transport Streams. * @@ -545,7 +545,7 @@ static void demux_ts_buffer_pes(demux_ts *this, unsigned char *ts, buf->size = m->size; buf->type = m->type; buf->pts = m->PTS; - buf->scr = this->PCR; + /* buf->scr = this->PCR; */ buf->decoder_info[0] = 1; m->fifo->put (m->fifo, buf); } @@ -557,7 +557,7 @@ static void demux_ts_buffer_pes(demux_ts *this, unsigned char *ts, buf->size = len; buf->type = m->type; buf->pts = 0; - buf->scr = 0; + /* buf->scr = 0; */ buf->input_pos = this->input->get_current_pos(this->input); buf->decoder_info[0] = 1; m->fifo->put (m->fifo, buf); diff --git a/src/dxr3/dxr3_decoder.c b/src/dxr3/dxr3_decoder.c index 651f6c8eb..cd7c26ee0 100644 --- a/src/dxr3/dxr3_decoder.c +++ b/src/dxr3/dxr3_decoder.c @@ -1,7 +1,7 @@ /* - * Copyright (C) 2000-2001 the xine project + * Copyright (C) 2000-2002 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 this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: dxr3_decoder.c,v 1.64 2002/03/10 21:16:16 miguelfreitas Exp $ + * $Id: dxr3_decoder.c,v 1.65 2002/03/11 12:31:25 guenter Exp $ * * dxr3 video and spu decoder plugin. Accepts the video and spu data * from XINE and sends it directly to the corresponding dxr3 devices. @@ -972,7 +972,7 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) return; } /* Is this also needed for subpicture? */ - if (buf->decoder_info[0] == 0) { + if (buf->decoder_flags & BUF_FLAG_PREVIEW) { #if LOG_SPU printf ("dxr3_spu: Dropping SPU channel %d. Preview data\n", stream_id); #endif diff --git a/src/liba52/xine_decoder.c b/src/liba52/xine_decoder.c index 0dbf203e3..530a2c9eb 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.17 2002/02/09 07:13:23 guenter Exp $ + * $Id: xine_decoder.c,v 1.18 2002/03/11 12:31:25 guenter Exp $ * * stuff needed to turn liba52 into a xine decoder plugin */ @@ -265,7 +265,7 @@ static inline void float_to_int (float * _f, int16_t * s16, int num_channels) { } } -static void a52dec_decode_frame (a52dec_decoder_t *this, uint32_t pts, uint32_t scr) { +static void a52dec_decode_frame (a52dec_decoder_t *this, int64_t pts) { int output_mode = AO_CAP_MODE_STEREO; @@ -380,7 +380,6 @@ static void a52dec_decode_frame (a52dec_decoder_t *this, uint32_t pts, uint32_t buf->num_frames = 256*6; buf->vpts = pts; - buf->scr = scr; this->audio_out->put_buffer (this->audio_out, buf); @@ -431,7 +430,6 @@ static void a52dec_decode_frame (a52dec_decoder_t *this, uint32_t pts, uint32_t buf->num_frames = 1536; buf->vpts = pts; - buf->scr = scr; this->audio_out->put_buffer (this->audio_out, buf); @@ -447,7 +445,7 @@ void a52dec_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { uint8_t *end = buf->content + buf->size; uint8_t byte; - if (buf->decoder_info[0] == 0) + if (buf->decoder_flags & BUF_FLAG_PREVIEW) return; /* @@ -464,7 +462,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, buf->scr); + a52dec_decode_frame (this, this->pts); #ifdef DEBUG_A52 write (a52file, this->frame_buffer, this->frame_length); #endif diff --git a/src/libdivx4/xine_decoder.c b/src/libdivx4/xine_decoder.c index 71f97efa7..d5bdaca64 100644 --- a/src/libdivx4/xine_decoder.c +++ b/src/libdivx4/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.18 2002/02/24 17:09:54 f1rmb Exp $ + * $Id: xine_decoder.c,v 1.19 2002/03/11 12:31:25 guenter Exp $ * * xine decoder plugin using divx4 * @@ -60,6 +60,8 @@ #if CATCH_SIGSEGV #include <signal.h> +#define LOG + /* to be able to restore the old handler */ void (*old_handler)(int); @@ -333,7 +335,7 @@ static int divx4_can_handle (video_decoder_t *this_gen, int buf_type) { /* divx4 currently does not support MSMPEG4 v1/v2 */ return ( (buf_type == BUF_VIDEO_MSMPEG4_V3 && this->can_handle_311) || /* buf_type == BUF_VIDEO_MSMPEG4_V12 || */ - buf_type == BUF_VIDEO_MPEG4); + buf_type == BUF_VIDEO_MPEG4 || buf_type == BUF_VIDEO_3IVX); } /* copied verbatim from ffmpeg plugin */ @@ -356,8 +358,17 @@ static void divx4_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { divx4_decoder_t *this = (divx4_decoder_t *) this_gen; - if (buf->decoder_info[0] == 0) { /* need to initialize */ +#ifdef LOG + printf ("divx4: decoding buffer %08x, flags = %08x\n", buf, buf->decoder_flags); +#endif + + if (buf->decoder_flags & BUF_FLAG_HEADER) { /* need to initialize */ /* only proceed if version is good and initialization succeeded */ + +#ifdef LOG + printf ("divx4: get_version...\n"); +#endif + divx4_get_version(this); this->decoder_ok = ( divx4_check_version(this) && divx4_init_decoder(this, buf) ); @@ -391,7 +402,7 @@ static void divx4_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { xine_fast_memcpy (&this->buf[this->size], buf->content, buf->size); this->size += buf->size; - if (buf->decoder_info[0] == 2) { /* need to decode a frame */ + if (buf->decoder_flags & BUF_FLAG_FRAME_END) { /* need to decode a frame */ /* allocate image (taken from ffmpeg plugin) */ img = this->video_out->get_frame (this->video_out, this->biWidth, this->biHeight, XINE_ASPECT_RATIO_DONT_TOUCH, @@ -525,7 +536,7 @@ video_decoder_t *init_video_decoder_plugin (int iface_version, xine_t *xine) { "use divx4 plugin for msmpeg4v3 streams", NULL, NULL, NULL); this->size = 0; - /* allow override of version checking by user */ + /* allow override of version checking by user */ this->version = cfg->register_num(cfg, "codec.divx4_forceversion", 0, "Divx version to check for (set to 0 (default) if unsure)", NULL, NULL, NULL); diff --git a/src/libdts/xine_decoder.c b/src/libdts/xine_decoder.c index 89b8cf1d2..b45dcf5c8 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.14 2002/02/09 07:13:23 guenter Exp $ + * $Id: xine_decoder.c,v 1.15 2002/03/11 12:31:25 guenter Exp $ * * 04-09-2001 DTS passtrough (C) Joachim Koenig * 09-12-2001 DTS passthrough inprovements (C) James Courtier-Dutton @@ -124,10 +124,8 @@ void dts_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { /* printf("DTS first access unit=%u\n",audio_buffer->first_access_unit); */ if (n == first_access_unit) { audio_buffer->vpts = buf->pts; - audio_buffer->scr = buf->scr; } else { audio_buffer->vpts = 0; - audio_buffer->scr = 0; } data_out=(uint8_t *) audio_buffer->mem; diff --git a/src/libffmpeg/xine_decoder.c b/src/libffmpeg/xine_decoder.c index 609a60ee7..d1cc5f602 100644 --- a/src/libffmpeg/xine_decoder.c +++ b/src/libffmpeg/xine_decoder.c @@ -1,7 +1,7 @@ /* - * Copyright (C) 2001 the xine project + * Copyright (C) 2001-2002 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 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.26 2002/02/09 07:13:23 guenter Exp $ + * $Id: xine_decoder.c,v 1.27 2002/03/11 12:31:25 guenter Exp $ * * xine decoder plugin using ffmpeg * @@ -42,6 +42,10 @@ #include "libavcodec/avcodec.h" #include "libavcodec/dsputil.h" +/* +#define LOG +*/ + /* now this is ripped of wine's vfw.h */ typedef struct { long biSize; @@ -129,12 +133,12 @@ static void ff_init (video_decoder_t *this_gen, vo_instance_t *video_out) { static void ff_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { ff_decoder_t *this = (ff_decoder_t *) this_gen; - /* - printf ("ffmpeg: processing packet type = %08x, buf : %d, buf->decoder_info[0]=%d\n", - buf->type, buf, buf->decoder_info[0]); - */ +#ifdef LOG + printf ("ffmpeg: processing packet type = %08x, buf : %d, buf->decoder_flags=%08x\n", + buf->type, buf, buf->decoder_flags); +#endif - if (buf->decoder_info[0] == 0) { + if (buf->decoder_flags & BUF_FLAG_HEADER) { AVCodec *codec = NULL; int codec_type; @@ -226,7 +230,7 @@ static void ff_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { this->size += buf->size; - if (buf->decoder_info[0] == 2) { + if (buf->decoder_flags & BUF_FLAG_FRAME_END) { vo_frame_t *img; int got_picture, len, y; diff --git a/src/liblpcm/xine_decoder.c b/src/liblpcm/xine_decoder.c index dbff95cda..07c3f8edd 100644 --- a/src/liblpcm/xine_decoder.c +++ b/src/liblpcm/xine_decoder.c @@ -1,7 +1,7 @@ /* - * Copyright (C) 2000-2001 the xine project + * Copyright (C) 2000-2002 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 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.19 2002/02/09 07:13:23 guenter Exp $ + * $Id: xine_decoder.c,v 1.20 2002/03/11 12:31:25 guenter Exp $ * * 31-8-2001 Added LPCM rate sensing. * (c) 2001 James Courtier-Dutton James@superbug.demon.co.uk @@ -89,7 +89,7 @@ void lpcm_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { int stream_be; audio_buffer_t *audio_buffer; - if (buf->decoder_info[0] == 0) { + if (buf->decoder_flags & BUF_FLAG_PREVIEW) { this->rate=buf->decoder_info[1]; this->bits_per_sample=buf->decoder_info[2] ; this->number_of_channels=buf->decoder_info[3] ; @@ -100,7 +100,7 @@ void lpcm_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { if (!this->output_open) { /* * with dvdnav we do not get a preview buffer with audio format - * information (buf->decoder_info[0] == 0). + * information (buf->decoder_flags & BUF_FLAG_PREVIEW). * grab the audio format from the first audio data buffer, in case * the audio format is not yet known. */ @@ -130,7 +130,6 @@ void lpcm_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { 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->put_buffer (this->audio_out, audio_buffer); diff --git a/src/libmad/xine_decoder.c b/src/libmad/xine_decoder.c index 854057761..15689a2c0 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.13 2002/02/09 07:13:23 guenter Exp $ + * $Id: xine_decoder.c,v 1.14 2002/03/11 12:31:25 guenter Exp $ * * stuff needed to turn libmad into a xine decoder plugin */ @@ -32,6 +32,10 @@ #include "synth.h" #include "xineutils.h" +/* +#define LOG +*/ + #define INPUT_BUF_SIZE 16384 typedef struct mad_decoder_s { @@ -82,7 +86,9 @@ static void mad_init (audio_decoder_t *this_gen, ao_instance_t *audio_out) { mad_stream_init (&this->stream); mad_frame_init (&this->frame); - /* printf ("libmad: init\n"); */ +#ifdef LOG + printf ("libmad: init\n"); +#endif } @@ -123,9 +129,10 @@ static void mad_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { mad_decoder_t *this = (mad_decoder_t *) this_gen; - /* + +#ifdef LOG printf ("libmad: decode data, decoder_info[0]: %d\n", buf->decoder_info[0]); - */ +#endif if (buf->size>(INPUT_BUF_SIZE-this->bytes_in_buffer)) { printf ("libmad: ALERT input buffer too small (%d bytes, %d avail)!\n", @@ -133,7 +140,7 @@ static void mad_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { buf->size = INPUT_BUF_SIZE-this->bytes_in_buffer; } - if (buf->decoder_info[0] >0) { + if ((buf->decoder_flags & BUF_FLAG_HEADER) == 0) { xine_fast_memcpy (&this->buffer[this->bytes_in_buffer], buf->content, buf->size); @@ -177,9 +184,11 @@ static void mad_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { || (this->output_sampling_rate != this->frame.header.samplerate) || (this->output_mode != mode)) { +#ifdef LOG printf ("libmad: audio sample rate %d mode %08x\n", this->frame.header.samplerate, mode); +#endif if (this->output_open) { this->audio_out->close (this->audio_out); @@ -226,14 +235,15 @@ static void mad_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { 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; } - /* printf ("libmad: decode worked\n"); */ +#ifdef LOG + printf ("libmad: decode worked\n"); +#endif } } diff --git a/src/libmpeg2/decode.c b/src/libmpeg2/decode.c index 68db8b3d5..a8099ef64 100644 --- a/src/libmpeg2/decode.c +++ b/src/libmpeg2/decode.c @@ -345,7 +345,6 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code, picture->current_frame->bad_frame = 1; picture->current_frame->drawn = 0; picture->current_frame->pts = mpeg2dec->pts; - picture->current_frame->scr = mpeg2dec->scr; picture->current_frame->top_field_first = picture->top_field_first; picture->current_frame->repeat_first_field = picture->repeat_first_field; @@ -418,7 +417,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 scr) + uint64_t pts) { int ret; uint8_t code; @@ -435,8 +434,6 @@ 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); @@ -521,7 +518,6 @@ 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; get_frame_duration(mpeg2dec, picture->backward_reference_frame); if( !picture->backward_reference_frame->drawn) picture->backward_reference_frame->draw (picture->backward_reference_frame); @@ -615,7 +611,6 @@ static void process_userdata(mpeg2dec_t *mpeg2dec, uint8_t *buffer) event.buffer = &buffer[2]; event.buf_len = end - &buffer[2]; event.pts = mpeg2dec->pts; - event.scr = mpeg2dec->scr; xine_send_event(mpeg2dec->xine, &event.event); } } diff --git a/src/libmpeg2/mpeg2.h b/src/libmpeg2/mpeg2.h index c2ee5f6ec..a0efeaac5 100644 --- a/src/libmpeg2/mpeg2.h +++ b/src/libmpeg2/mpeg2.h @@ -43,7 +43,8 @@ typedef struct mpeg2dec_s { /* last start code ? */ uint8_t code; - uint32_t pts, scr; + int64_t pts; + uint32_t last_repeat_first_field; xine_t *xine; } mpeg2dec_t ; @@ -57,7 +58,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 scr); + uint64_t pts); 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 91274771a..d3fadcf7f 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.23 2002/02/17 17:32:50 guenter Exp $ + * $Id: xine_decoder.c,v 1.24 2002/03/11 12:31:26 guenter Exp $ * * stuff needed to turn libmpeg2 into a xine decoder plugin */ @@ -81,12 +81,12 @@ static void mpeg2dec_decode_data (video_decoder_t *this_gen, buf_element_t *buf) pthread_mutex_lock (&this->lock); - if (buf->decoder_info[0] == 0) { + if (buf->decoder_flags & BUF_FLAG_PREVIEW) { mpeg2_find_sequence_header (&this->mpeg2, buf->content, buf->content + buf->size); } else { mpeg2_decode_data (&this->mpeg2, buf->content, buf->content + buf->size, - buf->pts, buf->scr); + buf->pts); } pthread_mutex_unlock (&this->lock); diff --git a/src/libspucc/cc_decoder.c b/src/libspucc/cc_decoder.c index 13230a8a2..d902a38fb 100644 --- a/src/libspucc/cc_decoder.c +++ b/src/libspucc/cc_decoder.c @@ -20,7 +20,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: cc_decoder.c,v 1.6 2002/01/08 20:38:05 cvogler Exp $ + * $Id: cc_decoder.c,v 1.7 2002/03/11 12:31:26 guenter Exp $ * * stuff needed to provide closed captioning decoding and display * @@ -315,8 +315,7 @@ struct cc_decoder_s { uint32_t lastcode; /* The PTS and SCR at which the captioning chunk started */ - uint32_t pts; - uint32_t scr; + int64_t pts; /* holds the NTSC frame offset to last known pts/scr */ uint32_t f_offset; @@ -757,11 +756,11 @@ static void ccmem_exit(cc_memory_t *this) /*----------------- cc_renderer_t methods -------------------------------*/ -static uint32_t cc_renderer_calc_vpts(cc_renderer_t *this, uint32_t pts, - uint32_t scr, uint32_t ntsc_frame_offset) +static uint32_t cc_renderer_calc_vpts(cc_renderer_t *this, int64_t pts, + uint32_t ntsc_frame_offset) { metronom_t *metronom = this->metronom; - uint32_t vpts = metronom->got_spu_packet(metronom, pts, 0, scr); + uint32_t vpts = metronom->got_spu_packet(metronom, pts, 0); return vpts + ntsc_frame_offset * NTSC_FRAME_DURATION; } @@ -773,7 +772,7 @@ static int cc_renderer_on_display(cc_renderer_t *this) } -static void cc_renderer_hide_caption(cc_renderer_t *this, uint32_t vpts) +static void cc_renderer_hide_caption(cc_renderer_t *this, int64_t vpts) { if (this->displayed) { this->osd_renderer->hide(this->cap_display, vpts); @@ -783,7 +782,7 @@ static void cc_renderer_hide_caption(cc_renderer_t *this, uint32_t vpts) static void cc_renderer_show_caption(cc_renderer_t *this, cc_buffer_t *buf, - uint32_t vpts) + int64_t vpts) { #ifdef LOG_DEBUG printf("spucc: cc_renderer: show\n"); @@ -960,8 +959,8 @@ static void cc_hide_displayed(cc_decoder_t *this) #endif if (cc_renderer_on_display(this->cc_cfg->renderer)) { - uint32_t vpts = cc_renderer_calc_vpts(this->cc_cfg->renderer, this->pts, - this->scr, this->f_offset); + int64_t vpts = cc_renderer_calc_vpts(this->cc_cfg->renderer, this->pts, + this->f_offset); cc_renderer_hide_caption(this->cc_cfg->renderer, vpts); } } @@ -975,7 +974,7 @@ static void cc_show_displayed(cc_decoder_t *this) if (cc_onscreen_displayable(this)) { uint32_t vpts = cc_renderer_calc_vpts(this->cc_cfg->renderer, this->pts, - this->scr, this->f_offset); + this->f_offset); #ifdef LOG_DEBUG printf("cc_decoder: cc_show_displayed: showing caption %u at vpts %u\n", this->capid, vpts); #endif @@ -1231,7 +1230,7 @@ static void cc_decode_EIA608(cc_decoder_t *this, uint16_t data) void decode_cc(cc_decoder_t *this, uint8_t *buffer, uint32_t buf_len, - uint32_t pts, uint32_t scr) + int64_t pts) { /* The first number may denote a channel number. I don't have the * EIA-708 standard, so it is hard to say. @@ -1259,7 +1258,6 @@ void decode_cc(cc_decoder_t *this, uint8_t *buffer, uint32_t buf_len, this->f_offset = 0; this->pts = pts; - this->scr = scr; while (curbytes < buf_len) { cc_code = *current++; @@ -1324,7 +1322,7 @@ cc_decoder_t *cc_decoder_open(cc_config_t *cc_cfg) this->lastcode = 0; this->capid = 0; - this->pts = this->scr = this->f_offset = 0; + this->pts = this->f_offset = 0; #ifdef LOG_DEBUG printf("spucc: cc_decoder_open\n"); diff --git a/src/libspucc/cc_decoder.h b/src/libspucc/cc_decoder.h index b054d8bd4..c741caff7 100644 --- a/src/libspucc/cc_decoder.h +++ b/src/libspucc/cc_decoder.h @@ -20,7 +20,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: cc_decoder.h,v 1.3 2002/01/07 23:04:26 cvogler Exp $ + * $Id: cc_decoder.h,v 1.4 2002/03/11 12:31:26 guenter Exp $ * * stuff needed to provide closed captioning decoding and display * @@ -56,7 +56,7 @@ void cc_decoder_close(cc_decoder_t *this_obj); void cc_decoder_init(void); void decode_cc(cc_decoder_t *this, uint8_t *buffer, uint32_t buf_len, - uint32_t pts, uint32_t scr); + int64_t pts); /* Instantiates a new closed captioning renderer. */ cc_renderer_t *cc_renderer_open(osd_renderer_t *osd_renderer, @@ -69,3 +69,4 @@ void cc_renderer_close(cc_renderer_t *this_obj); /* Updates the renderer configuration variables */ void cc_renderer_update_cfg(cc_renderer_t *this_obj, int video_width, int video_height); + diff --git a/src/libspucc/xine_decoder.c b/src/libspucc/xine_decoder.c index cfde5387b..e0db0f2bf 100644 --- a/src/libspucc/xine_decoder.c +++ b/src/libspucc/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.4 2002/02/09 07:13:23 guenter Exp $ + * $Id: xine_decoder.c,v 1.5 2002/03/11 12:31:26 guenter Exp $ * * closed caption spu decoder. receive data by events. * @@ -267,7 +267,7 @@ static void spudec_init (spu_decoder_t *this_gen, vo_instance_t *vo_out) { static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { spucc_decoder_t *this = (spucc_decoder_t *) this_gen; - if (buf->decoder_info[0] == 0) { + if (buf->decoder_flags & BUF_FLAG_PREVIEW) { } else { pthread_mutex_lock(&this->cc_mutex); if (this->cc_cfg.cc_enabled) { @@ -276,7 +276,7 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { if(this->cc_cfg.can_cc) { decode_cc(this->ccdec, buf->content, buf->size, - buf->pts, buf->scr); + buf->pts); } } pthread_mutex_unlock(&this->cc_mutex); @@ -321,8 +321,7 @@ static void spudec_event_listener(void *this_gen, xine_event_t *event_gen) { spucc_do_init (this, NULL); if (this->cc_cfg.can_cc) { decode_cc(this->ccdec, closed_caption->buffer, - closed_caption->buf_len, closed_caption->pts, - closed_caption->scr); + closed_caption->buf_len, closed_caption->pts); } } pthread_mutex_unlock(&this->cc_mutex); diff --git a/src/libspudec/xine_decoder.c b/src/libspudec/xine_decoder.c index ee824d9d1..98f8947b5 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.56 2002/02/09 07:13:23 guenter Exp $ + * $Id: xine_decoder.c,v 1.57 2002/03/11 12:31:26 guenter Exp $ * * stuff needed to turn libspu into a xine decoder plugin */ @@ -430,7 +430,7 @@ static void spudec_decode_nav(spudec_decoder_t *this, buf_element_t *buf) { it yet and we cannot provide correct vpts values. use current_time instead as an aproximation. */ - this->event.vpts = metronom->got_spu_packet(metronom, pci->pci_gi.vobu_s_ptm, 0, 0); + this->event.vpts = metronom->got_spu_packet(metronom, pci->pci_gi.vobu_s_ptm, 0); ovl_instance->add_event(ovl_instance, (void *)&this->event); } else { printf("libspudec: No video_overlay handles left for menu\n"); @@ -481,7 +481,7 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { } - if (buf->decoder_info[0] == 0) /* skip preview data */ + if (buf->decoder_flags & BUF_FLAG_PREVIEW) /* skip preview data */ return; if ( this->spu_stream_state[stream_id].stream_filter == 0) @@ -489,7 +489,7 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { if (buf->pts) { metronom_t *metronom = this->xine->metronom; - uint32_t vpts = metronom->got_spu_packet(metronom, buf->pts, 0, buf->scr); + uint32_t vpts = metronom->got_spu_packet(metronom, buf->pts, 0); if (vpts < this->buf_pts) { /* FIXME: Don't do this yet, diff --git a/src/libsputext/xine_decoder.c b/src/libsputext/xine_decoder.c index df1b1bdf4..4a941bc26 100644 --- a/src/libsputext/xine_decoder.c +++ b/src/libsputext/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 2002/02/27 19:10:37 jkeil Exp $ + * $Id: xine_decoder.c,v 1.16 2002/03/11 12:31:26 guenter Exp $ * * code based on mplayer module: * @@ -857,7 +857,7 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { */ pts_factor = 3000; - pts += this->xine->metronom->video_wrap_offset; + pts += this->xine->metronom->vpts_offset; pts_end = pts + (subtitle->end - subtitle->start) * pts_factor; @@ -888,7 +888,7 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { if (subtitle->start > (start_tenth+20)) return; - pts += this->xine->metronom->video_wrap_offset; + pts += this->xine->metronom->vpts_offset; pts_end = pts + (subtitle->end - subtitle->start)*900; } diff --git a/src/libw32dll/w32codec.c b/src/libw32dll/w32codec.c index 3c9dacd51..352f43ac1 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.63 2002/02/09 07:13:24 guenter Exp $ + * $Id: w32codec.c,v 1.64 2002/03/11 12:31:26 guenter Exp $ * * routines for using w32 codecs * DirectShow support by Miguel Freitas (Nov/2001) @@ -128,7 +128,6 @@ typedef struct w32a_decoder_s { unsigned char *buf; int size; int64_t pts; - int64_t scr; /* these are used for pts estimation */ int64_t lastpts, sumpts, sumsize; @@ -575,7 +574,7 @@ static void w32v_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { buf->decoder_info[0]=%d\n", buf->type, buf, buf->decoder_info[0]); */ - if (buf->decoder_info[0] == 0) { + if (buf->decoder_flags & BUF_FLAG_HEADER) { if ( buf->type & 0xff ) return; @@ -618,7 +617,7 @@ static void w32v_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { this->size += buf->size; - if (buf->decoder_info[0] == 2) { + if (buf->decoder_flags & BUF_FLAG_FRAME_END) { HRESULT ret; vo_frame_t *img; @@ -719,7 +718,6 @@ static void w32v_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { } img->pts = buf->pts; - img->scr = buf->scr; if(ret || this->skipframes) { if( !this->skipframes ) printf("w32codec: Error decompressing frame, err=%ld\n", (long)ret); @@ -977,8 +975,7 @@ static void w32a_decode_audio (w32a_decoder_t *this, unsigned char *data, uint32_t size, int frame_end, - int64_t pts, - int64_t scr) { + int64_t pts) { static ACMSTREAMHEADER ash; HRESULT hr; @@ -989,10 +986,9 @@ static void w32a_decode_audio (w32a_decoder_t *this, issues with some streams. */ - /* buffer empty -> take pts/scr from package */ + /* buffer empty -> take pts from package */ if( !this->size ) { this->pts = pts; - this->scr = scr; /* printf("w32codec: resync pts (%d)\n",this->pts); */ @@ -1006,7 +1002,6 @@ static void w32a_decode_audio (w32a_decoder_t *this, /* force resync every 4 seconds */ if( this->sumpts >= 4 * 90000 && pts ) { this->pts = pts - this->size * this->sumpts / this->sumsize; - this->scr = scr - this->size * this->sumpts / this->sumsize; /* printf("w32codec: estimated resync pts (%d)\n",this->pts); */ @@ -1090,11 +1085,10 @@ static void w32a_decode_audio (w32a_decoder_t *this, */ audio_buffer->num_frames = bufsize / (this->num_channels*2); audio_buffer->vpts = this->pts; - audio_buffer->scr = this->scr; this->audio_out->put_buffer (this->audio_out, audio_buffer); - this->pts = this->scr = 0; + this->pts = 0; DstLengthUsed -= bufsize; p += bufsize; } @@ -1119,7 +1113,7 @@ static void w32a_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { w32a_decoder_t *this = (w32a_decoder_t *) this_gen; - if (buf->decoder_info[0] == 0) { + if (buf->decoder_flags & BUF_FLAG_HEADER) { /* init package containing bih */ this->decoder_ok = w32a_init_audio (this, (WAVEFORMATEX *)buf->content, buf->type); @@ -1128,8 +1122,8 @@ static void w32a_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { return; w32a_decode_audio (this, buf->content, buf->size, - buf->decoder_info[0]==2, - buf->pts, buf->scr); + buf->decoder_flags & BUF_FLAG_FRAME_END, + buf->pts); } } diff --git a/src/xine-engine/audio_decoder.c b/src/xine-engine/audio_decoder.c index f329db056..2e4c9f5c8 100644 --- a/src/xine-engine/audio_decoder.c +++ b/src/xine-engine/audio_decoder.c @@ -1,7 +1,7 @@ /* - * Copyright (C) 2000-2001 the xine project + * Copyright (C) 2000-2002 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 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.63 2002/03/10 21:43:30 miguelfreitas Exp $ + * $Id: audio_decoder.c,v 1.64 2002/03/11 12:31:26 guenter Exp $ * * * functions that implement audio decoding @@ -84,7 +84,7 @@ void *audio_decoder_loop (void *this_gen) { this->audio_finished = 0; pthread_mutex_unlock (&this->finished_lock); - this->metronom->expect_audio_discontinuity (this->metronom); + this->metronom->audio_stream_start (this->metronom); break; @@ -98,7 +98,7 @@ void *audio_decoder_loop (void *this_gen) { pthread_mutex_lock (&this->finished_lock); - if (!this->audio_finished && (buf->decoder_info[0]==0)) { + if (!this->audio_finished && (buf->decoder_flags==BUF_FLAG_END_USER)) { this->audio_finished = 1; if (this->video_finished) { @@ -131,7 +131,7 @@ void *audio_decoder_loop (void *this_gen) { case BUF_CONTROL_DISCONTINUITY: printf ("audio_decoder: discontinuity ahead\n"); - this->metronom->expect_audio_discontinuity (this->metronom); + this->metronom->expect_audio_discontinuity (this->metronom, buf->disc_off); break; case BUF_CONTROL_AUDIO_CHANNEL: diff --git a/src/xine-engine/audio_out.c b/src/xine-engine/audio_out.c index 2c0bd80d4..56f777469 100644 --- a/src/xine-engine/audio_out.c +++ b/src/xine-engine/audio_out.c @@ -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.43 2002/03/01 09:29:50 guenter Exp $ + * $Id: audio_out.c,v 1.44 2002/03/11 12:31:26 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> @@ -474,7 +474,7 @@ static void ao_put_buffer (ao_instance_t *this, audio_buffer_t *buf) { pts = buf->vpts; buf->vpts = this->metronom->got_audio_samples (this->metronom, pts, - buf->num_frames, buf->scr); + buf->num_frames); #ifdef LOG printf ("audio_out: got buffer, pts=%lld, vpts=%lld\n", diff --git a/src/xine-engine/audio_out.h b/src/xine-engine/audio_out.h index d864be464..dd820a6f4 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.24 2002/02/17 17:32:50 guenter Exp $ + * $Id: audio_out.h,v 1.25 2002/03/11 12:31:26 guenter Exp $ */ #ifndef HAVE_AUDIO_OUT_H #define HAVE_AUDIO_OUT_H @@ -137,7 +137,6 @@ struct audio_buffer_s { int num_frames; int64_t vpts; - int64_t scr; uint32_t frame_header_count; uint32_t first_access_unit; }; diff --git a/src/xine-engine/buffer.h b/src/xine-engine/buffer.h index 995249a43..5444d78d5 100644 --- a/src/xine-engine/buffer.h +++ b/src/xine-engine/buffer.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2000-2001 the xine project + * Copyright (C) 2000-2002 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 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.34 2002/03/01 09:29:50 guenter Exp $ + * $Id: buffer.h,v 1.35 2002/03/11 12:31:26 guenter Exp $ * * * contents: @@ -98,6 +98,7 @@ extern "C" { #define BUF_VIDEO_REAL 0x02170000 #define BUF_VIDEO_VP31 0x02180000 #define BUF_VIDEO_H263 0x02190000 +#define BUF_VIDEO_3IVX 0x021A0000 /* audio buffer types: (please keep in sync with buffer_types.c) */ @@ -139,15 +140,18 @@ struct buf_element_s { buf_element_t *next; unsigned char *mem; - unsigned char *content; /* start of raw content in pMem (without header etc) */ + unsigned char *content; /* start of raw content in mem (without header etc) */ - int32_t size ; /* size of _content_ */ - int32_t max_size; + int32_t size ; /* size of _content_ */ + int32_t max_size; /* size of pre-allocated memory pointed to by "mem" */ uint32_t type; - int64_t pts; /* presentation time stamp, used for a/v sync */ - int64_t scr; /* system clock reference, used for discont. detection */ + int64_t pts; /* presentation time stamp, used for a/v sync */ + int64_t disc_off; /* discontinuity offset */ 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_flags; /* stuff like keyframe, is_header ... see below */ + uint32_t decoder_info[4]; /* additional decoder flags and other dec-spec. stuff */ void (*free_buffer) (buf_element_t *buf); @@ -157,6 +161,14 @@ struct buf_element_s { } ; +#define BUF_FLAG_KEYFRAME 0x0001 +#define BUF_FLAG_FRAME_START 0x0002 +#define BUF_FLAG_FRAME_END 0x0004 +#define BUF_FLAG_HEADER 0x0008 +#define BUF_FLAG_PREVIEW 0x0010 +#define BUF_FLAG_END_USER 0x0020 +#define BUF_FLAG_END_STREAM 0x0040 + typedef struct fifo_buffer_s fifo_buffer_t; struct fifo_buffer_s { diff --git a/src/xine-engine/buffer_types.c b/src/xine-engine/buffer_types.c index f9b66892f..fab61fa2f 100644 --- a/src/xine-engine/buffer_types.c +++ b/src/xine-engine/buffer_types.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: buffer_types.c,v 1.10 2002/02/09 07:13:24 guenter Exp $ + * $Id: buffer_types.c,v 1.11 2002/03/11 12:31:26 guenter Exp $ * * * contents: @@ -123,7 +123,6 @@ static video_db_t video_db[] = { mmioFOURCC('d', 'i', 'v', '5'), mmioFOURCC('D', 'I', 'V', '6'), mmioFOURCC('d', 'i', 'v', '6'), - mmioFOURCC('3', 'I', 'V', '1'), mmioFOURCC('A', 'P', '4', '1'), mmioFOURCC('M', 'P', 'G', '3'), 0 @@ -133,6 +132,14 @@ static video_db_t video_db[] = { }, { { + mmioFOURCC('3', 'I', 'V', '1'), + 0 + }, + BUF_VIDEO_3IVX, + "3ivx MPEG-4" +}, +{ + { mmioFOURCC('d', 'm', 'b', '1'), mmioFOURCC('M', 'J', 'P', 'G'), mmioFOURCC('m', 'j', 'p', 'a'), diff --git a/src/xine-engine/metronom.c b/src/xine-engine/metronom.c index b578ea5cf..e54bbca1c 100644 --- a/src/xine-engine/metronom.c +++ b/src/xine-engine/metronom.c @@ -1,7 +1,7 @@ /* * Copyright (C) 2000-2002 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 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.64 2002/03/10 21:16:15 miguelfreitas Exp $ + * $Id: metronom.c,v 1.65 2002/03/11 12:31:26 guenter Exp $ */ #ifdef HAVE_CONFIG_H @@ -253,7 +253,7 @@ static void metronom_set_audio_rate (metronom_t *this, int64_t pts_per_smpls) { } static int64_t metronom_got_spu_packet (metronom_t *this, int64_t pts, - int64_t duration, int64_t scr ) { + int64_t duration) { int64_t vpts; pthread_mutex_lock (&this->lock); @@ -265,47 +265,30 @@ static int64_t metronom_got_spu_packet (metronom_t *this, int64_t pts, this->spu_vpts=this->spu_vpts; } - /* - It happens with the dxr3 that got_spu_packet is called before - got_video_frame. Since video_wrap_offset is zero until then, - the return value would be wrong. In this case zero is returned. - - Also this->video_discontinuity means that scr discontinuity was - detected but this->video_wrap_offset not updated (would give - wrong values too). - */ - if ( this->video_discontinuity ) { - /* we can safely use audio_wrap_offset if already updated */ - if( !this->audio_discontinuity ) { - vpts = pts + this->audio_wrap_offset; - } else { - vpts = 0; - } - } else { - vpts = pts + this->video_wrap_offset; + if ( !this->in_discontinuity ) { + vpts = pts + this->vpts_offset; + } else { + vpts = 0; } pthread_mutex_unlock (&this->lock); return vpts; } -static void metronom_expect_video_discontinuity (metronom_t *this, int starting) { +static void metronom_handle_video_discontinuity (metronom_t *this, int is_stream_start, + int64_t disc_off) { pthread_mutex_lock (&this->lock); - this->video_starting = starting; - - this->video_discontinuity = 10; - this->video_discontinuity_count++; pthread_cond_signal (&this->video_discontinuity_reached); printf ("metronom: video discontinuity #%d\n", this->video_discontinuity_count); - if( this->have_audio ) { - while ( this->audio_discontinuity_count < - this->video_discontinuity_count ) { + if (this->have_audio) { + while (this->audio_discontinuity_count < + this->video_discontinuity_count) { printf ("metronom: waiting for audio discontinuity #%d\n", this->video_discontinuity_count); @@ -313,145 +296,89 @@ static void metronom_expect_video_discontinuity (metronom_t *this, int starting) pthread_cond_wait (&this->audio_discontinuity_reached, &this->lock); } - if ( this->video_vpts < this->audio_vpts ) { + if (this->video_vpts < this->audio_vpts) { this->video_vpts = this->audio_vpts; printf ("metronom: video vpts adjusted to %lld\n", this->video_vpts); } } - + + if (this->in_discontinuity) + this->vpts_offset = this->next_vpts_offset; + + if (is_stream_start) { + this->vpts_offset = this->video_vpts; + } else { + this->next_vpts_offset = this->vpts_offset - disc_off; + this->in_discontinuity = 30; + } pthread_mutex_unlock (&this->lock); } +static void metronom_video_stream_start (metronom_t *this) { + metronom_handle_video_discontinuity (this, 1, 0); +} + +static void metronom_expect_video_discontinuity (metronom_t *this, int64_t disc_off) { + metronom_handle_video_discontinuity (this, 0, disc_off); +} + static void metronom_got_video_frame (metronom_t *this, vo_frame_t *img) { int64_t vpts; int64_t pts = img->pts; int64_t duration = img->duration; - int pts_discontinuity = 0; pthread_mutex_lock (&this->lock); - - /* check for pts discontinuities against the predicted pts value */ - if (pts && this->last_video_pts) { - - int64_t diff, predicted_pts; - - predicted_pts = this->last_video_pts + duration; - - diff = pts - predicted_pts; - -#ifdef LOG - printf ("metronom: got video pts %lld, predicted %lld (= %lld + %lld) => diff %lld\n", - pts, predicted_pts, this->last_video_pts, duration, diff); -#endif - - if ( abs (diff) > WRAP_THRESHOLD ) { - pts_discontinuity = 1; - -#ifdef LOG - printf ("metronom: this is a video discontinuity\n"); -#endif + if (this->in_discontinuity) { + this->in_discontinuity--; - /* - * ignore discontinuities created by frame reordering around - * the REAL discontinuity. :) - */ - if( !this->video_discontinuity ) { - pts = 0; -#ifdef LOG - printf ("metronom: not expecting a video discontinuity => ignored\n"); -#endif - } - } + if (!this->in_discontinuity) + this->vpts_offset = this->next_vpts_offset; + else + pts = 0; /* ignore pts during discontinuities */ } if (pts) { + int64_t diff; + /* - * check if there was any pending SCR discontinuity (video_discontinuity - * is set from the decoder loop) together with pts discont. + * compare predicted (this->video_vpts) and given (pts+vpts_offset) + * pts values - hopefully they will be the same + * if not, for small diffs try to interpolate + * for big diffs: jump */ - if ( this->video_discontinuity && - (pts_discontinuity || this->video_starting) ) { - this->video_starting = 0; - this->video_discontinuity = 0; - this->wrap_diff_counter = 0; - - this->video_wrap_offset = this->video_vpts - pts; - - vpts = pts + this->video_wrap_offset; - - printf ("metronom: video pts discontinuity/start, pts is %lld, wrap_offset is %lld, vpts is %lld\n", - pts, this->video_wrap_offset, vpts); - - } else { - - int64_t diff; - - /* - * audio and video wrap are not allowed to differ for too long - */ - - if ( this->have_audio - && (this->video_wrap_offset != this->audio_wrap_offset) ){ + + vpts = pts + this->vpts_offset; - this->wrap_diff_counter++; - - if (this->wrap_diff_counter > MAX_NUM_WRAP_DIFF) { - - printf ("metronom: forcing video_wrap (%lld) and audio wrap (%lld)", - this->video_wrap_offset, this->audio_wrap_offset); - - if (this->video_wrap_offset > this->audio_wrap_offset) - this->audio_wrap_offset = this->video_wrap_offset; - else - this->video_wrap_offset = this->audio_wrap_offset; - - printf (" to %lld\n", this->video_wrap_offset); - - this->wrap_diff_counter = 0; - } - } - - /* - * compare predicted (this->video_vpts) and given (pts+wrap_offset) - * pts values - hopefully they will be the same - * if not, for small diffs try to interpolate - * for big diffs: jump - */ - - vpts = pts + this->video_wrap_offset; - - diff = this->video_vpts - vpts; + diff = this->video_vpts - vpts; #ifdef LOG - printf ("metronom: video diff is %lld (predicted %lld, given %lld)\n", - diff, this->video_vpts, vpts); + printf ("metronom: video diff is %lld (predicted %lld, given %lld)\n", + diff, this->video_vpts, vpts); #endif - if (abs (diff) > VIDEO_DRIFT_TOLERANCE) { + if (abs (diff) > VIDEO_DRIFT_TOLERANCE) { - this->video_vpts = vpts; - this->video_drift = 0; + this->video_vpts = vpts; + this->video_drift = 0; #ifdef LOG - printf ("metronom: video jump, ignoring predicted vpts\n"); + printf ("metronom: video jump\n"); #endif - } else if (diff) { + } else if (diff) { - this->video_drift = diff / 30; + this->video_drift = diff; #ifdef LOG - printf ("metronom: video drift, compensation will be %lld pts/frame\n", - this->video_drift); + printf ("metronom: video drift, drift is %lld\n", this->video_drift); #endif - } } - - this->last_video_pts = pts; - } else - this->last_video_pts = this->video_vpts - this->video_wrap_offset; + } + + this->video_vpts -= this->video_drift / 30; + this->video_drift -= this->video_drift / 30; img->vpts = this->video_vpts + this->av_offset; @@ -459,18 +386,16 @@ static void metronom_got_video_frame (metronom_t *this, vo_frame_t *img) { printf ("metronom: video vpts for %10lld : %10lld (duration:%lld)\n", pts, this->video_vpts, duration); #endif - - this->video_vpts += duration - this->video_drift; - img->duration -= this->video_drift; + + this->video_vpts += duration; pthread_mutex_unlock (&this->lock); } -static void metronom_expect_audio_discontinuity (metronom_t *this) { +static void metronom_expect_audio_discontinuity (metronom_t *this, int64_t disc_off) { pthread_mutex_lock (&this->lock); - this->audio_discontinuity = 10; this->audio_discontinuity_count++; pthread_cond_signal (&this->audio_discontinuity_reached); @@ -487,120 +412,40 @@ static void metronom_expect_audio_discontinuity (metronom_t *this) { } if ( this->audio_vpts < this->video_vpts ) { - this->audio_vpts = this->video_vpts; + this->audio_vpts = this->video_vpts; printf ("metronom: audio vpts adjusted to %lld\n", this->audio_vpts); } - - /* this->num_audio_samples_guessed = 1; */ - /* this->last_audio_pts = this->audio_vpts - this->audio_wrap_offset; */ + + /* next_vpts_offset, in_discontinuity is handled in expect_video_discontinuity */ pthread_mutex_unlock (&this->lock); } +static void metronom_audio_stream_start (metronom_t *this) { + metronom_expect_audio_discontinuity (this, 0); +} static int64_t metronom_got_audio_samples (metronom_t *this, int64_t pts, - int nsamples, int64_t scr) { + int nsamples) { int64_t vpts; #ifdef LOG - printf ("metronom: got %d audio samples, pts is %lld, last_pts is %lld, diff = %lld\n", - nsamples, pts, this->last_audio_pts, pts - this->last_audio_pts); - printf ("metronom: audio wrap offset is %lld\n", this->audio_wrap_offset); + printf ("metronom: got %d audio samples, pts is %lld\n", nsamples, pts); #endif pthread_mutex_lock (&this->lock); -#if 0 - if (this->audio_discontinuity && this->video_discontinuity) { - - /* this is needed to take care of still frame with no audio - were vpts are not updated. - we can only do it here because audio and video decoder threads - have just been synced */ - if ( this->audio_vpts < metronom_get_current_time(this) ) { - this->audio_vpts = metronom_get_current_time(this) + PREBUFFER_PTS_OFFSET; - this->video_vpts = this->audio_vpts; - printf ("metronom: audio/video vpts too old, adjusted to %lld\n", - this->audio_vpts); - } - } -#endif - + if (this->in_discontinuity) + pts = 0; /* ignore pts during discontinuities */ + if (pts) { - - /* - * discontinuity ? - */ - if ( this->audio_discontinuity ) { - this->audio_discontinuity = 0; - this->wrap_diff_counter = 0; - - this->audio_wrap_offset = this->audio_vpts - pts ; - - /* - * this->num_audio_samples_guessed - * (this->audio_pts_delta + this->pts_per_smpls) / AUDIO_SAMPLE_NUM ; - */ - - vpts = pts + this->audio_wrap_offset; - - printf ("metronom: audio pts discontinuity/start, pts is %lld, wrap_offset is %lld, vpts is %lld\n", - pts, this->audio_wrap_offset, vpts); - - - } else { - - /* - * audio and video wrap are not allowed to differ - * for too long - */ - - if ( this->video_wrap_offset != this->audio_wrap_offset ) { - this->wrap_diff_counter++; - - if (this->wrap_diff_counter > MAX_NUM_WRAP_DIFF) { - - printf ("metronom: forcing video_wrap (%lld) and audio wrap (%lld)", - this->video_wrap_offset, this->audio_wrap_offset); - - if (this->video_wrap_offset > this->audio_wrap_offset) - this->audio_wrap_offset = this->video_wrap_offset; - else - this->video_wrap_offset = this->audio_wrap_offset; - - printf ("to %lld\n", this->video_wrap_offset); - - this->wrap_diff_counter = 0; - } - } - - vpts = pts + this->audio_wrap_offset; - - /* - * calc delta to compensate wrong samplerates - */ - - if (this->last_audio_pts && (pts>this->last_audio_pts)) { - int32_t vpts_diff; - - vpts_diff = vpts - this->audio_vpts; - - this->audio_pts_delta += vpts_diff*AUDIO_SAMPLE_NUM / (this->num_audio_samples_guessed); - - if (abs(this->audio_pts_delta) >= MAX_AUDIO_DELTA) - this->audio_pts_delta = 0; - } - } - - this->num_audio_samples_guessed = 0; - this->last_audio_pts = pts; - this->audio_vpts = vpts; + vpts = pts + this->vpts_offset; + this->audio_vpts = vpts; } else vpts = this->audio_vpts; - this->audio_vpts += nsamples * (this->audio_pts_delta + this->pts_per_smpls) / AUDIO_SAMPLE_NUM; - this->num_audio_samples_guessed += nsamples; + this->audio_vpts += nsamples * this->pts_per_smpls / AUDIO_SAMPLE_NUM; #ifdef LOG printf ("metronom: audio vpts for %10lld : %10lld\n", pts, vpts); @@ -734,6 +579,8 @@ metronom_t * metronom_init (int have_audio, void *xine) { 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->audio_stream_start = metronom_audio_stream_start; + this->video_stream_start = metronom_video_stream_start; this->expect_audio_discontinuity = metronom_expect_audio_discontinuity; this->expect_video_discontinuity = metronom_expect_video_discontinuity; this->set_av_offset = metronom_set_av_offset; @@ -759,47 +606,26 @@ metronom_t * metronom_init (int have_audio, void *xine) { printf ("metronom: cannot create sync thread (%s)\n", strerror(err)); - pthread_cond_init (&this->video_discontinuity_reached, NULL); - pthread_cond_init (&this->audio_discontinuity_reached, NULL); - - this->av_offset = 0; - + this->av_offset = 0; + this->in_discontinuity = 0; + this->vpts_offset = 0; + this->next_vpts_offset = 0; /* initialize video stuff */ - this->have_audio = have_audio; this->video_vpts = PREBUFFER_PTS_OFFSET; - - this->last_video_pts = 0; this->video_drift = 0; - - this->video_wrap_offset = PREBUFFER_PTS_OFFSET; - this->wrap_diff_counter = 0; - - this->video_discontinuity = 0; this->video_discontinuity_count = 0; + pthread_cond_init (&this->video_discontinuity_reached, NULL); /* initialize audio stuff */ + this->have_audio = have_audio; this->audio_vpts = PREBUFFER_PTS_OFFSET; - - this->audio_pts_delta = 0; - - this->num_audio_samples_guessed = 1; - this->last_audio_pts = 0; - - this->audio_wrap_offset = PREBUFFER_PTS_OFFSET; - this->wrap_diff_counter = 0; - - this->audio_discontinuity = 0; this->audio_discontinuity_count = 0; + pthread_cond_init (&this->audio_discontinuity_reached, NULL); + return this; } - - - - - - diff --git a/src/xine-engine/metronom.h b/src/xine-engine/metronom.h index dd0cd703d..5ad28dcb2 100644 --- a/src/xine-engine/metronom.h +++ b/src/xine-engine/metronom.h @@ -1,7 +1,7 @@ /* * Copyright (C) 2000-2002 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 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.20 2002/03/10 21:16:15 miguelfreitas Exp $ + * $Id: metronom.h,v 1.21 2002/03/11 12:31:26 guenter Exp $ * * metronom: general pts => virtual calculation/assoc * @@ -58,8 +58,7 @@ typedef struct scr_plugin_s scr_plugin_t; struct metronom_s { /* - * Pointer to current xine object. We use a void pointer to avoid type declaration clash. - * Ugly but working. + * pointer to current xine object. a void pointer is used to avoid type declaration clash. */ void *xine; @@ -90,7 +89,6 @@ struct metronom_s { * * 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 * @@ -100,21 +98,19 @@ struct metronom_s { */ int64_t (*got_audio_samples) (metronom_t *this, int64_t pts, - int nsamples, int64_t scr); + int nsamples); /* * 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 * (this is the only pts to vpts function that cannot update the wrap_offset * due to the lack of regularity on spu packets) */ - int64_t (*got_spu_packet) (metronom_t *this, int64_t pts, int64_t duration, - int64_t scr); + int64_t (*got_spu_packet) (metronom_t *this, int64_t pts, int64_t duration); /* * tell metronom about discontinuities. @@ -136,8 +132,11 @@ struct metronom_s { * whenever we get a new pts we can calculate the new xxx_wrap_offset) * */ - void (*expect_audio_discontinuity) (metronom_t *this); - void (*expect_video_discontinuity) (metronom_t *this, int starting); + void (*expect_audio_discontinuity) (metronom_t *this, int64_t disc_off); + void (*expect_video_discontinuity) (metronom_t *this, int64_t disc_off); + + void (*audio_stream_start) (metronom_t *this); + void (*video_stream_start) (metronom_t *this); /* * manually correct audio <-> video sync @@ -203,21 +202,16 @@ struct metronom_s { int64_t pts_per_smpls; - int64_t audio_pts_delta; - int64_t video_vpts; int64_t spu_vpts; int64_t audio_vpts; - int64_t video_wrap_offset; - int64_t audio_wrap_offset; - int wrap_diff_counter; + int64_t vpts_offset; + int64_t next_vpts_offset; - int64_t last_video_pts; - int64_t video_drift; + int in_discontinuity; - int64_t last_audio_pts; - int num_audio_samples_guessed; + int64_t video_drift; int64_t av_offset; @@ -228,10 +222,7 @@ struct metronom_s { pthread_mutex_t lock; int have_audio; - int video_starting; - 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; diff --git a/src/xine-engine/video_decoder.c b/src/xine-engine/video_decoder.c index d5b1f9d4c..cd8e14142 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.75 2002/03/10 21:16:14 miguelfreitas Exp $ + * $Id: video_decoder.c,v 1.76 2002/03/11 12:31:26 guenter Exp $ * */ @@ -106,7 +106,7 @@ void *video_decoder_loop (void *this_gen) { pthread_mutex_unlock (&this->finished_lock); - this->metronom->expect_video_discontinuity (this->metronom, 1); + this->metronom->video_stream_start (this->metronom); break; @@ -155,7 +155,7 @@ void *video_decoder_loop (void *this_gen) { pthread_mutex_lock (&this->finished_lock); this->spu_finished = 1; - if (!this->video_finished && (buf->decoder_info[0]==0)) { + if (!this->video_finished && (buf->decoder_flags==BUF_FLAG_END_STREAM)) { this->video_finished = 1; @@ -186,7 +186,7 @@ void *video_decoder_loop (void *this_gen) { this->video_in_discontinuity = 1; - this->metronom->expect_video_discontinuity (this->metronom, 0); + this->metronom->expect_video_discontinuity (this->metronom, buf->disc_off); this->video_in_discontinuity = 0; break; diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c index 1e8216a5f..691700e91 100644 --- a/src/xine-engine/xine.c +++ b/src/xine-engine/xine.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: xine.c,v 1.105 2002/03/01 09:29:50 guenter Exp $ + * $Id: xine.c,v 1.106 2002/03/11 12:31:26 guenter Exp $ * * top-level xine functions * @@ -892,6 +892,8 @@ void xine_log (xine_t *this, int buf, const char *format, ...) { this->log_buffers[buf]->scratch_printf (this->log_buffers[buf], format, argp); + vprintf (format, argp); + va_end (argp); } |