Commit 42cb4bdf authored by Anton Belka's avatar Anton Belka Committed by Sebastian Dröge

discoverer: Add TOC support to discoverer and add -c/--toc parameters to gst-discoverer utility

parent 1c77a3d8
......@@ -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
......
......@@ -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)
{
......@@ -657,6 +668,23 @@ gst_discoverer_stream_info_get_tags (GstDiscovererStreamInfo * info)
return info->tags;
}
/**
* 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
......@@ -1057,6 +1085,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
......
......@@ -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;
}
......
......@@ -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);
......
......@@ -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];
......
......@@ -28,6 +28,7 @@
static gboolean async = FALSE;
static gboolean silent = FALSE;
static gboolean show_toc = FALSE;
static gboolean verbose = FALSE;
typedef struct
......@@ -339,10 +340,59 @@ print_tag_each (GQuark field_id, const GValue * value, gpointer user_data)
return TRUE;
}
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}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment