#include "gstbaseparse.h"
+#define GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC (1 << 0)
+
#define MIN_FRAMES_TO_POST_BITRATE 10
#define TARGET_DIFFERENCE (20 * GST_SECOND)
static gboolean gst_base_parse_is_seekable (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)
copy = g_slice_dup (GstBaseParseFrame, frame);
copy->buffer = gst_buffer_ref (frame->buffer);
+ copy->_private_flags &= ~GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC;
+
return copy;
}
static void
gst_base_parse_frame_free (GstBaseParseFrame * frame)
{
- if (frame->buffer)
+ if (frame->buffer) {
gst_buffer_unref (frame->buffer);
- g_slice_free (GstBaseParseFrame, frame);
+ frame->buffer = NULL;
+ }
+
+ if (!(frame->_private_flags & GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC))
+ g_slice_free (GstBaseParseFrame, frame);
}
GType
* @frame: #GstBaseParseFrame.
*
* Sets a #GstBaseParseFrame to initial state. Currently this means
- * all fields are zero-ed.
+ * all public fields are zero-ed and a private flag is set to make
+ * sure gst_base_parse_frame_free() only frees the contents but not
+ * the actual frame. Use this function to initialise a #GstBaseParseFrame
+ * allocated on the stack.
*
* Since: 0.10.33
*/
void
gst_base_parse_frame_init (GstBaseParse * parse, GstBaseParseFrame * frame)
{
- memset (frame, 0, sizeof (*frame));
+ memset (frame, 0, sizeof (GstBaseParseFrame));
+ frame->_private_flags = GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC;
}
-/* clear == frame no longer to be used following this */
-static void
-gst_base_parse_frame_clear (GstBaseParse * parse, GstBaseParseFrame * frame)
+/**
+ * gst_base_parse_frame_new:
+ * @buffer: (transfer none): a #GstBuffer
+ * @flags: the flags
+ * @overhead: number of bytes in this frame which should be counted as
+ * metadata overhead, ie. not used to calculate the average bitrate.
+ * Set to -1 to mark the entire frame as metadata. If in doubt, set to 0.
+ *
+ * Allocates a new #GstBaseParseFrame. This function is mainly for bindings,
+ * elements written in C should usually allocate the frame on the stack and
+ * then use gst_base_parse_frame_init() to initialise it.
+ *
+ * Returns: a newly-allocated #GstBaseParseFrame. Free with
+ * gst_base_parse_frame_free() when no longer needed, unless you gave
+ * away ownership to gst_base_parse_push_frame().
+ *
+ * Since: 0.10.33
+ */
+GstBaseParseFrame *
+gst_base_parse_frame_new (GstBuffer * buffer, GstBaseParseFrameFlags flags,
+ gint overhead)
{
- /* limited for now */
- if (frame->buffer) {
- gst_buffer_unref (frame->buffer);
- frame->buffer = NULL;
- }
-}
+ GstBaseParseFrame *frame;
-/* copy frame (taking ownership of contents of passed frame) */
-static GstBaseParseFrame *
-gst_base_parse_frame_copy_and_clear (GstBaseParseFrame * frame)
-{
- GstBaseParseFrame *copy;
+ frame = g_slice_new0 (GstBaseParseFrame);
+ frame->buffer = gst_buffer_ref (buffer);
- copy = g_slice_dup (GstBaseParseFrame, frame);
- memset (frame, 0, sizeof (GstBaseParseFrame));
- return copy;
+ return frame;
}
static inline void
/* gst_base_parse_handle_and_push_buffer:
* @parse: #GstBaseParse.
* @klass: #GstBaseParseClass.
- * @buffer: #GstBuffer.
+ * @frame: (transfer full): a #GstBaseParseFrame
*
* Parses the frame from given buffer and pushes it forward. Also performs
* timestamp handling and checks the segment limits.
* frames to decide on the format and queues them internally */
/* convert internal flow to OK and mark discont for the next buffer. */
if (ret == GST_BASE_PARSE_FLOW_DROPPED) {
- gst_base_parse_frame_clear (parse, frame);
+ gst_base_parse_frame_free (frame);
return GST_FLOW_OK;
} else if (ret == GST_BASE_PARSE_FLOW_QUEUED) {
- g_queue_push_tail (&parse->priv->queued_frames,
- gst_base_parse_frame_copy_and_clear (frame));
+ if (!(frame->_private_flags & GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC)) {
+ /* frame allocated on the heap, we can just take ownership */
+ g_queue_push_tail (&parse->priv->queued_frames, frame);
+ } else {
+ /* probably allocated on the stack, must make a proper copy */
+ g_queue_push_tail (&parse->priv->queued_frames,
+ gst_base_parse_frame_copy (frame));
+ gst_base_parse_frame_free (frame);
+ }
return GST_FLOW_OK;
} else if (ret != GST_FLOW_OK) {
return ret;
/**
* gst_base_parse_push_frame:
* @parse: #GstBaseParse.
- * @frame: #GstBaseParseFrame.
+ * @frame: (transfer full): a #GstBaseParseFrame
*
* Pushes the frame downstream, sends any pending events and
- * does some timestamp and segment handling.
+ * does some timestamp and segment handling. Takes ownership
+ * of @frame and will clear it (if it was initialised with
+ * gst_base_parse_frame_init()) or free it.
*
* This must be called with sinkpad STREAM_LOCK held.
*
parse->segment.last_stop < last_stop)
gst_segment_set_last_stop (&parse->segment, GST_FORMAT_TIME, last_stop);
- gst_base_parse_frame_clear (parse, frame);
+ gst_base_parse_frame_free (frame);
return ret;
}
GstBaseParse *parse;
GstBaseParseClass *klass;
GstFlowReturn ret = GST_FLOW_OK;
- GstBaseParseFrame frame = { 0, };
+ GstBaseParseFrame frame;
parse = GST_BASE_PARSE (gst_pad_get_parent (pad));
klass = GST_BASE_PARSE_GET_CLASS (parse);
}
}
+ gst_base_parse_frame_init (parse, &frame);
ret = gst_base_parse_scan_frame (parse, klass, &frame, TRUE);
if (ret != GST_FLOW_OK)
goto done;
gboolean orig_drain, orig_discont;
GstFlowReturn ret = GST_FLOW_OK;
GstBuffer *buf = NULL;
- GstBaseParseFrame frame = { 0, };
+ GstBaseParseFrame frame;
g_return_val_if_fail (GST_FLOW_ERROR, pos != NULL);
g_return_val_if_fail (GST_FLOW_ERROR, time != NULL);
GST_DEBUG_OBJECT (parse, "scanning for frame starting at %" G_GINT64_FORMAT
" (%#" G_GINT64_MODIFIER "x)", *pos, *pos);
+ gst_base_parse_frame_init (parse, &frame);
+
/* jump elsewhere and locate next frame */
parse->priv->offset = *pos;
ret = gst_base_parse_scan_frame (parse, klass, &frame, FALSE);
/* but it should provide proper time */
*time = GST_BUFFER_TIMESTAMP (buf);
*duration = GST_BUFFER_DURATION (buf);
- gst_base_parse_frame_clear (parse, &frame);
+
+ gst_base_parse_frame_free (&frame);
GST_LOG_OBJECT (parse,
"frame with time %" GST_TIME_FORMAT " at offset %" G_GINT64_FORMAT,