mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 10:11:08 +00:00
discoverer: add subtitles API
https://bugzilla.gnome.org/show_bug.cgi?id=639055
This commit is contained in:
parent
a912374342
commit
4b5bfb1fd4
5 changed files with 219 additions and 11 deletions
|
@ -39,6 +39,9 @@ static GstDiscovererAudioInfo
|
|||
static GstDiscovererVideoInfo
|
||||
* gst_discoverer_video_info_copy_int (GstDiscovererVideoInfo * ptr);
|
||||
|
||||
static GstDiscovererSubtitleInfo
|
||||
* gst_discoverer_subtitle_info_copy_int (GstDiscovererSubtitleInfo * ptr);
|
||||
|
||||
/* Per-stream information */
|
||||
|
||||
G_DEFINE_TYPE (GstDiscovererStreamInfo, gst_discoverer_stream_info,
|
||||
|
@ -110,6 +113,11 @@ gst_discoverer_info_copy_int (GstDiscovererStreamInfo * info,
|
|||
ret = (GstDiscovererStreamInfo *)
|
||||
gst_discoverer_video_info_copy_int ((GstDiscovererVideoInfo *) info);
|
||||
|
||||
} else if (ltyp == GST_TYPE_DISCOVERER_SUBTITLE_INFO) {
|
||||
ret = (GstDiscovererStreamInfo *)
|
||||
gst_discoverer_subtitle_info_copy_int ((GstDiscovererSubtitleInfo *)
|
||||
info);
|
||||
|
||||
} else
|
||||
ret = gst_discoverer_stream_info_new ();
|
||||
|
||||
|
@ -233,6 +241,48 @@ gst_discoverer_audio_info_copy_int (GstDiscovererAudioInfo * ptr)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* Subtitle information */
|
||||
G_DEFINE_TYPE (GstDiscovererSubtitleInfo, gst_discoverer_subtitle_info,
|
||||
GST_TYPE_DISCOVERER_STREAM_INFO);
|
||||
|
||||
static void
|
||||
gst_discoverer_subtitle_info_init (GstDiscovererSubtitleInfo * info)
|
||||
{
|
||||
info->language = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_discoverer_subtitle_info_finalize (GstDiscovererSubtitleInfo * info)
|
||||
{
|
||||
g_free (info->language);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_discoverer_subtitle_info_class_init (GstMiniObjectClass * klass)
|
||||
{
|
||||
klass->finalize =
|
||||
(GstMiniObjectFinalizeFunction) gst_discoverer_subtitle_info_finalize;
|
||||
}
|
||||
|
||||
static GstDiscovererSubtitleInfo *
|
||||
gst_discoverer_subtitle_info_new (void)
|
||||
{
|
||||
return (GstDiscovererSubtitleInfo *)
|
||||
gst_mini_object_new (GST_TYPE_DISCOVERER_SUBTITLE_INFO);
|
||||
}
|
||||
|
||||
static GstDiscovererSubtitleInfo *
|
||||
gst_discoverer_subtitle_info_copy_int (GstDiscovererSubtitleInfo * ptr)
|
||||
{
|
||||
GstDiscovererSubtitleInfo *ret;
|
||||
|
||||
ret = gst_discoverer_subtitle_info_new ();
|
||||
|
||||
ret->language = g_strdup (ptr->language);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Video information */
|
||||
G_DEFINE_TYPE (GstDiscovererVideoInfo, gst_discoverer_video_info,
|
||||
GST_TYPE_DISCOVERER_STREAM_INFO);
|
||||
|
@ -439,6 +489,25 @@ gst_discoverer_info_get_video_streams (GstDiscovererInfo * info)
|
|||
return gst_discoverer_info_get_streams (info, GST_TYPE_DISCOVERER_VIDEO_INFO);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_discoverer_info_get_subtitle_streams:
|
||||
* @info: a #GstDiscovererInfo
|
||||
*
|
||||
* Finds all the #GstDiscovererSubtitleInfo contained in @info
|
||||
*
|
||||
* Returns: (transfer full) (element-type Gst.DiscovererStreamInfo): A #GList of
|
||||
* matching #GstDiscovererStreamInfo. The caller should free it with
|
||||
* gst_discoverer_stream_info_list_free().
|
||||
*
|
||||
* Since: 0.10.36
|
||||
*/
|
||||
GList *
|
||||
gst_discoverer_info_get_subtitle_streams (GstDiscovererInfo * info)
|
||||
{
|
||||
return gst_discoverer_info_get_streams (info,
|
||||
GST_TYPE_DISCOVERER_SUBTITLE_INFO);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_discoverer_info_get_container_streams:
|
||||
* @info: a #GstDiscovererInfo
|
||||
|
@ -481,6 +550,8 @@ gst_discoverer_stream_info_get_stream_type_nick (GstDiscovererStreamInfo * info)
|
|||
else
|
||||
return "video";
|
||||
}
|
||||
if (GST_IS_DISCOVERER_SUBTITLE_INFO (info))
|
||||
return "subtitles";
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
|
@ -818,6 +889,24 @@ gst_discoverer_video_info_is_image (const GstDiscovererVideoInfo * info)
|
|||
return info->is_image;
|
||||
}
|
||||
|
||||
/* GstDiscovererSubtitleInfo */
|
||||
|
||||
#define SUBTITLE_INFO_ACCESSOR_CODE(fieldname, type, failval) \
|
||||
GENERIC_ACCESSOR_CODE(gst_discoverer_subtitle_info, GstDiscovererSubtitleInfo*, \
|
||||
GST_TYPE_DISCOVERER_SUBTITLE_INFO, \
|
||||
fieldname, type, failval)
|
||||
|
||||
/**
|
||||
* gst_discoverer_subtitle_info_get_language:
|
||||
* @info: a #GstDiscovererSubtitleInfo
|
||||
*
|
||||
* Returns: the language of the stream, or NULL if unknown.
|
||||
*
|
||||
* Since: 0.10.36
|
||||
*/
|
||||
|
||||
SUBTITLE_INFO_ACCESSOR_CODE (language, const gchar *, NULL);
|
||||
|
||||
/* GstDiscovererInfo */
|
||||
|
||||
#define DISCOVERER_INFO_ACCESSOR_CODE(fieldname, type, failval) \
|
||||
|
|
|
@ -437,13 +437,9 @@ _event_probe (GstPad * pad, GstEvent * event, PrivateStream * ps)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
uridecodebin_pad_added_cb (GstElement * uridecodebin, GstPad * pad,
|
||||
GstDiscoverer * dc)
|
||||
static gboolean
|
||||
is_subtitle_caps (const GstCaps * caps)
|
||||
{
|
||||
PrivateStream *ps;
|
||||
GstPad *sinkpad = NULL;
|
||||
GstCaps *caps;
|
||||
static GstCaps *subs_caps = NULL;
|
||||
|
||||
if (!subs_caps) {
|
||||
|
@ -453,6 +449,17 @@ uridecodebin_pad_added_cb (GstElement * uridecodebin, GstPad * pad,
|
|||
"video/x-dvd-subpicture; ");
|
||||
}
|
||||
|
||||
return gst_caps_can_intersect (caps, subs_caps);
|
||||
}
|
||||
|
||||
static void
|
||||
uridecodebin_pad_added_cb (GstElement * uridecodebin, GstPad * pad,
|
||||
GstDiscoverer * dc)
|
||||
{
|
||||
PrivateStream *ps;
|
||||
GstPad *sinkpad = NULL;
|
||||
GstCaps *caps;
|
||||
|
||||
GST_DEBUG_OBJECT (dc, "pad %s:%s", GST_DEBUG_PAD_NAME (pad));
|
||||
|
||||
ps = g_slice_new0 (PrivateStream);
|
||||
|
@ -470,8 +477,8 @@ uridecodebin_pad_added_cb (GstElement * uridecodebin, GstPad * pad,
|
|||
|
||||
caps = gst_pad_get_caps_reffed (pad);
|
||||
|
||||
if (gst_caps_can_intersect (caps, subs_caps)) {
|
||||
/* Subtitle streams are sparse and don't provide any information - don't
|
||||
if (is_subtitle_caps (caps)) {
|
||||
/* Subtitle streams are sparse and may not provide any information - don't
|
||||
* wait for data to preroll */
|
||||
g_object_set (ps->sink, "async", FALSE, NULL);
|
||||
}
|
||||
|
@ -714,6 +721,36 @@ collect_information (GstDiscoverer * dc, const GstStructure * st,
|
|||
|
||||
return (GstDiscovererStreamInfo *) info;
|
||||
|
||||
} else if (is_subtitle_caps (caps)) {
|
||||
GstDiscovererSubtitleInfo *info;
|
||||
|
||||
if (parent)
|
||||
info = (GstDiscovererSubtitleInfo *) parent;
|
||||
else {
|
||||
info = (GstDiscovererSubtitleInfo *)
|
||||
gst_mini_object_new (GST_TYPE_DISCOVERER_SUBTITLE_INFO);
|
||||
info->parent.caps = caps;
|
||||
}
|
||||
|
||||
if (gst_structure_id_has_field (st, _TAGS_QUARK)) {
|
||||
const gchar *language;
|
||||
|
||||
gst_structure_id_get (st, _TAGS_QUARK,
|
||||
GST_TYPE_STRUCTURE, &tags_st, NULL);
|
||||
|
||||
language = gst_structure_get_string (caps_st, GST_TAG_LANGUAGE_CODE);
|
||||
if (language)
|
||||
info->language = g_strdup (language);
|
||||
|
||||
/* FIXME: Is it worth it to remove the tags we've parsed? */
|
||||
info->parent.tags = gst_tag_list_merge (info->parent.tags,
|
||||
(GstTagList *) tags_st, GST_TAG_MERGE_REPLACE);
|
||||
gst_structure_free (tags_st);
|
||||
|
||||
}
|
||||
|
||||
return (GstDiscovererStreamInfo *) info;
|
||||
|
||||
} else {
|
||||
/* None of the above - populate what information we can */
|
||||
GstDiscovererStreamInfo *info;
|
||||
|
@ -977,7 +1014,7 @@ discoverer_collect (GstDiscoverer * dc)
|
|||
* caps named image/<foo> (th exception being MJPEG video which is also
|
||||
* type image/jpeg), and should consist of precisely one stream (actually
|
||||
* initially there are 2, the image and raw stream, but we squash these
|
||||
* while parsing the stream topology). At some ponit, if we find that these
|
||||
* while parsing the stream topology). At some point, if we find that these
|
||||
* conditions are not sufficient, we can count the number of decoders and
|
||||
* parsers in the chain, and if there's more than one decoder, or any
|
||||
* parser at all, we should not mark this as an image.
|
||||
|
@ -989,8 +1026,8 @@ discoverer_collect (GstDiscoverer * dc)
|
|||
gst_caps_get_structure (dc->priv->current_info->stream_info->caps, 0);
|
||||
|
||||
if (g_str_has_prefix (gst_structure_get_name (st), "image/"))
|
||||
((GstDiscovererVideoInfo *) dc->priv->current_info->
|
||||
stream_info)->is_image = TRUE;
|
||||
((GstDiscovererVideoInfo *) dc->priv->current_info->stream_info)->
|
||||
is_image = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -140,6 +140,26 @@ guint gst_discoverer_video_info_get_bitrate(const GstDiscovererVideoIn
|
|||
guint gst_discoverer_video_info_get_max_bitrate(const GstDiscovererVideoInfo* info);
|
||||
gboolean gst_discoverer_video_info_is_image(const GstDiscovererVideoInfo* info);
|
||||
|
||||
/**
|
||||
* GstDiscovererSubtitleInfo:
|
||||
*
|
||||
* #GstDiscovererStreamInfo specific to subtitle streams (this includes text and
|
||||
* image based ones).
|
||||
*
|
||||
* Since: 0.10.36
|
||||
*/
|
||||
#define GST_TYPE_DISCOVERER_SUBTITLE_INFO \
|
||||
(gst_discoverer_subtitle_info_get_type ())
|
||||
#define GST_DISCOVERER_SUBTITLE_INFO(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DISCOVERER_SUBTITLE_INFO, GstDiscovererSubtitleInfo))
|
||||
#define GST_IS_DISCOVERER_SUBTITLE_INFO(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DISCOVERER_SUBTITLE_INFO))
|
||||
typedef struct _GstDiscovererSubtitleInfo GstDiscovererSubtitleInfo;
|
||||
typedef GstMiniObjectClass GstDiscovererSubtitleInfoClass;
|
||||
GType gst_discoverer_subtitle_info_get_type (void);
|
||||
|
||||
const gchar * gst_discoverer_subtitle_info_get_language(const GstDiscovererSubtitleInfo* info);
|
||||
|
||||
/**
|
||||
* GstDiscovererResult:
|
||||
* @GST_DISCOVERER_OK: The discovery was successful
|
||||
|
@ -199,6 +219,7 @@ GList * gst_discoverer_info_get_streams (GstDiscovererInfo *in
|
|||
GType streamtype);
|
||||
GList * gst_discoverer_info_get_audio_streams (GstDiscovererInfo *info);
|
||||
GList * gst_discoverer_info_get_video_streams (GstDiscovererInfo *info);
|
||||
GList * gst_discoverer_info_get_subtitle_streams (GstDiscovererInfo *info);
|
||||
GList * gst_discoverer_info_get_container_streams (GstDiscovererInfo *info);
|
||||
|
||||
void gst_discoverer_stream_info_list_free (GList *infos);
|
||||
|
|
|
@ -64,6 +64,12 @@ struct _GstDiscovererVideoInfo {
|
|||
gboolean is_image;
|
||||
};
|
||||
|
||||
struct _GstDiscovererSubtitleInfo {
|
||||
GstDiscovererStreamInfo parent;
|
||||
|
||||
gchar *language;
|
||||
};
|
||||
|
||||
struct _GstDiscovererInfo {
|
||||
GstMiniObject parent;
|
||||
|
||||
|
|
|
@ -171,6 +171,57 @@ gst_stream_video_information_to_string (GstDiscovererStreamInfo * info,
|
|||
return g_string_free (s, FALSE);
|
||||
}
|
||||
|
||||
static gchar *
|
||||
gst_stream_subtitle_information_to_string (GstDiscovererStreamInfo * info,
|
||||
gint depth)
|
||||
{
|
||||
GstDiscovererSubtitleInfo *subtitle_info;
|
||||
GString *s;
|
||||
gchar *tmp;
|
||||
const gchar *ctmp;
|
||||
int len = 400;
|
||||
const GstTagList *tags;
|
||||
GstCaps *caps;
|
||||
|
||||
g_return_val_if_fail (info != NULL, NULL);
|
||||
|
||||
s = g_string_sized_new (len);
|
||||
|
||||
my_g_string_append_printf (s, "Codec:\n");
|
||||
caps = gst_discoverer_stream_info_get_caps (info);
|
||||
tmp = gst_caps_to_string (caps);
|
||||
gst_caps_unref (caps);
|
||||
my_g_string_append_printf (s, " %s\n", tmp);
|
||||
g_free (tmp);
|
||||
|
||||
my_g_string_append_printf (s, "Additional info:\n");
|
||||
if (gst_discoverer_stream_info_get_misc (info)) {
|
||||
tmp = gst_structure_to_string (gst_discoverer_stream_info_get_misc (info));
|
||||
my_g_string_append_printf (s, " %s\n", tmp);
|
||||
g_free (tmp);
|
||||
} else {
|
||||
my_g_string_append_printf (s, " None\n");
|
||||
}
|
||||
|
||||
subtitle_info = (GstDiscovererSubtitleInfo *) info;
|
||||
ctmp = gst_discoverer_subtitle_info_get_language (subtitle_info);
|
||||
my_g_string_append_printf (s, "Language: %s\n", ctmp ? ctmp : "<unknown>");
|
||||
|
||||
my_g_string_append_printf (s, "Tags:\n");
|
||||
tags = gst_discoverer_stream_info_get_tags (info);
|
||||
if (tags) {
|
||||
tmp = gst_structure_to_string ((GstStructure *) tags);
|
||||
my_g_string_append_printf (s, " %s\n", tmp);
|
||||
g_free (tmp);
|
||||
} else {
|
||||
my_g_string_append_printf (s, " None\n");
|
||||
}
|
||||
if (verbose)
|
||||
my_g_string_append_printf (s, "\n");
|
||||
|
||||
return g_string_free (s, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
print_stream_info (GstDiscovererStreamInfo * info, void *depth)
|
||||
{
|
||||
|
@ -204,6 +255,10 @@ print_stream_info (GstDiscovererStreamInfo * info, void *depth)
|
|||
desc =
|
||||
gst_stream_video_information_to_string (info,
|
||||
GPOINTER_TO_INT (depth) + 1);
|
||||
else if (GST_IS_DISCOVERER_SUBTITLE_INFO (info))
|
||||
desc =
|
||||
gst_stream_subtitle_information_to_string (info,
|
||||
GPOINTER_TO_INT (depth) + 1);
|
||||
if (desc) {
|
||||
g_print ("%s", desc);
|
||||
g_free (desc);
|
||||
|
|
Loading…
Reference in a new issue