baseparse: simplify and improve frame state handling

Use a frame flag to signal to subclass it should reset any retained
state w.r.t. frame parsing since the frame being passed is 'new',
i.e. not related to previously passed and processed data.
This commit is contained in:
Mark Nauwelaerts 2012-02-15 17:11:54 +01:00
parent 2609c7b452
commit bfa4bb7150
2 changed files with 18 additions and 42 deletions

View file

@ -323,10 +323,10 @@ struct _GstBaseParsePrivate
/* Newsegment event to be sent after SEEK */
GstEvent *pending_segment;
/* frame previously passed to subclass (might be re-used) */
GstBaseParseFrame *prev_frame;
/* offset corresponding to above frame */
/* offset of last parsed frame/data */
gint64 prev_offset;
/* force a new frame, regardless of offset */
gboolean new_frame;
/* whether we are merely scanning for a frame */
gboolean scanning;
/* ... and resulting frame, if any */
@ -762,11 +762,7 @@ gst_base_parse_reset (GstBaseParse * parse)
if (parse->priv->adapter)
gst_adapter_clear (parse->priv->adapter);
/* we know it is not alloc'ed, but maybe other stuff to free, some day ... */
if (parse->priv->prev_frame) {
gst_base_parse_frame_free (parse->priv->prev_frame);
parse->priv->prev_frame = NULL;
}
parse->priv->new_frame = TRUE;
g_list_foreach (parse->priv->detect_buffers, (GFunc) gst_buffer_unref, NULL);
g_list_free (parse->priv->detect_buffers);
@ -1082,10 +1078,7 @@ gst_base_parse_sink_eventfunc (GstBaseParse * parse, GstEvent * event)
parse->priv->flushing = FALSE;
parse->priv->discont = TRUE;
parse->priv->last_ts = GST_CLOCK_TIME_NONE;
if (parse->priv->prev_frame) {
gst_base_parse_frame_free (parse->priv->prev_frame);
parse->priv->prev_frame = NULL;
}
parse->priv->new_frame = TRUE;
break;
case GST_EVENT_EOS:
@ -1725,23 +1718,18 @@ gst_base_parse_prepare_frame (GstBaseParse * parse, GstBuffer * buffer)
GST_BUFFER_OFFSET (buffer) = parse->priv->offset;
if (parse->priv->prev_frame) {
if (parse->priv->prev_offset == parse->priv->offset) {
frame = parse->priv->prev_frame;
} else {
gst_base_parse_frame_free (parse->priv->prev_frame);
}
parse->priv->prev_frame = NULL;
}
if (!frame) {
frame = gst_base_parse_frame_new (buffer, 0, 0);
}
frame = gst_base_parse_frame_new (buffer, 0, 0);
/* also ensure to update state flags */
gst_base_parse_frame_update (parse, frame, buffer);
gst_buffer_unref (buffer);
if (parse->priv->prev_offset != parse->priv->offset || parse->priv->new_frame) {
GST_LOG_OBJECT (parse, "marking as new frame");
parse->priv->new_frame = FALSE;
frame->flags |= GST_BASE_PARSE_FRAME_FLAG_NEW_FRAME;
}
frame->offset = parse->priv->prev_offset = parse->priv->offset;
/* use default handler to provide initial (upstream) metadata */
@ -1750,15 +1738,6 @@ gst_base_parse_prepare_frame (GstBaseParse * parse, GstBuffer * buffer)
return frame;
}
static void
gst_base_parse_unprepare_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
{
g_assert (parse->priv->prev_frame == NULL);
parse->priv->prev_frame = frame;
gst_base_parse_frame_update (parse, frame, NULL);
}
/* Wraps buffer in a frame and dispatches to subclass.
* Also manages data skipping and offset handling (including adapter flushing).
* Takes ownership of @buffer */
@ -1790,7 +1769,6 @@ gst_base_parse_handle_buffer (GstBaseParse * parse, GstBuffer * buffer,
frame = gst_base_parse_prepare_frame (parse, buffer);
ret = klass->handle_frame (parse, frame, skip);
gst_base_parse_unprepare_frame (parse, frame);
*flushed = parse->priv->flushed;
@ -1805,14 +1783,6 @@ gst_base_parse_handle_buffer (GstBaseParse * parse, GstBuffer * buffer,
/* subclass can only do one of these, or semantics are too unclear */
g_assert (*skip == 0 || *flushed == 0);
/* if it did something, clear frame state,
* though this should also trigger the offset check anyway */
if (*skip != 0 || *flushed != 0) {
GST_LOG_OBJECT (parse, "clearing prev frame");
gst_base_parse_frame_free (parse->priv->prev_frame);
parse->priv->prev_frame = NULL;
}
/* track skipping */
if (*skip > 0) {
GstClockTime timestamp;
@ -1849,6 +1819,8 @@ exit:
gst_adapter_clear (parse->priv->adapter);
}
gst_base_parse_frame_free (frame);
return ret;
}

View file

@ -93,6 +93,9 @@ G_BEGIN_DECLS
/**
* GstBaseParseFrameFlags:
* @GST_BASE_PARSE_FRAME_FLAG_NONE: no flag
* @GST_BASE_PARSE_FRAME_FLAG_NEW_FRAME: set by baseclass if current frame
* is passed for processing to the subclass for the first time
* (and not set on subsequent calls with same data).
* @GST_BASE_PARSE_FRAME_FLAG_NO_FRAME: set to indicate this buffer should not be
* counted as frame, e.g. if this frame is dependent on a previous one.
* As it is not counted as a frame, bitrate increases but frame to time
@ -112,6 +115,7 @@ G_BEGIN_DECLS
*/
typedef enum {
GST_BASE_PARSE_FRAME_FLAG_NONE = 0,
GST_BASE_PARSE_FRAME_FLAG_NEW_FRAME = (1 << 0),
GST_BASE_PARSE_FRAME_FLAG_NO_FRAME = (1 << 0),
GST_BASE_PARSE_FRAME_FLAG_CLIP = (1 << 1),
GST_BASE_PARSE_FRAME_FLAG_DROP = (1 << 2),