static void gst_base_parse_loop (GstPad * pad);
static gboolean gst_base_parse_check_frame (GstBaseParse * parse,
- GstBuffer * buffer, guint * framesize, gint * skipsize);
-
+ GstBaseParseFrame * frame, guint * framesize, gint * skipsize);
static GstFlowReturn gst_base_parse_parse_frame (GstBaseParse * parse,
- GstBuffer * buffer);
+ GstBaseParseFrame * frame);
static gboolean gst_base_parse_sink_eventfunc (GstBaseParse * parse,
GstEvent * event);
GST_DEBUG_OBJECT (parse, "init ok");
}
+/**
+ * gst_base_parse_frame_init:
+ * @parse: #GstBaseParse.
+ * @fmt: #GstBaseParseFrame.
+ *
+ * Sets a #GstBaseParseFrame to initial state. Currently this means
+ * all fields are zero-ed.
+ */
+void
+gst_base_parse_frame_init (GstBaseParse * parse, GstBaseParseFrame * frame)
+{
+ memset (frame, 0, sizeof (*frame));
+}
+
+/* clear == frame no longer to be used following this */
+static void
+gst_base_parse_frame_clear (GstBaseParse * parse, GstBaseParseFrame * frame)
+{
+ /* limited for now */
+ if (frame->buffer) {
+ gst_buffer_unref (frame->buffer);
+ frame->buffer = NULL;
+ }
+}
+
+static inline void
+gst_base_parse_frame_update (GstBaseParse * parse, GstBaseParseFrame * frame,
+ GstBuffer * buf)
+{
+ gst_buffer_replace (&frame->buffer, buf);
+ if (parse->priv->drain) {
+ frame->flags |= GST_BASE_PARSE_FRAME_FLAG_DRAIN;
+ } else {
+ frame->flags &= ~(GST_BASE_PARSE_FRAME_FLAG_DRAIN);
+ }
+ /* losing sync is pretty much a discont (and vice versa), no ? */
+ if (!parse->priv->discont) {
+ frame->flags |= GST_BASE_PARSE_FRAME_FLAG_SYNC;
+ } else {
+ frame->flags &= ~(GST_BASE_PARSE_FRAME_FLAG_SYNC);
+ }
+}
+
static void
gst_base_parse_reset (GstBaseParse * parse)
{
*/
static gboolean
gst_base_parse_check_frame (GstBaseParse * parse,
- GstBuffer * buffer, guint * framesize, gint * skipsize)
+ GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
{
- *framesize = GST_BUFFER_SIZE (buffer);
+ *framesize = GST_BUFFER_SIZE (frame->buffer);
*skipsize = 0;
return TRUE;
}
* Default callback for parse_frame.
*/
static GstFlowReturn
-gst_base_parse_parse_frame (GstBaseParse * parse, GstBuffer * buffer)
+gst_base_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
{
+ GstBuffer *buffer = frame->buffer;
+
if (!GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
GST_CLOCK_TIME_IS_VALID (parse->priv->next_ts)) {
GST_BUFFER_TIMESTAMP (buffer) = parse->priv->next_ts;
* running average bitrate of the stream so far.
*/
static void
-gst_base_parse_update_bitrates (GstBaseParse * parse, GstBuffer * buffer)
+gst_base_parse_update_bitrates (GstBaseParse * parse, GstBaseParseFrame * frame)
{
/* Only update the tag on a 10 kbps delta */
static const gint update_threshold = 10000;
GstBaseParseClass *klass;
guint64 data_len, frame_dur;
- gint overhead = 0, frame_bitrate, old_avg_bitrate;
+ gint overhead, frame_bitrate, old_avg_bitrate;
gboolean update_min = FALSE, update_avg = FALSE, update_max = FALSE;
+ GstBuffer *buffer = frame->buffer;
klass = GST_BASE_PARSE_GET_CLASS (parse);
- if (klass->get_frame_overhead) {
- overhead = klass->get_frame_overhead (parse, buffer);
- if (overhead == -1)
- return;
- }
+ overhead = frame->overhead;
+ if (overhead == -1)
+ return;
data_len = GST_BUFFER_SIZE (buffer) - overhead;
parse->priv->data_bytecount += data_len;
* Returns: #GstFlowReturn
*/
static GstFlowReturn
-gst_base_parse_handle_and_push_buffer (GstBaseParse * parse,
- GstBaseParseClass * klass, GstBuffer * buffer)
+gst_base_parse_handle_and_push_frame (GstBaseParse * parse,
+ GstBaseParseClass * klass, GstBaseParseFrame * frame)
{
GstFlowReturn ret;
gint64 offset;
+ GstBuffer *buffer;
+
+ g_return_val_if_fail (frame != NULL, GST_FLOW_ERROR);
+
+ buffer = frame->buffer;
if (parse->priv->discont) {
GST_DEBUG_OBJECT (parse, "marking DISCONT");
/* store offset as it might get overwritten */
offset = GST_BUFFER_OFFSET (buffer);
- ret = klass->parse_frame (parse, buffer);
+ ret = klass->parse_frame (parse, frame);
+ /* sync */
+ buffer = frame->buffer;
+ /* subclass must play nice */
+ g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
/* check initial frame to determine if subclass/format can provide ts.
* If so, that allows and enables extra seek and duration determining options */
}
/* re-use default handler to add missing metadata as-much-as-possible */
- gst_base_parse_parse_frame (parse, buffer);
+ gst_base_parse_parse_frame (parse, frame);
if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
GST_BUFFER_DURATION_IS_VALID (buffer)) {
parse->priv->next_ts =
* 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_buffer_unref (buffer);
+ gst_base_parse_frame_clear (parse, frame);
return GST_FLOW_OK;
} else if (ret != GST_FLOW_OK) {
return ret;
}
- return gst_base_parse_push_buffer (parse, buffer);
+ return gst_base_parse_push_frame (parse, frame);
}
/**
- * gst_base_parse_push_buffer:
+ * gst_base_parse_push_frame:
* @parse: #GstBaseParse.
- * @buffer: #GstBuffer.
+ * @frame: #GstBaseParseFrame.
*
- * Pushes the buffer downstream, sends any pending events and
+ * Pushes the frame downstream, sends any pending events and
* does some timestamp and segment handling.
*
- * This must be called with srcpad STREAM_LOCK held.
+ * This must be called with sinkpad STREAM_LOCK held.
*
* Returns: #GstFlowReturn
*/
GstFlowReturn
-gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer)
+gst_base_parse_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
{
GstFlowReturn ret = GST_FLOW_OK;
GstClockTime last_start = GST_CLOCK_TIME_NONE;
GstClockTime last_stop = GST_CLOCK_TIME_NONE;
GstBaseParseClass *klass = GST_BASE_PARSE_GET_CLASS (parse);
+ GstBuffer *buffer;
+
+ g_return_val_if_fail (frame != NULL, GST_FLOW_ERROR);
+ g_return_val_if_fail (frame->buffer != NULL, GST_FLOW_ERROR);
+
+ buffer = frame->buffer;
GST_LOG_OBJECT (parse,
"processing buffer of size %d with ts %" GST_TIME_FORMAT
/* update stats */
parse->priv->bytecount += GST_BUFFER_SIZE (buffer);
- if (!GST_BUFFER_FLAG_IS_SET (buffer, GST_BASE_PARSE_BUFFER_FLAG_NO_FRAME)) {
+ if (G_LIKELY (!(frame->flags & GST_BASE_PARSE_FRAME_FLAG_NO_FRAME))) {
parse->priv->framecount++;
if (GST_BUFFER_DURATION_IS_VALID (buffer)) {
parse->priv->acc_duration += GST_BUFFER_DURATION (buffer);
}
}
- GST_BUFFER_FLAG_UNSET (buffer, GST_BASE_PARSE_BUFFER_FLAG_NO_FRAME);
if (parse->priv->update_interval &&
(parse->priv->framecount % parse->priv->update_interval) == 0)
gst_base_parse_update_duration (parse);
/* should have caps by now */
g_return_val_if_fail (GST_PAD_CAPS (parse->srcpad), GST_FLOW_ERROR);
- gst_buffer_set_caps (buffer, GST_PAD_CAPS (parse->srcpad));
-
/* segment adjustment magic; only if we are running the whole show */
if (!parse->priv->passthrough && parse->segment.rate > 0.0 &&
(parse->priv->pad_mode == GST_ACTIVATE_PULL ||
/* update bitrates and optionally post corresponding tags
* (following newsegment) */
- gst_base_parse_update_bitrates (parse, buffer);
+ gst_base_parse_update_bitrates (parse, frame);
if (G_UNLIKELY (parse->priv->pending_events)) {
GList *l;
parse->priv->pending_events = NULL;
}
- if (klass->pre_push_buffer)
- ret = klass->pre_push_buffer (parse, buffer);
- else
- ret = GST_BASE_PARSE_FLOW_CLIP;
+ if (klass->pre_push_frame) {
+ ret = klass->pre_push_frame (parse, frame);
+ } else {
+ frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP;
+ }
+
+ /* take final ownership of frame buffer */
+ buffer = frame->buffer;
+ frame->buffer = NULL;
+
+ /* subclass must play nice */
+ g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
+
+ /* decorate */
+ gst_buffer_set_caps (buffer, GST_PAD_CAPS (parse->srcpad));
parse->priv->seen_keyframe |= parse->priv->is_video &&
!GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
- if (ret == GST_BASE_PARSE_FLOW_CLIP) {
+ if (frame->flags & GST_BASE_PARSE_FRAME_FLAG_CLIP) {
if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
GST_CLOCK_TIME_IS_VALID (parse->segment.stop) &&
GST_BUFFER_TIMESTAMP (buffer) >
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);
+
return ret;
}
const guint8 *data;
guint old_min_size = 0, min_size, av;
GstClockTime timestamp;
+ GstBaseParseFrame _frame = { 0, };
+ GstBaseParseFrame *frame;
parse = GST_BASE_PARSE (GST_OBJECT_PARENT (pad));
bclass = GST_BASE_PARSE_GET_CLASS (parse);
+ frame = &_frame;
if (G_LIKELY (buffer)) {
GST_LOG_OBJECT (parse, "buffer size: %d, offset = %" G_GINT64_FORMAT,
GST_BUFFER_SIZE (buffer), GST_BUFFER_OFFSET (buffer));
if (G_UNLIKELY (parse->priv->passthrough)) {
- buffer = gst_buffer_make_metadata_writable (buffer);
- return gst_base_parse_push_buffer (parse, buffer);
+ frame->buffer = gst_buffer_make_metadata_writable (buffer);
+ return gst_base_parse_push_frame (parse, frame);
}
/* upstream feeding us in reverse playback;
* gather each fragment, then process it in single run */
/* Parse and push as many frames as possible */
/* Stop either when adapter is empty or we are flushing */
while (!parse->priv->flushing) {
+ gboolean res;
+
tmpbuf = gst_buffer_new ();
old_min_size = 0;
}
skip = -1;
- if (bclass->check_valid_frame (parse, tmpbuf, &fsize, &skip)) {
+ gst_base_parse_frame_update (parse, frame, tmpbuf);
+ res = bclass->check_valid_frame (parse, frame, &fsize, &skip);
+ gst_buffer_replace (&frame->buffer, NULL);
+ if (res) {
if (gst_adapter_available (parse->adapter) < fsize) {
GST_DEBUG_OBJECT (parse,
"found valid frame but not enough data available (only %d bytes)",
parse->priv->prev_ts = parse->priv->next_ts = timestamp;
}
- ret = gst_base_parse_handle_and_push_buffer (parse, bclass, outbuf);
+ frame->buffer = outbuf;
+ ret = gst_base_parse_handle_and_push_frame (parse, bclass, frame);
GST_PAD_STREAM_UNLOCK (parse->srcpad);
if (ret != GST_FLOW_OK) {
* ajusts sync, drain and offset going along */
static GstFlowReturn
gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass,
- GstBuffer ** buf, gboolean full)
+ GstBaseParseFrame * frame, gboolean full)
{
GstBuffer *buffer, *outbuf;
GstFlowReturn ret = GST_FLOW_OK;
guint fsize = 0, min_size, old_min_size = 0;
gint skip = 0;
- g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);
+ g_return_val_if_fail (frame != NULL, GST_FLOW_ERROR);
GST_LOG_OBJECT (parse, "scanning for frame at offset %" G_GUINT64_FORMAT
" (%#" G_GINT64_MODIFIER "x)", parse->priv->offset, parse->priv->offset);
while (TRUE) {
+ gboolean res;
min_size = MAX (parse->priv->min_frame_size, fsize);
/* loop safety check */
parse->priv->drain = TRUE;
skip = -1;
- if (klass->check_valid_frame (parse, buffer, &fsize, &skip)) {
+ gst_base_parse_frame_update (parse, frame, buffer);
+ res = klass->check_valid_frame (parse, frame, &fsize, &skip);
+ gst_buffer_replace (&frame->buffer, NULL);
+ if (res) {
parse->priv->drain = FALSE;
GST_LOG_OBJECT (parse, "valid frame of size %d at pos %d", fsize, skip);
break;
parse->priv->offset += fsize;
- *buf = outbuf;
+ frame->buffer = outbuf;
done:
return ret;
{
GstBaseParse *parse;
GstBaseParseClass *klass;
- GstBuffer *outbuf;
GstFlowReturn ret = GST_FLOW_OK;
+ GstBaseParseFrame frame = { 0, };
parse = GST_BASE_PARSE (gst_pad_get_parent (pad));
klass = GST_BASE_PARSE_GET_CLASS (parse);
}
}
- ret = gst_base_parse_scan_frame (parse, klass, &outbuf, TRUE);
+ ret = gst_base_parse_scan_frame (parse, klass, &frame, TRUE);
if (ret != GST_FLOW_OK)
goto done;
- /* This always unrefs the outbuf, even if error occurs */
- ret = gst_base_parse_handle_and_push_buffer (parse, klass, outbuf);
+ /* This always cleans up frame, even if error occurs */
+ ret = gst_base_parse_handle_and_push_frame (parse, klass, &frame);
/* eat expected eos signalling past segment in reverse playback */
if (parse->segment.rate < 0.0 && ret == GST_FLOW_UNEXPECTED &&
lead_out, parse->priv->lead_out_ts / GST_MSECOND);
}
-/**
- * gst_base_parse_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);
-
- /* losing sync is pretty much a discont (and vice versa), no ? */
- ret = !parse->priv->discont;
-
- GST_DEBUG_OBJECT (parse, "sync: %d", ret);
- return ret;
-}
-
-/**
- * gst_base_parse_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);
-
- /* losing sync is pretty much a discont (and vice versa), no ? */
- ret = parse->priv->drain;
-
- GST_DEBUG_OBJECT (parse, "drain: %d", ret);
- return ret;
-}
-
static gboolean
gst_base_parse_get_duration (GstBaseParse * parse, GstFormat format,
GstClockTime * duration)
gboolean orig_drain, orig_discont;
GstFlowReturn ret = GST_FLOW_OK;
GstBuffer *buf = NULL;
+ GstBaseParseFrame frame = { 0, };
g_return_val_if_fail (GST_FLOW_ERROR, pos != NULL);
g_return_val_if_fail (GST_FLOW_ERROR, time != NULL);
/* jump elsewhere and locate next frame */
parse->priv->offset = *pos;
- ret = gst_base_parse_scan_frame (parse, klass, &buf, FALSE);
+ ret = gst_base_parse_scan_frame (parse, klass, &frame, FALSE);
if (ret != GST_FLOW_OK)
goto done;
+ buf = frame.buffer;
GST_LOG_OBJECT (parse,
"peek parsing frame at offset %" G_GUINT64_FORMAT
" (%#" G_GINT64_MODIFIER "x) of size %d",
/* get offset first, subclass parsing might dump other stuff in there */
*pos = GST_BUFFER_OFFSET (buf);
- ret = klass->parse_frame (parse, buf);
+ ret = klass->parse_frame (parse, &frame);
+ buf = frame.buffer;
/* but it should provide proper time */
*time = GST_BUFFER_TIMESTAMP (buf);
*duration = GST_BUFFER_DURATION (buf);
- gst_buffer_unref (buf);
+ gst_base_parse_frame_clear (parse, &frame);
GST_LOG_OBJECT (parse,
"frame with time %" GST_TIME_FORMAT " at offset %" G_GINT64_FORMAT,
#define GST_BASE_PARSE_FLOW_DROPPED GST_FLOW_CUSTOM_SUCCESS
/**
- * GST_BASE_PARSE_FLOW_CLIP:
+ * GstBaseParseFrameFlags:
+ * @GST_BASE_PARSE_FRAME_FLAG_NONE: no flag
+ * @GST_BASE_PARSE_FRAME_FLAG_SYNC: indicates if parsing is 'in sync'
+ * @GST_BASE_PARSE_FRAME_FLAG_DRAIN: indicates if parser is 'draining'.
+ * That is, leftover data (e.g. in FLUSH or EOS situation) is being parsed.
+ * @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
+ * conversions are maintained.
+ * @GST_BASE_PARSE_FRAME_FLAG_CLIP: @pre_push_buffer can set this to indicate
+ * that regular segment clipping can still be performed (as opposed to
+ * any custom one having been done).
*
- * A #GstFlowReturn that can be returned from pre_push_buffer to
- * indicate that regular segment clipping should be performed.
+ * Flags to be used in a #GstBaseParseFrame.
*
* Since: 0.10.x
*/
-#define GST_BASE_PARSE_FLOW_CLIP GST_FLOW_CUSTOM_SUCCESS_1
+typedef enum {
+ GST_BASE_PARSE_FRAME_FLAG_NONE = 0,
+ GST_BASE_PARSE_FRAME_FLAG_SYNC = (1 << 0),
+ GST_BASE_PARSE_FRAME_FLAG_DRAIN = (1 << 1),
+ GST_BASE_PARSE_FRAME_FLAG_NO_FRAME = (1 << 2),
+ GST_BASE_PARSE_FRAME_FLAG_CLIP = (1 << 3)
+} GstBaseParseFrameFlags;
/**
- * GST_BASE_PARSE_BUFFER_FLAG_NO_FRAME:
+ * GstBaseParseFrame:
+ * @buffer: data to check for valid frame or parsed frame.
+ * Subclass is allowed to replace this buffer.
+ * @overhead: subclass can set this to indicates the metadata overhead
+ * for the given frame, which is then used to enable more accurate bitrate
+ * computations. If this is -1, it is assumed that this frame should be
+ * skipped in bitrate calculation.
+ * @flags: a combination of input and output #GstBaseParseFrameFlags that
+ * convey additional context to subclass or allow subclass to tune
+ * subsequent #GstBaseParse actions.
*
- * A #GstBufferFlag that can be set to have this buffer not 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 conversions are maintained.
+ * Frame (context) data passed to each frame parsing virtual methods. In
+ * addition to providing the data to be checked for a valid frame or an already
+ * identified frame, it conveys additional metadata or control information
+ * from and to the subclass w.r.t. the particular frame in question (rather
+ * than global parameters). Some of these may apply to each parsing stage, others
+ * only to some a particular one. These parameters are effectively zeroed at start
+ * of each frame's processing, i.e. parsing virtual method invocation sequence.
*
* Since: 0.10.x
*/
-#define GST_BASE_PARSE_BUFFER_FLAG_NO_FRAME GST_BUFFER_FLAG_LAST
+typedef struct {
+ GstBuffer *buffer;
+ guint flags;
+ gint overhead;
+} GstBaseParseFrame;
+
+/**
+ * GST_BASE_PARSE_FRAME_SYNC:
+ * @frame: base parse frame instance
+ *
+ * Obtains current sync status indicated in frame.
+ *
+ * Since: 0.10.x
+ */
+#define GST_BASE_PARSE_FRAME_SYNC(frame) (!!(frame->flags & GST_BASE_PARSE_FRAME_FLAG_SYNC))
+
+/**
+ * GST_BASE_PARSE_FRAME_DRAIN:
+ * @frame: base parse frame instance
+ *
+ * Obtains current drain status indicated in frame.
+ *
+ * Since: 0.10.x
+ */
+#define GST_BASE_PARSE_FRAME_DRAIN(frame) (!!(frame->flags & GST_BASE_PARSE_FRAME_FLAG_DRAIN))
/**
* GST_BASE_PARSE_SEEK_TABLE: Additional metadata provides more accurate seeking.
*
* Indicates what level (of quality) of seeking is possible.
+ *
+ * Since: 0.10.x
*/
typedef enum _GstBaseParseSeekable {
GST_BASE_PARSE_SEEK_NONE,
GstCaps *caps);
gboolean (*check_valid_frame) (GstBaseParse *parse,
- GstBuffer *buffer,
+ GstBaseParseFrame *frame,
guint *framesize,
gint *skipsize);
GstFlowReturn (*parse_frame) (GstBaseParse *parse,
- GstBuffer *buffer);
+ GstBaseParseFrame *frame);
+
+ GstFlowReturn (*pre_push_frame) (GstBaseParse *parse,
+ GstBaseParseFrame *frame);
gboolean (*convert) (GstBaseParse * parse,
GstFormat src_format,
gboolean (*src_event) (GstBaseParse *parse,
GstEvent *event);
- gint (*get_frame_overhead) (GstBaseParse *parse,
- GstBuffer *buf);
-
- GstFlowReturn (*pre_push_buffer) (GstBaseParse *parse,
- GstBuffer *buf);
-
/*< private >*/
- gpointer _gst_reserved[GST_PADDING_LARGE];
+ gpointer _gst_reserved[GST_PADDING_LARGE];
};
GType gst_base_parse_get_type (void);
+void gst_base_parse_frame_init (GstBaseParse * parse, GstBaseParseFrame * frame);
-GstFlowReturn gst_base_parse_push_buffer (GstBaseParse *parse,
- GstBuffer *buffer);
+GstFlowReturn gst_base_parse_push_frame (GstBaseParse *parse,
+ GstBaseParseFrame *frame);
void gst_base_parse_set_duration (GstBaseParse *parse,
GstFormat fmt, gint64 duration, gint interval);
void gst_base_parse_set_seek (GstBaseParse * parse,
GstBaseParseSeekable seek, guint bitrate);
-void gst_base_parse_set_min_frame_size (GstBaseParse *parse,
- guint min_size);
+void gst_base_parse_set_min_frame_size (GstBaseParse *parse, guint min_size);
+
void gst_base_parse_set_passthrough (GstBaseParse * parse, gboolean passthrough);
void gst_base_parse_set_frame_props (GstBaseParse * parse, guint fps_num,
guint fps_den, guint lead_in, guint lead_out);
-gboolean gst_base_parse_get_sync (GstBaseParse * parse);
-
-gboolean gst_base_parse_get_drain (GstBaseParse * parse);
-
gboolean gst_base_parse_convert_default (GstBaseParse * parse,
GstFormat src_format, gint64 src_value,
GstFormat dest_format, gint64 * dest_value);