mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 20:21:24 +00:00
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:
parent
e6cc145352
commit
2ce79998a1
1 changed files with 79 additions and 32 deletions
|
@ -275,6 +275,7 @@ gst_avi_demux_reset (GstAviDemux * avi)
|
|||
|
||||
avi->state = GST_AVI_DEMUX_START;
|
||||
avi->offset = 0;
|
||||
avi->building_index = FALSE;
|
||||
|
||||
avi->index_offset = 0;
|
||||
g_free (avi->avih);
|
||||
|
@ -288,6 +289,10 @@ gst_avi_demux_reset (GstAviDemux * avi)
|
|||
gst_event_unref (avi->seg_event);
|
||||
avi->seg_event = NULL;
|
||||
}
|
||||
if (avi->seek_event) {
|
||||
gst_event_unref (avi->seek_event);
|
||||
avi->seek_event = NULL;
|
||||
}
|
||||
|
||||
if (avi->globaltags)
|
||||
gst_tag_list_free (avi->globaltags);
|
||||
|
@ -1564,7 +1569,7 @@ out_of_mem:
|
|||
* Create and push a flushing seek event upstream
|
||||
*/
|
||||
static gboolean
|
||||
avi_demux_do_push_seek (GstAviDemux * demux, guint64 offset)
|
||||
perform_seek_to_offset (GstAviDemux * demux, guint64 offset)
|
||||
{
|
||||
GstEvent *event;
|
||||
gboolean res = 0;
|
||||
|
@ -1591,6 +1596,7 @@ gst_avi_demux_read_subindexes_push (GstAviDemux * avi)
|
|||
{
|
||||
guint32 tag = 0, size;
|
||||
GstBuffer *buf = NULL;
|
||||
guint odml_stream;
|
||||
|
||||
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))
|
||||
return TRUE;
|
||||
|
||||
if ((tag != GST_MAKE_FOURCC ('i', 'x', '0' + avi->odml_stream / 10,
|
||||
'0' + avi->odml_stream % 10)) &&
|
||||
(tag != GST_MAKE_FOURCC ('0' + avi->odml_stream / 10,
|
||||
'0' + avi->odml_stream % 10, 'i', 'x'))) {
|
||||
/* this is the ODML chunk we expect */
|
||||
odml_stream = avi->odml_stream;
|
||||
|
||||
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_FOURCC_ARGS (tag));
|
||||
return FALSE;
|
||||
|
@ -1614,22 +1623,31 @@ gst_avi_demux_read_subindexes_push (GstAviDemux * avi)
|
|||
gst_adapter_flush (avi->adapter, 8);
|
||||
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;
|
||||
|
||||
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;
|
||||
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;
|
||||
} else {
|
||||
/* get stream stats now */
|
||||
/* we're done, get stream stats now */
|
||||
avi->have_index = gst_avi_demux_do_index_stats (avi);
|
||||
|
||||
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)));
|
||||
avi->idx1_offset = offset + 8 + GST_ROUND_UP_2 (size);
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
@ -2889,7 +2907,6 @@ gst_avi_demux_stream_scan (GstAviDemux * avi)
|
|||
/* collect stats */
|
||||
avi->have_index = gst_avi_demux_do_index_stats (avi);
|
||||
|
||||
|
||||
return TRUE;
|
||||
|
||||
/* 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
|
||||
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
|
||||
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,
|
||||
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))) {
|
||||
GST_DEBUG_OBJECT (avi, "seek event failed!");
|
||||
return FALSE;
|
||||
|
@ -4233,7 +4250,9 @@ gst_avi_demux_handle_seek_push (GstAviDemux * avi, GstPad * pad,
|
|||
/* check for having parsed index already */
|
||||
if (!avi->have_index) {
|
||||
guint64 offset;
|
||||
gboolean building_index;
|
||||
|
||||
GST_OBJECT_LOCK (avi);
|
||||
/* handle the seek event in the chain function */
|
||||
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);
|
||||
avi->seek_event = gst_event_ref (event);
|
||||
|
||||
if (!avi->building_index) {
|
||||
avi->building_index = 1;
|
||||
/* set the building_index flag so that only one thread can setup the
|
||||
* structures for index seeking. */
|
||||
building_index = avi->building_index;
|
||||
if (!building_index) {
|
||||
avi->building_index = TRUE;
|
||||
if (avi->stream[0].indexes) {
|
||||
avi->odml_stream = 0;
|
||||
avi->odml_subidxs = avi->stream[avi->odml_stream].indexes;
|
||||
|
@ -4251,12 +4273,15 @@ gst_avi_demux_handle_seek_push (GstAviDemux * avi, GstPad * pad,
|
|||
} else {
|
||||
offset = avi->idx1_offset;
|
||||
}
|
||||
}
|
||||
GST_OBJECT_UNLOCK (avi);
|
||||
|
||||
if (!building_index) {
|
||||
/* seek to the first subindex or legacy index */
|
||||
GST_INFO_OBJECT (avi,
|
||||
"Seeking to legacy index/first subindex at %" G_GUINT64_FORMAT,
|
||||
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
|
||||
|
@ -5075,14 +5100,16 @@ gst_avi_demux_chain (GstPad * pad, GstBuffer * buf)
|
|||
res = gst_avi_demux_stream_data (avi);
|
||||
break;
|
||||
case GST_AVI_DEMUX_SEEK:
|
||||
{
|
||||
GstEvent *event;
|
||||
|
||||
res = GST_FLOW_OK;
|
||||
|
||||
/* 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 */
|
||||
res = GST_FLOW_ERROR;
|
||||
break;
|
||||
}
|
||||
goto index_failed;
|
||||
|
||||
if (!avi->stream[0].indexes && !avi->have_index
|
||||
&& avi->avih->flags & GST_RIFF_AVIH_HASINDEX)
|
||||
gst_avi_demux_stream_index_push (avi);
|
||||
|
@ -5095,14 +5122,19 @@ gst_avi_demux_chain (GstPad * pad, GstBuffer * buf)
|
|||
break;
|
||||
}
|
||||
|
||||
GST_OBJECT_LOCK (avi);
|
||||
event = avi->seek_event;
|
||||
avi->seek_event = NULL;
|
||||
GST_OBJECT_UNLOCK (avi);
|
||||
|
||||
/* calculate and perform seek */
|
||||
if (!avi_demux_handle_seek_push (avi, avi->sinkpad, avi->seek_event)) {
|
||||
GST_WARNING ("Push mode seek failed");
|
||||
res = GST_FLOW_ERROR;
|
||||
}
|
||||
gst_event_unref (avi->seek_event);
|
||||
if (!avi_demux_handle_seek_push (avi, avi->sinkpad, event))
|
||||
goto seek_failed;
|
||||
|
||||
gst_event_unref (event);
|
||||
avi->state = GST_AVI_DEMUX_MOVI;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
GST_ELEMENT_ERROR (avi, STREAM, FAILED, (NULL),
|
||||
("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_flow_get_name (res));
|
||||
|
||||
if (G_UNLIKELY (avi->abort_buffering)) {
|
||||
avi->abort_buffering = FALSE;
|
||||
res = GST_FLOW_ERROR;
|
||||
GST_ELEMENT_ERROR (avi, STREAM, DEMUX, (NULL), ("unhandled buffer size"));
|
||||
}
|
||||
if (G_UNLIKELY (avi->abort_buffering))
|
||||
goto abort_buffering;
|
||||
|
||||
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
|
||||
|
|
Loading…
Reference in a new issue