baseparse: fix/enhance DISCONT marking

In particular, consider DISCONT == !sync, and allow subclass to query
sync state, as it may want to perform additional checks depending
on whether sync was achieved earlier on.
Also arrange for subclass to query whether leftover data is being drained.
This commit is contained in:
Mark Nauwelaerts 2009-10-28 14:06:13 +01:00 committed by Tim-Philipp Müller
parent 48b4912c2e
commit 1bc8301c79
2 changed files with 65 additions and 3 deletions

View file

@ -83,7 +83,8 @@
* contain a valid frame, this call must return FALSE and optionally * contain a valid frame, this call must return FALSE and optionally
* set the @skipsize value to inform base class that how many bytes * set the @skipsize value to inform base class that how many bytes
* it needs to skip in order to find a valid frame. The passed buffer * it needs to skip in order to find a valid frame. The passed buffer
* is read-only. * is read-only. Note that @check_valid_frame might receive any small
* amount of input data when leftover data is being drained (e.g. at EOS).
* </para></listitem> * </para></listitem>
* <listitem><para> * <listitem><para>
* After valid frame is found, it will be passed again to subclass with * After valid frame is found, it will be passed again to subclass with
@ -214,6 +215,7 @@ struct _GstBaseParsePrivate
gboolean discont; gboolean discont;
gboolean flushing; gboolean flushing;
gboolean drain;
gint64 offset; gint64 offset;
GstClockTime next_ts; GstClockTime next_ts;
@ -1030,13 +1032,13 @@ gst_base_parse_drain (GstBaseParse * parse)
guint avail; guint avail;
GST_DEBUG_OBJECT (parse, "draining"); GST_DEBUG_OBJECT (parse, "draining");
parse->priv->drain = TRUE;
for (;;) { for (;;) {
avail = gst_adapter_available (parse->adapter); avail = gst_adapter_available (parse->adapter);
if (!avail) if (!avail)
break; break;
gst_base_parse_set_min_frame_size (parse, avail);
if (gst_base_parse_chain (parse->sinkpad, NULL) != GST_FLOW_OK) { if (gst_base_parse_chain (parse->sinkpad, NULL) != GST_FLOW_OK) {
break; break;
} }
@ -1047,6 +1049,8 @@ gst_base_parse_drain (GstBaseParse * parse)
gst_adapter_clear (parse->adapter); gst_adapter_clear (parse->adapter);
} }
} }
parse->priv->drain = FALSE;
} }
@ -1095,6 +1099,10 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer)
min_size = parse->priv->min_frame_size; min_size = parse->priv->min_frame_size;
GST_BASE_PARSE_UNLOCK (parse); GST_BASE_PARSE_UNLOCK (parse);
if (G_UNLIKELY (parse->priv->drain)) {
min_size = gst_adapter_available (parse->adapter);
}
/* 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)",
@ -1129,11 +1137,13 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer)
GST_LOG_OBJECT (parse, "finding sync, skipping %d bytes", skip); GST_LOG_OBJECT (parse, "finding sync, skipping %d bytes", skip);
gst_adapter_flush (parse->adapter, skip); gst_adapter_flush (parse->adapter, skip);
parse->priv->offset += skip; parse->priv->offset += skip;
parse->priv->discont = TRUE;
} else if (skip == -1) { } else if (skip == -1) {
/* subclass didn't touch this value. By default we skip 1 byte */ /* subclass didn't touch this value. By default we skip 1 byte */
GST_LOG_OBJECT (parse, "finding sync, skipping 1 byte"); GST_LOG_OBJECT (parse, "finding sync, skipping 1 byte");
gst_adapter_flush (parse->adapter, 1); gst_adapter_flush (parse->adapter, 1);
parse->priv->offset++; parse->priv->offset++;
parse->priv->discont = TRUE;
} }
/* There is a possibility that subclass set the skip value to zero. /* There is a possibility that subclass set the skip value to zero.
This means that it has probably found a frame but wants to ask This means that it has probably found a frame but wants to ask
@ -1307,9 +1317,11 @@ gst_base_parse_loop (GstPad * pad)
if (skip > 0) { if (skip > 0) {
GST_LOG_OBJECT (parse, "finding sync, skipping %d bytes", skip); GST_LOG_OBJECT (parse, "finding sync, skipping %d bytes", skip);
parse->priv->offset += skip; parse->priv->offset += skip;
parse->priv->discont = TRUE;
} else if (skip == -1) { } else if (skip == -1) {
GST_LOG_OBJECT (parse, "finding sync, skipping 1 byte"); GST_LOG_OBJECT (parse, "finding sync, skipping 1 byte");
parse->priv->offset++; parse->priv->offset++;
parse->priv->discont = TRUE;
} }
GST_DEBUG_OBJECT (parse, "finding sync..."); GST_DEBUG_OBJECT (parse, "finding sync...");
gst_buffer_unref (buffer); gst_buffer_unref (buffer);
@ -1423,7 +1435,7 @@ gst_base_parse_activate (GstBaseParse * parse, gboolean active)
GST_OBJECT_LOCK (parse); GST_OBJECT_LOCK (parse);
gst_segment_init (&parse->segment, GST_FORMAT_TIME); gst_segment_init (&parse->segment, GST_FORMAT_TIME);
parse->priv->duration = -1; parse->priv->duration = -1;
parse->priv->discont = FALSE; parse->priv->discont = TRUE;
parse->priv->flushing = FALSE; parse->priv->flushing = FALSE;
parse->priv->offset = 0; parse->priv->offset = 0;
parse->priv->update_interval = 0; parse->priv->update_interval = 0;
@ -1646,6 +1658,52 @@ gst_base_parse_set_frame_props (GstBaseParse * parse, guint fps_num,
GST_BASE_PARSE_UNLOCK (parse); GST_BASE_PARSE_UNLOCK (parse);
} }
/**
* gst_base_transform_get_sync:
* @parse: the #GstBaseParse to query
*
* Returns TRUE if parser is considered 'in sync'. That is, frames have been
* continuously successfully parsed and pushed.
*/
gboolean
gst_base_parse_get_sync (GstBaseParse * parse)
{
gboolean ret;
g_return_val_if_fail (parse != NULL, FALSE);
GST_BASE_PARSE_LOCK (parse);
/* losing sync is pretty much a discont (and vice versa), no ? */
ret = !parse->priv->discont;
GST_BASE_PARSE_UNLOCK (parse);
GST_DEBUG_OBJECT (parse, "sync: %d", ret);
return ret;
}
/**
* gst_base_transform_get_drain:
* @parse: the #GstBaseParse to query
*
* Returns TRUE if parser is currently 'draining'. That is, leftover data
* (e.g. in FLUSH or EOS situation) is being parsed.
*/
gboolean
gst_base_parse_get_drain (GstBaseParse * parse)
{
gboolean ret;
g_return_val_if_fail (parse != NULL, FALSE);
GST_BASE_PARSE_LOCK (parse);
/* losing sync is pretty much a discont (and vice versa), no ? */
ret = parse->priv->drain;
GST_BASE_PARSE_UNLOCK (parse);
GST_DEBUG_OBJECT (parse, "drain: %d", ret);
return ret;
}
/** /**
* gst_base_parse_get_querytypes: * gst_base_parse_get_querytypes:
* @pad: GstPad * @pad: GstPad

View file

@ -239,6 +239,10 @@ void gst_base_parse_set_passthrough (GstBaseParse * parse, gboolean passthrough)
void gst_base_parse_set_frame_props (GstBaseParse * parse, guint fps_num, void gst_base_parse_set_frame_props (GstBaseParse * parse, guint fps_num,
guint fps_den, gint interval); guint fps_den, gint interval);
gboolean gst_base_parse_get_sync (GstBaseParse * parse);
gboolean gst_base_parse_get_drain (GstBaseParse * parse);
G_END_DECLS G_END_DECLS
#endif /* __GST_BASE_PARSE_H__ */ #endif /* __GST_BASE_PARSE_H__ */