baseparse: remove is_seekable vmethod and use a set_seek instead
authorMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
Fri, 17 Sep 2010 16:24:22 +0000 (18:24 +0200)
committerTim-Philipp Müller <tim.muller@collabora.co.uk>
Fri, 8 Apr 2011 17:07:07 +0000 (18:07 +0100)
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
gst/audioparsers/gstbaseparse.c
gst/audioparsers/gstbaseparse.h

index c1012ba53f0b0c812223f33fc2bc531784ec80a4..50cb9e447f23e7039729d7410f28c0b063d11fb2 100644 (file)
@@ -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.
index 23ea2b066ddf72b3e4bc5814ba1e1e31814a6aec..ea89b251042c269ba999b6976eb02e5f5d10f140 100644 (file)
@@ -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",
index b31c8530f0c43b897d3c376e18f9d77d7e1ace02..ccb761d4d18079b166071dcf1087a015e192a6f3 100644 (file)
@@ -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);