discoverer: Add TOC support to discoverer and add -c/--toc parameters to gst-discover...
authorAnton Belka <antonbelka@gmail.com>
Sun, 20 May 2012 23:01:17 +0000 (02:01 +0300)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Mon, 21 May 2012 06:52:05 +0000 (08:52 +0200)
docs/libs/gst-plugins-base-libs-sections.txt
gst-libs/gst/pbutils/gstdiscoverer-types.c
gst-libs/gst/pbutils/gstdiscoverer.c
gst-libs/gst/pbutils/gstdiscoverer.h
gst-libs/gst/pbutils/pbutils-private.h
tools/gst-discoverer.c

index c2e9033..41a1d00 100644 (file)
@@ -2271,6 +2271,7 @@ gst_discoverer_info_get_result
 gst_discoverer_info_get_stream_info
 gst_discoverer_info_get_stream_list
 gst_discoverer_info_get_tags
+gst_discoverer_info_get_toc
 gst_discoverer_info_get_uri
 gst_discoverer_info_get_seekable
 gst_discoverer_info_ref
@@ -2286,6 +2287,7 @@ gst_discoverer_stream_info_get_misc
 gst_discoverer_stream_info_get_next
 gst_discoverer_stream_info_get_previous
 gst_discoverer_stream_info_get_tags
+gst_discoverer_stream_info_get_toc
 gst_discoverer_stream_info_ref
 gst_discoverer_stream_info_unref
 gst_discoverer_stream_info_list_free
index 5b63305..098899f 100644 (file)
@@ -67,6 +67,9 @@ gst_discoverer_stream_info_finalize (GObject * object)
   if (info->tags)
     gst_tag_list_free (info->tags);
 
+  if (info->toc)
+    gst_toc_free (info->toc);
+
   if (info->misc)
     gst_structure_free (info->misc);
 }
@@ -126,6 +129,9 @@ gst_discoverer_info_copy_int (GstDiscovererStreamInfo * info,
   if (info->tags)
     ret->tags = gst_tag_list_copy (info->tags);
 
+  if (info->toc)
+    ret->toc = gst_toc_copy (info->toc);
+
   if (info->misc)
     ret->misc = gst_structure_copy (info->misc);
 
@@ -361,6 +367,9 @@ gst_discoverer_info_finalize (GObject * object)
 
   if (info->tags)
     gst_tag_list_free (info->tags);
+
+  if (info->toc)
+    gst_toc_free (info->toc);
 }
 
 static GstDiscovererInfo *
@@ -412,6 +421,9 @@ gst_discoverer_info_copy (GstDiscovererInfo * ptr)
   if (ptr->tags)
     ret->tags = gst_tag_list_copy (ptr->tags);
 
+  if (ptr->toc)
+    ret->toc = gst_toc_copy (ptr->toc);
+
   g_hash_table_destroy (stream_map);
   return ret;
 }
@@ -648,7 +660,6 @@ gst_discoverer_stream_info_get_caps (GstDiscovererStreamInfo * info)
  *
  * Since: 0.10.31
  */
