mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
discoverer: Add TOC support to discoverer and add -c/--toc parameters to gst-discoverer utility
This commit is contained in:
parent
1c77a3d801
commit
42cb4bdf67
6 changed files with 158 additions and 3 deletions
|
@ -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}
|
||||
|
|
Loading…
Reference in a new issue