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 *video_channels; /* links to selector pads */
GPtrArray *audio_channels; /* links to selector pads */ GPtrArray *audio_channels; /* links to selector pads */
GPtrArray *text_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 */ /* uridecodebins for uri and subtitle uri */
GstElement *uridecodebin; GstElement *uridecodebin;
@ -934,8 +935,10 @@ init_group (GstPlayBin * playbin, GstSourceGroup * group)
group->video_channels = g_ptr_array_new (); group->video_channels = g_ptr_array_new ();
group->audio_channels = g_ptr_array_new (); group->audio_channels = g_ptr_array_new ();
group->text_channels = g_ptr_array_new (); group->text_channels = g_ptr_array_new ();
group->subp_channels = g_ptr_array_new ();
group->lock = g_mutex_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->playbin = playbin;
group->selector[0].media = "audio/x-raw-"; group->selector[0].media = "audio/x-raw-";
group->selector[0].type = GST_PLAY_SINK_TYPE_AUDIO_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].media = "video/x-raw-";
group->selector[2].type = GST_PLAY_SINK_TYPE_VIDEO_RAW; group->selector[2].type = GST_PLAY_SINK_TYPE_VIDEO_RAW;
group->selector[2].channels = group->video_channels; group->selector[2].channels = group->video_channels;
group->selector[3].media = "video/"; group->selector[3].media = "video/x-dvd-subpicture";
group->selector[3].type = GST_PLAY_SINK_TYPE_VIDEO; group->selector[3].type = GST_PLAY_SINK_TYPE_SUBPIC;
group->selector[3].channels = group->video_channels; group->selector[3].channels = group->subp_channels;
group->selector[4].media = "text/"; group->selector[4].media = "video/";
group->selector[4].type = GST_PLAY_SINK_TYPE_TEXT; group->selector[4].type = GST_PLAY_SINK_TYPE_VIDEO;
group->selector[4].channels = group->text_channels; 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 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->video_channels, TRUE);
g_ptr_array_free (group->audio_channels, TRUE); g_ptr_array_free (group->audio_channels, TRUE);
g_ptr_array_free (group->text_channels, TRUE); g_ptr_array_free (group->text_channels, TRUE);
g_ptr_array_free (group->subp_channels, TRUE);
g_mutex_free (group->lock); 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", "pad %s:%s with caps %" GST_PTR_FORMAT " added in group %p",
GST_DEBUG_PAD_NAME (pad), caps, group); 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 */ /* major type of the pad, this determines the selector to use */
for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) { for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
if (g_str_has_prefix (name, group->selector[i].media)) { 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: case GST_PLAY_SINK_TYPE_TEXT:
signal = SIGNAL_TEXT_CHANGED; signal = SIGNAL_TEXT_CHANGED;
break; break;
case GST_PLAY_SINK_TYPE_SUBPIC:
default: default:
signal = -1; signal = -1;
} }
@ -1805,12 +1808,6 @@ done:
return; return;
/* ERRORS */ /* ERRORS */
blacklisted_type:
{
GST_WARNING_OBJECT (playbin, "blacklisted type %s for pad %s:%s",
name, GST_DEBUG_PAD_NAME (pad));
goto done;
}
unknown_type: unknown_type:
{ {
GST_ERROR_OBJECT (playbin, "unknown type %s for pad %s:%s", GST_ERROR_OBJECT (playbin, "unknown type %s for pad %s:%s",

View file

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

View file

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