From 0198d6320b3f6c72eca7b9ea7d6fd2d251c02251 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Fri, 17 Sep 2010 18:24:22 +0200 Subject: [PATCH] baseparse: remove is_seekable vmethod and use a set_seek instead Seekability, like duration, etc is unlikely to change (frequently), and the default assumption covers most cases, so let subclass set when needed. At the same time, allow subclass to indicate if it has seek-metadata (table) available, and possibly have it provide an average bitrate. --- gst/audioparsers/gstaacparse.c | 28 ++++------------------ gst/audioparsers/gstbaseparse.c | 52 ++++++++++++++++++++++++++--------------- gst/audioparsers/gstbaseparse.h | 24 ++++++++++++++----- 3 files changed, 55 insertions(+), 49 deletions(-) diff --git a/gst/audioparsers/gstaacparse.c b/gst/audioparsers/gstaacparse.c index c1012ba..50cb9e4 100644 --- a/gst/audioparsers/gstaacparse.c +++ b/gst/audioparsers/gstaacparse.c @@ -95,8 +95,6 @@ gboolean gst_aacparse_convert (GstBaseParse * parse, GstFormat src_format, gint64 src_value, GstFormat dest_format, gint64 * dest_value); -gboolean gst_aacparse_is_seekable (GstBaseParse * parse); - gint gst_aacparse_get_frame_overhead (GstBaseParse * parse, GstBuffer * buffer); gboolean gst_aacparse_event (GstBaseParse * parse, GstEvent * event); @@ -158,7 +156,6 @@ gst_aacparse_class_init (GstAacParseClass * klass) parse_class->start = GST_DEBUG_FUNCPTR (gst_aacparse_start); parse_class->stop = GST_DEBUG_FUNCPTR (gst_aacparse_stop); parse_class->set_sink_caps = GST_DEBUG_FUNCPTR (gst_aacparse_sink_setcaps); - parse_class->is_seekable = GST_DEBUG_FUNCPTR (gst_aacparse_is_seekable); parse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_aacparse_parse_frame); parse_class->check_valid_frame = GST_DEBUG_FUNCPTR (gst_aacparse_check_valid_frame); @@ -492,6 +489,10 @@ gst_aacparse_detect_stream (GstAacParse * aacparse, aacparse->header_type = DSPAAC_HEADER_ADIF; aacparse->mpegversion = 4; + /* no way to seek this */ + gst_base_parse_set_seek (GST_BASE_PARSE (aacparse), + GST_BASE_PARSE_SEEK_NONE, 0); + /* Skip the "ADIF" bytes */ adif = data + i + 4; @@ -689,27 +690,6 @@ gst_aacparse_stop (GstBaseParse * parse) /** - * gst_aacparse_is_seekable: - * @parse: #GstBaseParse. - * - * Implementation of "is_seekable" vmethod in #GstBaseParse class. - * - * Returns: TRUE if the current stream is seekable. - */ -gboolean -gst_aacparse_is_seekable (GstBaseParse * parse) -{ - GstAacParse *aacparse; - - aacparse = GST_AACPARSE (parse); - GST_DEBUG_OBJECT (aacparse, "IS_SEEKABLE: %d", - aacparse->header_type != DSPAAC_HEADER_ADIF); - - /* Not seekable if ADIF header is found */ - return (aacparse->header_type != DSPAAC_HEADER_ADIF); -} - -/** * gst_aacparse_get_frame_overhead: * @parse: #GstBaseParse. * @buffer: #GstBuffer. diff --git a/gst/audioparsers/gstbaseparse.c b/gst/audioparsers/gstbaseparse.c index 23ea2b0..ea89b25 100644 --- a/gst/audioparsers/gstbaseparse.c +++ b/gst/audioparsers/gstbaseparse.c @@ -218,6 +218,8 @@ struct _GstBaseParsePrivate gboolean passthrough; guint fps_num, fps_den; guint update_interval; + guint bitrate; + GstBaseParseSeekable seekable; gboolean discont; gboolean flushing; @@ -307,8 +309,6 @@ static gboolean gst_base_parse_sink_eventfunc (GstBaseParse * parse, static gboolean gst_base_parse_src_eventfunc (GstBaseParse * parse, GstEvent * event); -static gboolean gst_base_parse_is_seekable (GstBaseParse * parse); - static void gst_base_parse_drain (GstBaseParse * parse); static void gst_base_parse_post_bitrates (GstBaseParse * parse, @@ -359,7 +359,6 @@ gst_base_parse_class_init (GstBaseParseClass * klass) klass->check_valid_frame = gst_base_parse_check_frame; klass->parse_frame = gst_base_parse_parse_frame; klass->src_event = gst_base_parse_src_eventfunc; - klass->is_seekable = gst_base_parse_is_seekable; klass->convert = gst_base_parse_convert_default; GST_DEBUG_CATEGORY_INIT (gst_base_parse_debug, "baseparse", 0, @@ -752,7 +751,7 @@ gst_base_parse_src_eventfunc (GstBaseParse * parse, GstEvent * event) switch (GST_EVENT_TYPE (event)) { case GST_EVENT_SEEK: { - if (bclass->is_seekable (parse)) { + if (parse->priv->seekable > GST_BASE_PARSE_SEEK_NONE) { handled = gst_base_parse_handle_seek (parse, event); } break; @@ -765,20 +764,6 @@ gst_base_parse_src_eventfunc (GstBaseParse * parse, GstEvent * event) /** - * gst_base_parse_is_seekable: - * @parse: #GstBaseParse. - * - * Default handler for is_seekable. - * - * Returns: Always TRUE. - */ -static gboolean -gst_base_parse_is_seekable (GstBaseParse * parse) -{ - return TRUE; -} - -/** * gst_base_parse_convert_default: * @parse: #GstBaseParse. * @src_format: #GstFormat describing the source format. @@ -965,6 +950,11 @@ gst_base_parse_update_bitrates (GstBaseParse * parse, GstBuffer * buffer) return; } + /* override if subclass provided bitrate, e.g. metadata based */ + if (parse->priv->bitrate) { + parse->priv->avg_bitrate = parse->priv->bitrate; + } + frame_bitrate = (8 * data_len * GST_SECOND) / frame_dur; if (frame_bitrate < parse->priv->min_bitrate) { @@ -1628,6 +1618,8 @@ gst_base_parse_activate (GstBaseParse * parse, gboolean active) parse->priv->update_interval = 0; parse->priv->fps_num = parse->priv->fps_den = 0; parse->priv->frame_duration = GST_CLOCK_TIME_NONE; + parse->priv->seekable = GST_BASE_PARSE_SEEK_DEFAULT; + parse->priv->bitrate = 0; parse->priv->framecount = 0; parse->priv->bytecount = 0; parse->priv->acc_duration = 0; @@ -1773,6 +1765,27 @@ gst_base_parse_set_duration (GstBaseParse * parse, GST_BASE_PARSE_UNLOCK (parse); } +/** + * gst_base_parse_set_seek: + * @parse: #GstBaseParse. + * @seek: #GstBaseParseSeekable. + * @abitrate: average bitrate. + * + * Sets whether and how the media is seekable (in time). + * Also optionally provides average bitrate detected in media (if non-zero), + * e.g. based on metadata, as it will be posted to the application. + * + * By default, announced average bitrate is estimated, and seekability is assumed + * possible based on estimated bitrate. + */ +void +gst_base_parse_set_seek (GstBaseParse * parse, + GstBaseParseSeekable seek, guint bitrate) +{ + parse->priv->seekable = seek; + parse->priv->bitrate = bitrate; +} + /** * gst_base_parse_set_min_frame_size: @@ -2038,7 +2051,8 @@ gst_base_parse_query (GstPad * pad, GstQuery * query) res = gst_pad_query_default (pad, query); /* we may be able to help if in TIME */ - if (fmt == GST_FORMAT_TIME && klass->is_seekable (parse)) { + if (fmt == GST_FORMAT_TIME && + parse->priv->seekable > GST_BASE_PARSE_SEEK_NONE) { gst_query_parse_seeking (query, &fmt, &seekable, NULL, NULL); /* already OK if upstream takes care */ GST_LOG_OBJECT (parse, "upstream handled %d, seekable %d", diff --git a/gst/audioparsers/gstbaseparse.h b/gst/audioparsers/gstbaseparse.h index b31c853..ccb761d 100644 --- a/gst/audioparsers/gstbaseparse.h +++ b/gst/audioparsers/gstbaseparse.h @@ -130,6 +130,21 @@ G_BEGIN_DECLS */ #define GST_BASE_PARSE_UNLOCK(obj) g_mutex_unlock (GST_BASE_PARSE_CAST (obj)->parse_lock) + +/** + * GstBaseParseSeekable: + * @GST_BASE_PARSE_SEEK_NONE: No seeking possible. + * GST_BASE_PARSE_SEEK_DEFAULT: Default seeking possible using estimated bitrate. + * GST_BASE_PARSE_SEEK_TABLE: Additional metadata provides more accurate seeking. + * + * Indicates what level (of quality) of seeking is possible. + */ +typedef enum _GstBaseParseSeekable { + GST_BASE_PARSE_SEEK_NONE, + GST_BASE_PARSE_SEEK_DEFAULT, + GST_BASE_PARSE_SEEK_TABLE +} GstBaseParseSeekable; + typedef struct _GstBaseParse GstBaseParse; typedef struct _GstBaseParseClass GstBaseParseClass; typedef struct _GstBaseParsePrivate GstBaseParsePrivate; @@ -196,10 +211,6 @@ struct _GstBaseParse { * @src_event: Optional. * Event handler on the source pad. Should return TRUE * if the event was handled and can be dropped. - * @is_seekable: Optional. - * Subclass can override this if it wants to control the - * seekability of the stream. Otherwise the element assumes - * that stream is always seekable. * * @get_frame_overhead: Finds the metadata overhead for the given frame. This * is used to enable more accurate bitrate computations. @@ -256,8 +267,6 @@ struct _GstBaseParseClass { gboolean (*src_event) (GstBaseParse *parse, GstEvent *event); - gboolean (*is_seekable) (GstBaseParse *parse); - gint (*get_frame_overhead) (GstBaseParse *parse, GstBuffer *buf); @@ -278,6 +287,9 @@ void gst_base_parse_set_duration (GstBaseParse *parse, GstFormat fmt, gint64 duration); +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_passthrough (GstBaseParse * parse, gboolean passthrough); -- 2.7.4