Separate the movi processing loop from the index/entry parsing loop

Original commit message from CVS:
Separate the movi processing loop from the index/entry parsing loop
Detect when the index starts from 0 or from the movi chunck offset
This commit is contained in:
Wim Taymans 2002-06-18 19:17:04 +00:00
parent 8b72069ccb
commit d9b0cf77a2
2 changed files with 56 additions and 15 deletions

View file

@ -153,6 +153,10 @@ static void gst_avi_demux_init (GstAviDemux *avi_demux);
static void gst_avi_demux_loop (GstElement *element); static void gst_avi_demux_loop (GstElement *element);
static gboolean gst_avi_demux_process_chunk (GstAviDemux *avi_demux, guint64 *filepos,
guint32 desired_tag,
gint rec_depth, guint32 *chunksize);
static gboolean gst_avi_demux_send_event (GstElement *element, GstEvent *event); static gboolean gst_avi_demux_send_event (GstElement *element, GstEvent *event);
static gboolean gst_avi_demux_handle_src_event (GstPad *pad, GstEvent *event); static gboolean gst_avi_demux_handle_src_event (GstPad *pad, GstEvent *event);
@ -231,6 +235,7 @@ gst_avi_demux_init (GstAviDemux *avi_demux)
avi_demux->index_entries = NULL; avi_demux->index_entries = NULL;
avi_demux->index_size = 0; avi_demux->index_size = 0;
avi_demux->seek_pending = 0; avi_demux->seek_pending = 0;
avi_demux->restart = FALSE;
} }
@ -681,6 +686,14 @@ gst_avi_demux_parse_index (GstAviDemux *avi_demux,
target->size = entry[i].size; target->size = entry[i].size;
target->offset = entry[i].offset; target->offset = entry[i].offset;
/* figure out if the index is 0 based or relative to the MOVI start */
if (i == 0) {
if (target->offset < filepos)
avi_demux->index_offset = filepos;
else
avi_demux->index_offset = 0;
}
target->bytes_before = stream->total_bytes; target->bytes_before = stream->total_bytes;
target->frames_before = stream->total_frames; target->frames_before = stream->total_frames;
@ -714,7 +727,6 @@ gst_avi_demux_parse_index (GstAviDemux *avi_demux,
gst_buffer_unref (buf); gst_buffer_unref (buf);
end: end:
avi_demux->index_offset = filepos;
GST_DEBUG (GST_CAT_PLUGIN_INFO, "index offset at %08lx", filepos); GST_DEBUG (GST_CAT_PLUGIN_INFO, "index offset at %08lx", filepos);
if (!gst_bytestream_seek (avi_demux->bs, filepos, GST_SEEK_METHOD_SET)) { if (!gst_bytestream_seek (avi_demux->bs, filepos, GST_SEEK_METHOD_SET)) {
@ -1060,14 +1072,6 @@ gst_avi_demux_read_chunk (GstAviDemux *avi_demux, guint32 *id, guint32 *size)
GstByteStream *bs = avi_demux->bs; GstByteStream *bs = avi_demux->bs;
guint32 got_bytes; guint32 got_bytes;
if (avi_demux->seek_pending) {
GST_DEBUG (0, "avidemux: seek pending to %lld %08llx", avi_demux->seek_offset, avi_demux->seek_offset);
if (!gst_bytestream_seek (avi_demux->bs, avi_demux->seek_offset, GST_SEEK_METHOD_SET)) {
GST_INFO (GST_CAT_PLUGIN_INFO, "avidemux: could not seek");
}
avi_demux->seek_pending = FALSE;
}
do { do {
got_bytes = gst_bytestream_peek_bytes (bs, (guint8**)&chunk, sizeof (gst_riff_chunk)); got_bytes = gst_bytestream_peek_bytes (bs, (guint8**)&chunk, sizeof (gst_riff_chunk));
if (got_bytes == sizeof (gst_riff_chunk)) { if (got_bytes == sizeof (gst_riff_chunk)) {
@ -1083,6 +1087,36 @@ gst_avi_demux_read_chunk (GstAviDemux *avi_demux, guint32 *id, guint32 *size)
return TRUE; return TRUE;
} }
static gboolean
gst_avi_demux_process_movi (GstAviDemux *avi_demux, gint rec_depth, guint64 *filepos)
{
guint32 subchunksize = 0;
while (!avi_demux->restart) { /* while not showed all: */
if (avi_demux->seek_pending) {
GST_DEBUG (0, "avidemux: seek pending to %lld %08llx", avi_demux->seek_offset, avi_demux->seek_offset);
if (!gst_bytestream_seek (avi_demux->bs, avi_demux->seek_offset, GST_SEEK_METHOD_SET)) {
GST_INFO (GST_CAT_PLUGIN_INFO, "avidemux: could not seek");
}
else {
*filepos = avi_demux->seek_offset;
}
avi_demux->seek_pending = FALSE;
}
GST_INFO (GST_CAT_PLUGIN_INFO, "process chunk filepos %08llx", *filepos);
/* recurse for subchunks of RIFF and LIST chunks: */
if (!gst_avi_demux_process_chunk (avi_demux, filepos, 0,
rec_depth + 1, &subchunksize)) {
return FALSE;
}
/* we are running in an infinite loop, we need to _yield
* from time to time */
gst_element_yield (GST_ELEMENT (avi_demux));
}
return TRUE;
}
static gboolean static gboolean
gst_avi_demux_process_chunk (GstAviDemux *avi_demux, guint64 *filepos, gst_avi_demux_process_chunk (GstAviDemux *avi_demux, guint64 *filepos,
guint32 desired_tag, guint32 desired_tag,
@ -1133,7 +1167,9 @@ gst_avi_demux_process_chunk (GstAviDemux *avi_demux, guint64 *filepos,
} }
if (avi_demux->avih.bufsize) if (avi_demux->avih.bufsize)
gst_bytestream_size_hint (avi_demux->bs, avi_demux->avih.bufsize); gst_bytestream_size_hint (avi_demux->bs, avi_demux->avih.bufsize);
break;
gst_avi_demux_process_movi (avi_demux, rec_depth, filepos);
goto done;
default: default:
/* flush the form type */ /* flush the form type */
gst_bytestream_flush_fast (bs, sizeof (guint32)); gst_bytestream_flush_fast (bs, sizeof (guint32));
@ -1154,6 +1190,8 @@ gst_avi_demux_process_chunk (GstAviDemux *avi_demux, guint64 *filepos,
%u %u\n", *filepos, *chunksize, datashowed); %u %u\n", *filepos, *chunksize, datashowed);
return FALSE; return FALSE;
} }
if (avi_demux->restart)
goto done;
subchunksize = ((subchunksize + 1) & ~1); subchunksize = ((subchunksize + 1) & ~1);
@ -1261,9 +1299,6 @@ gst_avi_demux_process_chunk (GstAviDemux *avi_demux, guint64 *filepos,
} }
done: done:
/* we are running in an infinite loop, we need to _yield
* from time to time */
gst_element_yield (GST_ELEMENT (avi_demux));
return TRUE; return TRUE;
} }
@ -1280,11 +1315,14 @@ gst_avi_demux_loop (GstElement *element)
avi_demux = GST_AVI_DEMUX (element); avi_demux = GST_AVI_DEMUX (element);
avi_demux->restart = FALSE;
/* this is basically an infinite loop */ /* this is basically an infinite loop */
if (!gst_avi_demux_process_chunk (avi_demux, &filepos, GST_RIFF_TAG_RIFF, 0, &chunksize)) { if (!gst_avi_demux_process_chunk (avi_demux, &filepos, GST_RIFF_TAG_RIFF, 0, &chunksize)) {
gst_element_error (element, "This doesn't appear to be an AVI file"); gst_element_error (element, "This doesn't appear to be an AVI file");
return; return;
} }
if (!avi_demux->restart)
/* if we exit the loop we are EOS */ /* if we exit the loop we are EOS */
gst_pad_event_default (avi_demux->sinkpad, gst_event_new (GST_EVENT_EOS)); gst_pad_event_default (avi_demux->sinkpad, gst_event_new (GST_EVENT_EOS));
} }
@ -1299,6 +1337,7 @@ gst_avi_demux_change_state (GstElement *element)
break; break;
case GST_STATE_READY_TO_PAUSED: case GST_STATE_READY_TO_PAUSED:
avi_demux->bs = gst_bytestream_new (avi_demux->sinkpad); avi_demux->bs = gst_bytestream_new (avi_demux->sinkpad);
avi_demux->last_seek = 0;
break; break;
case GST_STATE_PAUSED_TO_PLAYING: case GST_STATE_PAUSED_TO_PLAYING:
break; break;
@ -1306,6 +1345,7 @@ gst_avi_demux_change_state (GstElement *element)
break; break;
case GST_STATE_PAUSED_TO_READY: case GST_STATE_PAUSED_TO_READY:
gst_bytestream_destroy (avi_demux->bs); gst_bytestream_destroy (avi_demux->bs);
avi_demux->restart = TRUE;
break; break;
case GST_STATE_READY_TO_NULL: case GST_STATE_READY_TO_NULL:
break; break;

View file

@ -108,6 +108,7 @@ struct _GstAviDemux {
gboolean seek_pending; gboolean seek_pending;
gint64 seek_offset; gint64 seek_offset;
guint64 last_seek; guint64 last_seek;
gboolean restart;
}; };
struct _GstAviDemuxClass { struct _GstAviDemuxClass {