diff options
Diffstat (limited to 'src/demuxers/demux_roq.c')
-rw-r--r-- | src/demuxers/demux_roq.c | 309 |
1 files changed, 108 insertions, 201 deletions
diff --git a/src/demuxers/demux_roq.c b/src/demuxers/demux_roq.c index 381da363d..fc7212a8f 100644 --- a/src/demuxers/demux_roq.c +++ b/src/demuxers/demux_roq.c @@ -21,7 +21,7 @@ * For more information regarding the RoQ file format, visit: * http://www.csse.monash.edu.au/~timf/ * - * $Id: demux_roq.c,v 1.25 2002/10/27 16:14:28 tmmm Exp $ + * $Id: demux_roq.c,v 1.26 2002/10/28 03:24:43 miguelfreitas Exp $ */ #ifdef HAVE_CONFIG_H @@ -31,8 +31,6 @@ #include <stdio.h> #include <fcntl.h> #include <unistd.h> -#include <pthread.h> -#include <sched.h> #include <string.h> #include <stdlib.h> @@ -65,11 +63,6 @@ typedef struct { input_plugin_t *input; - pthread_t thread; - int thread_running; - pthread_mutex_t mutex; - int send_end_buffers; - off_t start; int status; @@ -178,7 +171,7 @@ static int open_roq_file(demux_roq_t *this) { return 1; } -static void *demux_roq_loop (void *this_gen) { +static int demux_roq_send_chunk(demux_plugin_t *this_gen) { demux_roq_t *this = (demux_roq_t *) this_gen; buf_element_t *buf = NULL; @@ -190,154 +183,116 @@ static void *demux_roq_loop (void *this_gen) { unsigned int audio_byte_count = 0; off_t current_file_pos; - pthread_mutex_lock( &this->mutex ); + /* fetch the next preamble */ + if (this->input->read(this->input, preamble, RoQ_CHUNK_PREAMBLE_SIZE) != + RoQ_CHUNK_PREAMBLE_SIZE) { + this->status = DEMUX_FINISHED; + return this->status; + } + chunk_type = LE_16(&preamble[0]); + chunk_size = LE_32(&preamble[2]); + + /* if the chunk is an audio chunk, route it to the audio fifo */ + if ((chunk_type == RoQ_SOUND_MONO) || (chunk_type == RoQ_SOUND_STEREO)) { + /* rewind over the preamble */ + this->input->seek(this->input, -RoQ_CHUNK_PREAMBLE_SIZE, SEEK_CUR); - /* start after the signature chunk */ - this->input->seek(this->input, RoQ_CHUNK_PREAMBLE_SIZE, SEEK_SET); + /* adjust the chunk size */ + chunk_size += RoQ_CHUNK_PREAMBLE_SIZE; - /* do-while needed to seek after demux finished */ - do { - /* main demuxer loop */ - while (this->status == DEMUX_OK) { + if( this->audio_fifo ) { + + /* do this calculation carefully because I can't trust the + * 64-bit numerical manipulation */ + audio_pts = audio_byte_count; + audio_pts *= 90000; + audio_pts /= (RoQ_AUDIO_SAMPLE_RATE * this->audio_channels); + audio_byte_count += chunk_size - 8; /* do not count the preamble */ + + current_file_pos = this->input->get_current_pos(this->input); + + /* packetize the audio */ + while (chunk_size) { + buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + buf->type = BUF_AUDIO_ROQ; + buf->input_pos = current_file_pos; + buf->pts = audio_pts; + + if (chunk_size > buf->max_size) + buf->size = buf->max_size; + else + buf->size = chunk_size; + chunk_size -= buf->size; + + if (this->input->read(this->input, buf->content, buf->size) != + buf->size) { + this->status = DEMUX_FINISHED; + break; + } - /* fetch the next preamble */ + if (!chunk_size) + buf->decoder_flags |= BUF_FLAG_FRAME_END; + this->audio_fifo->put(this->audio_fifo, buf); + } + } else { + /* no audio -> skip chunk */ + this->input->seek(this->input, chunk_size, SEEK_CUR); + } + } else if (chunk_type == RoQ_INFO) { + /* skip 8 bytes */ + this->input->seek(this->input, 8, SEEK_CUR); + } else if ((chunk_type == RoQ_QUAD_CODEBOOK) || + (chunk_type == RoQ_QUAD_VQ)) { + + current_file_pos = this->input->get_current_pos(this->input) - + RoQ_CHUNK_PREAMBLE_SIZE; + + /* if the chunk is video, check if it is a codebook */ + if (chunk_type == RoQ_QUAD_CODEBOOK) { + /* if it is, figure in the size of the next VQ chunk, too */ + this->input->seek(this->input, chunk_size, SEEK_CUR); if (this->input->read(this->input, preamble, RoQ_CHUNK_PREAMBLE_SIZE) != RoQ_CHUNK_PREAMBLE_SIZE) { this->status = DEMUX_FINISHED; - break; + return this->status; } - chunk_type = LE_16(&preamble[0]); - chunk_size = LE_32(&preamble[2]); - /* if the chunk is an audio chunk, route it to the audio fifo */ - if ((chunk_type == RoQ_SOUND_MONO) || (chunk_type == RoQ_SOUND_STEREO)) { - /* rewind over the preamble */ - this->input->seek(this->input, -RoQ_CHUNK_PREAMBLE_SIZE, SEEK_CUR); + /* rewind to the start of the codebook chunk */ + this->input->seek(this->input, current_file_pos, SEEK_SET); - /* adjust the chunk size */ - chunk_size += RoQ_CHUNK_PREAMBLE_SIZE; - - if( this->audio_fifo ) { - - /* do this calculation carefully because I can't trust the - * 64-bit numerical manipulation */ - audio_pts = audio_byte_count; - audio_pts *= 90000; - audio_pts /= (RoQ_AUDIO_SAMPLE_RATE * this->audio_channels); - audio_byte_count += chunk_size - 8; /* do not count the preamble */ - - current_file_pos = this->input->get_current_pos(this->input); - - /* packetize the audio */ - while (chunk_size) { - buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); - buf->type = BUF_AUDIO_ROQ; - buf->input_pos = current_file_pos; - buf->pts = audio_pts; - - if (chunk_size > buf->max_size) - buf->size = buf->max_size; - else - buf->size = chunk_size; - chunk_size -= buf->size; - - if (this->input->read(this->input, buf->content, buf->size) != - buf->size) { - this->status = DEMUX_FINISHED; - break; - } - - if (!chunk_size) - buf->decoder_flags |= BUF_FLAG_FRAME_END; - this->audio_fifo->put(this->audio_fifo, buf); - } - } else { - /* no audio -> skip chunk */ - this->input->seek(this->input, chunk_size, SEEK_CUR); - } - } else if (chunk_type == RoQ_INFO) { - /* skip 8 bytes */ - this->input->seek(this->input, 8, SEEK_CUR); - } else if ((chunk_type == RoQ_QUAD_CODEBOOK) || - (chunk_type == RoQ_QUAD_VQ)) { - - current_file_pos = this->input->get_current_pos(this->input) - - RoQ_CHUNK_PREAMBLE_SIZE; - - /* if the chunk is video, check if it is a codebook */ - if (chunk_type == RoQ_QUAD_CODEBOOK) { - /* if it is, figure in the size of the next VQ chunk, too */ - this->input->seek(this->input, chunk_size, SEEK_CUR); - if (this->input->read(this->input, preamble, RoQ_CHUNK_PREAMBLE_SIZE) != - RoQ_CHUNK_PREAMBLE_SIZE) { - this->status = DEMUX_FINISHED; - break; - } - - /* rewind to the start of the codebook chunk */ - this->input->seek(this->input, current_file_pos, SEEK_SET); - - /* figure out the total video chunk size */ - chunk_size += (2 * RoQ_CHUNK_PREAMBLE_SIZE) + LE_32(&preamble[2]); - } + /* figure out the total video chunk size */ + chunk_size += (2 * RoQ_CHUNK_PREAMBLE_SIZE) + LE_32(&preamble[2]); + } - /* packetize the video chunk and route it to the video fifo */ - while (chunk_size) { - buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); - buf->type = BUF_VIDEO_ROQ; - buf->input_pos = current_file_pos; - buf->pts = video_pts_counter; - - if (chunk_size > buf->max_size) - buf->size = buf->max_size; - else - buf->size = chunk_size; - chunk_size -= buf->size; - - if (this->input->read(this->input, buf->content, buf->size) != - buf->size) { - this->status = DEMUX_FINISHED; - break; - } - - if (!chunk_size) - buf->decoder_flags |= BUF_FLAG_FRAME_END; - this->video_fifo->put(this->video_fifo, buf); - } - video_pts_counter += this->frame_pts_inc; - } else { - printf ("demux_roq: encountered bad chunk type: %d\n", chunk_type); + /* packetize the video chunk and route it to the video fifo */ + while (chunk_size) { + buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); + buf->type = BUF_VIDEO_ROQ; + buf->input_pos = current_file_pos; + buf->pts = video_pts_counter; + + if (chunk_size > buf->max_size) + buf->size = buf->max_size; + else + buf->size = chunk_size; + chunk_size -= buf->size; + + if (this->input->read(this->input, buf->content, buf->size) != + buf->size) { + this->status = DEMUX_FINISHED; + break; } - /* someone may want to interrupt us */ - pthread_mutex_unlock(&this->mutex); - /* give demux_*_stop a chance to interrupt us */ - sched_yield(); - pthread_mutex_lock(&this->mutex); - } - - /* wait before sending end buffers: user might want to do a new seek */ - while(this->send_end_buffers && this->video_fifo->size(this->video_fifo) && - this->status != DEMUX_OK){ - pthread_mutex_unlock( &this->mutex ); - xine_usec_sleep(100000); - pthread_mutex_lock( &this->mutex ); + if (!chunk_size) + buf->decoder_flags |= BUF_FLAG_FRAME_END; + this->video_fifo->put(this->video_fifo, buf); } - } while (this->status == DEMUX_OK); - - printf ("demux_roq: demux loop finished (status: %d)\n", - this->status); - - this->status = DEMUX_FINISHED; - - if (this->send_end_buffers) { - xine_demux_control_end(this->stream, BUF_FLAG_END_STREAM); + video_pts_counter += this->frame_pts_inc; + } else { + printf ("demux_roq: encountered bad chunk type: %d\n", chunk_type); } - this->thread_running = 0; - pthread_mutex_unlock( &this->mutex ); - - return NULL; + return this->status; } static void demux_roq_send_headers(demux_plugin_t *this_gen) { @@ -345,8 +300,6 @@ static void demux_roq_send_headers(demux_plugin_t *this_gen) { demux_roq_t *this = (demux_roq_t *) this_gen; buf_element_t *buf; - pthread_mutex_lock(&this->mutex); - this->video_fifo = this->stream->video_fifo; this->audio_fifo = this->stream->audio_fifo; @@ -394,76 +347,32 @@ static void demux_roq_send_headers(demux_plugin_t *this_gen) { } xine_demux_control_headers_done (this->stream); - - pthread_mutex_unlock (&this->mutex); } -static int demux_roq_start (demux_plugin_t *this_gen, +static int demux_roq_seek (demux_plugin_t *this_gen, off_t start_pos, int start_time) { demux_roq_t *this = (demux_roq_t *) this_gen; - int err; - - pthread_mutex_lock(&this->mutex); /* if thread is not running, initialize demuxer */ - if (!this->thread_running) { + if( !this->stream->demux_thread_running ) { /* send new pts */ xine_demux_control_newpts(this->stream, 0, 0); this->status = DEMUX_OK; - this->send_end_buffers = 1; - this->thread_running = 1; - - if ((err = pthread_create (&this->thread, NULL, demux_roq_loop, this)) != 0) { - printf ("demux_roq: can't create new thread (%s)\n", strerror(err)); - abort(); - } - + + /* start after the signature chunk */ + this->input->seek(this->input, RoQ_CHUNK_PREAMBLE_SIZE, SEEK_SET); + this->status = DEMUX_OK; } - - pthread_mutex_unlock(&this->mutex); - - return DEMUX_OK; -} - -static int demux_roq_seek (demux_plugin_t *this_gen, - off_t start_pos, int start_time) { - - /* RoQ files are not meant to be seekable; don't even bother */ - - return 0; -} - -static void demux_roq_stop (demux_plugin_t *this_gen) { - - demux_roq_t *this = (demux_roq_t *) this_gen; - void *p; - - pthread_mutex_lock( &this->mutex ); - - if (!this->thread_running) { - pthread_mutex_unlock( &this->mutex ); - return; - } - - this->send_end_buffers = 0; - this->status = DEMUX_FINISHED; - - pthread_mutex_unlock( &this->mutex ); - pthread_join (this->thread, &p); - - xine_demux_flush_engine(this->stream); - - xine_demux_control_end(this->stream, BUF_FLAG_END_USER); + + return this->status; } static void demux_roq_dispose (demux_plugin_t *this) { - demux_roq_stop(this); - free(this); } @@ -495,17 +404,15 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str this->input = input; this->demux_plugin.send_headers = demux_roq_send_headers; - this->demux_plugin.start = demux_roq_start; + this->demux_plugin.send_chunk = demux_roq_send_chunk; this->demux_plugin.seek = demux_roq_seek; - this->demux_plugin.stop = demux_roq_stop; this->demux_plugin.dispose = demux_roq_dispose; this->demux_plugin.get_status = demux_roq_get_status; this->demux_plugin.get_stream_length = demux_roq_get_stream_length; this->demux_plugin.demux_class = class_gen; this->status = DEMUX_FINISHED; - pthread_mutex_init (&this->mutex, NULL); - + switch (stream->content_detection_method) { case METHOD_BY_CONTENT: @@ -635,6 +542,6 @@ static void *init_plugin (xine_t *xine, void *data) { plugin_info_t xine_plugin_info[] = { /* type, API, "name", version, special_info, init_function */ - { PLUGIN_DEMUX, 14, "roq", XINE_VERSION_CODE, NULL, init_plugin }, + { PLUGIN_DEMUX, 15, "roq", XINE_VERSION_CODE, NULL, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; |