baseparse: add GST_BASE_PARSE_FLOW_QUEUED to queue buffers until caps are known

This is useful for parser like flacparse or h264parse which may need to process
some buffers before they can construct the final caps, in which case they may
want to delay pushing the initial buffers until the full and proper caps are
known.

https://bugzilla.gnome.org/show_bug.cgi?id=646341
This commit is contained in:
Zaheer Abbas Merali 2011-04-02 13:02:01 +01:00 committed by Tim-Philipp Müller
parent 22b7dfc800
commit 783dbb9a71
2 changed files with 64 additions and 0 deletions

View file

@ -263,6 +263,9 @@ struct _GstBaseParsePrivate
GList *pending_events;
/* frames/buffers that are queued and ready to go on OK */
GList *queued_frames;
GstBuffer *cache;
/* index entry storage, either ours or provided */
@ -398,6 +401,12 @@ static GstFlowReturn gst_base_parse_process_fragment (GstBaseParse * parse,
static gboolean gst_base_parse_is_seekable (GstBaseParse * parse);
static void gst_base_parse_push_pending_frame (GstBaseParseFrame * frame,
GstBaseParse * parse);
static void gst_base_parse_frame_free (GstBaseParseFrame * frame);
static GstBaseParseFrame *gst_base_parse_frame_copy_and_clear (GstBaseParseFrame
* frame);
static void
gst_base_parse_clear_queues (GstBaseParse * parse)
{
@ -440,6 +449,11 @@ gst_base_parse_finalize (GObject * object)
g_list_free (parse->priv->pending_events);
parse->priv->pending_events = NULL;
g_list_foreach (parse->priv->queued_frames,
(GFunc) gst_base_parse_frame_free, NULL);
g_list_free (parse->priv->queued_frames);
parse->priv->queued_frames = NULL;
if (parse->priv->index) {
gst_object_unref (parse->priv->index);
parse->priv->index = NULL;
@ -556,6 +570,25 @@ gst_base_parse_frame_clear (GstBaseParse * parse, GstBaseParseFrame * frame)
}
}
/* free frame allocated with copy_and_clear (and not on the stack) */
static void
gst_base_parse_frame_free (GstBaseParseFrame * frame)
{
gst_base_parse_frame_clear (NULL, frame);
g_slice_free (GstBaseParseFrame, frame);
}
/* copy frame (taking ownership of contents of passed frame) */
static GstBaseParseFrame *
gst_base_parse_frame_copy_and_clear (GstBaseParseFrame * frame)
{
GstBaseParseFrame *copy;
copy = g_slice_dup (GstBaseParseFrame, frame);
memset (frame, 0, sizeof (GstBaseParseFrame));
return copy;
}
static inline void
gst_base_parse_frame_update (GstBaseParse * parse, GstBaseParseFrame * frame,
GstBuffer * buf)
@ -1559,13 +1592,35 @@ gst_base_parse_handle_and_push_frame (GstBaseParse * parse,
if (ret == GST_BASE_PARSE_FLOW_DROPPED) {
gst_base_parse_frame_clear (parse, frame);
return GST_FLOW_OK;
} else if (ret == GST_BASE_PARSE_FLOW_QUEUED) {
parse->priv->queued_frames = g_list_append (parse->priv->queued_frames,
gst_base_parse_frame_copy_and_clear (frame));
return GST_FLOW_OK;
} else if (ret != GST_FLOW_OK) {
return ret;
}
/* All OK, push queued frames if there are any */
if (G_UNLIKELY (parse->priv->queued_frames != NULL)) {
g_list_foreach (parse->priv->queued_frames,
(GFunc) gst_base_parse_push_pending_frame, parse);
g_list_free (parse->priv->queued_frames);
parse->priv->queued_frames = NULL;
}
return gst_base_parse_push_frame (parse, frame);
}
static void
gst_base_parse_push_pending_frame (GstBaseParseFrame * frame,
GstBaseParse * parse)
{
gst_buffer_set_caps (frame->buffer,
GST_PAD_CAPS (GST_BASE_PARSE_SRC_PAD (parse)));
gst_base_parse_push_frame (parse, frame);
gst_base_parse_frame_free (frame);
}
/**
* gst_base_parse_push_frame:
* @parse: #GstBaseParse.

View file

@ -65,6 +65,15 @@ G_BEGIN_DECLS
*/
#define GST_BASE_PARSE_FLOW_DROPPED GST_FLOW_CUSTOM_SUCCESS
/**
* GST_BASE_PARSE_FLOW_QUEUED:
* A #GstFlowReturn that can be returned from parse frame to indicate that
* the buffer will be queued to be pushed when the next OK
*
* Since: 0.10.33
*/
#define GST_BASE_PARSE_FLOW_QUEUED GST_FLOW_CUSTOM_SUCCESS_1
/**
* GstBaseParseFrameFlags:
* @GST_BASE_PARSE_FRAME_FLAG_NONE: no flag