mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-25 09:40:37 +00:00
gst/playback/: Implement subtitles.
Original commit message from CVS: 2006-01-30 Julien MOUTTE <julien@moutte.net> * gst/playback/gstplaybasebin.c: (group_commit), (queue_overrun), (setup_subtitle), (setup_source), (set_active_source): * gst/playback/gstplaybin.c: (gst_play_bin_dispose), (gen_text_element), (gen_audio_element), (gen_vis_element), (remove_sinks), (add_sink), (setup_sinks): Implement subtitles.
This commit is contained in:
parent
dc46970cdf
commit
950ab0ef96
3 changed files with 156 additions and 68 deletions
|
@ -1,3 +1,11 @@
|
||||||
|
2006-01-30 Julien MOUTTE <julien@moutte.net>
|
||||||
|
|
||||||
|
* gst/playback/gstplaybasebin.c: (group_commit), (queue_overrun),
|
||||||
|
(setup_subtitle), (setup_source), (set_active_source):
|
||||||
|
* gst/playback/gstplaybin.c: (gst_play_bin_dispose),
|
||||||
|
(gen_text_element), (gen_audio_element), (gen_vis_element),
|
||||||
|
(remove_sinks), (add_sink), (setup_sinks): Implement subtitles.
|
||||||
|
|
||||||
2006-01-29 Sebastien Moutte <sebastien@moutte.net>
|
2006-01-29 Sebastien Moutte <sebastien@moutte.net>
|
||||||
|
|
||||||
* gst-libs/gst/audio/audio.h: (GST_CLOCK_TIME_TO_FRAMES)
|
* gst-libs/gst/audio/audio.h: (GST_CLOCK_TIME_TO_FRAMES)
|
||||||
|
|
|
@ -408,10 +408,12 @@ group_commit (GstPlayBaseBin * play_base_bin, gboolean fatal, gboolean subtitle)
|
||||||
sig_id =
|
sig_id =
|
||||||
GPOINTER_TO_INT (g_object_get_data (G_OBJECT (element), "signal_id"));
|
GPOINTER_TO_INT (g_object_get_data (G_OBJECT (element), "signal_id"));
|
||||||
|
|
||||||
|
if (sig_id) {
|
||||||
GST_LOG ("removing preroll signal %s", GST_ELEMENT_NAME (element));
|
GST_LOG ("removing preroll signal %s", GST_ELEMENT_NAME (element));
|
||||||
g_signal_handler_disconnect (G_OBJECT (element), sig_id);
|
g_signal_handler_disconnect (G_OBJECT (element), sig_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GST_DEBUG ("signal group done");
|
GST_DEBUG ("signal group done");
|
||||||
GROUP_SIGNAL (play_base_bin);
|
GROUP_SIGNAL (play_base_bin);
|
||||||
|
@ -501,10 +503,15 @@ queue_overrun (GstElement * element, GstPlayBaseBin * play_base_bin)
|
||||||
{
|
{
|
||||||
GST_DEBUG ("queue %s overrun", GST_ELEMENT_NAME (element));
|
GST_DEBUG ("queue %s overrun", GST_ELEMENT_NAME (element));
|
||||||
|
|
||||||
group_commit (play_base_bin, FALSE, FALSE);
|
group_commit (play_base_bin, FALSE,
|
||||||
|
GST_OBJECT_PARENT (GST_OBJECT_CAST (element)) ==
|
||||||
|
GST_OBJECT (play_base_bin->subtitle));
|
||||||
|
|
||||||
g_signal_handlers_disconnect_by_func (element,
|
g_signal_handlers_disconnect_by_func (element,
|
||||||
G_CALLBACK (queue_overrun), play_base_bin);
|
G_CALLBACK (queue_overrun), play_base_bin);
|
||||||
|
/* We have disconnected this signal, remove the signal_id from the object
|
||||||
|
data */
|
||||||
|
g_object_set_data (G_OBJECT (element), "signal_id", NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Used for time-based buffering. */
|
/* Used for time-based buffering. */
|
||||||
|
@ -1057,7 +1064,7 @@ setup_subtitle (GstPlayBaseBin * play_base_bin, gchar * sub_uri)
|
||||||
return NULL;
|
return NULL;
|
||||||
subparse = gst_element_factory_make ("decodebin", "subtitle-decoder");
|
subparse = gst_element_factory_make ("decodebin", "subtitle-decoder");
|
||||||
|
|
||||||
subbin = gst_bin_new ("subbin");
|
subbin = gst_bin_new ("subtitle-bin");
|
||||||
gst_bin_add_many (GST_BIN (subbin), source, subparse, NULL);
|
gst_bin_add_many (GST_BIN (subbin), source, subparse, NULL);
|
||||||
gst_element_link (source, subparse);
|
gst_element_link (source, subparse);
|
||||||
|
|
||||||
|
@ -1193,71 +1200,45 @@ setup_source (GstPlayBaseBin * play_base_bin, gchar ** new_location)
|
||||||
|
|
||||||
/* do subs */
|
/* do subs */
|
||||||
if (subbin) {
|
if (subbin) {
|
||||||
#if 0
|
|
||||||
gint sig4, sig5, sig6;
|
|
||||||
GstElement *db;
|
GstElement *db;
|
||||||
|
|
||||||
play_base_bin->subtitle = subbin;
|
play_base_bin->subtitle = subbin;
|
||||||
db = gst_bin_get_by_name (GST_BIN (subbin), "subtitle-decoder");
|
db = gst_bin_get_by_name (GST_BIN (subbin), "subtitle-decoder");
|
||||||
|
|
||||||
/* don't add yet, because we will preroll, and subs shouldn't
|
|
||||||
* preroll (we shouldn't preroll more than once source). */
|
|
||||||
gst_element_set_state (subbin, GST_STATE_PAUSED);
|
|
||||||
|
|
||||||
/* do type detection, without adding (so no preroll) */
|
/* do type detection, without adding (so no preroll) */
|
||||||
g_signal_connect (G_OBJECT (db),
|
g_signal_connect (G_OBJECT (db), "new-decoded-pad",
|
||||||
"new-decoded-pad", G_CALLBACK (new_decoded_pad), play_base_bin);
|
G_CALLBACK (new_decoded_pad), play_base_bin);
|
||||||
g_signal_connect (G_OBJECT (db), "no-more-pads",
|
g_signal_connect (G_OBJECT (db), "no-more-pads",
|
||||||
G_CALLBACK (no_more_pads), play_base_bin);
|
G_CALLBACK (no_more_pads), play_base_bin);
|
||||||
|
g_signal_connect (G_OBJECT (db), "unknown-type",
|
||||||
|
G_CALLBACK (unknown_type), play_base_bin);
|
||||||
|
|
||||||
if (!play_base_bin->is_stream) {
|
if (!play_base_bin->is_stream) {
|
||||||
sig4 = g_signal_connect (G_OBJECT (db),
|
|
||||||
"unknown-type", G_CALLBACK (unknown_type), play_base_bin);
|
|
||||||
sig5 = g_signal_connect (G_OBJECT (subbin), "error",
|
|
||||||
G_CALLBACK (thread_error), error);
|
|
||||||
|
|
||||||
/* either when the queues are filled or when the decoder element
|
/* either when the queues are filled or when the decoder element
|
||||||
* has no more dynamic streams, the cond is unlocked. We can remove
|
* has no more dynamic streams, the cond is unlocked. We can remove
|
||||||
* the signal handlers then
|
* the signal handlers then
|
||||||
*/
|
*/
|
||||||
g_mutex_lock (play_base_bin->group_lock);
|
|
||||||
if (gst_element_set_state (subbin, GST_STATE_PLAYING) ==
|
|
||||||
GST_STATE_CHANGE_SUCCESS) {
|
|
||||||
GST_DEBUG ("waiting for first group...");
|
|
||||||
sig6 = g_signal_connect (G_OBJECT (subbin),
|
|
||||||
"state-changed", G_CALLBACK (state_change), play_base_bin);
|
|
||||||
g_cond_wait (play_base_bin->group_cond, play_base_bin->group_lock);
|
|
||||||
GST_DEBUG ("group done !");
|
|
||||||
} else {
|
|
||||||
GST_DEBUG ("state change failed, subtitle cannot be loaded");
|
|
||||||
sig6 = 0;
|
|
||||||
}
|
|
||||||
g_mutex_unlock (play_base_bin->group_lock);
|
|
||||||
|
|
||||||
if (sig6 != 0)
|
|
||||||
g_signal_handler_disconnect (G_OBJECT (subbin), sig6);
|
|
||||||
|
|
||||||
g_signal_handler_disconnect (G_OBJECT (subbin), sig5);
|
|
||||||
g_signal_handler_disconnect (G_OBJECT (db), sig4);
|
|
||||||
|
|
||||||
gst_element_set_state (subbin, GST_STATE_PAUSED);
|
gst_element_set_state (subbin, GST_STATE_PAUSED);
|
||||||
|
|
||||||
|
GROUP_LOCK (play_base_bin);
|
||||||
|
GST_DEBUG ("waiting for first group...");
|
||||||
|
GROUP_WAIT (play_base_bin);
|
||||||
|
GST_DEBUG ("group done !");
|
||||||
|
GROUP_UNLOCK (play_base_bin);
|
||||||
|
|
||||||
if (!play_base_bin->building_group ||
|
if (!play_base_bin->building_group ||
|
||||||
play_base_bin->building_group->type[GST_STREAM_TYPE_TEXT - 1].npads ==
|
play_base_bin->building_group->type[GST_STREAM_TYPE_TEXT - 1].npads ==
|
||||||
0) {
|
0) {
|
||||||
if (*error) {
|
|
||||||
g_error_free (*error);
|
|
||||||
*error = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_DEBUG ("No subtitle found - ignoring");
|
GST_DEBUG ("No subtitle found - ignoring");
|
||||||
gst_object_unref (play_base_bin->subtitle);
|
gst_element_set_state (subbin, GST_STATE_NULL);
|
||||||
|
gst_object_unref (GST_OBJECT (play_base_bin->subtitle));
|
||||||
play_base_bin->subtitle = NULL;
|
play_base_bin->subtitle = NULL;
|
||||||
} else {
|
} else {
|
||||||
GST_DEBUG ("Subtitle set-up successful");
|
GST_DEBUG ("Subtitle set-up successful");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* now see if the source element emits raw audio/video all by itself,
|
/* now see if the source element emits raw audio/video all by itself,
|
||||||
|
@ -1361,6 +1342,10 @@ setup_source (GstPlayBaseBin * play_base_bin, gchar ** new_location)
|
||||||
g_signal_connect (G_OBJECT (play_base_bin->decoder),
|
g_signal_connect (G_OBJECT (play_base_bin->decoder),
|
||||||
"unknown-type", G_CALLBACK (unknown_type), play_base_bin);
|
"unknown-type", G_CALLBACK (unknown_type), play_base_bin);
|
||||||
|
|
||||||
|
if (play_base_bin->subtitle) {
|
||||||
|
gst_bin_add (GST_BIN (play_base_bin), play_base_bin->subtitle);
|
||||||
|
}
|
||||||
|
|
||||||
play_base_bin->need_rebuild = FALSE;
|
play_base_bin->need_rebuild = FALSE;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -1618,7 +1603,7 @@ set_active_source (GstPlayBaseBin * play_base_bin,
|
||||||
GST_LOG ("Muting group type: %d", type);
|
GST_LOG ("Muting group type: %d", type);
|
||||||
g_object_set (sel, "active-pad", "", NULL);
|
g_object_set (sel, "active-pad", "", NULL);
|
||||||
} else {
|
} else {
|
||||||
GST_LOG ("Unuting group type: %d", type);
|
GST_LOG ("Unmuting group type: %d", type);
|
||||||
}
|
}
|
||||||
mute_group_type (group, type, !have_active);
|
mute_group_type (group, type, !have_active);
|
||||||
}
|
}
|
||||||
|
|
|
@ -265,6 +265,10 @@ gst_play_bin_dispose (GObject * object)
|
||||||
gst_object_unref (play_bin->pending_visualisation);
|
gst_object_unref (play_bin->pending_visualisation);
|
||||||
play_bin->pending_visualisation = NULL;
|
play_bin->pending_visualisation = NULL;
|
||||||
}
|
}
|
||||||
|
if (play_bin->textoverlay_element != NULL) {
|
||||||
|
gst_object_unref (play_bin->textoverlay_element);
|
||||||
|
play_bin->textoverlay_element = NULL;
|
||||||
|
}
|
||||||
g_free (play_bin->font_desc);
|
g_free (play_bin->font_desc);
|
||||||
play_bin->font_desc = NULL;
|
play_bin->font_desc = NULL;
|
||||||
|
|
||||||
|
@ -657,34 +661,53 @@ gen_text_element (GstPlayBin * play_bin)
|
||||||
GstElement *element, *csp, *overlay, *vbin;
|
GstElement *element, *csp, *overlay, *vbin;
|
||||||
GstPad *pad;
|
GstPad *pad;
|
||||||
|
|
||||||
|
/* Create our bin */
|
||||||
|
element = gst_bin_new ("textbin");
|
||||||
|
|
||||||
|
/* Text overlay */
|
||||||
overlay = gst_element_factory_make ("textoverlay", "overlay");
|
overlay = gst_element_factory_make ("textoverlay", "overlay");
|
||||||
|
|
||||||
|
/* Create the video rendering bin */
|
||||||
|
vbin = gen_video_element (play_bin);
|
||||||
|
|
||||||
|
/* If no overlay return the video bin */
|
||||||
|
if (!overlay) {
|
||||||
|
GST_WARNING ("No overlay (pango) element, subtitles disabled");
|
||||||
|
return vbin;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set some parameters */
|
||||||
g_object_set (G_OBJECT (overlay),
|
g_object_set (G_OBJECT (overlay),
|
||||||
"halign", "center", "valign", "bottom", NULL);
|
"halign", "center", "valign", "bottom", NULL);
|
||||||
play_bin->textoverlay_element = overlay;
|
|
||||||
if (play_bin->font_desc) {
|
if (play_bin->font_desc) {
|
||||||
g_object_set (G_OBJECT (play_bin->textoverlay_element),
|
g_object_set (G_OBJECT (play_bin->textoverlay_element),
|
||||||
"font-desc", play_bin->font_desc, NULL);
|
"font-desc", play_bin->font_desc, NULL);
|
||||||
}
|
}
|
||||||
vbin = gen_video_element (play_bin);
|
|
||||||
if (!overlay) {
|
/* Take a ref */
|
||||||
g_warning ("No overlay (pango) element, subtitles disabled");
|
play_bin->textoverlay_element = GST_ELEMENT (gst_object_ref (overlay));
|
||||||
return vbin;
|
|
||||||
}
|
|
||||||
csp = gst_element_factory_make ("ffmpegcolorspace", "subtitlecsp");
|
csp = gst_element_factory_make ("ffmpegcolorspace", "subtitlecsp");
|
||||||
element = gst_bin_new ("textbin");
|
|
||||||
gst_element_link_many (csp, overlay, vbin, NULL);
|
/* Add our elements */
|
||||||
gst_bin_add_many (GST_BIN (element), csp, overlay, vbin, NULL);
|
gst_bin_add_many (GST_BIN (element), csp, overlay, vbin, NULL);
|
||||||
|
|
||||||
|
/* Link */
|
||||||
|
gst_element_link_pads (csp, "src", overlay, "video_sink");
|
||||||
|
gst_element_link_pads (overlay, "src", vbin, "sink");
|
||||||
|
|
||||||
|
/* Add ghost pads on the subtitle bin */
|
||||||
pad = gst_element_get_pad (overlay, "text_sink");
|
pad = gst_element_get_pad (overlay, "text_sink");
|
||||||
#define gst_element_add_ghost_pad(element, pad, name) \
|
gst_element_add_pad (element, gst_ghost_pad_new ("text_sink", pad));
|
||||||
gst_element_add_pad (element, gst_ghost_pad_new (name, pad))
|
|
||||||
gst_element_add_ghost_pad (element, pad, "text_sink");
|
|
||||||
gst_object_unref (pad);
|
gst_object_unref (pad);
|
||||||
|
|
||||||
pad = gst_element_get_pad (csp, "sink");
|
pad = gst_element_get_pad (csp, "sink");
|
||||||
gst_element_add_ghost_pad (element, pad, "sink");
|
gst_element_add_pad (element, gst_ghost_pad_new ("sink", pad));
|
||||||
gst_object_unref (pad);
|
gst_object_unref (pad);
|
||||||
|
|
||||||
|
/* Set state to READY */
|
||||||
|
gst_element_set_state (element, GST_STATE_READY);
|
||||||
|
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -751,7 +774,7 @@ gen_audio_element (GstPlayBin * play_bin)
|
||||||
gst_element_link_pads (volume, "src", sink, "sink");
|
gst_element_link_pads (volume, "src", sink, "sink");
|
||||||
|
|
||||||
pad = gst_element_get_pad (conv, "sink");
|
pad = gst_element_get_pad (conv, "sink");
|
||||||
gst_element_add_ghost_pad (element, pad, "sink");
|
gst_element_add_pad (element, gst_ghost_pad_new ("sink", pad));
|
||||||
gst_object_unref (pad);
|
gst_object_unref (pad);
|
||||||
|
|
||||||
gst_element_set_state (element, GST_STATE_READY);
|
gst_element_set_state (element, GST_STATE_READY);
|
||||||
|
@ -850,7 +873,7 @@ gen_vis_element (GstPlayBin * play_bin)
|
||||||
gst_object_unref (pad);
|
gst_object_unref (pad);
|
||||||
|
|
||||||
pad = gst_element_get_pad (tee, "sink");
|
pad = gst_element_get_pad (tee, "sink");
|
||||||
gst_element_add_ghost_pad (element, pad, "sink");
|
gst_element_add_pad (element, gst_ghost_pad_new ("sink", pad));
|
||||||
gst_object_unref (pad);
|
gst_object_unref (pad);
|
||||||
|
|
||||||
return element;
|
return element;
|
||||||
|
@ -942,7 +965,10 @@ remove_sinks (GstPlayBin * play_bin)
|
||||||
play_bin->frame = NULL;
|
play_bin->frame = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (play_bin->textoverlay_element) {
|
||||||
|
gst_object_unref (play_bin->textoverlay_element);
|
||||||
play_bin->textoverlay_element = NULL;
|
play_bin->textoverlay_element = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* loop over the streams and set up the pipeline to play this
|
/* loop over the streams and set up the pipeline to play this
|
||||||
|
@ -955,7 +981,8 @@ remove_sinks (GstPlayBin * play_bin)
|
||||||
* one can switch the streams.
|
* one can switch the streams.
|
||||||
*/
|
*/
|
||||||
static gboolean
|
static gboolean
|
||||||
add_sink (GstPlayBin * play_bin, GstElement * sink, GstPad * srcpad)
|
add_sink (GstPlayBin * play_bin, GstElement * sink, GstPad * srcpad,
|
||||||
|
GstPad * subtitle_pad)
|
||||||
{
|
{
|
||||||
GstPad *sinkpad;
|
GstPad *sinkpad;
|
||||||
GstPadLinkReturn linkres;
|
GstPadLinkReturn linkres;
|
||||||
|
@ -988,8 +1015,19 @@ add_sink (GstPlayBin * play_bin, GstElement * sink, GstPad * srcpad)
|
||||||
if (GST_PAD_LINK_FAILED (linkres))
|
if (GST_PAD_LINK_FAILED (linkres))
|
||||||
goto link_failed;
|
goto link_failed;
|
||||||
|
|
||||||
|
if (GST_IS_PAD (subtitle_pad)) {
|
||||||
|
sinkpad = gst_element_get_pad (sink, "text_sink");
|
||||||
|
linkres = gst_pad_link (subtitle_pad, sinkpad);
|
||||||
|
gst_object_unref (sinkpad);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* try to link the subtitle pad of the sink to the stream */
|
||||||
|
if (GST_PAD_LINK_FAILED (linkres)) {
|
||||||
|
goto subtitle_failed;
|
||||||
|
}
|
||||||
|
|
||||||
/* we got the sink succesfully linked, now keep the sink
|
/* we got the sink succesfully linked, now keep the sink
|
||||||
* in out internal list */
|
* in our internal list */
|
||||||
play_bin->sinks = g_list_prepend (play_bin->sinks, sink);
|
play_bin->sinks = g_list_prepend (play_bin->sinks, sink);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -1018,6 +1056,22 @@ link_failed:
|
||||||
gst_bin_remove (GST_BIN (play_bin), sink);
|
gst_bin_remove (GST_BIN (play_bin), sink);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
subtitle_failed:
|
||||||
|
{
|
||||||
|
gchar *capsstr;
|
||||||
|
GstCaps *caps;
|
||||||
|
|
||||||
|
/* could not link this stream */
|
||||||
|
caps = gst_pad_get_caps (subtitle_pad);
|
||||||
|
capsstr = gst_caps_to_string (caps);
|
||||||
|
GST_DEBUG_OBJECT (play_bin,
|
||||||
|
"subtitle link failed when adding sink, caps %s, reason %d", capsstr,
|
||||||
|
linkres);
|
||||||
|
g_free (capsstr);
|
||||||
|
g_free (caps);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -1027,7 +1081,7 @@ setup_sinks (GstPlayBaseBin * play_base_bin, GstPlayBaseGroup * group)
|
||||||
GList *streaminfo = NULL, *s;
|
GList *streaminfo = NULL, *s;
|
||||||
gboolean need_vis = FALSE;
|
gboolean need_vis = FALSE;
|
||||||
gboolean need_text = FALSE;
|
gboolean need_text = FALSE;
|
||||||
GstPad *textsrcpad = NULL, *textsinkpad = NULL, *pad;
|
GstPad *textsrcpad = NULL, *pad = NULL;
|
||||||
GstElement *sink;
|
GstElement *sink;
|
||||||
gboolean res = TRUE;
|
gboolean res = TRUE;
|
||||||
|
|
||||||
|
@ -1069,30 +1123,71 @@ setup_sinks (GstPlayBaseBin * play_base_bin, GstPlayBaseGroup * group)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
pad = gst_element_get_pad (group->type[GST_STREAM_TYPE_AUDIO - 1].preroll,
|
pad = gst_element_get_pad (group->type[GST_STREAM_TYPE_AUDIO - 1].preroll,
|
||||||
"src");
|
"src");
|
||||||
res = add_sink (play_bin, sink, pad);
|
res = add_sink (play_bin, sink, pad, NULL);
|
||||||
gst_object_unref (pad);
|
gst_object_unref (pad);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* link video */
|
/* link video */
|
||||||
if (group->type[GST_STREAM_TYPE_VIDEO - 1].npads > 0) {
|
if (group->type[GST_STREAM_TYPE_VIDEO - 1].npads > 0) {
|
||||||
if (need_text) {
|
if (need_text) {
|
||||||
sink = gen_text_element (play_bin);
|
GstObject *parent = NULL, *grandparent = NULL;
|
||||||
|
GstPad *ghost = NULL;
|
||||||
|
|
||||||
textsinkpad = gst_element_get_pad (sink, "text_sink");
|
sink = gen_text_element (play_bin);
|
||||||
textsrcpad =
|
textsrcpad =
|
||||||
gst_element_get_pad (group->type[GST_STREAM_TYPE_TEXT - 1].preroll,
|
gst_element_get_pad (group->type[GST_STREAM_TYPE_TEXT - 1].preroll,
|
||||||
"src");
|
"src");
|
||||||
gst_pad_link (textsrcpad, textsinkpad);
|
/* This pad is from subtitle-bin, we need to create a ghost pad to have
|
||||||
gst_object_unref (textsinkpad);
|
common grandparents */
|
||||||
|
parent = gst_object_get_parent (GST_OBJECT (textsrcpad));
|
||||||
|
if (!parent) {
|
||||||
|
GST_WARNING_OBJECT (textsrcpad, "subtitle pad has no parent !");
|
||||||
gst_object_unref (textsrcpad);
|
gst_object_unref (textsrcpad);
|
||||||
|
textsrcpad = NULL;
|
||||||
|
goto beach;
|
||||||
|
}
|
||||||
|
|
||||||
|
grandparent = gst_object_get_parent (parent);
|
||||||
|
if (!grandparent) {
|
||||||
|
GST_WARNING_OBJECT (textsrcpad, "subtitle pad has no grandparent !");
|
||||||
|
gst_object_unref (parent);
|
||||||
|
gst_object_unref (textsrcpad);
|
||||||
|
textsrcpad = NULL;
|
||||||
|
goto beach;
|
||||||
|
}
|
||||||
|
|
||||||
|
ghost = gst_ghost_pad_new ("text_src", textsrcpad);
|
||||||
|
if (!GST_IS_PAD (ghost)) {
|
||||||
|
GST_WARNING_OBJECT (textsrcpad, "failed creating ghost pad for "
|
||||||
|
"subtitle-bin");
|
||||||
|
gst_object_unref (parent);
|
||||||
|
gst_object_unref (grandparent);
|
||||||
|
gst_object_unref (textsrcpad);
|
||||||
|
textsrcpad = NULL;
|
||||||
|
goto beach;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gst_element_add_pad (GST_ELEMENT (grandparent), ghost)) {
|
||||||
|
gst_object_unref (textsrcpad);
|
||||||
|
textsrcpad = ghost;
|
||||||
|
} else {
|
||||||
|
GST_WARNING_OBJECT (ghost, "failed adding ghost pad on subtitle-bin");
|
||||||
|
gst_object_unref (ghost);
|
||||||
|
gst_object_unref (textsrcpad);
|
||||||
|
textsrcpad = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_object_unref (parent);
|
||||||
|
gst_object_unref (grandparent);
|
||||||
} else {
|
} else {
|
||||||
sink = gen_video_element (play_bin);
|
sink = gen_video_element (play_bin);
|
||||||
}
|
}
|
||||||
|
beach:
|
||||||
if (!sink)
|
if (!sink)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
pad = gst_element_get_pad (group->type[GST_STREAM_TYPE_VIDEO - 1].preroll,
|
pad = gst_element_get_pad (group->type[GST_STREAM_TYPE_VIDEO - 1].preroll,
|
||||||
"src");
|
"src");
|
||||||
res = add_sink (play_bin, sink, pad);
|
res = add_sink (play_bin, sink, pad, textsrcpad);
|
||||||
gst_object_unref (pad);
|
gst_object_unref (pad);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue