baseparse: Fix push mode seeking (aacparse, amrparse)

Sending the flush-start event forward before taking the stream lock actually
works, in contrast to deadlocking in downstream preroll_wait (hunk 1).

After that we get the chain function being stuck in a busy loop. This is fixed
by updating the minimum frame size inside the synchronization loop because the
subclass asks for more data in this way (hunk 2).

Finally, this leads to a very probable crash because the subclass can find a
valid frame with a size greater than the currently available data in the
adapter. This makes the subsequent gst_adapter_take_buffer call return NULL,
which is not expected (hunk 3).
This commit is contained in:
René Stadler 2009-04-05 03:50:19 +03:00
parent 9c6e21d1f6
commit 0293f54d06
2 changed files with 24 additions and 10 deletions

View file

@ -605,10 +605,11 @@ gst_base_parse_sink_eventfunc (GstBaseParse * parse, GstEvent * event)
case GST_EVENT_FLUSH_START: case GST_EVENT_FLUSH_START:
parse->priv->flushing = TRUE; parse->priv->flushing = TRUE;
handled = gst_pad_push_event (parse->srcpad, event);
/* Wait for _chain() to exit by taking the srcpad STREAM_LOCK */ /* Wait for _chain() to exit by taking the srcpad STREAM_LOCK */
GST_PAD_STREAM_LOCK (parse->srcpad); GST_PAD_STREAM_LOCK (parse->srcpad);
handled = gst_pad_push_event (parse->srcpad, event);
GST_PAD_STREAM_UNLOCK (parse->srcpad); GST_PAD_STREAM_UNLOCK (parse->srcpad);
break; break;
case GST_EVENT_FLUSH_STOP: case GST_EVENT_FLUSH_STOP:
@ -896,12 +897,12 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer)
while (!parse->priv->flushing) { while (!parse->priv->flushing) {
tmpbuf = gst_buffer_new (); tmpbuf = gst_buffer_new ();
/* Synchronization loop */
for (;;) {
GST_BASE_PARSE_LOCK (parse); GST_BASE_PARSE_LOCK (parse);
min_size = parse->priv->min_frame_size; min_size = parse->priv->min_frame_size;
GST_BASE_PARSE_UNLOCK (parse); GST_BASE_PARSE_UNLOCK (parse);
/* Synchronization loop */
for (;;) {
/* Collect at least min_frame_size bytes */ /* Collect at least min_frame_size bytes */
if (gst_adapter_available (parse->adapter) < min_size) { if (gst_adapter_available (parse->adapter) < min_size) {
GST_DEBUG_OBJECT (parse, "not enough data available (only %d bytes)", GST_DEBUG_OBJECT (parse, "not enough data available (only %d bytes)",
@ -923,6 +924,12 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer)
skip = -1; skip = -1;
if (bclass->check_valid_frame (parse, tmpbuf, &fsize, &skip)) { if (bclass->check_valid_frame (parse, tmpbuf, &fsize, &skip)) {
if (gst_adapter_available (parse->adapter) < fsize) {
GST_DEBUG_OBJECT (parse,
"found valid frame but not enough data available (only %d bytes)",
gst_adapter_available (parse->adapter));
goto done;
}
break; break;
} }
if (skip > 0) { if (skip > 0) {

View file

@ -605,10 +605,11 @@ gst_base_parse_sink_eventfunc (GstBaseParse * parse, GstEvent * event)
case GST_EVENT_FLUSH_START: case GST_EVENT_FLUSH_START:
parse->priv->flushing = TRUE; parse->priv->flushing = TRUE;
handled = gst_pad_push_event (parse->srcpad, event);
/* Wait for _chain() to exit by taking the srcpad STREAM_LOCK */ /* Wait for _chain() to exit by taking the srcpad STREAM_LOCK */
GST_PAD_STREAM_LOCK (parse->srcpad); GST_PAD_STREAM_LOCK (parse->srcpad);
handled = gst_pad_push_event (parse->srcpad, event);
GST_PAD_STREAM_UNLOCK (parse->srcpad); GST_PAD_STREAM_UNLOCK (parse->srcpad);
break; break;
case GST_EVENT_FLUSH_STOP: case GST_EVENT_FLUSH_STOP:
@ -896,12 +897,12 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer)
while (!parse->priv->flushing) { while (!parse->priv->flushing) {
tmpbuf = gst_buffer_new (); tmpbuf = gst_buffer_new ();
/* Synchronization loop */
for (;;) {
GST_BASE_PARSE_LOCK (parse); GST_BASE_PARSE_LOCK (parse);
min_size = parse->priv->min_frame_size; min_size = parse->priv->min_frame_size;
GST_BASE_PARSE_UNLOCK (parse); GST_BASE_PARSE_UNLOCK (parse);
/* Synchronization loop */
for (;;) {
/* Collect at least min_frame_size bytes */ /* Collect at least min_frame_size bytes */
if (gst_adapter_available (parse->adapter) < min_size) { if (gst_adapter_available (parse->adapter) < min_size) {
GST_DEBUG_OBJECT (parse, "not enough data available (only %d bytes)", GST_DEBUG_OBJECT (parse, "not enough data available (only %d bytes)",
@ -923,6 +924,12 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer)
skip = -1; skip = -1;
if (bclass->check_valid_frame (parse, tmpbuf, &fsize, &skip)) { if (bclass->check_valid_frame (parse, tmpbuf, &fsize, &skip)) {
if (gst_adapter_available (parse->adapter) < fsize) {
GST_DEBUG_OBJECT (parse,
"found valid frame but not enough data available (only %d bytes)",
gst_adapter_available (parse->adapter));
goto done;
}
break; break;
} }
if (skip > 0) { if (skip > 0) {