discoverer: add subtitles API

https://bugzilla.gnome.org/show_bug.cgi?id=639055
This commit is contained in:
Vincent Penquerc'h 2011-08-24 15:04:50 +01:00 committed by Sebastian Dröge
parent a912374342
commit 4b5bfb1fd4
5 changed files with 219 additions and 11 deletions

View file

@ -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) \

View file

@ -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;
}
}

View file

@ -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);

View file

@ -64,6 +64,12 @@ struct _GstDiscovererVideoInfo {
gboolean is_image;
};
struct _GstDiscovererSubtitleInfo {
GstDiscovererStreamInfo parent;
gchar *language;
};
struct _GstDiscovererInfo {
GstMiniObject parent;

View file

@ -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);