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
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
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);
}
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);
if (info->tags)
gst_tag_list_free (info->tags);
+
+ if (info->toc)
+ gst_toc_free (info->toc);
}
static GstDiscovererInfo *
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;
}
*
* Since: 0.10.31
*/
-
const GstTagList *
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
*
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
*
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;
GstElement *queue;
GstElement *sink;
GstTagList *tags;
+ GstToc *toc;
} PrivateStream;
struct _GstDiscovererPrivate
_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");
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;
}
if (ps->tags) {
gst_tag_list_free (ps->tags);
}
+ if (ps->toc) {
+ gst_toc_free (ps->toc);
+ }
g_slice_free (PrivateStream, ps);
}
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;
}
GstCaps *caps;
GstStructure *caps_st;
GstTagList *tags_st;
+ GstToc *toc_st;
const gchar *name;
int tmp;
guint utmp;
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,
(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;
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,
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;
}
}
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;
}
*
* 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.
*
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);
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);
GstCaps *caps;
GstTagList *tags;
+ GstToc *toc;
GstStructure *misc;
gpointer _gst_reserved[GST_PADDING];
GstClockTime duration;
GstStructure *misc;
GstTagList *tags;
+ GstToc *toc;
gboolean seekable;
gpointer _gst_reserved[GST_PADDING];
static gboolean async = FALSE;
static gboolean silent = FALSE;
+static gboolean show_toc = FALSE;
static gboolean verbose = FALSE;
typedef struct
}
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)));
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
"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}