diff options
author | Mike Melanson <mike@multimedia.cx> | 2002-09-30 01:16:15 +0000 |
---|---|---|
committer | Mike Melanson <mike@multimedia.cx> | 2002-09-30 01:16:15 +0000 |
commit | 6ab806af7e98df9e520773e4d6612c329f8cc285 (patch) | |
tree | 9014050e40eb826fa0fd89f89a1df7232d0d1ccd /src | |
parent | ecd49b8ecd304b060062cb032ead1058fd4d3c03 (diff) | |
download | xine-lib-6ab806af7e98df9e520773e4d6612c329f8cc285.tar.gz xine-lib-6ab806af7e98df9e520773e4d6612c329f8cc285.tar.bz2 |
implemented proper frame duration calculation, fixed temporal position
reporting, and modified demuxer to be able to seek on start
CVS patchset: 2761
CVS date: 2002/09/30 01:16:15
Diffstat (limited to 'src')
-rw-r--r-- | src/demuxers/demux_qt.c | 97 |
1 files changed, 60 insertions, 37 deletions
diff --git a/src/demuxers/demux_qt.c b/src/demuxers/demux_qt.c index b03c2ab03..9d222568c 100644 --- a/src/demuxers/demux_qt.c +++ b/src/demuxers/demux_qt.c @@ -30,7 +30,7 @@ * build_frame_table * free_qt_info * - * $Id: demux_qt.c,v 1.88 2002/09/28 17:13:16 tmmm Exp $ + * $Id: demux_qt.c,v 1.89 2002/09/30 01:16:15 tmmm Exp $ * */ @@ -231,7 +231,6 @@ typedef struct { unsigned int modification_time; unsigned int timescale; /* base clock frequency is Hz */ unsigned int duration; - off_t input_length; int64_t moov_first_offset; int64_t moov_last_offset; @@ -293,6 +292,9 @@ typedef struct { unsigned int current_frame; unsigned int last_frame; + off_t data_start; + off_t data_size; + } demux_qt_t; /********************************************************************** @@ -371,7 +373,6 @@ qt_info *create_qt_info(void) { info->modification_time = 0; info->timescale = 0; info->duration = 0; - info->input_length = 0; info->audio_codec = 0; info->audio_sample_rate = 0; @@ -1033,11 +1034,11 @@ static qt_error build_frame_table(qt_sample_table *sample_table, /* if this is the last edit list entry, don't let the duration * expire (so set it to an absurdly large value) */ if (edit_list_index == sample_table->edit_list_count) - edit_list_duration = 0xFFFFFFFF; + edit_list_duration = 0xFFFFFFFFFFFF; //printf ("edit list table exists, initial = %d, %lld\n", edit_list_media_time, edit_list_duration); } else { edit_list_media_time = 0; - edit_list_duration = 0xFFFFFFFF; + edit_list_duration = 0xFFFFFFFFFFFF; //printf ("no edit list table, initial = %d, %lld\n", edit_list_media_time, edit_list_duration); } @@ -1047,11 +1048,10 @@ static qt_error build_frame_table(qt_sample_table *sample_table, //printf ("%d: (before) pts = %lld...", i, sample_table->frames[i].pts); - if (sample_table->frames[i].pts < edit_list_media_time) + if (sample_table->frames[i].pts < edit_list_media_time) sample_table->frames[i].pts = edit_list_pts_counter; else { - /* this is not strictly correct but seems to work well enough */ - if (i < sample_table->frame_count) + if (i < sample_table->frame_count - 1) frame_duration = (sample_table->frames[i + 1].pts - sample_table->frames[i].pts); @@ -1081,11 +1081,11 @@ static qt_error build_frame_table(qt_sample_table *sample_table, /* if this is the last edit list entry, don't let the duration * expire (so set it to an absurdly large value) */ if (edit_list_index == sample_table->edit_list_count) - edit_list_duration = 0xFFFFFFFF; + edit_list_duration = 0xFFFFFFFFFFFF; //printf ("edit list table exists: %d, %lld\n", edit_list_media_time, edit_list_duration); } else { edit_list_media_time = 0; - edit_list_duration = 0xFFFFFFFF; + edit_list_duration = 0xFFFFFFFFFFFF; //printf ("no edit list table (or expired): %d, %lld\n", edit_list_media_time, edit_list_duration); } } @@ -1347,8 +1347,6 @@ static qt_error open_qt_file(qt_info *info, input_plugin_t *input) { return info->last_error; } - info->input_length = input->get_length (input); - /* traverse through the file looking for the moov atom */ info->moov_first_offset = -1; @@ -1471,8 +1469,7 @@ static void *demux_qt_loop (void *this_gen) { demux_qt_t *this = (demux_qt_t *) this_gen; buf_element_t *buf = NULL; - int64_t last_frame_pts = 0; - unsigned int i; + unsigned int i, j; unsigned int remaining_sample_bytes; int edit_list_compensation = 0; int frame_duration; @@ -1495,9 +1492,6 @@ static void *demux_qt_loop (void *this_gen) { if (this->last_frame + 1 != this->current_frame) { /* send new pts */ xine_demux_control_newpts(this->xine, this->qt->frames[i].pts, BUF_FLAG_SEEK); - - /* reset last_frame_pts on seek */ - last_frame_pts = 0; } this->last_frame = this->current_frame; @@ -1525,11 +1519,22 @@ static void *demux_qt_loop (void *this_gen) { this->input->seek(this->input, this->qt->frames[i].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->qt->frame_count) { + if (this->qt->frames[j].type == MEDIA_VIDEO) { + frame_duration = + this->qt->frames[j].pts - this->qt->frames[i].pts; + break; + } + } + /* Due to the edit lists, some successive frames have the same pts * which would ordinarily cause frame_duration to be 0 which can * cause DIV-by-0 errors in the engine. Perform this little trick * to compensate. */ - frame_duration = this->qt->frames[i].pts - last_frame_pts; if (!frame_duration) { frame_duration = 1; edit_list_compensation++; @@ -1538,18 +1543,24 @@ static void *demux_qt_loop (void *this_gen) { edit_list_compensation = 0; } +/* +printf ("hey %d) video frame, size %d, pts %lld, duration %d\n", + i, + this->qt->frames[i].size, + this->qt->frames[i].pts, + frame_duration); +*/ + while (remaining_sample_bytes) { buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = this->qt->video_type; - buf->input_pos = this->qt->frames[i].offset; - buf->input_length = this->qt->input_length; + buf->input_pos = this->qt->frames[i].offset - this->data_start; + buf->input_length = this->data_size; buf->input_time = this->qt->frames[i].pts / 90000; buf->pts = this->qt->frames[i].pts; - if (last_frame_pts) { - buf->decoder_flags |= BUF_FLAG_FRAMERATE; - buf->decoder_info[0] = 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; @@ -1571,7 +1582,7 @@ static void *demux_qt_loop (void *this_gen) { this->video_fifo->put(this->video_fifo, buf); } - last_frame_pts = buf->pts; + } else if ((this->qt->frames[i].type == MEDIA_AUDIO) && this->audio_fifo && this->qt->audio_type) { /* load an audio sample and packetize it */ @@ -1579,11 +1590,18 @@ static void *demux_qt_loop (void *this_gen) { this->input->seek(this->input, this->qt->frames[i].offset, SEEK_SET); +/* +printf ("you %d) audio frame, size %d, pts %lld\n", + i, + this->qt->frames[i].size, + this->qt->frames[i].pts); +*/ + while (remaining_sample_bytes) { buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); buf->type = this->qt->audio_type; buf->input_pos = this->qt->frames[i].offset; - buf->input_length = this->qt->input_length; + buf->input_length = this->data_size; buf->input_time = this->qt->frames[i].pts / 90000; buf->pts = this->qt->frames[i].pts; @@ -1663,6 +1681,12 @@ static int demux_qt_send_headers (demux_qt_t *this) { return DEMUX_CANNOT_HANDLE; } + this->data_start = this->qt->frames[0].offset; + this->data_size = + this->qt->frames[this->qt->frame_count - 1].offset + + this->qt->frames[this->qt->frame_count - 1].size - + this->data_size; + this->bih.biWidth = this->qt->video_width; this->bih.biHeight = this->qt->video_height; this->bih.biBitCount = this->qt->video_depth; @@ -1758,17 +1782,22 @@ static int demux_qt_open(demux_plugin_t *this_gen, return DEMUX_CANNOT_HANDLE; } +static int demux_qt_seek (demux_plugin_t *this_gen, + off_t start_pos, int start_time); + static int demux_qt_start (demux_plugin_t *this_gen, - off_t start_pos, int start_time) { + off_t start_pos, int start_time) { demux_qt_t *this = (demux_qt_t *) this_gen; buf_element_t *buf; int err; + /* perform a seek with the start_pos before starting the demuxer */ + demux_qt_seek(this_gen, start_pos, start_time); + pthread_mutex_lock(&this->mutex); /* if thread is not running, initialize demuxer */ if (!this->thread_running) { - this->waiting_for_keyframe = 0; /* print vital stats */ xine_log (this->xine, XINE_LOG_MSG, @@ -1857,7 +1886,6 @@ static int demux_qt_start (demux_plugin_t *this_gen, this->send_end_buffers = 1; this->thread_running = 1; - this->current_frame = 0; this->last_frame = 0; if ((err = pthread_create (&this->thread, NULL, demux_qt_loop, this)) != 0) { @@ -1871,9 +1899,8 @@ static int demux_qt_start (demux_plugin_t *this_gen, return DEMUX_OK; } - static int demux_qt_seek (demux_plugin_t *this_gen, - off_t start_pos, int start_time) { + off_t start_pos, int start_time) { demux_qt_t *this = (demux_qt_t *) this_gen; int best_index; @@ -1884,11 +1911,7 @@ static int demux_qt_seek (demux_plugin_t *this_gen, pthread_mutex_lock(&this->mutex); - if (!this->thread_running) { - status = this->status; - pthread_mutex_unlock( &this->mutex ); - return status; - } + this->waiting_for_keyframe = 0; /* perform a binary search on the sample table, testing the offset * boundaries first */ @@ -1940,7 +1963,7 @@ static int demux_qt_seek (demux_plugin_t *this_gen, this->current_frame = best_index; this->status = DEMUX_OK; - + xine_demux_flush_engine(this->xine); pthread_mutex_unlock( &this->mutex ); |