-
 const GstTagList *
 gst_discoverer_stream_info_get_tags (GstDiscovererStreamInfo * info)
 {
@@ -658,6 +669,23 @@ gst_discoverer_stream_info_get_tags (GstDiscovererStreamInfo * info)
 }
 
 /**
+ * gst_discoverer_stream_info_get_toc:
+ * @info: a #GstDiscovererStreamInfo
+ *
+ * Returns: (transfer none): the TOC contained in this stream. If you wish to
+ * use the TOC after the life-time of @info you will need to copy it.
+ *
+ * Since: 0.11.92
+ */
+const GstToc *
+gst_discoverer_stream_info_get_toc (GstDiscovererStreamInfo * info)
+{
+  g_return_val_if_fail (GST_IS_DISCOVERER_STREAM_INFO (info), NULL);
+
+  return info->toc;
+}
+
+/**
  * gst_discoverer_stream_info_get_misc:
  * @info: a #GstDiscovererStreamInfo
  *
@@ -1058,6 +1086,18 @@ DISCOVERER_INFO_ACCESSOR_CODE (misc, const GstStructure *, NULL);
 DISCOVERER_INFO_ACCESSOR_CODE (tags, const GstTagList *, NULL);
 
 /**
+ * gst_discoverer_info_get_toc:
+ * @info: a #GstDiscovererInfo
+ *
+ * Returns: (transfer none): TOC contained in the URI. If you wish to use
+ * the TOC after the life-time of @info, you will need to copy it.
+ *
+ * Since: 0.11.92
+ */
+
+DISCOVERER_INFO_ACCESSOR_CODE (toc, const GstToc *, NULL);
+
+/**
  * gst_discoverer_info_ref:
  * @info: a #GstDiscovererInfo
  *
index 94d1823..16e8089 100644 (file)
@@ -57,6 +57,7 @@ GST_DEBUG_CATEGORY_STATIC (discoverer_debug);
 
 static GQuark _CAPS_QUARK;
 static GQuark _TAGS_QUARK;
+static GQuark _TOC_QUARK;
 static GQuark _MISSING_PLUGIN_QUARK;
 static GQuark _STREAM_TOPOLOGY_QUARK;
 static GQuark _TOPOLOGY_PAD_QUARK;
@@ -69,6 +70,7 @@ typedef struct
   GstElement *queue;
   GstElement *sink;
   GstTagList *tags;
+  GstToc *toc;
 } PrivateStream;
 
 struct _GstDiscovererPrivate
@@ -135,6 +137,7 @@ _do_init (void)
 
   _CAPS_QUARK = g_quark_from_static_string ("caps");
   _TAGS_QUARK = g_quark_from_static_string ("tags");
+  _TOC_QUARK = g_quark_from_static_string ("toc");
   _MISSING_PLUGIN_QUARK = g_quark_from_static_string ("missing-plugin");
   _STREAM_TOPOLOGY_QUARK = g_quark_from_static_string ("stream-topology");
   _TOPOLOGY_PAD_QUARK = g_quark_from_static_string ("pad");
@@ -449,6 +452,20 @@ _event_probe (GstPad * pad, GstPadProbeInfo * info, PrivateStream * ps)
     DISCO_UNLOCK (ps->dc);
   }
 
+  if (GST_EVENT_TYPE (event) == GST_EVENT_TOC) {
+    GstToc *tmp;
+
+    gst_event_parse_toc (event, &tmp, NULL);
+    GST_DEBUG_OBJECT (pad, "toc %" GST_PTR_FORMAT, tmp);
+    DISCO_LOCK (ps->dc);
+    ps->toc = tmp;
+    if (G_LIKELY (ps->dc->priv->processing)) {
+      GST_DEBUG_OBJECT (pad, "private stream %p toc %" GST_PTR_FORMAT, ps, tmp);
+    } else
+      GST_DEBUG_OBJECT (pad, "Dropping toc since preroll is done");
+    DISCO_UNLOCK (ps->dc);
+  }
+
   return GST_PAD_PROBE_OK;
 }
 
@@ -616,6 +633,9 @@ uridecodebin_pad_removed_cb (GstElement * uridecodebin, GstPad * pad,
   if (ps->tags) {
     gst_tag_list_free (ps->tags);
   }
+  if (ps->toc) {
+    gst_toc_free (ps->toc);
+  }
 
   g_slice_free (PrivateStream, ps);
 
@@ -648,6 +668,8 @@ collect_stream_information (GstDiscoverer * dc, PrivateStream * ps, guint idx)
   }
   if (ps->tags)
     gst_structure_id_set (st, _TAGS_QUARK, GST_TYPE_TAG_LIST, ps->tags, NULL);
+  if (ps->toc)
+    gst_structure_id_set (st, _TOC_QUARK, GST_TYPE_TOC, ps->toc, NULL);
 
   return st;
 }
@@ -679,6 +701,7 @@ collect_information (GstDiscoverer * dc, const GstStructure * st,
   GstCaps *caps;
   GstStructure *caps_st;
   GstTagList *tags_st;
+  GstToc *toc_st;
   const gchar *name;
   int tmp;
   guint utmp;
@@ -729,6 +752,11 @@ collect_information (GstDiscoverer * dc, const GstStructure * st,
       gst_discoverer_merge_and_replace_tags (&info->parent.tags, tags_st);
     }
 
+    if (gst_structure_id_has_field (st, _TOC_QUARK)) {
+      gst_structure_id_get (st, _TOC_QUARK, GST_TYPE_TOC, &toc_st, NULL);
+      info->parent.toc = toc_st;
+    }
+
     if (!info->language && ((GstDiscovererStreamInfo *) info)->tags) {
       gchar *language;
       if (gst_tag_list_get_string (((GstDiscovererStreamInfo *) info)->tags,
@@ -787,6 +815,11 @@ collect_information (GstDiscoverer * dc, const GstStructure * st,
           (GstTagList *) tags_st);
     }
 
+    if (gst_structure_id_has_field (st, _TOC_QUARK)) {
+      gst_structure_id_get (st, _TOC_QUARK, GST_TYPE_TOC, &toc_st, NULL);
+      info->parent.toc = toc_st;
+    }
+
     gst_caps_unref (caps);
     return (GstDiscovererStreamInfo *) info;
 
@@ -815,6 +848,11 @@ collect_information (GstDiscoverer * dc, const GstStructure * st,
       gst_discoverer_merge_and_replace_tags (&info->parent.tags, tags_st);
     }
 
+    if (gst_structure_id_has_field (st, _TOC_QUARK)) {
+      gst_structure_id_get (st, _TOC_QUARK, GST_TYPE_TOC, &toc_st, NULL);
+      info->parent.toc = toc_st;
+    }
+
     if (!info->language && ((GstDiscovererStreamInfo *) info)->tags) {
       gchar *language;
       if (gst_tag_list_get_string (((GstDiscovererStreamInfo *) info)->tags,
@@ -843,6 +881,10 @@ collect_information (GstDiscoverer * dc, const GstStructure * st,
       gst_discoverer_merge_and_replace_tags (&info->tags, tags_st);
     }
 
+    if (gst_structure_id_get (st, _TOC_QUARK, GST_TYPE_TOC, &toc_st, NULL)) {
+      info->toc = toc_st;
+    }
+
     gst_caps_unref (caps);
     return info;
   }
@@ -1285,6 +1327,18 @@ handle_message (GstDiscoverer * dc, GstMessage * msg)
     }
       break;
 
+    case GST_MESSAGE_TOC:
+    {
+      GstToc *tmp;
+
+      gst_message_parse_toc (msg, &tmp, NULL);
+      GST_DEBUG_OBJECT (GST_MESSAGE_SRC (msg), "Got toc %" GST_PTR_FORMAT, tmp);
+      dc->priv->current_info->toc = tmp;
+      GST_DEBUG_OBJECT (GST_MESSAGE_SRC (msg), "Current info %p, toc %"
+          GST_PTR_FORMAT, dc->priv->current_info, tmp);
+    }
+      break;
+
     default:
       break;
   }
index 611bc89..28d3ae4 100644 (file)
@@ -50,7 +50,6 @@ GType gst_discoverer_stream_info_get_type (void);
  *
  * As a simple example, if you run #GstDiscoverer on an AVI file with one audio
  * and one video stream, you will get a #GstDiscovererContainerInfo
- * corresponding to the AVI container, which in turn will have a
  * #GstDiscovererAudioInfo sub-stream and a #GstDiscovererVideoInfo sub-stream
  * for the audio and video streams respectively.
  *
@@ -63,6 +62,7 @@ GstDiscovererStreamInfo* gst_discoverer_stream_info_get_previous(GstDiscovererSt
 GstDiscovererStreamInfo* gst_discoverer_stream_info_get_next(GstDiscovererStreamInfo* info);
 GstCaps*                 gst_discoverer_stream_info_get_caps(GstDiscovererStreamInfo* info);
 const GstTagList*        gst_discoverer_stream_info_get_tags(GstDiscovererStreamInfo* info);
+const GstToc*            gst_discoverer_stream_info_get_toc(GstDiscovererStreamInfo* info);
 const GstStructure*      gst_discoverer_stream_info_get_misc(GstDiscovererStreamInfo* info);
 const gchar *            gst_discoverer_stream_info_get_stream_type_nick(GstDiscovererStreamInfo* info);
 
@@ -214,7 +214,8 @@ GList*                    gst_discoverer_info_get_stream_list(GstDiscovererInfo*
 GstClockTime              gst_discoverer_info_get_duration(const GstDiscovererInfo* info);
 gboolean                  gst_discoverer_info_get_seekable(const GstDiscovererInfo* info);
 const GstStructure*       gst_discoverer_info_get_misc(const GstDiscovererInfo* info);
-const GstTagList*         gst_discoverer_info_get_tags(const GstDiscovererInfo* info);
+const GstTagList*         gst_discoverer_info_get_tags(const GstDiscovererInfo* info); 
+const GstToc*             gst_discoverer_info_get_toc(const GstDiscovererInfo* info);
 
 GList *                   gst_discoverer_info_get_streams (GstDiscovererInfo *info,
                                                           GType streamtype);
index 7efa6ab..48eea55 100644 (file)
@@ -26,6 +26,7 @@ struct _GstDiscovererStreamInfo {
 
   GstCaps               *caps;
   GstTagList            *tags;
+  GstToc                *toc;
   GstStructure          *misc;
 
   gpointer _gst_reserved[GST_PADDING];
@@ -96,6 +97,7 @@ struct _GstDiscovererInfo {
   GstClockTime duration;
   GstStructure *misc;
   GstTagList *tags;
+  GstToc *toc;
   gboolean seekable;
 
   gpointer _gst_reserved[GST_PADDING];
index e1a4cd8..ee07b42 100644 (file)
@@ -28,6 +28,7 @@
 
 static gboolean async = FALSE;
 static gboolean silent = FALSE;
+static gboolean show_toc = FALSE;
 static gboolean verbose = FALSE;
 
 typedef struct
@@ -340,9 +341,58 @@ print_tag_each (GQuark field_id, const GValue * value, gpointer user_data)
 }
 
 static void
+print_tag_foreach (const GstTagList * tags, const gchar * tag,
+    gpointer user_data)
+{
+  GValue val = { 0, };
+  gchar *str;
+  gint depth = GPOINTER_TO_INT (user_data);
+
+  gst_tag_list_copy_value (&val, tags, tag);
+
+  if (G_VALUE_HOLDS_STRING (&val))
+    str = g_value_dup_string (&val);
+  else
+    str = gst_value_serialize (&val);
+
+  g_print ("%*s%s: %s\n", 2 * depth, " ", gst_tag_get_nick (tag), str);
+  g_free (str);
+
+  g_value_unset (&val);
+}
+
+#define MAX_INDENT 40
+
+static void
+print_toc_entry (gpointer data, gpointer user_data)
+{
+  GstTocEntry *entry = (GstTocEntry *) data;
+  gint depth = GPOINTER_TO_INT (user_data);
+  guint indent = MIN (GPOINTER_TO_UINT (user_data), MAX_INDENT);
+  gint64 start, stop;
+
+  gst_toc_entry_get_start_stop (entry, &start, &stop);
+  g_print ("%*s%s: start: %" GST_TIME_FORMAT " stop: %" GST_TIME_FORMAT "\n",
+      depth, " ", gst_toc_entry_type_get_nick (entry->type),
+      GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
+  indent += 2;
+
+  /* print tags */
+  if (entry->type == GST_TOC_ENTRY_TYPE_CHAPTER)
+    g_print ("%*sTags:\n", 2 * depth, " ");
+  gst_tag_list_foreach (entry->tags, print_tag_foreach,
+      GUINT_TO_POINTER (indent));
+
+  /* loop over sub-toc entries */
+  g_list_foreach (entry->subentries, print_toc_entry,
+      GUINT_TO_POINTER (indent));
+}
+
+static void
 print_properties (GstDiscovererInfo * info, gint tab)
 {
   const GstTagList *tags;
+  const GstToc *toc;
 
   g_print ("%*sDuration: %" GST_TIME_FORMAT "\n", tab + 1, " ",
       GST_TIME_ARGS (gst_discoverer_info_get_duration (info)));
@@ -353,6 +403,10 @@ print_properties (GstDiscovererInfo * info, gint tab)
     gst_structure_foreach ((const GstStructure *) tags, print_tag_each,
         GINT_TO_POINTER (tab + 5));
   }
+  if (show_toc && (toc = gst_discoverer_info_get_toc (info))) {
+    g_print ("%*sTOC: \n", tab + 1, " ");
+    g_list_foreach (toc->entries, print_toc_entry, GUINT_TO_POINTER (tab + 5));
+  }
 }
 
 static void
@@ -511,6 +565,8 @@ main (int argc, char **argv)
         "Specify timeout (in seconds, default 10)", "T"},
     /* {"elem", 'e', 0, G_OPTION_ARG_NONE, &elem_seek, */
     /*     "Seek on elements instead of pads", NULL}, */
+    {"toc", 'c', 0, G_OPTION_ARG_NONE, &show_toc,
+        "Output TOC (chapters and editions)", NULL},
     {"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
         "Verbose properties", NULL},
     {NULL}