mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-17 22:06:41 +00:00
gst/playback/: First stab at integrating DVD subpicture overlay into playbin. Successfully plugs and plays, but the q...
Original commit message from CVS: * gst/playback/gstplaybasebin.c: * gst/playback/gstplaybasebin.h: * gst/playback/gstplaybin.c: * gst/playback/gststreamselector.c: First stab at integrating DVD subpicture overlay into playbin. Successfully plugs and plays, but the queues need shrinking - 3 seconds of video is too much buffering.
This commit is contained in:
parent
8b24a3a057
commit
024d0e56f5
6 changed files with 150 additions and 20 deletions
10
ChangeLog
10
ChangeLog
|
@ -1,3 +1,13 @@
|
|||
2008-07-14 Jan Schmidt <thaytan@noraisin.net>
|
||||
|
||||
* gst/playback/gstplaybasebin.c:
|
||||
* gst/playback/gstplaybasebin.h:
|
||||
* gst/playback/gstplaybin.c:
|
||||
* gst/playback/gststreamselector.c:
|
||||
First stab at integrating DVD subpicture overlay into
|
||||
playbin. Successfully plugs and plays, but the queues need
|
||||
shrinking - 3 seconds of video is too much buffering.
|
||||
|
||||
2008-07-11 Stefan Kost <ensonic@users.sf.net>
|
||||
|
||||
* gst/audioconvert/gstaudioconvert.c:
|
||||
|
|
2
common
2
common
|
@ -1 +1 @@
|
|||
Subproject commit 79ade7b9c9bf47eee491ceee4cf3ea116140ad35
|
||||
Subproject commit a100efef186a5f8999fe3aa42c0720f5123c08eb
|
|
@ -791,6 +791,8 @@ gen_preroll_element (GstPlayBaseBin * play_base_bin,
|
|||
prename = "text";
|
||||
else if (type == GST_STREAM_TYPE_AUDIO)
|
||||
prename = "audio";
|
||||
else if (type == GST_STREAM_TYPE_SUBPICTURE)
|
||||
prename = "subpicture";
|
||||
else
|
||||
g_return_if_reached ();
|
||||
|
||||
|
@ -1337,6 +1339,9 @@ new_decoded_pad_full (GstElement * element, GstPad * pad, gboolean last,
|
|||
if (g_str_has_prefix (mimetype, "audio/") &&
|
||||
parent != GST_OBJECT_CAST (play_base_bin->subtitle)) {
|
||||
type = GST_STREAM_TYPE_AUDIO;
|
||||
} else if (g_str_has_prefix (mimetype, "video/x-dvd-subpicture") &&
|
||||
parent != GST_OBJECT_CAST (play_base_bin->subtitle)) {
|
||||
type = GST_STREAM_TYPE_SUBPICTURE;
|
||||
} else if (g_str_has_prefix (mimetype, "video/") &&
|
||||
parent != GST_OBJECT_CAST (play_base_bin->subtitle)) {
|
||||
type = GST_STREAM_TYPE_VIDEO;
|
||||
|
@ -1569,7 +1574,7 @@ static const gchar *no_media_mimes[] = {
|
|||
|
||||
/* mime types we consider raw media */
|
||||
static const gchar *raw_mimes[] = {
|
||||
"audio/x-raw", "video/x-raw", NULL
|
||||
"audio/x-raw", "video/x-raw", "video/x-dvd-subpicture", NULL
|
||||
};
|
||||
|
||||
#define IS_STREAM_URI(uri) (array_has_value (stream_uris, uri))
|
||||
|
|
|
@ -63,8 +63,8 @@ typedef struct
|
|||
GstElement *preroll;
|
||||
GstElement *selector;
|
||||
gboolean done;
|
||||
#define NUM_TYPES 3
|
||||
} type[NUM_TYPES]; /* AUDIO, VIDEO, TEXT */
|
||||
#define NUM_TYPES 4
|
||||
} type[NUM_TYPES]; /* AUDIO, VIDEO, TEXT, SUBPIC */
|
||||
} GstPlayBaseGroup;
|
||||
|
||||
struct _GstPlayBaseBin {
|
||||
|
|
|
@ -262,6 +262,7 @@ struct _GstPlayBin
|
|||
GstElement *pending_visualisation;
|
||||
GstElement *volume_element;
|
||||
GstElement *textoverlay_element;
|
||||
GstElement *spu_element;
|
||||
gfloat volume;
|
||||
|
||||
/* these are the currently active sinks */
|
||||
|
@ -431,6 +432,7 @@ gst_play_bin_init (GstPlayBin * play_bin)
|
|||
play_bin->pending_visualisation = NULL;
|
||||
play_bin->volume_element = NULL;
|
||||
play_bin->textoverlay_element = NULL;
|
||||
play_bin->spu_element = NULL;
|
||||
play_bin->volume = 1.0;
|
||||
play_bin->sinks = NULL;
|
||||
play_bin->frame = NULL;
|
||||
|
@ -476,6 +478,10 @@ gst_play_bin_dispose (GObject * object)
|
|||
gst_object_unref (play_bin->textoverlay_element);
|
||||
play_bin->textoverlay_element = NULL;
|
||||
}
|
||||
if (play_bin->spu_element != NULL) {
|
||||
gst_object_unref (play_bin->spu_element);
|
||||
play_bin->spu_element = NULL;
|
||||
}
|
||||
g_free (play_bin->font_desc);
|
||||
play_bin->font_desc = NULL;
|
||||
|
||||
|
@ -911,7 +917,7 @@ link_failed:
|
|||
* | tbin +-------------+ |
|
||||
* | +-----+ | textoverlay | +------+ |
|
||||
* | | csp | +--video_sink | | vbin | |
|
||||
* video_sink-sink src+ +-text_sink src-sink | |
|
||||
* video_sink-sink src+ +-text_sink src---sink | |
|
||||
* | +-----+ | +-------------+ +------+ |
|
||||
* text_sink-------------+ |
|
||||
* +--------------------------------------------------+
|
||||
|
@ -920,16 +926,11 @@ link_failed:
|
|||
* videosink without the text_sink pad.
|
||||
*/
|
||||
static GstElement *
|
||||
gen_text_element (GstPlayBin * play_bin)
|
||||
add_text_element (GstPlayBin * play_bin, GstElement * vbin)
|
||||
{
|
||||
GstElement *element, *csp, *overlay, *vbin;
|
||||
GstElement *element, *csp, *overlay;
|
||||
GstPad *pad;
|
||||
|
||||
/* Create the video rendering bin, error is posted when this fails. */
|
||||
vbin = gen_video_element (play_bin);
|
||||
if (!vbin)
|
||||
return NULL;
|
||||
|
||||
/* Text overlay */
|
||||
overlay = gst_element_factory_make ("textoverlay", "overlay");
|
||||
|
||||
|
@ -969,6 +970,13 @@ gen_text_element (GstPlayBin * play_bin)
|
|||
gst_element_add_pad (element, gst_ghost_pad_new ("sink", pad));
|
||||
gst_object_unref (pad);
|
||||
|
||||
/* If the vbin provides a subpicture sink pad, ghost it too */
|
||||
pad = gst_element_get_static_pad (vbin, "subpicture_sink");
|
||||
if (pad) {
|
||||
gst_element_add_pad (element, gst_ghost_pad_new ("subpicture_sink", pad));
|
||||
gst_object_unref (pad);
|
||||
}
|
||||
|
||||
/* Set state to READY */
|
||||
gst_element_set_state (element, GST_STATE_READY);
|
||||
|
||||
|
@ -984,6 +992,74 @@ no_overlay:
|
|||
}
|
||||
}
|
||||
|
||||
/* make an element for rendering DVD subpictures onto output video
|
||||
*
|
||||
* +---------------------------------------------+
|
||||
* | tbin +--------+ |
|
||||
* | +-----+ | | +------+ |
|
||||
* | | csp | src-videosink | | vbin | |
|
||||
* video_sink-sink src+ | src-sink | |
|
||||
* | +-----+ +subpicture | +------+ |
|
||||
* subpicture_pad--------+ +--------+ |
|
||||
* +---------- ----------------------------------+
|
||||
*
|
||||
*/
|
||||
static GstElement *
|
||||
add_spu_element (GstPlayBin * play_bin, GstElement * vbin)
|
||||
{
|
||||
GstElement *element, *csp, *overlay;
|
||||
GstPad *pad;
|
||||
|
||||
/* DVD spu overlay */
|
||||
GST_DEBUG_OBJECT (play_bin, "Attempting to insert DVD SPU element");
|
||||
|
||||
overlay = gst_element_factory_make ("dvdspu", "overlay");
|
||||
|
||||
/* If no overlay return the video bin without subpicture support. */
|
||||
if (!overlay)
|
||||
goto no_overlay;
|
||||
|
||||
/* Create our bin */
|
||||
element = gst_bin_new ("spubin");
|
||||
|
||||
/* Take a ref */
|
||||
play_bin->spu_element = GST_ELEMENT_CAST (gst_object_ref (overlay));
|
||||
|
||||
/* we know this will succeed, as the video bin already created one before */
|
||||
csp = gst_element_factory_make ("ffmpegcolorspace", "spucsp");
|
||||
|
||||
/* Add our elements */
|
||||
gst_bin_add_many (GST_BIN_CAST (element), csp, overlay, vbin, NULL);
|
||||
|
||||
/* Link */
|
||||
gst_element_link_pads (csp, "src", overlay, "video");
|
||||
gst_element_link_pads (overlay, "src", vbin, "sink");
|
||||
|
||||
/* Add ghost pad on the subpicture bin so it looks like vbin */
|
||||
pad = gst_element_get_static_pad (csp, "sink");
|
||||
gst_element_add_pad (element, gst_ghost_pad_new ("sink", pad));
|
||||
gst_object_unref (pad);
|
||||
|
||||
pad = gst_element_get_static_pad (overlay, "subpicture");
|
||||
gst_element_add_pad (element, gst_ghost_pad_new ("subpicture_sink", pad));
|
||||
gst_object_unref (pad);
|
||||
|
||||
/* Set state to READY */
|
||||
gst_element_set_state (element, GST_STATE_READY);
|
||||
|
||||
return element;
|
||||
|
||||
/* ERRORS */
|
||||
no_overlay:
|
||||
{
|
||||
post_missing_element_message (play_bin, "dvdspu");
|
||||
GST_WARNING_OBJECT (play_bin,
|
||||
"No DVD overlay (dvdspu) element. "
|
||||
"menu highlight/subtitles unavailable");
|
||||
return vbin;
|
||||
}
|
||||
}
|
||||
|
||||
/* make the element (bin) that contains the elements needed to perform
|
||||
* audio playback.
|
||||
*
|
||||
|
@ -1479,8 +1555,10 @@ static gboolean
|
|||
setup_sinks (GstPlayBaseBin * play_base_bin, GstPlayBaseGroup * group)
|
||||
{
|
||||
GstPlayBin *play_bin = GST_PLAY_BIN (play_base_bin);
|
||||
gboolean have_video = FALSE;
|
||||
gboolean need_vis = FALSE;
|
||||
gboolean need_text = FALSE;
|
||||
gboolean need_spu = FALSE;
|
||||
GstPad *textsrcpad = NULL, *pad = NULL, *origtextsrcpad = NULL;
|
||||
GstElement *sink;
|
||||
gboolean res = TRUE;
|
||||
|
@ -1492,10 +1570,12 @@ setup_sinks (GstPlayBaseBin * play_base_bin, GstPlayBaseGroup * group)
|
|||
GST_DEBUG_OBJECT (play_base_bin, "setupsinks");
|
||||
|
||||
/* find out what to do */
|
||||
if (group->type[GST_STREAM_TYPE_VIDEO - 1].npads > 0 &&
|
||||
group->type[GST_STREAM_TYPE_TEXT - 1].npads > 0) {
|
||||
have_video = (group->type[GST_STREAM_TYPE_VIDEO - 1].npads > 0);
|
||||
need_spu = (group->type[GST_STREAM_TYPE_SUBPICTURE - 1].npads != 0);
|
||||
|
||||
if (have_video && group->type[GST_STREAM_TYPE_TEXT - 1].npads > 0) {
|
||||
need_text = TRUE;
|
||||
} else if (group->type[GST_STREAM_TYPE_VIDEO - 1].npads == 0 &&
|
||||
} else if (!have_video &&
|
||||
group->type[GST_STREAM_TYPE_AUDIO - 1].npads > 0 &&
|
||||
play_bin->visualisation != NULL) {
|
||||
need_vis = TRUE;
|
||||
|
@ -1521,12 +1601,23 @@ setup_sinks (GstPlayBaseBin * play_base_bin, GstPlayBaseGroup * group)
|
|||
}
|
||||
|
||||
/* link video */
|
||||
if (group->type[GST_STREAM_TYPE_VIDEO - 1].npads > 0) {
|
||||
if (have_video) {
|
||||
/* Create the video rendering bin, error is posted when this fails. */
|
||||
sink = gen_video_element (play_bin);
|
||||
if (!sink)
|
||||
return FALSE;
|
||||
if (need_spu) {
|
||||
sink = add_spu_element (play_bin, sink);
|
||||
}
|
||||
|
||||
if (need_text) {
|
||||
GstObject *parent = NULL, *grandparent = NULL;
|
||||
GstPad *ghost = NULL;
|
||||
|
||||
sink = gen_text_element (play_bin);
|
||||
/* Add the subtitle overlay element into the video sink */
|
||||
sink = add_text_element (play_bin, sink);
|
||||
|
||||
/* Link the incoming subtitle stream into the output bin */
|
||||
textsrcpad =
|
||||
gst_element_get_static_pad (group->type[GST_STREAM_TYPE_TEXT -
|
||||
1].preroll, "src");
|
||||
|
@ -1589,8 +1680,6 @@ setup_sinks (GstPlayBaseBin * play_base_bin, GstPlayBaseGroup * group)
|
|||
|
||||
gst_object_unref (parent);
|
||||
gst_object_unref (grandparent);
|
||||
} else {
|
||||
sink = gen_video_element (play_bin);
|
||||
}
|
||||
beach:
|
||||
if (!sink)
|
||||
|
@ -1606,6 +1695,30 @@ setup_sinks (GstPlayBaseBin * play_base_bin, GstPlayBaseGroup * group)
|
|||
gst_pad_set_blocked_async (origtextsrcpad, FALSE, dummy_blocked_cb, NULL);
|
||||
gst_object_unref (origtextsrcpad);
|
||||
}
|
||||
|
||||
/* If we have a DVD subpicture stream, link it to the SPU now */
|
||||
if (need_spu) {
|
||||
GstPad *subpic_pad;
|
||||
GstPad *spu_sink_pad;
|
||||
|
||||
subpic_pad =
|
||||
gst_element_get_static_pad (group->type[GST_STREAM_TYPE_SUBPICTURE
|
||||
- 1].preroll, "src");
|
||||
spu_sink_pad = gst_element_get_static_pad (sink, "subpicture_sink");
|
||||
if (subpic_pad && spu_sink_pad) {
|
||||
GST_LOG_OBJECT (play_bin, "Linking DVD subpicture stream onto SPU");
|
||||
gst_pad_set_blocked_async (subpic_pad, TRUE, dummy_blocked_cb, NULL);
|
||||
if (gst_pad_link (subpic_pad, spu_sink_pad) != GST_PAD_LINK_OK) {
|
||||
GST_WARNING_OBJECT (play_bin,
|
||||
"Failed to link DVD subpicture stream onto SPU");
|
||||
}
|
||||
gst_pad_set_blocked_async (subpic_pad, FALSE, dummy_blocked_cb, NULL);
|
||||
}
|
||||
if (subpic_pad)
|
||||
gst_object_unref (subpic_pad);
|
||||
if (spu_sink_pad)
|
||||
gst_object_unref (spu_sink_pad);
|
||||
}
|
||||
}
|
||||
|
||||
/* remove the sinks now, pipeline get_state will now wait for the
|
||||
|
|
|
@ -254,12 +254,14 @@ gst_selector_pad_event (GstPad * pad, GstEvent * event)
|
|||
gboolean forward = TRUE;
|
||||
GstStreamSelector *sel;
|
||||
GstSelectorPad *selpad;
|
||||
GstPad *active_sinkpad;
|
||||
|
||||
sel = GST_STREAM_SELECTOR (gst_pad_get_parent (pad));
|
||||
selpad = GST_SELECTOR_PAD_CAST (pad);
|
||||
|
||||
/* only forward if we are dealing with the active sinkpad */
|
||||
forward = gst_stream_selector_is_active_sinkpad (sel, pad);
|
||||
active_sinkpad = gst_stream_selector_activate_sinkpad (sel, pad);
|
||||
forward = (active_sinkpad == pad);
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_FLUSH_STOP:
|
||||
|
|
Loading…
Reference in a new issue