playbin2: first support for subpictures

Add beginnings of subpicture support.
This commit is contained in:
Wim Taymans 2009-03-24 17:12:53 +01:00
parent c081c6b747
commit e7b382c6a9
3 changed files with 85 additions and 52 deletions

View file

@ -274,6 +274,7 @@ struct _GstSourceGroup
GPtrArray *video_channels; /* links to selector pads */
GPtrArray *audio_channels; /* links to selector pads */
GPtrArray *text_channels; /* links to selector pads */
GPtrArray *subp_channels; /* links to selector pads */
/* uridecodebins for uri and subtitle uri */
GstElement *uridecodebin;
@ -934,8 +935,10 @@ init_group (GstPlayBin * playbin, GstSourceGroup * group)
group->video_channels = g_ptr_array_new ();
group->audio_channels = g_ptr_array_new ();
group->text_channels = g_ptr_array_new ();
group->subp_channels = g_ptr_array_new ();
group->lock = g_mutex_new ();
/* init selectors */
/* init selectors. The selector is found by finding the first prefix that
* matches the media. */
group->playbin = playbin;
group->selector[0].media = "audio/x-raw-";
group->selector[0].type = GST_PLAY_SINK_TYPE_AUDIO_RAW;
@ -946,12 +949,15 @@ init_group (GstPlayBin * playbin, GstSourceGroup * group)
group->selector[2].media = "video/x-raw-";
group->selector[2].type = GST_PLAY_SINK_TYPE_VIDEO_RAW;
group->selector[2].channels = group->video_channels;
group->selector[3].media = "video/";
group->selector[3].type = GST_PLAY_SINK_TYPE_VIDEO;
group->selector[3].channels = group->video_channels;
group->selector[4].media = "text/";
group->selector[4].type = GST_PLAY_SINK_TYPE_TEXT;
group->selector[4].channels = group->text_channels;
group->selector[3].media = "video/x-dvd-subpicture";
group->selector[3].type = GST_PLAY_SINK_TYPE_SUBPIC;
group->selector[3].channels = group->subp_channels;
group->selector[4].media = "video/";
group->selector[4].type = GST_PLAY_SINK_TYPE_VIDEO;
group->selector[4].channels = group->video_channels;
group->selector[5].media = "text/";
group->selector[5].type = GST_PLAY_SINK_TYPE_TEXT;
group->selector[5].channels = group->text_channels;
}
static void
@ -961,6 +967,7 @@ free_group (GstPlayBin * playbin, GstSourceGroup * group)
g_ptr_array_free (group->video_channels, TRUE);
g_ptr_array_free (group->audio_channels, TRUE);
g_ptr_array_free (group->text_channels, TRUE);
g_ptr_array_free (group->subp_channels, TRUE);
g_mutex_free (group->lock);
}
@ -1708,11 +1715,6 @@ pad_added_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group)
"pad %s:%s with caps %" GST_PTR_FORMAT " added in group %p",
GST_DEBUG_PAD_NAME (pad), caps, group);
for (i = 0; blacklisted_mimes[i]; i++) {
if (!strcmp (name, blacklisted_mimes[i]))
goto blacklisted_type;
}
/* major type of the pad, this determines the selector to use */
for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
if (g_str_has_prefix (name, group->selector[i].media)) {
@ -1792,6 +1794,7 @@ pad_added_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group)
case GST_PLAY_SINK_TYPE_TEXT:
signal = SIGNAL_TEXT_CHANGED;
break;
case GST_PLAY_SINK_TYPE_SUBPIC:
default:
signal = -1;
}
@ -1805,12 +1808,6 @@ done:
return;
/* ERRORS */
blacklisted_type:
{
GST_WARNING_OBJECT (playbin, "blacklisted type %s for pad %s:%s",
name, GST_DEBUG_PAD_NAME (pad));
goto done;
}
unknown_type:
{
GST_ERROR_OBJECT (playbin, "unknown type %s for pad %s:%s",

View file

@ -110,23 +110,31 @@ struct _GstPlaySink
GstPlayFlags flags;
/* chains */
GstPlayAudioChain *audiochain;
GstPlayVideoChain *videochain;
GstPlayVisChain *vischain;
GstPlayTextChain *textchain;
/* audio */
GstPad *audio_pad;
gboolean audio_pad_raw;
/* audio tee */
GstElement *audio_tee;
GstPad *audio_tee_sink;
GstPad *audio_tee_asrc;
GstPad *audio_tee_vissrc;
/* video */
GstPad *video_pad;
gboolean video_pad_raw;
/* text */
GstPad *text_pad;
/* subpictures */
GstPad *subp_pad;
/* properties */
GstElement *audio_sink;
GstElement *video_sink;
@ -769,12 +777,13 @@ try_element (GstPlaySink * playsink, GstElement * element)
*
*/
static GstPlayVideoChain *
gen_video_chain (GstPlaySink * playsink, gboolean raw, gboolean async)
gen_video_chain (GstPlaySink * playsink, gboolean raw, gboolean async,
gboolean queue)
{
GstPlayVideoChain *chain;
GstBin *bin;
GstPad *pad;
GstElement *prev, *elem;
GstElement *head, *prev, *elem;
chain = g_new0 (GstPlayVideoChain, 1);
chain->chain.playsink = playsink;
@ -821,15 +830,20 @@ gen_video_chain (GstPlaySink * playsink, gboolean raw, gboolean async)
gst_object_sink (bin);
gst_bin_add (bin, chain->sink);
/* decouple decoder from sink, this improves playback quite a lot since the
* decoder can continue while the sink blocks for synchronisation. We don't
* need a lot of buffers as this consumes a lot of memory and we don't want
* too little because else we would be context switching too quickly. */
chain->queue = gst_element_factory_make ("queue", "vqueue");
g_object_set (G_OBJECT (chain->queue), "max-size-buffers", 3,
"max-size-bytes", 0, "max-size-time", (gint64) 0, NULL);
gst_bin_add (bin, chain->queue);
prev = chain->queue;
if (queue) {
/* decouple decoder from sink, this improves playback quite a lot since the
* decoder can continue while the sink blocks for synchronisation. We don't
* need a lot of buffers as this consumes a lot of memory and we don't want
* too little because else we would be context switching too quickly. */
chain->queue = gst_element_factory_make ("queue", "vqueue");
g_object_set (G_OBJECT (chain->queue), "max-size-buffers", 3,
"max-size-bytes", 0, "max-size-time", (gint64) 0, NULL);
gst_bin_add (bin, chain->queue);
head = prev = chain->queue;
} else {
head = chain->sink;
prev = NULL;
}
if (raw && !(playsink->flags & GST_PLAY_FLAG_NATIVE_VIDEO)) {
GST_DEBUG_OBJECT (playsink, "creating ffmpegcolorspace");
@ -841,9 +855,12 @@ gen_video_chain (GstPlaySink * playsink, gboolean raw, gboolean async)
"ffmpegcolorspace"), ("video rendering might fail"));
} else {
gst_bin_add (bin, chain->conv);
if (!gst_element_link_pads (prev, "src", chain->conv, "sink"))
goto link_failed;
if (prev) {
if (!gst_element_link_pads (prev, "src", chain->conv, "sink"))
goto link_failed;
} else {
head = chain->conv;
}
prev = chain->conv;
}
@ -856,19 +873,23 @@ gen_video_chain (GstPlaySink * playsink, gboolean raw, gboolean async)
"videoscale"), ("possibly a liboil version mismatch?"));
} else {
gst_bin_add (bin, chain->scale);
if (!gst_element_link_pads (prev, "src", chain->scale, "sink"))
goto link_failed;
if (prev) {
if (!gst_element_link_pads (prev, "src", chain->scale, "sink"))
goto link_failed;
} else {
head = chain->scale;
}
prev = chain->scale;
}
}
/* be more careful with the pad from the custom sink element, it might not
* be named 'sink' */
if (!gst_element_link_pads (prev, "src", chain->sink, NULL))
goto link_failed;
if (prev) {
GST_DEBUG_OBJECT (playsink, "linking to sink");
if (!gst_element_link_pads (prev, "src", chain->sink, NULL))
goto link_failed;
}
pad = gst_element_get_static_pad (chain->queue, "sink");
pad = gst_element_get_static_pad (head, "sink");
chain->sinkpad = gst_ghost_pad_new ("sink", pad);
gst_object_unref (pad);
@ -896,7 +917,8 @@ link_failed:
}
static gboolean
setup_video_chain (GstPlaySink * playsink, gboolean raw, gboolean async)
setup_video_chain (GstPlaySink * playsink, gboolean raw, gboolean async,
gboolean queue)
{
GstElement *elem;
GstPlayVideoChain *chain;
@ -1456,12 +1478,12 @@ gboolean
gst_play_sink_reconfigure (GstPlaySink * playsink)
{
GstPlayFlags flags;
gboolean need_audio, need_video, need_vis, need_text;
gboolean need_audio, need_video, need_vis, need_text, need_subp;
GST_DEBUG_OBJECT (playsink, "reconfiguring");
/* assume we need nothing */
need_audio = need_video = need_vis = need_text = FALSE;
need_audio = need_video = need_vis = need_text = need_subp = FALSE;
GST_PLAY_SINK_LOCK (playsink);
GST_OBJECT_LOCK (playsink);
@ -1500,20 +1522,22 @@ gst_play_sink_reconfigure (GstPlaySink * playsink)
/* set up video pipeline */
if (need_video) {
gboolean raw, async;
gboolean raw, async, queue;
/* we need a raw sink when we do vis or when we have a raw pad */
raw = need_vis ? TRUE : playsink->video_pad_raw;
/* we try to set the sink async=FALSE when we need vis, this way we can
* avoid a queue in the audio chain. */
async = !need_vis;
/* put a little queue in front of the video */
queue = TRUE;
GST_DEBUG_OBJECT (playsink, "adding video, raw %d",
playsink->video_pad_raw);
if (playsink->videochain) {
/* try to reactivate the chain */
if (!setup_video_chain (playsink, raw, async)) {
if (!setup_video_chain (playsink, raw, async, queue)) {
add_chain (GST_PLAY_CHAIN (playsink->videochain), FALSE);
activate_chain (GST_PLAY_CHAIN (playsink->videochain), FALSE);
free_chain ((GstPlayChain *) playsink->videochain);
@ -1522,7 +1546,7 @@ gst_play_sink_reconfigure (GstPlaySink * playsink)
}
if (!playsink->videochain) {
playsink->videochain = gen_video_chain (playsink, raw, async);
playsink->videochain = gen_video_chain (playsink, raw, async, queue);
}
if (playsink->videochain) {
GST_DEBUG_OBJECT (playsink, "adding video chain");
@ -1553,8 +1577,8 @@ gst_play_sink_reconfigure (GstPlaySink * playsink)
playsink->audio_tee_vissrc = NULL;
}
srcpad =
gst_element_get_static_pad (GST_ELEMENT_CAST (playsink->vischain->
chain.bin), "src");
gst_element_get_static_pad (GST_ELEMENT_CAST (playsink->
vischain->chain.bin), "src");
gst_pad_unlink (srcpad, playsink->videochain->sinkpad);
}
add_chain (GST_PLAY_CHAIN (playsink->videochain), FALSE);
@ -1683,8 +1707,8 @@ gst_play_sink_reconfigure (GstPlaySink * playsink)
if (playsink->vischain) {
GST_DEBUG_OBJECT (playsink, "setting up vis chain");
srcpad =
gst_element_get_static_pad (GST_ELEMENT_CAST (playsink->vischain->
chain.bin), "src");
gst_element_get_static_pad (GST_ELEMENT_CAST (playsink->
vischain->chain.bin), "src");
add_chain (GST_PLAY_CHAIN (playsink->vischain), TRUE);
activate_chain (GST_PLAY_CHAIN (playsink->vischain), TRUE);
if (playsink->audio_tee_vissrc == NULL) {
@ -1925,6 +1949,15 @@ gst_play_sink_request_pad (GstPlaySink * playsink, GstPlaySinkType type)
created = TRUE;
break;
}
case GST_PLAY_SINK_TYPE_SUBPIC:
GST_LOG_OBJECT (playsink, "ghosting subpicture pad");
if (!playsink->subp_pad) {
playsink->subp_pad =
gst_ghost_pad_new_no_target ("subp_sink", GST_PAD_SINK);
created = TRUE;
}
res = playsink->subp_pad;
break;
default:
res = NULL;
break;

View file

@ -55,8 +55,11 @@ typedef enum {
GST_PLAY_SINK_TYPE_VIDEO = 2,
GST_PLAY_SINK_TYPE_VIDEO_RAW = 3,
GST_PLAY_SINK_TYPE_TEXT = 4,
GST_PLAY_SINK_TYPE_LAST = 5,
GST_PLAY_SINK_TYPE_FLUSHING = 6
GST_PLAY_SINK_TYPE_SUBPIC = 5,
GST_PLAY_SINK_TYPE_LAST = 6,
/* this is a dummy pad */
GST_PLAY_SINK_TYPE_FLUSHING = 7
} GstPlaySinkType;
typedef struct _GstPlaySink GstPlaySink;