Commit f2f9bf04 authored by Wim Taymans's avatar Wim Taymans

gst/playback/Makefile.am: Group decodebin2 and uridecodebin into the same...

gst/playback/Makefile.am: Group decodebin2 and uridecodebin into the same plugin so that they can share the GEnumType.

Original commit message from CVS:
* gst/playback/Makefile.am:
Group decodebin2 and uridecodebin into the same plugin so that they
can share the GEnumType.
* gst/playback/gstdecodebin2.c: (_gst_array_accumulator),
(_gst_select_accumulator), (gst_decode_bin_class_init),
(gst_decode_bin_init), (gst_decode_bin_autoplug_sort),
(gst_decode_bin_autoplug_select), (gst_decode_bin_autoplug_add),
(analyze_new_pad), (connect_pad), (gst_decode_bin_plugin_init):
Add signal to sort factories instead of the more awkward autoplug-select
signal.
Modify autoplug_select so that we can try, skip or expose the
autopluggin of an element on a pad.
* gst/playback/gstfactorylists.c: (compare_ranks),
(decoders_filter), (sinks_filter), (gst_factory_list_is_type),
(element_filter), (gst_factory_list_get_elements),
(gst_factory_list_debug), (gst_factory_list_filter):
* gst/playback/gstfactorylists.h:
Simplify the API, allow getting elements based on mask.
* gst/playback/gstplay-marshal.list:
Add some more marshallers.
* gst/playback/gstplaybin2.c: (init_group), (gst_play_bin_init),
(gst_play_bin_finalize), (pad_removed_cb), (autoplug_factories_cb),
(autoplug_select_cb), (activate_group):
Add support for managing non-raw sinks by providing a custom element and
sink list to decodebin2.
Try to plug non-raw sinks when decodebin2 using autoplug-select of
decodebin2.
* gst/playback/gstplaysink.c: (gen_video_chain), (gen_audio_chain),
(gst_play_sink_set_mode), (gst_play_sink_request_pad):
* gst/playback/gstplaysink.h:
Add support for raw and non-raw sinks.
Add support to force sinks selected by playbin2.
Don't plug raw converters for non-raw sinks.
* gst/playback/gsturidecodebin.c: (_gst_array_accumulator),
(_gst_select_accumulator), (gst_uri_decode_bin_class_init),
(proxy_autoplug_select_signal), (gst_uri_decode_bin_plugin_init),
(plugin_init):
Use right accumulators.
Proxy new signal.
parent 75aa0424
2007-12-05 Wim Taymans <wim.taymans@gmail.com>
* gst/playback/Makefile.am:
Group decodebin2 and uridecodebin into the same plugin so that they
can share the GEnumType.
* gst/playback/gstdecodebin2.c: (_gst_array_accumulator),
(_gst_select_accumulator), (gst_decode_bin_class_init),
(gst_decode_bin_init), (gst_decode_bin_autoplug_sort),
(gst_decode_bin_autoplug_select), (gst_decode_bin_autoplug_add),
(analyze_new_pad), (connect_pad), (gst_decode_bin_plugin_init):
Add signal to sort factories instead of the more awkward autoplug-select
signal.
Modify autoplug_select so that we can try, skip or expose the
autopluggin of an element on a pad.
* gst/playback/gstfactorylists.c: (compare_ranks),
(decoders_filter), (sinks_filter), (gst_factory_list_is_type),
(element_filter), (gst_factory_list_get_elements),
(gst_factory_list_debug), (gst_factory_list_filter):
* gst/playback/gstfactorylists.h:
Simplify the API, allow getting elements based on mask.
* gst/playback/gstplay-marshal.list:
Add some more marshallers.
* gst/playback/gstplaybin2.c: (init_group), (gst_play_bin_init),
(gst_play_bin_finalize), (pad_removed_cb), (autoplug_factories_cb),
(autoplug_select_cb), (activate_group):
Add support for managing non-raw sinks by providing a custom element and
sink list to decodebin2.
Try to plug non-raw sinks when decodebin2 using autoplug-select of
decodebin2.
* gst/playback/gstplaysink.c: (gen_video_chain), (gen_audio_chain),
(gst_play_sink_set_mode), (gst_play_sink_request_pad):
* gst/playback/gstplaysink.h:
Add support for raw and non-raw sinks.
Add support to force sinks selected by playbin2.
Don't plug raw converters for non-raw sinks.
* gst/playback/gsturidecodebin.c: (_gst_array_accumulator),
(_gst_select_accumulator), (gst_uri_decode_bin_class_init),
(proxy_autoplug_select_signal), (gst_uri_decode_bin_plugin_init),
(plugin_init):
Use right accumulators.
Proxy new signal.
2007-12-03 Wim Taymans <wim.taymans@gmail.com>
* gst-libs/gst/rtp/gstbasertppayload.c: (gst_basertppayload_push):
......@@ -7,8 +7,7 @@ built_headers = gstplay-marshal.h
plugindir = $(libdir)/gstreamer-@GST_MAJORMINOR@
plugin_LTLIBRARIES = libgstplaybin.la libgstdecodebin.la libgstdecodebin2.la libgstqueue2.la \
libgsturidecodebin.la
plugin_LTLIBRARIES = libgstplaybin.la libgstdecodebin.la libgstdecodebin2.la libgstqueue2.la
libgstplaybin_la_SOURCES = \
gstplayback.c \
......@@ -16,6 +15,7 @@ libgstplaybin_la_SOURCES = \
gstplaybin2.c \
gstplaysink.c \
gstplaybasebin.c \
gstplay-enum.c \
gstfactorylists.c \
gststreaminfo.c \
gststreamselector.c
......@@ -35,7 +35,7 @@ libgstdecodebin_la_LIBADD = \
$(top_builddir)/gst-libs/gst/pbutils/libgstpbutils-@GST_MAJORMINOR@.la \
$(GST_LIBS)
libgstdecodebin2_la_SOURCES = gstdecodebin2.c gstfactorylists.c
libgstdecodebin2_la_SOURCES = gstdecodebin2.c gsturidecodebin.c gstfactorylists.c gstplay-enum.c
nodist_libgstdecodebin2_la_SOURCES = $(built_sources)
libgstdecodebin2_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS)
libgstdecodebin2_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
......@@ -49,19 +49,12 @@ libgstqueue2_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS)
libgstqueue2_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstqueue2_la_LIBADD = $(GST_LIBS)
libgsturidecodebin_la_SOURCES = gsturidecodebin.c
nodist_libgsturidecodebin_la_SOURCES = $(built_sources)
libgsturidecodebin_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS)
libgsturidecodebin_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgsturidecodebin_la_LIBADD = \
$(top_builddir)/gst-libs/gst/pbutils/libgstpbutils-@GST_MAJORMINOR@.la \
$(GST_LIBS)
noinst_HEADERS = \
gstplaybasebin.h \
gstplaysink.h \
gststreaminfo.h \
gstfactorylists.h \
gstplay-enum.h \
gststreamselector.h
noinst_PROGRAMS = test decodetest test2 test3 test4 test5 test6 test7
......
This diff is collapsed.
......@@ -20,6 +20,11 @@
#include "gstfactorylists.h"
typedef struct
{
GstFactoryListType type;
} FilterData;
/* function used to sort element features. We first sort on the rank, then
* on the element name (to get a consistent, predictable list) */
static gint
......@@ -44,61 +49,15 @@ compare_ranks (GValue * v1, GValue * v2)
return diff;
}
#if 0
static void
print_feature (GstPluginFeature * feature)
{
const gchar *rname;
rname = gst_plugin_feature_get_name (feature);
GST_DEBUG ("%s", rname);
}
#endif
/* get a filtered feature list as a GValueArray */
static GValueArray *
get_feature_array (GstPluginFeatureFilter filter)
{
GValueArray *result;
GList *walk, *list;
result = g_value_array_new (0);
/* get the feature list using the filter */
list = gst_default_registry_feature_filter (filter, FALSE, NULL);
/* convert to an array */
for (walk = list; walk; walk = g_list_next (walk)) {
GstElementFactory *factory = GST_ELEMENT_FACTORY (walk->data);
GValue val = { 0, };
g_value_init (&val, G_TYPE_OBJECT);
g_value_set_object (&val, factory);
g_value_array_append (result, &val);
g_value_unset (&val);
}
gst_plugin_feature_list_free (list);
/* sort on rank and name */
g_value_array_sort (result, (GCompareFunc) compare_ranks);
return result;
}
/* the filter function for selecting the elements we can use in
* autoplugging */
static gboolean
decoders_filter (GstPluginFeature * feature)
decoders_filter (GstElementFactory * factory)
{
guint rank;
const gchar *klass;
/* we only care about element factories */
if (!GST_IS_ELEMENT_FACTORY (feature))
return FALSE;
klass = gst_element_factory_get_klass (GST_ELEMENT_FACTORY (feature));
klass = gst_element_factory_get_klass (factory);
/* only demuxers, decoders, depayloaders and parsers can play */
if (strstr (klass, "Demux") == NULL &&
strstr (klass, "Decoder") == NULL &&
......@@ -108,7 +67,7 @@ decoders_filter (GstPluginFeature * feature)
}
/* only select elements with autoplugging rank */
rank = gst_plugin_feature_get_rank (feature);
rank = gst_plugin_feature_get_rank (GST_PLUGIN_FEATURE (factory));
if (rank < GST_RANK_MARGINAL)
return FALSE;
......@@ -118,16 +77,12 @@ decoders_filter (GstPluginFeature * feature)
/* the filter function for selecting the elements we can use in
* autoplugging */
static gboolean
sinks_filter (GstPluginFeature * feature)
sinks_filter (GstElementFactory * factory)
{
guint rank;
const gchar *klass;
/* we only care about element factories */
if (!GST_IS_ELEMENT_FACTORY (feature))
return FALSE;
klass = gst_element_factory_get_klass (GST_ELEMENT_FACTORY (feature));
klass = gst_element_factory_get_klass (factory);
/* only sinks can play */
if (strstr (klass, "Sink") == NULL) {
return FALSE;
......@@ -139,53 +94,115 @@ sinks_filter (GstPluginFeature * feature)
}
/* only select elements with autoplugging rank */
rank = gst_plugin_feature_get_rank (feature);
rank = gst_plugin_feature_get_rank (GST_PLUGIN_FEATURE (factory));
if (rank < GST_RANK_MARGINAL)
return FALSE;
return TRUE;
}
/**
* gst_factory_list_get_decoders:
* gst_factory_list_is_type:
* @factory: a #GstElementFactory
* @type: a #GstFactoryListType
*
* Get a sorted list of factories that can be used in decoding pipelines.
* Check if @factory if of the given types.
*
* Returns: a #GValueArray of #GstElementFactory elements. Use
* g_value_array_free() after usage.
* Returns: %TRUE if @factory is of @type.
*/
GValueArray *
gst_factory_list_get_decoders (void)
gboolean
gst_factory_list_is_type (GstElementFactory * factory, GstFactoryListType type)
{
GValueArray *result;
gboolean res = FALSE;
/* first filter out the interesting element factories */
result = get_feature_array ((GstPluginFeatureFilter) decoders_filter);
if (!res && (type & GST_FACTORY_LIST_SINK))
res = sinks_filter (factory);
if (!res && (type & GST_FACTORY_LIST_DECODER))
res = decoders_filter (factory);
return result;
return res;
}
static gboolean
element_filter (GstPluginFeature * feature, FilterData * data)
{
gboolean res;
/* we only care about element factories */
if (!GST_IS_ELEMENT_FACTORY (feature))
return FALSE;
res = gst_factory_list_is_type (GST_ELEMENT_FACTORY (feature), data->type);
return res;
}
/**
* gst_factory_list_get_sinks:
* gst_factory_list_get_elements:
* @type: a #GstFactoryListType
*
* Get a sorted list of factories that can be used as sinks in a decoding
* pipeline.
* Get a sorted list of factories of @type.
*
* Returns: a #GValueArray of #GstElementFactory elements. Use
* g_value_array_free() after usage.
*/
GValueArray *
gst_factory_list_get_sinks (void)
gst_factory_list_get_elements (GstFactoryListType type)
{
GValueArray *result;
GList *walk, *list;
FilterData data;
/* first filter out the interesting element factories */
result = get_feature_array ((GstPluginFeatureFilter) sinks_filter);
result = g_value_array_new (0);
/* prepare type */
data.type = type;
/* get the feature list using the filter */
list =
gst_default_registry_feature_filter ((GstPluginFeatureFilter)
element_filter, FALSE, &data);
/* convert to an array */
for (walk = list; walk; walk = g_list_next (walk)) {
GstElementFactory *factory = GST_ELEMENT_FACTORY (walk->data);
GValue val = { 0, };
g_value_init (&val, G_TYPE_OBJECT);
g_value_set_object (&val, factory);
g_value_array_append (result, &val);
g_value_unset (&val);
}
gst_plugin_feature_list_free (list);
/* sort on rank and name */
g_value_array_sort (result, (GCompareFunc) compare_ranks);
return result;
}
/**
* gst_factory_list_debug:
* @array: an array of element factories
*
* Debug the element factory names in @array.
*/
void
gst_factory_list_debug (GValueArray * array)
{
gint i;
for (i = 0; i < array->n_values; i++) {
GValue *value;
GstPluginFeature *feature;
value = g_value_array_get_nth (array, i);
feature = g_value_get_object (value);
GST_DEBUG ("%s", gst_plugin_feature_get_name (feature));
}
}
/**
* gst_factory_list_filter:
* @array: a #GValueArray to filter
......
......@@ -25,8 +25,17 @@
G_BEGIN_DECLS
GValueArray * gst_factory_list_get_decoders (void);
GValueArray * gst_factory_list_get_sinks (void);
typedef enum {
GST_FACTORY_LIST_DECODER = (1 << 0),
GST_FACTORY_LIST_ENCODER = (1 << 1),
GST_FACTORY_LIST_SINK = (1 << 2),
GST_FACTORY_LIST_SRC = (1 << 3)
} GstFactoryListType;
gboolean gst_factory_list_is_type (GstElementFactory *factory, GstFactoryListType type);
GValueArray * gst_factory_list_get_elements (GstFactoryListType type);
void gst_factory_list_debug (GValueArray *array);
GValueArray * gst_factory_list_filter (GValueArray *array, const GstCaps *caps);
......
BOOLEAN:OBJECT,OBJECT
BOOLEAN:OBJECT,OBJECT,OBJECT
BOXED:OBJECT,OBJECT
VOID:OBJECT,BOOLEAN
INT:OBJECT,OBJECT,BOXED
ENUM:OBJECT,OBJECT,BOXED
ENUM:OBJECT,OBJECT,OBJECT
BOXED:OBJECT,OBJECT,BOXED
......@@ -248,6 +248,7 @@
#include <gst/gst-i18n-plugin.h>
#include <gst/pbutils/pbutils.h>
#include "gstplay-enum.h"
#include "gstplaysink.h"
#include "gstfactorylists.h"
#include "gststreaminfo.h"
......@@ -321,8 +322,7 @@ struct _GstPlayBin
/* our play sink */
GstPlaySink *playsink;
GValueArray *elements; /* factories we can use for selecting sinks */
GValueArray *sinks; /* factories we can use for selecting sinks */
GValueArray *elements; /* factories we can use for selecting elements */
};
struct _GstPlayBinClass
......@@ -530,20 +530,28 @@ init_group (GstPlayBin * playbin, GstSourceGroup * group)
{
/* init selectors */
group->playbin = playbin;
group->selector[0].media = "audio/";
group->selector[0].type = GST_PLAY_SINK_TYPE_AUDIO;
group->selector[0].media = "audio/x-raw-";
group->selector[0].type = GST_PLAY_SINK_TYPE_AUDIO_RAW;
group->selector[0].mode = GST_PLAY_SINK_MODE_AUDIO;
group->selector[1].media = "video/";
group->selector[1].type = GST_PLAY_SINK_TYPE_VIDEO;
group->selector[1].mode = GST_PLAY_SINK_MODE_VIDEO;
group->selector[2].media = "text/";
group->selector[2].type = GST_PLAY_SINK_TYPE_TEXT;
group->selector[2].mode = GST_PLAY_SINK_MODE_TEXT;
group->selector[1].media = "audio/";
group->selector[1].type = GST_PLAY_SINK_TYPE_AUDIO;
group->selector[1].mode = GST_PLAY_SINK_MODE_AUDIO;
group->selector[2].media = "video/x-raw-";
group->selector[2].type = GST_PLAY_SINK_TYPE_VIDEO_RAW;
group->selector[2].mode = GST_PLAY_SINK_MODE_VIDEO;
group->selector[3].media = "video/";
group->selector[3].type = GST_PLAY_SINK_TYPE_VIDEO;
group->selector[3].mode = GST_PLAY_SINK_MODE_VIDEO;
group->selector[4].media = "text/";
group->selector[4].type = GST_PLAY_SINK_TYPE_TEXT;
group->selector[4].mode = GST_PLAY_SINK_MODE_TEXT;
}
static void
gst_play_bin_init (GstPlayBin * playbin)
{
GstFactoryListType type;
/* init groups */
playbin->curr_group = &playbin->groups[0];
playbin->next_group = &playbin->groups[1];
......@@ -551,7 +559,9 @@ gst_play_bin_init (GstPlayBin * playbin)
init_group (playbin, &playbin->groups[1]);
/* first filter out the interesting element factories */
playbin->sinks = gst_factory_list_get_sinks ();
type = GST_FACTORY_LIST_DECODER | GST_FACTORY_LIST_SINK;
playbin->elements = gst_factory_list_get_elements (type);
gst_factory_list_debug (playbin->elements);
/* get the caps */
}
......@@ -563,7 +573,7 @@ gst_play_bin_finalize (GObject * object)
play_bin = GST_PLAY_BIN (object);
g_value_array_free (play_bin->sinks);
g_value_array_free (play_bin->elements);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
......@@ -868,7 +878,6 @@ not_linked:
GST_DEBUG_OBJECT (playbin, "pad not linked");
return;
}
}
/* we get called when all pads are available and we must connect the sinks to
......@@ -949,25 +958,96 @@ drained_cb (GstElement * decodebin, GstSourceGroup * group)
}
}
/* a callback is called */
/* Called when we must provide a list of factories to plug to @pad with @caps.
* We first check if we have a sink that can handle the format and if we do, we
* return NULL, to expose the pad. If we have no sink (or the sink does not
* work), we return the list of elements that can connect. */
static GValueArray *
autoplug_factories_cb (GstElement * decodebin, GstPad * pad,
GstCaps * caps, GstSourceGroup * group)
{
GstPlayBin *playbin;
GValueArray *result = NULL;
GValueArray *result;
playbin = group->playbin;
GST_DEBUG_OBJECT (playbin, "continue group %p for %s:%s, %" GST_PTR_FORMAT,
GST_DEBUG_OBJECT (playbin, "factories group %p for %s:%s, %" GST_PTR_FORMAT,
group, GST_DEBUG_PAD_NAME (pad), caps);
/* filter out the elements based on the caps. */
result = gst_factory_list_filter (playbin->elements, caps);
GST_DEBUG_OBJECT (playbin, "found factories %p", result);
gst_factory_list_debug (result);
return result;
}
/* We are asked to select an element. See if the next element to check
* is a sink. If this is the case, we see if the sink works by setting it to
* READY. If the sink works, we return -2 to make decodebin expose the raw pad
* so that we can setup the mixers. */
static GstAutoplugSelectResult
autoplug_select_cb (GstElement * decodebin, GstPad * pad,
GstCaps * caps, GstElementFactory * factory, GstSourceGroup * group)
{
GstPlayBin *playbin;
GstElement *element;
const gchar *klass;
playbin = group->playbin;
GST_DEBUG_OBJECT (playbin, "select group %p for %s:%s, %" GST_PTR_FORMAT,
group, GST_DEBUG_PAD_NAME (pad), caps);
GST_DEBUG_OBJECT (playbin, "checking factory %s",
GST_PLUGIN_FEATURE_NAME (factory));
/* if it's not a sink, we just make decodebin try it */
if (!gst_factory_list_is_type (factory, GST_FACTORY_LIST_SINK))
return GST_AUTOPLUG_SELECT_TRY;
/* it's a sink, see if an instance of it actually works */
GST_DEBUG_OBJECT (playbin, "we found a sink");
if ((element = gst_element_factory_create (factory, NULL)) == NULL) {
GST_WARNING_OBJECT (playbin, "Could not create an element from %s",
gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)));
return GST_AUTOPLUG_SELECT_SKIP;
}
/* ... activate it ... We do this before adding it to the bin so that we
* don't accidentally make it post error messages that will stop
* everything. */
if ((gst_element_set_state (element,
GST_STATE_READY)) == GST_STATE_CHANGE_FAILURE) {
GST_WARNING_OBJECT (playbin, "Couldn't set %s to READY",
GST_ELEMENT_NAME (element));
gst_object_unref (element);
return GST_AUTOPLUG_SELECT_SKIP;
}
/* at this point, we have the sink working, configure it in playsink */
klass = gst_element_factory_get_klass (factory);
/* get klass to figure out if it's audio or video */
if (strstr (klass, "Audio")) {
GST_DEBUG_OBJECT (playbin, "configure audio sink");
gst_play_sink_set_audio_sink (playbin->playsink, element);
} else if (strstr (klass, "Video")) {
GST_DEBUG_OBJECT (playbin, "configure video sink");
gst_play_sink_set_video_sink (playbin->playsink, element);
} else {
GST_WARNING_OBJECT (playbin, "unknown sink klass %s found", klass);
}
/* tell decodebin to expose the pad because we are going to use this
* sink */
GST_DEBUG_OBJECT (playbin, "we found a working sink, expose pad");
return GST_AUTOPLUG_SELECT_EXPOSE;
}
/* unlink a group of uridecodebins from the sink */
static void
unlink_group (GstPlayBin * playbin, GstSourceGroup * group)
......@@ -1022,11 +1102,14 @@ activate_group (GstPlayBin * playbin, GstSourceGroup * group)
* next uri */
g_signal_connect (uridecodebin, "drained", G_CALLBACK (drained_cb), group);
/* will be called when a new media type is found. We will see if we have a
* working sink that can natively handle this format. */
/* will be called when a new media type is found. We return a list of decoders
* including sinks for decodebin to try */
g_signal_connect (uridecodebin, "autoplug-factories",
G_CALLBACK (autoplug_factories_cb), group);
g_signal_connect (uridecodebin, "autoplug-select",
G_CALLBACK (autoplug_select_cb), group);
/* */
gst_bin_add (GST_BIN_CAST (playbin), uridecodebin);
group->uridecodebin = uridecodebin;
......
......@@ -74,7 +74,9 @@ struct _GstPlaySink
GstPlayChain *videochain;
GstPad *audio_pad;
gboolean audio_pad_raw;
GstPad *video_pad;
gboolean video_pad_raw;
GstPad *text_pad;
/* properties */
......@@ -388,7 +390,7 @@ beach:
play_sink);
}
static void
void
gst_play_sink_set_video_sink (GstPlaySink * play_sink, GstElement * sink)
{
GST_OBJECT_LOCK (play_sink);
......@@ -403,7 +405,7 @@ gst_play_sink_set_video_sink (GstPlaySink * play_sink, GstElement * sink)
GST_OBJECT_UNLOCK (play_sink);
}
static void
void
gst_play_sink_set_audio_sink (GstPlaySink * play_sink, GstElement * sink)
{
GST_OBJECT_LOCK (play_sink);
......@@ -418,7 +420,7 @@ gst_play_sink_set_audio_sink (GstPlaySink * play_sink, GstElement * sink)
GST_OBJECT_UNLOCK (play_sink);
}
static void
void
gst_play_sink_set_vis_plugin (GstPlaySink * play_sink,
GstElement * pending_visualisation)
{
......@@ -622,7 +624,7 @@ activate_chain (GstPlayChain * chain, gboolean activate)
*
*/
static GstPlayChain *
gen_video_chain (GstPlaySink * play_sink)
gen_video_chain (GstPlaySink * play_sink, gboolean raw)
{
GstPlayVideoChain *chain;
GstBin *bin;
......@@ -650,11 +652,17 @@ gen_video_chain (GstPlaySink * play_sink)
gst_object_sink (bin);
gst_bin_add (bin, chain->sink);
if (raw) {
chain->conv = gst_element_factory_make ("ffmpegcolorspace", "vconv");
if (chain->conv == NULL)
goto no_colorspace;
gst_bin_add (bin, chain->conv);
chain->conv = gst_element_factory_make ("ffmpegcolorspace", "vconv");
if (chain->conv == NULL)
goto no_colorspace;
gst_bin_add (bin, chain->conv);
chain->scale = gst_element_factory_make ("videoscale", "vscale");
if (chain->scale == NULL)
goto no_videoscale;
gst_bin_add (bin, chain->scale);
}
/* decouple decoder from sink, this improves playback quite a lot since the
* decoder can continue while the sink blocks for synchronisation. We don't
......@@ -665,19 +673,21 @@ gen_video_chain (GstPlaySink * play_sink)
"max-size-bytes", 0, "max-size-time", (gint64) 0, NULL);
gst_bin_add (bin, chain->queue);
chain->scale = gst_element_factory_make ("videoscale", "vscale");
if (chain->scale == NULL)
goto no_videoscale;
gst_bin_add (bin, chain->scale);
if (raw) {
gst_element_link_pads (chain->conv, "src", chain->queue, "sink");
gst_element_link_pads (chain->queue, "src", chain->scale, "sink");
/* be more careful with the pad from the custom sink element, it might not
* be named 'sink' */
if (!gst_element_link_pads (chain->scale, "src", chain->sink, NULL))
goto link_failed;
gst_element_link_pads (chain->conv, "src", chain->queue, "sink");
gst_element_link_pads (chain->queue, "src", chain->scale, "sink");
/* be more careful with the pad from the custom sink element, it might not
* be named 'sink' */
if (!gst_element_link_pads (chain->scale, "src", chain->sink, NULL))
goto link_failed;
pad = gst_element_get_pad (chain->conv, "sink");
} else {
if (!gst_element_link_pads (chain->queue, "src", chain->sink, NULL))
goto link_failed;
pad = gst_element_get_pad (chain->queue, "sink");