baseparse: add another hook for subclass prior to pushing buffer

... and allow subclass to perform custom segment clipping, or to
emit tags or messages at this time.
This commit is contained in:
Mark Nauwelaerts 2010-09-17 17:21:46 +02:00 committed by Tim-Philipp Müller
parent b51b5d4b29
commit 4b0f92db79
2 changed files with 67 additions and 17 deletions

View file

@ -1063,6 +1063,7 @@ gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer)
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);
GST_LOG_OBJECT (parse,
"processing buffer of size %d with ts %" GST_TIME_FORMAT
@ -1142,24 +1143,42 @@ gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer)
/* TODO: Add to seek table */
if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
GST_CLOCK_TIME_IS_VALID (parse->segment.stop) &&
GST_BUFFER_TIMESTAMP (buffer) > parse->segment.stop) {
GST_LOG_OBJECT (parse, "Dropped frame, after segment");
if (klass->pre_push_buffer)
ret = klass->pre_push_buffer (parse, buffer);
else
ret = GST_BASE_PARSE_FLOW_CLIP;
if (ret == GST_BASE_PARSE_FLOW_CLIP) {
if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
GST_CLOCK_TIME_IS_VALID (parse->segment.stop) &&
GST_BUFFER_TIMESTAMP (buffer) > parse->segment.stop) {
GST_LOG_OBJECT (parse, "Dropped frame, after segment");
ret = GST_FLOW_UNEXPECTED;
} else if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
GST_BUFFER_DURATION_IS_VALID (buffer) &&
GST_CLOCK_TIME_IS_VALID (parse->segment.start) &&
GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer)
< parse->segment.start) {
GST_LOG_OBJECT (parse, "Dropped frame, before segment");
ret = GST_BASE_PARSE_FLOW_DROPPED;
} else {
ret = GST_FLOW_OK;
}
}
if (ret == GST_BASE_PARSE_FLOW_DROPPED) {
GST_LOG_OBJECT (parse, "frame (%d bytes) dropped",
GST_BUFFER_SIZE (buffer));
gst_buffer_unref (buffer);
} else if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
GST_BUFFER_DURATION_IS_VALID (buffer) &&
GST_CLOCK_TIME_IS_VALID (parse->segment.start) &&
GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer)
< parse->segment.start) {
/* FIXME: subclass needs way to override the start as downstream might
* need frames before for proper decoding */
GST_LOG_OBJECT (parse, "Dropped frame, before segment");
gst_buffer_unref (buffer);
} else {
ret = GST_FLOW_OK;
} else if (ret == GST_FLOW_OK) {
ret = gst_pad_push (parse->srcpad, buffer);
GST_LOG_OBJECT (parse, "frame (%d bytes) pushed: %d",
GST_BUFFER_SIZE (buffer), ret);
GST_LOG_OBJECT (parse, "frame (%d bytes) pushed: %s",
GST_BUFFER_SIZE (buffer), gst_flow_get_name (ret));
} else {
gst_buffer_unref (buffer);
GST_LOG_OBJECT (parse, "frame (%d bytes) not pushed: %s",
GST_BUFFER_SIZE (buffer), gst_flow_get_name (ret));
}
/* Update current running segment position */

View file

@ -68,16 +68,37 @@ G_BEGIN_DECLS
*/
#define GST_BASE_PARSE_SINK_PAD(obj) (GST_BASE_PARSE_CAST (obj)->sinkpad)
/**
* GST_BASE_PARSE_SEGMENT:
* @obj: base parse instance
*
* Gives the segment of the element.
*
* Since: 0.10.x
*/
#define GST_BASE_PARSE_SEGMENT(obj) (GST_BASE_PARSE_CAST (obj)->segment)
/**
* GST_BASE_PARSE_FLOW_DROPPED:
*
* A #GstFlowReturn that can be returned from parse_frame to
* indicate that no output buffer was generated.
* indicate that no output buffer was generated, or from pre_push_buffer to
* to forego pushing buffer.
*
* Since: 0.10.x
*/
#define GST_BASE_PARSE_FLOW_DROPPED GST_FLOW_CUSTOM_SUCCESS
/**
* GST_BASE_PARSE_FLOW_CLIP:
*
* A #GstFlowReturn that can be returned from pre_push_buffer to
* indicate that regular segment clipping should be performed.
*
* Since: 0.10.x
*/
#define GST_BASE_PARSE_FLOW_CLIP GST_FLOW_CUSTOM_SUCCESS_1
/**
* GST_BASE_PARSE_BUFFER_FLAG_NO_FRAME:
*
@ -186,6 +207,13 @@ struct _GstBaseParse {
* this returns -1, it is assumed that this frame should
* be skipped in bitrate calculation.
*
* @pre_push_buffer: Optional.
* Called just prior to pushing a frame (after any pending
* events have been sent) to give subclass a chance to perform
* additional actions at this time (e.g. tag sending) or to
* decide whether this buffer should be dropped or no
* (e.g. custom segment clipping).
*
* Subclasses can override any of the available virtual methods or not, as
* needed. At minimum @check_valid_frame and @parse_frame needs to be
* overridden.
@ -233,6 +261,9 @@ struct _GstBaseParseClass {
gint (*get_frame_overhead) (GstBaseParse *parse,
GstBuffer *buf);
GstFlowReturn (*pre_push_buffer) (GstBaseParse *parse,
GstBuffer *buf);
/*< private >*/
gpointer _gst_reserved[GST_PADDING_LARGE];
};