diff options
author | James Stembridge <jstembridge@users.sourceforge.net> | 2003-07-19 16:11:39 +0000 |
---|---|---|
committer | James Stembridge <jstembridge@users.sourceforge.net> | 2003-07-19 16:11:39 +0000 |
commit | cd36313e5d9ce2a46deecff304d4709c0f18ee5f (patch) | |
tree | 3b9d1dec5cead7a3465fdb3cf721e9b6b3587627 | |
parent | f8efba7eed3bf478b8b47bbf644482a0a097350f (diff) | |
download | xine-lib-cd36313e5d9ce2a46deecff304d4709c0f18ee5f.tar.gz xine-lib-cd36313e5d9ce2a46deecff304d4709c0f18ee5f.tar.bz2 |
1) more reliable method of detecting the end of the file
2) support files containing multiple audio/video streams
CVS patchset: 5190
CVS date: 2003/07/19 16:11:39
-rw-r--r-- | src/demuxers/demux_real.c | 120 |
1 files changed, 86 insertions, 34 deletions
diff --git a/src/demuxers/demux_real.c b/src/demuxers/demux_real.c index cdaab8e78..4a618aa4e 100644 --- a/src/demuxers/demux_real.c +++ b/src/demuxers/demux_real.c @@ -30,7 +30,7 @@ * * Based on FFmpeg's libav/rm.c. * - * $Id: demux_real.c,v 1.61 2003/07/18 23:34:36 jstembridge Exp $ + * $Id: demux_real.c,v 1.62 2003/07/19 16:11:39 jstembridge Exp $ */ #ifdef HAVE_CONFIG_H @@ -130,8 +130,6 @@ typedef struct { off_t data_start; off_t data_size; unsigned int duration; - unsigned int packet_count; - unsigned int current_packet; real_stream_t video_streams[MAX_VIDEO_STREAMS]; int num_video_streams; @@ -328,7 +326,6 @@ static void real_parse_headers (demux_real_t *this) { this->data_start = 0; this->data_size = 0; - this->current_packet = 0; this->num_video_streams = 0; this->num_audio_streams = 0; @@ -383,13 +380,11 @@ static void real_parse_headers (demux_real_t *this) { if (chunk_type == PROP_TAG) { - this->packet_count = BE_32(&chunk_buffer[18]); this->duration = BE_32(&chunk_buffer[22]); this->index_start = BE_32(&chunk_buffer[30]); this->data_start = BE_32(&chunk_buffer[34]); this->avg_bitrate = BE_32(&chunk_buffer[6]); - lprintf("PROP: packet count: %d\n", this->packet_count); lprintf("PROP: duration: %d ms\n", this->duration); lprintf("PROP: index start: %llX\n", this->index_start); lprintf("PROP: data start: %llX\n", this->data_start); @@ -543,31 +538,89 @@ unknown: } /* Read index tables */ - if((this->input->get_capabilities (this->input) & INPUT_CAP_SEEKABLE) != 0) + if(INPUT_IS_SEEKABLE(this->input)) real_parse_index(this); - /* Select audio and video stream to play */ + /* Simple stream selection case - 0/1 audio/video streams */ if(this->num_video_streams == 1) this->video_stream = &this->video_streams[0]; - else if(this->num_video_streams) { - /* FIXME: Determine which stream to play */ - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, - "multiple video streams not supported\n"); - this->status = DEMUX_FINISHED; - return; - } else + else this->video_stream = NULL; - + if(this->num_audio_streams == 1) this->audio_stream = &this->audio_streams[0]; - else if(this->num_audio_streams) { - /* FIXME: Determine which stream to play */ - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, - "multiple audio streams not supported\n"); - this->status = DEMUX_FINISHED; - return; - } else - this->audio_stream = NULL; + else + this->audio_stream = NULL; + + /* In the case of multiple audio/video streams select the first + streams found in the file */ + if((this->num_video_streams > 1) || (this->num_audio_streams > 1)) { + int len, offset; + off_t original_pos = 0; + char search_buffer[MAX_PREVIEW_SIZE]; + + /* Get data to search through for stream chunks */ + if(INPUT_IS_SEEKABLE(this->input)) { + original_pos = this->input->get_current_pos(this->input); + + if((len = this->input->read(this->input, search_buffer, MAX_PREVIEW_SIZE)) <= 0) { + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + "failed to read header\n"); + this->status = DEMUX_FINISHED; + return; + } + + offset = 0; + } else if((this->input->get_capabilities(this->input) & INPUT_CAP_PREVIEW) != 0) { + if((len = this->input->get_optional_data(this->input, search_buffer, INPUT_OPTIONAL_DATA_PREVIEW)) <= 0) { + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + "failed to read header\n"); + this->status = DEMUX_FINISHED; + return; + } + + /* Preview data starts at the beginning of the file */ + offset = this->data_start + 18; + } else { + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + "unable to search for correct stream\n"); + this->status = DEMUX_FINISHED; + return; + } + + while((offset < len) && + ((!this->video_stream && (this->num_video_streams > 0)) || + (!this->audio_stream && (this->num_audio_streams > 0)))) { + uint32_t id; + int i, stream; + + /* Check for end of the data chunk */ + if(((id = BE_32(&search_buffer[0])) == DATA_TAG) || + (id == INDX_TAG)) + break; + + stream = BE_16(&search_buffer[offset + 4]); + + for(i = 0; !this->video_stream && (i < this->num_video_streams); i++) { + if(stream == this->video_streams[i].mdpr->stream_number) { + this->video_stream = &this->video_streams[i]; + lprintf("selecting video stream: %d\n", stream); + } + } + + for(i = 0; !this->audio_stream && (i < this->num_audio_streams); i++) { + if(stream == this->audio_streams[i].mdpr->stream_number) { + this->audio_stream = &this->audio_streams[i]; + lprintf("selecting audio stream: %d\n", stream); + } + } + + offset += BE_16(&search_buffer[offset + 2]); + } + + if(INPUT_IS_SEEKABLE(this->input)) + this->input->seek(this->input, original_pos, SEEK_SET); + } /* Send headers and set meta info */ if(this->video_stream) { @@ -761,7 +814,7 @@ static int demux_real_send_chunk(demux_plugin_t *this_gen) { demux_real_t *this = (demux_real_t *) this_gen; char header[DATA_PACKET_HEADER_SIZE]; int stream, size, keyframe; - uint32_t timestamp; + uint32_t id, timestamp; int64_t pts; off_t offset; @@ -779,6 +832,14 @@ static int demux_real_send_chunk(demux_plugin_t *this_gen) { return this->status; } + /* Check to see if we've gone past the end of the data chunk */ + if(((id = BE_32(&header[0])) == DATA_TAG) || + (id == INDX_TAG)) { + lprintf("finished reading data chunk\n"); + this->status = DEMUX_FINISHED; + return this->status; + } + /* read the packet information */ stream = BE_16(&header[4]); offset = this->input->get_current_pos(this->input); @@ -989,12 +1050,6 @@ discard: } - if(this->packet_count && (this->current_packet == (this->packet_count - 1))) { - lprintf("read all packets\n"); - this->status = DEMUX_FINISHED; - } else - this->current_packet++; - #if 0 this->current_data_chunk_packet_count--; @@ -1112,9 +1167,6 @@ static int demux_real_seek (demux_plugin_t *this_gen, this->input->seek(this->input, index[i].offset, SEEK_SET); - /* is packet number global or is it local to current data chunk? */ - this->current_packet = index[i].packetno; - if(this->stream->demux_thread_running) { this->buf_flag_seek = 1; xine_demux_flush_engine(this->stream); |