diff --git a/gst/audioparsers/gstaacparse.c b/gst/audioparsers/gstaacparse.c index c1012ba53f..50cb9e447f 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; @@ -688,27 +689,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. diff --git a/gst/audioparsers/gstbaseparse.c b/gst/audioparsers/gstbaseparse.c index 23ea2b066d..ea89b25104 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; @@ -764,20 +763,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. @@ -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 b31c8530f0..ccb761d4d1 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);