From e7b382c6a9e1bec3cf7772989a9093818a112de9 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Tue, 24 Mar 2009 17:12:53 +0100 Subject: [PATCH] playbin2: first support for subpictures Add beginnings of subpicture support. --- gst/playback/gstplaybin2.c | 33 +++++++--------- gst/playback/gstplaysink.c | 97 +++++++++++++++++++++++++++++++--------------- gst/playback/gstplaysink.h | 7 +++- 3 files changed, 85 insertions(+), 52 deletions(-) diff --git a/gst/playback/gstplaybin2.c b/gst/playback/gstplaybin2.c index f5c7f70..71c3e8e 100644 --- a/gst/playback/gstplaybin2.c +++ b/gst/playback/gstplaybin2.c @@ -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", diff --git a/gst/playback/gstplaysink.c b/gst/playback/gstplaysink.c index 1773c70..53401d1 100644 --- a/gst/playback/gstplaysink.c +++ b/gst/playback/gstplaysink.c @@ -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; diff --git a/gst/playback/gstplaysink.h b/gst/playback/gstplaysink.h index aa62521..d04c17a 100644 --- a/gst/playback/gstplaysink.h +++ b/gst/playback/gstplaysink.h @@ -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; -- 2.7.4