diff options
Diffstat (limited to 'src/demuxers/demux_film.c')
-rw-r--r-- | src/demuxers/demux_film.c | 512 |
1 files changed, 201 insertions, 311 deletions
diff --git a/src/demuxers/demux_film.c b/src/demuxers/demux_film.c index 7ad7b2063..4994cac8e 100644 --- a/src/demuxers/demux_film.c +++ b/src/demuxers/demux_film.c @@ -21,7 +21,7 @@ * For more information on the FILM file format, visit: * http://www.pcisys.net/~melanson/codecs/ * - * $Id: demux_film.c,v 1.40 2002/10/27 18:48:40 tmmm Exp $ + * $Id: demux_film.c,v 1.41 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> @@ -72,11 +70,6 @@ typedef struct { input_plugin_t *input; - pthread_t thread; - int thread_running; - pthread_mutex_t mutex; - int send_end_buffers; - off_t data_start; off_t data_size; int status; @@ -275,7 +268,7 @@ static int open_film_file(demux_film_t *film) { return 1; } -static void *demux_film_loop (void *this_gen) { +static int demux_film_send_chunk(demux_plugin_t *this_gen) { demux_film_t *this = (demux_film_t *) this_gen; buf_element_t *buf = NULL; @@ -285,254 +278,219 @@ static void *demux_film_loop (void *this_gen) { unsigned int remaining_sample_bytes; int64_t frame_duration; - pthread_mutex_lock( &this->mutex ); - - /* do-while needed to seek after demux finished */ - do { - /* main demuxer loop */ - while (this->status == DEMUX_OK) { + i = this->current_sample; - /* 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 ); + /* if there is an incongruency between last and current sample, it + * must be time to send a new pts */ + if (this->last_sample + 1 != this->current_sample) { + /* send new pts */ + xine_demux_control_newpts(this->stream, this->sample_table[i].pts, + (this->sample_table[i].pts) ? BUF_FLAG_SEEK : 0); + } - i = this->current_sample; + this->last_sample = this->current_sample; + this->current_sample++; - /* if there is an incongruency between last and current sample, it - * must be time to send a new pts */ - if (this->last_sample + 1 != this->current_sample) { - /* send new pts */ - xine_demux_control_newpts(this->stream, this->sample_table[i].pts, - (this->sample_table[i].pts) ? BUF_FLAG_SEEK : 0); - } + /* check if all the samples have been sent */ + if (i >= this->sample_count) { + this->status = DEMUX_FINISHED; + return this->status; + } - this->last_sample = this->current_sample; - this->current_sample++; + /* check if we're only sending audio samples until the next keyframe */ + if ((this->waiting_for_keyframe) && + (this->sample_table[i].syncinfo1 != 0xFFFFFFFF)) { + if ((this->sample_table[i].syncinfo1 & 0x80000000) == 0) { + this->waiting_for_keyframe = 0; + } else { + /* move on to the next sample */ + return this->status; + } + } - /* check if all the samples have been sent */ - if (i >= this->sample_count) { - this->status = DEMUX_FINISHED; + if ((this->sample_table[i].syncinfo1 != 0xFFFFFFFF) && + (this->video_type == BUF_VIDEO_CINEPAK)) { + /* do a special song and dance when loading CVID data */ + if (this->version[0]) + cvid_chunk_size = this->sample_table[i].sample_size - 2; + else + cvid_chunk_size = this->sample_table[i].sample_size - 6; + + /* reset flag */ + fixed_cvid_header = 0; + + remaining_sample_bytes = cvid_chunk_size; + this->input->seek(this->input, this->sample_table[i].sample_offset, + SEEK_SET); + + /* frame duration is the pts diff between this video frame and + * the next video frame (so search for the next video frame) */ + frame_duration = 0; + j = i; + while (++j < this->sample_count) { + if (this->sample_table[j].syncinfo1 != 0xFFFFFFFF) { + frame_duration = + this->sample_table[j].pts - this->sample_table[i].pts; break; } + } - /* check if we're only sending audio samples until the next keyframe */ - if ((this->waiting_for_keyframe) && - (this->sample_table[i].syncinfo1 != 0xFFFFFFFF)) { - if ((this->sample_table[i].syncinfo1 & 0x80000000) == 0) { - this->waiting_for_keyframe = 0; - } else { - /* move on to the next sample */ - continue; - } - } + while (remaining_sample_bytes) { + buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); + buf->type = this->video_type; + buf->input_pos = + this->sample_table[i].sample_offset - this->data_start; + buf->input_length = this->data_size; + buf->input_time = this->sample_table[i].pts / 90000; + buf->pts = this->sample_table[i].pts; + + /* set the frame duration */ + buf->decoder_flags |= BUF_FLAG_FRAMERATE; + buf->decoder_info[0] = frame_duration; + + if (remaining_sample_bytes > buf->max_size) + buf->size = buf->max_size; + else + buf->size = remaining_sample_bytes; + remaining_sample_bytes -= buf->size; - if ((this->sample_table[i].syncinfo1 != 0xFFFFFFFF) && - (this->video_type == BUF_VIDEO_CINEPAK)) { - /* do a special song and dance when loading CVID data */ - if (this->version[0]) - cvid_chunk_size = this->sample_table[i].sample_size - 2; - else - cvid_chunk_size = this->sample_table[i].sample_size - 6; - - /* reset flag */ - fixed_cvid_header = 0; - - remaining_sample_bytes = cvid_chunk_size; - this->input->seek(this->input, this->sample_table[i].sample_offset, - SEEK_SET); - - /* frame duration is the pts diff between this video frame and - * the next video frame (so search for the next video frame) */ - frame_duration = 0; - j = i; - while (++j < this->sample_count) { - if (this->sample_table[j].syncinfo1 != 0xFFFFFFFF) { - frame_duration = - this->sample_table[j].pts - this->sample_table[i].pts; - break; - } + if (!fixed_cvid_header) { + if (this->input->read(this->input, buf->content, 10) != 10) { + this->status = DEMUX_FINISHED; + break; } - while (remaining_sample_bytes) { - buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); - buf->type = this->video_type; - buf->input_pos = - this->sample_table[i].sample_offset - this->data_start; - buf->input_length = this->data_size; - buf->input_time = this->sample_table[i].pts / 90000; - buf->pts = this->sample_table[i].pts; - - /* set the frame duration */ - buf->decoder_flags |= BUF_FLAG_FRAMERATE; - buf->decoder_info[0] = frame_duration; - - if (remaining_sample_bytes > buf->max_size) - buf->size = buf->max_size; - else - buf->size = remaining_sample_bytes; - remaining_sample_bytes -= buf->size; - - if (!fixed_cvid_header) { - if (this->input->read(this->input, buf->content, 10) != 10) { - this->status = DEMUX_FINISHED; - break; - } - - /* skip over the extra non-spec CVID bytes */ - this->input->seek(this->input, - this->sample_table[i].sample_size - cvid_chunk_size, SEEK_CUR); - - /* load the rest of the chunk */ - if (this->input->read(this->input, buf->content + 10, - buf->size - 10) != buf->size - 10) { - this->status = DEMUX_FINISHED; - break; - } - - /* adjust the length in the CVID data chunk */ - buf->content[1] = (cvid_chunk_size >> 16) & 0xFF; - buf->content[2] = (cvid_chunk_size >> 8) & 0xFF; - buf->content[3] = (cvid_chunk_size >> 0) & 0xFF; - - fixed_cvid_header = 1; - } else { - if (this->input->read(this->input, buf->content, buf->size) != - buf->size) { - this->status = DEMUX_FINISHED; - break; - } - } - - if ((this->sample_table[i].syncinfo1 & 0x80000000) == 0) - buf->decoder_flags |= BUF_FLAG_KEYFRAME; - if (!remaining_sample_bytes) - buf->decoder_flags |= BUF_FLAG_FRAME_END; - this->video_fifo->put(this->video_fifo, buf); - } + /* skip over the extra non-spec CVID bytes */ + this->input->seek(this->input, + this->sample_table[i].sample_size - cvid_chunk_size, SEEK_CUR); - } else if (this->sample_table[i].syncinfo1 != 0xFFFFFFFF) { - - /* load a non-cvid video chunk */ - remaining_sample_bytes = this->sample_table[i].sample_size; - this->input->seek(this->input, this->sample_table[i].sample_offset, - SEEK_SET); - - /* frame duration is the pts diff between this video frame and - * the next video frame (so search for the next video frame) */ - frame_duration = 0; - j = i; - while (++j < this->sample_count) { - if (this->sample_table[j].syncinfo1 != 0xFFFFFFFF) { - frame_duration = - this->sample_table[j].pts - this->sample_table[i].pts; - break; - } + /* load the rest of the chunk */ + if (this->input->read(this->input, buf->content + 10, + buf->size - 10) != buf->size - 10) { + this->status = DEMUX_FINISHED; + break; } - while (remaining_sample_bytes) { - buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); - buf->type = this->video_type; - buf->input_pos = - this->sample_table[i].sample_offset - this->data_start; - buf->input_length = this->data_size; - buf->input_time = this->sample_table[i].pts / 90000; - buf->pts = this->sample_table[i].pts; - - /* set the frame duration */ - buf->decoder_flags |= BUF_FLAG_FRAMERATE; - buf->decoder_info[0] = frame_duration; - - if (remaining_sample_bytes > buf->max_size) - buf->size = buf->max_size; - else - buf->size = remaining_sample_bytes; - remaining_sample_bytes -= buf->size; - - if (this->input->read(this->input, buf->content, buf->size) != - buf->size) { - this->status = DEMUX_FINISHED; - break; - } - - if ((this->sample_table[i].syncinfo1 & 0x80000000) == 0) - buf->decoder_flags |= BUF_FLAG_KEYFRAME; - if (!remaining_sample_bytes) - buf->decoder_flags |= BUF_FLAG_FRAME_END; - this->video_fifo->put(this->video_fifo, buf); - } - } else if( this->audio_fifo ) { - /* load an audio sample and packetize it */ - remaining_sample_bytes = this->sample_table[i].sample_size; - this->input->seek(this->input, this->sample_table[i].sample_offset, - SEEK_SET); - - while (remaining_sample_bytes) { - buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); - buf->type = this->audio_type; - buf->input_pos = - this->sample_table[i].sample_offset - this->data_start; - buf->input_length = this->data_size; - buf->input_time = this->sample_table[i].pts / 90000; - buf->pts = this->sample_table[i].pts; - - if (remaining_sample_bytes > buf->max_size) - buf->size = buf->max_size; - else - buf->size = remaining_sample_bytes; - remaining_sample_bytes -= buf->size; - - if (this->input->read(this->input, buf->content, buf->size) != - buf->size) { - this->status = DEMUX_FINISHED; - break; - } - - if (this->video_type == BUF_VIDEO_SEGA) { - /* if the file uses the SEGA video codec, assume this is - * sign/magnitude audio */ - for (j = 0; j < buf->size; j++) - if (buf->content[j] < 0x80) - buf->content[j] += 0x80; - else - buf->content[j] = -(buf->content[j] & 0x7F) + 0x80; - } else if (this->audio_bits == 8) { - /* convert 8-bit data from signed -> unsigned */ - for (j = 0; j < buf->size; j++) - buf->content[j] += 0x80; - } - - if (!remaining_sample_bytes) - buf->decoder_flags |= BUF_FLAG_FRAME_END; - - this->audio_fifo->put(this->audio_fifo, buf); + /* adjust the length in the CVID data chunk */ + buf->content[1] = (cvid_chunk_size >> 16) & 0xFF; + buf->content[2] = (cvid_chunk_size >> 8) & 0xFF; + buf->content[3] = (cvid_chunk_size >> 0) & 0xFF; + + fixed_cvid_header = 1; + } else { + if (this->input->read(this->input, buf->content, buf->size) != + buf->size) { + this->status = DEMUX_FINISHED; + break; } } + + if ((this->sample_table[i].syncinfo1 & 0x80000000) == 0) + buf->decoder_flags |= BUF_FLAG_KEYFRAME; + if (!remaining_sample_bytes) + buf->decoder_flags |= BUF_FLAG_FRAME_END; + this->video_fifo->put(this->video_fifo, buf); } - /* 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 ); + } else if (this->sample_table[i].syncinfo1 != 0xFFFFFFFF) { + + /* load a non-cvid video chunk */ + remaining_sample_bytes = this->sample_table[i].sample_size; + this->input->seek(this->input, this->sample_table[i].sample_offset, + SEEK_SET); + + /* frame duration is the pts diff between this video frame and + * the next video frame (so search for the next video frame) */ + frame_duration = 0; + j = i; + while (++j < this->sample_count) { + if (this->sample_table[j].syncinfo1 != 0xFFFFFFFF) { + frame_duration = + this->sample_table[j].pts - this->sample_table[i].pts; + break; + } } - } while (this->status == DEMUX_OK); + while (remaining_sample_bytes) { + buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); + buf->type = this->video_type; + buf->input_pos = + this->sample_table[i].sample_offset - this->data_start; + buf->input_length = this->data_size; + buf->input_time = this->sample_table[i].pts / 90000; + buf->pts = this->sample_table[i].pts; + + /* set the frame duration */ + buf->decoder_flags |= BUF_FLAG_FRAMERATE; + buf->decoder_info[0] = frame_duration; + + if (remaining_sample_bytes > buf->max_size) + buf->size = buf->max_size; + else + buf->size = remaining_sample_bytes; + remaining_sample_bytes -= buf->size; - this->current_sample = this->last_sample = 0; + if (this->input->read(this->input, buf->content, buf->size) != + buf->size) { + this->status = DEMUX_FINISHED; + break; + } - this->status = DEMUX_FINISHED; + if ((this->sample_table[i].syncinfo1 & 0x80000000) == 0) + buf->decoder_flags |= BUF_FLAG_KEYFRAME; + if (!remaining_sample_bytes) + buf->decoder_flags |= BUF_FLAG_FRAME_END; + this->video_fifo->put(this->video_fifo, buf); + } + } else if( this->audio_fifo ) { + /* load an audio sample and packetize it */ + remaining_sample_bytes = this->sample_table[i].sample_size; + this->input->seek(this->input, this->sample_table[i].sample_offset, + SEEK_SET); + + while (remaining_sample_bytes) { + buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + buf->type = this->audio_type; + buf->input_pos = + this->sample_table[i].sample_offset - this->data_start; + buf->input_length = this->data_size; + buf->input_time = this->sample_table[i].pts / 90000; + buf->pts = this->sample_table[i].pts; + + if (remaining_sample_bytes > buf->max_size) + buf->size = buf->max_size; + else + buf->size = remaining_sample_bytes; + remaining_sample_bytes -= buf->size; - if (this->send_end_buffers) { - xine_demux_control_end(this->stream, BUF_FLAG_END_STREAM); - } + if (this->input->read(this->input, buf->content, buf->size) != + buf->size) { + this->status = DEMUX_FINISHED; + break; + } - this->thread_running = 0; - pthread_mutex_unlock( &this->mutex ); + if (this->video_type == BUF_VIDEO_SEGA) { + /* if the file uses the SEGA video codec, assume this is + * sign/magnitude audio */ + for (j = 0; j < buf->size; j++) + if (buf->content[j] < 0x80) + buf->content[j] += 0x80; + else + buf->content[j] = -(buf->content[j] & 0x7F) + 0x80; + } else if (this->audio_bits == 8) { + /* convert 8-bit data from signed -> unsigned */ + for (j = 0; j < buf->size; j++) + buf->content[j] += 0x80; + } - return NULL; + if (!remaining_sample_bytes) + buf->decoder_flags |= BUF_FLAG_FRAME_END; + + this->audio_fifo->put(this->audio_fifo, buf); + } + } + + return this->status; } static void demux_film_send_headers(demux_plugin_t *this_gen) { @@ -540,8 +498,6 @@ static void demux_film_send_headers(demux_plugin_t *this_gen) { demux_film_t *this = (demux_film_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; @@ -588,42 +544,6 @@ static void demux_film_send_headers(demux_plugin_t *this_gen) { } xine_demux_control_headers_done (this->stream); - - pthread_mutex_unlock (&this->mutex); -} - -static int demux_film_seek (demux_plugin_t *this_gen, - off_t start_pos, int start_time); - -static int demux_film_start (demux_plugin_t *this_gen, - off_t start_pos, int start_time) { - - demux_film_t *this = (demux_film_t *) this_gen; - int err; - - demux_film_seek(this_gen, start_pos, start_time); - - pthread_mutex_lock(&this->mutex); - - /* if thread is not running, initialize demuxer */ - if (!this->thread_running) { - - this->status = DEMUX_OK; - this->send_end_buffers = 1; - this->thread_running = 1; - this->waiting_for_keyframe = 0; - - this->last_sample = 0; - - if ((err = pthread_create (&this->thread, NULL, demux_film_loop, this)) != 0) { - printf ("demux_film: can't create new thread (%s)\n", strerror(err)); - abort(); - } - } - - pthread_mutex_unlock(&this->mutex); - - return DEMUX_OK; } static int demux_film_seek (demux_plugin_t *this_gen, @@ -633,9 +553,6 @@ static int demux_film_seek (demux_plugin_t *this_gen, int left, middle, right; int found; int64_t keyframe_pts; - int status; - - pthread_mutex_lock( &this->mutex ); this->waiting_for_keyframe = 0; @@ -644,9 +561,8 @@ static int demux_film_seek (demux_plugin_t *this_gen, if (start_pos <= 0) best_index = 0; else if (start_pos >= this->data_size) { - status = this->status = DEMUX_FINISHED; - pthread_mutex_unlock( &this->mutex ); - return status; + this->status = DEMUX_FINISHED; + return this->status; } else { start_pos += this->data_start; left = 0; @@ -691,45 +607,21 @@ static int demux_film_seek (demux_plugin_t *this_gen, } this->current_sample = best_index; - status = this->status = DEMUX_OK; + this->status = DEMUX_OK; xine_demux_flush_engine(this->stream); - pthread_mutex_unlock( &this->mutex ); - - return status; -} - -static void demux_film_stop (demux_plugin_t *this_gen) { - - demux_film_t *this = (demux_film_t *) this_gen; - void *p; - - pthread_mutex_lock( &this->mutex ); + + if( !this->stream->demux_thread_running ) { + this->waiting_for_keyframe = 0; - if (!this->thread_running) { - pthread_mutex_unlock( &this->mutex ); - return; + this->last_sample = 0; } - - this->send_end_buffers = 0; - this->status = DEMUX_FINISHED; - - pthread_mutex_unlock( &this->mutex ); - pthread_join (this->thread, &p); - - this->current_sample = this->last_sample = 0; - - xine_demux_flush_engine(this->stream); - - xine_demux_control_end(this->stream, BUF_FLAG_END_USER); + + return this->status; } static void demux_film_dispose (demux_plugin_t *this_gen) { demux_film_t *this = (demux_film_t *) this_gen; - demux_film_stop(this_gen); - - pthread_mutex_destroy (&this->mutex); - if (this->sample_table) free(this->sample_table); free(this); @@ -763,16 +655,14 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str this->input = input; this->demux_plugin.send_headers = demux_film_send_headers; - this->demux_plugin.start = demux_film_start; + this->demux_plugin.send_chunk = demux_film_send_chunk; this->demux_plugin.seek = demux_film_seek; - this->demux_plugin.stop = demux_film_stop; this->demux_plugin.dispose = demux_film_dispose; this->demux_plugin.get_status = demux_film_get_status; this->demux_plugin.get_stream_length = demux_film_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) { @@ -897,6 +787,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, "film", XINE_VERSION_CODE, NULL, init_plugin }, + { PLUGIN_DEMUX, 15, "film", XINE_VERSION_CODE, NULL, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; |