avidemux: cleanups

Make sure we reset the demuxer correctly wrt parsing the index.
Don't leak pending seek events.
Rename some methods to reflect what they do and to avoid confusion with similar
method names.
Try to make the seeking threadsafe by protecting the setup code with a lock.
Make sure we post errors when a seek fails.
This commit is contained in:
Wim Taymans 2010-01-18 17:13:06 +01:00 committed by Robert Swain
parent e6cc145352
commit 2ce79998a1

View File

@ -275,6 +275,7 @@ gst_avi_demux_reset (GstAviDemux * avi)
avi->state = GST_AVI_DEMUX_START; avi->state = GST_AVI_DEMUX_START;
avi->offset = 0; avi->offset = 0;
avi->building_index = FALSE;
avi->index_offset = 0; avi->index_offset = 0;
g_free (avi->avih); g_free (avi->avih);
@ -288,6 +289,10 @@ gst_avi_demux_reset (GstAviDemux * avi)
gst_event_unref (avi->seg_event); gst_event_unref (avi->seg_event);
avi->seg_event = NULL; avi->seg_event = NULL;
} }
if (avi->seek_event) {
gst_event_unref (avi->seek_event);
avi->seek_event = NULL;
}
if (avi->globaltags) if (avi->globaltags)
gst_tag_list_free (avi->globaltags); gst_tag_list_free (avi->globaltags);
@ -1564,7 +1569,7 @@ out_of_mem:
* Create and push a flushing seek event upstream * Create and push a flushing seek event upstream
*/ */
static gboolean static gboolean
avi_demux_do_push_seek (GstAviDemux * demux, guint64 offset) perform_seek_to_offset (GstAviDemux * demux, guint64 offset)
{ {
GstEvent *event; GstEvent *event;
gboolean res = 0; gboolean res = 0;
@ -1591,6 +1596,7 @@ gst_avi_demux_read_subindexes_push (GstAviDemux * avi)
{ {
guint32 tag = 0, size; guint32 tag = 0, size;
GstBuffer *buf = NULL; GstBuffer *buf = NULL;
guint odml_stream;
GST_DEBUG_OBJECT (avi, "read subindexes for %d streams", avi->num_streams); GST_DEBUG_OBJECT (avi, "read subindexes for %d streams", avi->num_streams);
@ -1600,10 +1606,13 @@ gst_avi_demux_read_subindexes_push (GstAviDemux * avi)
if (!gst_avi_demux_peek_chunk (avi, &tag, &size)) if (!gst_avi_demux_peek_chunk (avi, &tag, &size))
return TRUE; return TRUE;
if ((tag != GST_MAKE_FOURCC ('i', 'x', '0' + avi->odml_stream / 10, /* this is the ODML chunk we expect */
'0' + avi->odml_stream % 10)) && odml_stream = avi->odml_stream;
(tag != GST_MAKE_FOURCC ('0' + avi->odml_stream / 10,
'0' + avi->odml_stream % 10, 'i', 'x'))) { if ((tag != GST_MAKE_FOURCC ('i', 'x', '0' + odml_stream / 10,
'0' + odml_stream % 10)) &&
(tag != GST_MAKE_FOURCC ('0' + odml_stream / 10,
'0' + odml_stream % 10, 'i', 'x'))) {
GST_WARNING_OBJECT (avi, "Not an ix## chunk (%" GST_FOURCC_FORMAT ")", GST_WARNING_OBJECT (avi, "Not an ix## chunk (%" GST_FOURCC_FORMAT ")",
GST_FOURCC_ARGS (tag)); GST_FOURCC_ARGS (tag));
return FALSE; return FALSE;
@ -1614,22 +1623,31 @@ gst_avi_demux_read_subindexes_push (GstAviDemux * avi)
gst_adapter_flush (avi->adapter, 8); gst_adapter_flush (avi->adapter, 8);
buf = gst_adapter_take_buffer (avi->adapter, size); buf = gst_adapter_take_buffer (avi->adapter, size);
if (!gst_avi_demux_parse_subindex (avi, &avi->stream[avi->odml_stream], buf)) if (!gst_avi_demux_parse_subindex (avi, &avi->stream[odml_stream], buf))
return FALSE; return FALSE;
if (avi->odml_subidxs[++avi->odml_subidx] == GST_BUFFER_OFFSET_NONE) { /* we parsed the index, go to next subindex */
avi->odml_subidx++;
if (avi->odml_subidxs[avi->odml_subidx] == GST_BUFFER_OFFSET_NONE) {
/* we reached the end of the indexes for this stream, move to the next
* stream to handle the first index */
avi->odml_stream++;
avi->odml_subidx = 0; avi->odml_subidx = 0;
if (++avi->odml_stream < avi->num_streams) {
if (avi->odml_stream < avi->num_streams) {
/* there are more indexes */
avi->odml_subidxs = avi->stream[avi->odml_stream].indexes; avi->odml_subidxs = avi->stream[avi->odml_stream].indexes;
} else { } else {
/* get stream stats now */ /* we're done, get stream stats now */
avi->have_index = gst_avi_demux_do_index_stats (avi); avi->have_index = gst_avi_demux_do_index_stats (avi);
return TRUE; return TRUE;
} }
} }
return avi_demux_do_push_seek (avi, avi->odml_subidxs[avi->odml_subidx]); /* seek to next index */
return perform_seek_to_offset (avi, avi->odml_subidxs[avi->odml_subidx]);
} }
/* /*
@ -2684,7 +2702,7 @@ gst_avi_demux_stream_index_push (GstAviDemux * avi)
(8 + GST_ROUND_UP_2 (size))); (8 + GST_ROUND_UP_2 (size)));
avi->idx1_offset = offset + 8 + GST_ROUND_UP_2 (size); avi->idx1_offset = offset + 8 + GST_ROUND_UP_2 (size);
/* issue seek to allow chain function to handle it and return! */ /* issue seek to allow chain function to handle it and return! */
avi_demux_do_push_seek (avi, avi->idx1_offset); perform_seek_to_offset (avi, avi->idx1_offset);
return; return;
} }
@ -2889,7 +2907,6 @@ gst_avi_demux_stream_scan (GstAviDemux * avi)
/* collect stats */ /* collect stats */
avi->have_index = gst_avi_demux_do_index_stats (avi); avi->have_index = gst_avi_demux_do_index_stats (avi);
return TRUE; return TRUE;
/* ERRORS */ /* ERRORS */
@ -3937,7 +3954,7 @@ gst_avi_demux_do_seek (GstAviDemux * avi, GstSegment * segment)
} }
/* /*
* Handle seek event. * Handle seek event in pull mode.
*/ */
static gboolean static gboolean
gst_avi_demux_handle_seek (GstAviDemux * avi, GstPad * pad, GstEvent * event) gst_avi_demux_handle_seek (GstAviDemux * avi, GstPad * pad, GstEvent * event)
@ -4092,7 +4109,7 @@ no_format:
} }
/* /*
* Handle seek event. * Handle seek event in push mode.
*/ */
static gboolean static gboolean
avi_demux_handle_seek_push (GstAviDemux * avi, GstPad * pad, GstEvent * event) avi_demux_handle_seek_push (GstAviDemux * avi, GstPad * pad, GstEvent * event)
@ -4213,7 +4230,7 @@ avi_demux_handle_seek_push (GstAviDemux * avi, GstPad * pad, GstEvent * event)
GST_DEBUG_OBJECT (avi, "Seeking to offset %" G_GUINT64_FORMAT, GST_DEBUG_OBJECT (avi, "Seeking to offset %" G_GUINT64_FORMAT,
stream->index[index].offset); stream->index[index].offset);
if (!avi_demux_do_push_seek (avi, if (!perform_seek_to_offset (avi,
stream->index[index].offset - (avi->stream[0].indexes ? 8 : 0))) { stream->index[index].offset - (avi->stream[0].indexes ? 8 : 0))) {
GST_DEBUG_OBJECT (avi, "seek event failed!"); GST_DEBUG_OBJECT (avi, "seek event failed!");
return FALSE; return FALSE;
@ -4233,7 +4250,9 @@ gst_avi_demux_handle_seek_push (GstAviDemux * avi, GstPad * pad,
/* check for having parsed index already */ /* check for having parsed index already */
if (!avi->have_index) { if (!avi->have_index) {
guint64 offset; guint64 offset;
gboolean building_index;
GST_OBJECT_LOCK (avi);
/* handle the seek event in the chain function */ /* handle the seek event in the chain function */
avi->state = GST_AVI_DEMUX_SEEK; avi->state = GST_AVI_DEMUX_SEEK;
@ -4242,8 +4261,11 @@ gst_avi_demux_handle_seek_push (GstAviDemux * avi, GstPad * pad,
gst_event_unref (avi->seek_event); gst_event_unref (avi->seek_event);
avi->seek_event = gst_event_ref (event); avi->seek_event = gst_event_ref (event);
if (!avi->building_index) { /* set the building_index flag so that only one thread can setup the
avi->building_index = 1; * structures for index seeking. */
building_index = avi->building_index;
if (!building_index) {
avi->building_index = TRUE;
if (avi->stream[0].indexes) { if (avi->stream[0].indexes) {
avi->odml_stream = 0; avi->odml_stream = 0;
avi->odml_subidxs = avi->stream[avi->odml_stream].indexes; avi->odml_subidxs = avi->stream[avi->odml_stream].indexes;
@ -4251,12 +4273,15 @@ gst_avi_demux_handle_seek_push (GstAviDemux * avi, GstPad * pad,
} else { } else {
offset = avi->idx1_offset; offset = avi->idx1_offset;
} }
}
GST_OBJECT_UNLOCK (avi);
if (!building_index) {
/* seek to the first subindex or legacy index */ /* seek to the first subindex or legacy index */
GST_INFO_OBJECT (avi, GST_INFO_OBJECT (avi,
"Seeking to legacy index/first subindex at %" G_GUINT64_FORMAT, "Seeking to legacy index/first subindex at %" G_GUINT64_FORMAT,
offset); offset);
return avi_demux_do_push_seek (avi, offset); return perform_seek_to_offset (avi, offset);
} }
/* FIXME: we have to always return true so that we don't block the seek /* FIXME: we have to always return true so that we don't block the seek
@ -5075,14 +5100,16 @@ gst_avi_demux_chain (GstPad * pad, GstBuffer * buf)
res = gst_avi_demux_stream_data (avi); res = gst_avi_demux_stream_data (avi);
break; break;
case GST_AVI_DEMUX_SEEK: case GST_AVI_DEMUX_SEEK:
{
GstEvent *event;
res = GST_FLOW_OK; res = GST_FLOW_OK;
/* obtain and parse indexes */ /* obtain and parse indexes */
if (avi->stream[0].indexes && !gst_avi_demux_read_subindexes_push (avi)) { if (avi->stream[0].indexes && !gst_avi_demux_read_subindexes_push (avi))
/* seek in subindex read function failed */ /* seek in subindex read function failed */
res = GST_FLOW_ERROR; goto index_failed;
break;
}
if (!avi->stream[0].indexes && !avi->have_index if (!avi->stream[0].indexes && !avi->have_index
&& avi->avih->flags & GST_RIFF_AVIH_HASINDEX) && avi->avih->flags & GST_RIFF_AVIH_HASINDEX)
gst_avi_demux_stream_index_push (avi); gst_avi_demux_stream_index_push (avi);
@ -5095,14 +5122,19 @@ gst_avi_demux_chain (GstPad * pad, GstBuffer * buf)
break; break;
} }
GST_OBJECT_LOCK (avi);
event = avi->seek_event;
avi->seek_event = NULL;
GST_OBJECT_UNLOCK (avi);
/* calculate and perform seek */ /* calculate and perform seek */
if (!avi_demux_handle_seek_push (avi, avi->sinkpad, avi->seek_event)) { if (!avi_demux_handle_seek_push (avi, avi->sinkpad, event))
GST_WARNING ("Push mode seek failed"); goto seek_failed;
res = GST_FLOW_ERROR;
} gst_event_unref (event);
gst_event_unref (avi->seek_event);
avi->state = GST_AVI_DEMUX_MOVI; avi->state = GST_AVI_DEMUX_MOVI;
break; break;
}
default: default:
GST_ELEMENT_ERROR (avi, STREAM, FAILED, (NULL), GST_ELEMENT_ERROR (avi, STREAM, FAILED, (NULL),
("Illegal internal state")); ("Illegal internal state"));
@ -5113,13 +5145,28 @@ gst_avi_demux_chain (GstPad * pad, GstBuffer * buf)
GST_DEBUG_OBJECT (avi, "state: %d res:%s", avi->state, GST_DEBUG_OBJECT (avi, "state: %d res:%s", avi->state,
gst_flow_get_name (res)); gst_flow_get_name (res));
if (G_UNLIKELY (avi->abort_buffering)) { if (G_UNLIKELY (avi->abort_buffering))
avi->abort_buffering = FALSE; goto abort_buffering;
res = GST_FLOW_ERROR;
GST_ELEMENT_ERROR (avi, STREAM, DEMUX, (NULL), ("unhandled buffer size"));
}
return res; return res;
/* ERRORS */
index_failed:
{
GST_ELEMENT_ERROR (avi, STREAM, DEMUX, (NULL), ("failed to read indexes"));
return GST_FLOW_ERROR;
}
seek_failed:
{
GST_ELEMENT_ERROR (avi, STREAM, DEMUX, (NULL), ("push mode seek failed"));
return GST_FLOW_ERROR;
}
abort_buffering:
{
avi->abort_buffering = FALSE;
GST_ELEMENT_ERROR (avi, STREAM, DEMUX, (NULL), ("unhandled buffer size"));
return GST_FLOW_ERROR;
}
} }
static gboolean static gboolean