mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 10:11:08 +00:00
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.
This commit is contained in:
parent
75aa042450
commit
f2f9bf045b
10 changed files with 571 additions and 252 deletions
48
ChangeLog
48
ChangeLog
|
@ -1,3 +1,51 @@
|
|||
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
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include <gst/pbutils/pbutils.h>
|
||||
|
||||
#include "gstplay-marshal.h"
|
||||
#include "gstplay-enum.h"
|
||||
#include "gstfactorylists.h"
|
||||
|
||||
/* generic templates */
|
||||
|
@ -121,9 +122,12 @@ struct _GstDecodeBinClass
|
|||
/* signal fired to get a list of factories to try to autoplug */
|
||||
GValueArray *(*autoplug_factories) (GstElement * element, GstPad * pad,
|
||||
GstCaps * caps);
|
||||
/* signal fired to sort the factories */
|
||||
GValueArray *(*autoplug_sort) (GstElement * element, GstPad * pad,
|
||||
GstCaps * caps, GValueArray * factories);
|
||||
/* signal fired to select from the proposed list of factories */
|
||||
gint (*autoplug_select) (GstElement * element, GstPad * pad, GstCaps * caps,
|
||||
GValueArray * factories);
|
||||
GstAutoplugSelectResult (*autoplug_select) (GstElement * element,
|
||||
GstPad * pad, GstCaps * caps, GstElementFactory * factory);
|
||||
|
||||
/* fired when the last group is drained */
|
||||
void (*drained) (GstElement * element);
|
||||
|
@ -138,6 +142,7 @@ enum
|
|||
SIGNAL_AUTOPLUG_CONTINUE,
|
||||
SIGNAL_AUTOPLUG_FACTORIES,
|
||||
SIGNAL_AUTOPLUG_SELECT,
|
||||
SIGNAL_AUTOPLUG_SORT,
|
||||
SIGNAL_DRAINED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
@ -170,8 +175,10 @@ static gboolean gst_decode_bin_autoplug_continue (GstElement * element,
|
|||
GstPad * pad, GstCaps * caps);
|
||||
static GValueArray *gst_decode_bin_autoplug_factories (GstElement *
|
||||
element, GstPad * pad, GstCaps * caps);
|
||||
static gint gst_decode_bin_autoplug_select (GstElement * element,
|
||||
GstPad * pad, GstCaps * caps, GValueArray * list);
|
||||
static GValueArray *gst_decode_bin_autoplug_sort (GstElement * element,
|
||||
GstPad * pad, GstCaps * caps, GValueArray * factories);
|
||||
static GstAutoplugSelectResult gst_decode_bin_autoplug_select (GstElement *
|
||||
element, GstPad * pad, GstCaps * caps, GstElementFactory * factory);
|
||||
|
||||
static void gst_decode_bin_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec);
|
||||
|
@ -336,6 +343,33 @@ _gst_boolean_accumulator (GSignalInvocationHint * ihint,
|
|||
return myboolean;
|
||||
}
|
||||
|
||||
/* we collect the first result */
|
||||
static gboolean
|
||||
_gst_array_accumulator (GSignalInvocationHint * ihint,
|
||||
GValue * return_accu, const GValue * handler_return, gpointer dummy)
|
||||
{
|
||||
gpointer array;
|
||||
|
||||
array = g_value_get_boxed (handler_return);
|
||||
if (!(ihint->run_type & G_SIGNAL_RUN_CLEANUP))
|
||||
g_value_set_boxed (return_accu, array);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_gst_select_accumulator (GSignalInvocationHint * ihint,
|
||||
GValue * return_accu, const GValue * handler_return, gpointer dummy)
|
||||
{
|
||||
GstAutoplugSelectResult res;
|
||||
|
||||
res = g_value_get_enum (handler_return);
|
||||
if (!(ihint->run_type & G_SIGNAL_RUN_CLEANUP))
|
||||
g_value_set_enum (return_accu, res);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_decode_bin_class_init (GstDecodeBinClass * klass)
|
||||
{
|
||||
|
@ -435,10 +469,31 @@ gst_decode_bin_class_init (GstDecodeBinClass * klass)
|
|||
gst_decode_bin_signals[SIGNAL_AUTOPLUG_FACTORIES] =
|
||||
g_signal_new ("autoplug-factories", G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass,
|
||||
autoplug_factories), NULL, NULL,
|
||||
autoplug_factories), _gst_array_accumulator, NULL,
|
||||
gst_play_marshal_BOXED__OBJECT_OBJECT, G_TYPE_VALUE_ARRAY, 2,
|
||||
GST_TYPE_PAD, GST_TYPE_CAPS);
|
||||
|
||||
/**
|
||||
* GstDecodeBin2::autoplug-sort:
|
||||
* @pad: The #GstPad.
|
||||
* @caps: The #GstCaps.
|
||||
* @factories: A #GValueArray of possible #GstElementFactory to use.
|
||||
*
|
||||
* Once decodebin2 has found the possible #GstElementFactory objects to try
|
||||
* for @caps on @pad, this signal is emited. The purpose of the signal is for
|
||||
* the application to perform additional sorting or filtering on the element
|
||||
* factory array.
|
||||
*
|
||||
* The callee should copy and modify @factories.
|
||||
*
|
||||
* Returns: A new sorted array of #GstElementFactory objects.
|
||||
*/
|
||||
gst_decode_bin_signals[SIGNAL_AUTOPLUG_SORT] =
|
||||
g_signal_new ("autoplug-sort", G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, autoplug_sort),
|
||||
NULL, NULL, gst_play_marshal_BOXED__OBJECT_OBJECT_BOXED,
|
||||
G_TYPE_VALUE_ARRAY, 3, GST_TYPE_PAD, GST_TYPE_CAPS, G_TYPE_VALUE_ARRAY);
|
||||
|
||||
/**
|
||||
* GstDecodeBin2::autoplug-select:
|
||||
* @pad: The #GstPad.
|
||||
|
@ -451,14 +506,16 @@ gst_decode_bin_class_init (GstDecodeBinClass * klass)
|
|||
*
|
||||
* Returns: A #gint indicating what factory index from the @factories array
|
||||
* that you wish decodebin2 to use for trying to decode the given @caps.
|
||||
* -1 to stop selection of a factory. The default handler always
|
||||
* returns the first possible factory.
|
||||
* Return -1 to stop selection of a factory and expose the pad as a raw type.
|
||||
* The default handler always returns the first possible factory (index 0).
|
||||
*/
|
||||
gst_decode_bin_signals[SIGNAL_AUTOPLUG_SELECT] =
|
||||
g_signal_new ("autoplug-select", G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, autoplug_select),
|
||||
NULL, NULL, gst_play_marshal_INT__OBJECT_OBJECT_BOXED,
|
||||
G_TYPE_INT, 3, GST_TYPE_PAD, GST_TYPE_CAPS, G_TYPE_VALUE_ARRAY);
|
||||
_gst_select_accumulator, NULL,
|
||||
gst_play_marshal_ENUM__OBJECT_OBJECT_OBJECT,
|
||||
GST_TYPE_AUTOPLUG_SELECT_RESULT, 3, GST_TYPE_PAD, GST_TYPE_CAPS,
|
||||
GST_TYPE_ELEMENT_FACTORY);
|
||||
|
||||
/**
|
||||
* GstDecodeBin2::drained
|
||||
|
@ -487,6 +544,7 @@ gst_decode_bin_class_init (GstDecodeBinClass * klass)
|
|||
GST_DEBUG_FUNCPTR (gst_decode_bin_autoplug_continue);
|
||||
klass->autoplug_factories =
|
||||
GST_DEBUG_FUNCPTR (gst_decode_bin_autoplug_factories);
|
||||
klass->autoplug_sort = GST_DEBUG_FUNCPTR (gst_decode_bin_autoplug_sort);
|
||||
klass->autoplug_select = GST_DEBUG_FUNCPTR (gst_decode_bin_autoplug_select);
|
||||
|
||||
gst_element_class_add_pad_template (gstelement_klass,
|
||||
|
@ -504,7 +562,8 @@ static void
|
|||
gst_decode_bin_init (GstDecodeBin * decode_bin)
|
||||
{
|
||||
/* first filter out the interesting element factories */
|
||||
decode_bin->factories = gst_factory_list_get_decoders ();
|
||||
decode_bin->factories =
|
||||
gst_factory_list_get_elements (GST_FACTORY_LIST_DECODER);
|
||||
|
||||
/* we create the typefind element only once */
|
||||
decode_bin->typefind = gst_element_factory_make ("typefind", "typefind");
|
||||
|
@ -754,17 +813,28 @@ gst_decode_bin_autoplug_factories (GstElement * element, GstPad * pad,
|
|||
return result;
|
||||
}
|
||||
|
||||
static gint
|
||||
gst_decode_bin_autoplug_select (GstElement * element, GstPad * pad,
|
||||
static GValueArray *
|
||||
gst_decode_bin_autoplug_sort (GstElement * element, GstPad * pad,
|
||||
GstCaps * caps, GValueArray * factories)
|
||||
{
|
||||
g_return_val_if_fail (factories != NULL, -1);
|
||||
g_return_val_if_fail (factories->n_values > 0, -1);
|
||||
GValueArray *result;
|
||||
|
||||
GST_DEBUG_OBJECT (element, "default autoplug-select returns 0");
|
||||
result = g_value_array_copy (factories);
|
||||
|
||||
/* Return first factory. */
|
||||
return 0;
|
||||
GST_DEBUG_OBJECT (element, "autoplug-sort returns %p", result);
|
||||
|
||||
/* return input */
|
||||
return result;
|
||||
}
|
||||
|
||||
static GstAutoplugSelectResult
|
||||
gst_decode_bin_autoplug_select (GstElement * element, GstPad * pad,
|
||||
GstCaps * caps, GstElementFactory * factory)
|
||||
{
|
||||
GST_DEBUG_OBJECT (element, "default autoplug-select returns TRY");
|
||||
|
||||
/* Try factory. */
|
||||
return GST_AUTOPLUG_SELECT_TRY;
|
||||
}
|
||||
|
||||
/********
|
||||
|
@ -776,7 +846,7 @@ static gboolean is_demuxer_element (GstElement * srcelement);
|
|||
|
||||
static gboolean connect_pad (GstDecodeBin * dbin, GstElement * src,
|
||||
GstPad * pad, GstCaps * caps, GValueArray * factories,
|
||||
GstDecodeGroup * group);
|
||||
GstDecodeGroup * group, gboolean * expose);
|
||||
static gboolean connect_element (GstDecodeBin * dbin, GstElement * element,
|
||||
GstDecodeGroup * group);
|
||||
static void expose_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
|
||||
|
@ -813,7 +883,8 @@ analyze_new_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
|
|||
GstCaps * caps, GstDecodeGroup * group)
|
||||
{
|
||||
gboolean apcontinue = TRUE;
|
||||
GValueArray *factories = NULL;
|
||||
GValueArray *factories = NULL, *result = NULL;
|
||||
gboolean expose;
|
||||
|
||||
GST_DEBUG_OBJECT (dbin, "Pad %s:%s caps:%" GST_PTR_FORMAT,
|
||||
GST_DEBUG_PAD_NAME (pad), caps);
|
||||
|
@ -856,12 +927,22 @@ analyze_new_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
|
|||
goto unknown_type;
|
||||
}
|
||||
|
||||
/* 1.d else continue autoplugging something from the list. */
|
||||
/* 1.d sort some more. */
|
||||
g_signal_emit (G_OBJECT (dbin),
|
||||
gst_decode_bin_signals[SIGNAL_AUTOPLUG_SORT], 0, pad, caps, factories,
|
||||
&result);
|
||||
g_value_array_free (factories);
|
||||
factories = result;
|
||||
|
||||
/* 1.e else continue autoplugging something from the list. */
|
||||
GST_LOG_OBJECT (pad, "Let's continue discovery on this pad");
|
||||
connect_pad (dbin, src, pad, caps, factories, group);
|
||||
connect_pad (dbin, src, pad, caps, factories, group, &expose);
|
||||
|
||||
g_value_array_free (factories);
|
||||
|
||||
if (expose)
|
||||
goto expose_pad;
|
||||
|
||||
return;
|
||||
|
||||
expose_pad:
|
||||
|
@ -934,7 +1015,8 @@ setup_caps_delay:
|
|||
*/
|
||||
static gboolean
|
||||
connect_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
|
||||
GstCaps * caps, GValueArray * factories, GstDecodeGroup * group)
|
||||
GstCaps * caps, GValueArray * factories, GstDecodeGroup * group,
|
||||
gboolean * expose)
|
||||
{
|
||||
gboolean res = FALSE;
|
||||
GstPad *mqpad = NULL;
|
||||
|
@ -942,6 +1024,8 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
|
|||
g_return_val_if_fail (factories != NULL, FALSE);
|
||||
g_return_val_if_fail (factories->n_values > 0, FALSE);
|
||||
|
||||
*expose = FALSE;
|
||||
|
||||
GST_DEBUG_OBJECT (dbin, "pad %s:%s , group:%p",
|
||||
GST_DEBUG_PAD_NAME (pad), group);
|
||||
|
||||
|
@ -964,32 +1048,37 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
|
|||
|
||||
/* 2. Try to create an element and link to it */
|
||||
while (factories->n_values > 0) {
|
||||
gint factidx;
|
||||
GstAutoplugSelectResult ret;
|
||||
GstElementFactory *factory;
|
||||
GstElement *element;
|
||||
GstPad *sinkpad;
|
||||
|
||||
/* emit autoplug-select */
|
||||
/* take first factory */
|
||||
factory = g_value_get_object (g_value_array_get_nth (factories, 0));
|
||||
/* Remove selected factory from the list. */
|
||||
g_value_array_remove (factories, 0);
|
||||
|
||||
/* emit autoplug-select to see what we should do with it. */
|
||||
g_signal_emit (G_OBJECT (dbin),
|
||||
gst_decode_bin_signals[SIGNAL_AUTOPLUG_SELECT],
|
||||
0, pad, caps, factories, &factidx);
|
||||
0, pad, caps, factory, &ret);
|
||||
|
||||
/* when the function returns -1, we leave the loop and stop */
|
||||
if (factidx == -1) {
|
||||
GST_DEBUG_OBJECT (dbin, "autoplug select returned -1");
|
||||
break;
|
||||
switch (ret) {
|
||||
case GST_AUTOPLUG_SELECT_TRY:
|
||||
GST_DEBUG_OBJECT (dbin, "autoplug select requested try");
|
||||
break;
|
||||
case GST_AUTOPLUG_SELECT_EXPOSE:
|
||||
GST_DEBUG_OBJECT (dbin, "autoplug select requested expose");
|
||||
*expose = TRUE;
|
||||
goto beach;
|
||||
case GST_AUTOPLUG_SELECT_SKIP:
|
||||
GST_DEBUG_OBJECT (dbin, "autoplug select requested skip");
|
||||
continue;
|
||||
default:
|
||||
GST_WARNING_OBJECT (dbin, "autoplug select returned unhandled %d", ret);
|
||||
break;
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (dbin, "autoplug select returned %d", factidx);
|
||||
|
||||
factory = g_value_get_object (g_value_array_get_nth (factories, factidx));
|
||||
|
||||
/* factory is != NULL now since the default handler selects the first
|
||||
* factory if all connected user handlers returned NULL. */
|
||||
|
||||
/* Remove selected factory from the list. */
|
||||
g_value_array_remove (factories, factidx);
|
||||
|
||||
/* 2.1. Try to create an element */
|
||||
if ((element = gst_element_factory_create (factory, NULL)) == NULL) {
|
||||
GST_WARNING_OBJECT (dbin, "Could not create an element from %s",
|
||||
|
@ -997,7 +1086,18 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
|
|||
continue;
|
||||
}
|
||||
|
||||
/* 2.3. Find its sink pad */
|
||||
/* ... 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 (dbin, "Couldn't set %s to READY",
|
||||
GST_ELEMENT_NAME (element));
|
||||
gst_object_unref (element);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* 2.3. Find its sink pad, this should work after activating it. */
|
||||
if (!(sinkpad = find_sink_pad (element))) {
|
||||
GST_WARNING_OBJECT (dbin, "Element %s doesn't have a sink pad",
|
||||
GST_ELEMENT_NAME (element));
|
||||
|
@ -1006,7 +1106,7 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
|
|||
}
|
||||
|
||||
/* 2.4 add it ... */
|
||||
if (!(gst_bin_add (GST_BIN (dbin), element))) {
|
||||
if (!(gst_bin_add (GST_BIN_CAST (dbin), element))) {
|
||||
GST_WARNING_OBJECT (dbin, "Couldn't add %s to the bin",
|
||||
GST_ELEMENT_NAME (element));
|
||||
gst_object_unref (sinkpad);
|
||||
|
@ -1014,16 +1114,6 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
|
|||
continue;
|
||||
}
|
||||
|
||||
/* ... activate it ... */
|
||||
if ((gst_element_set_state (element,
|
||||
GST_STATE_READY)) == GST_STATE_CHANGE_FAILURE) {
|
||||
GST_WARNING_OBJECT (dbin, "Couldn't set %s to READY",
|
||||
GST_ELEMENT_NAME (element));
|
||||
gst_object_unref (sinkpad);
|
||||
gst_bin_remove (GST_BIN (dbin), element);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* 2.5 ...and try to link */
|
||||
if ((gst_pad_link (pad, sinkpad)) != GST_PAD_LINK_OK) {
|
||||
GST_WARNING_OBJECT (dbin, "Link failed on pad %s:%s",
|
||||
|
@ -1053,10 +1143,10 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
|
|||
break;
|
||||
}
|
||||
|
||||
beach:
|
||||
if (mqpad)
|
||||
gst_object_unref (mqpad);
|
||||
|
||||
beach:
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -2306,8 +2396,8 @@ missing_fakesink:
|
|||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
plugin_init (GstPlugin * plugin)
|
||||
gboolean
|
||||
gst_decode_bin_plugin_init (GstPlugin * plugin)
|
||||
{
|
||||
GST_DEBUG_CATEGORY_INIT (gst_decode_bin_debug, "decodebin2", 0,
|
||||
"decoder bin");
|
||||
|
@ -2321,9 +2411,3 @@ plugin_init (GstPlugin * plugin)
|
|||
return gst_element_register (plugin, "decodebin2", GST_RANK_NONE,
|
||||
GST_TYPE_DECODE_BIN);
|
||||
}
|
||||
|
||||
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
|
||||
GST_VERSION_MINOR,
|
||||
"decodebin2",
|
||||
"decoder bin newer version", plugin_init, VERSION, GST_LICENSE,
|
||||
GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
|
||||
|
|
|
@ -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,29 +49,119 @@ compare_ranks (GValue * v1, GValue * v2)
|
|||
return diff;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
print_feature (GstPluginFeature * feature)
|
||||
/* the filter function for selecting the elements we can use in
|
||||
* autoplugging */
|
||||
static gboolean
|
||||
decoders_filter (GstElementFactory * factory)
|
||||
{
|
||||
const gchar *rname;
|
||||
guint rank;
|
||||
const gchar *klass;
|
||||
|
||||
rname = gst_plugin_feature_get_name (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 &&
|
||||
strstr (klass, "Depayloader") == NULL &&
|
||||
strstr (klass, "Parse") == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GST_DEBUG ("%s", rname);
|
||||
/* only select elements with autoplugging rank */
|
||||
rank = gst_plugin_feature_get_rank (GST_PLUGIN_FEATURE (factory));
|
||||
if (rank < GST_RANK_MARGINAL)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* get a filtered feature list as a GValueArray */
|
||||
static GValueArray *
|
||||
get_feature_array (GstPluginFeatureFilter filter)
|
||||
/* the filter function for selecting the elements we can use in
|
||||
* autoplugging */
|
||||
static gboolean
|
||||
sinks_filter (GstElementFactory * factory)
|
||||
{
|
||||
guint rank;
|
||||
const gchar *klass;
|
||||
|
||||
klass = gst_element_factory_get_klass (factory);
|
||||
/* only sinks can play */
|
||||
if (strstr (klass, "Sink") == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* must be audio or video sink */
|
||||
if (strstr (klass, "Audio") == NULL && strstr (klass, "Video") == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* only select elements with autoplugging rank */
|
||||
rank = gst_plugin_feature_get_rank (GST_PLUGIN_FEATURE (factory));
|
||||
if (rank < GST_RANK_MARGINAL)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_factory_list_is_type:
|
||||
* @factory: a #GstElementFactory
|
||||
* @type: a #GstFactoryListType
|
||||
*
|
||||
* Check if @factory if of the given types.
|
||||
*
|
||||
* Returns: %TRUE if @factory is of @type.
|
||||
*/
|
||||
gboolean
|
||||
gst_factory_list_is_type (GstElementFactory * factory, GstFactoryListType type)
|
||||
{
|
||||
gboolean res = FALSE;
|
||||
|
||||
if (!res && (type & GST_FACTORY_LIST_SINK))
|
||||
res = sinks_filter (factory);
|
||||
if (!res && (type & GST_FACTORY_LIST_DECODER))
|
||||
res = decoders_filter (factory);
|
||||
|
||||
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_elements:
|
||||
* @type: a #GstFactoryListType
|
||||
*
|
||||
* 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_elements (GstFactoryListType type)
|
||||
{
|
||||
GValueArray *result;
|
||||
GList *walk, *list;
|
||||
FilterData data;
|
||||
|
||||
result = g_value_array_new (0);
|
||||
|
||||
/* prepare type */
|
||||
data.type = type;
|
||||
|
||||
/* get the feature list using the filter */
|
||||
list = gst_default_registry_feature_filter (filter, FALSE, NULL);
|
||||
list =
|
||||
gst_default_registry_feature_filter ((GstPluginFeatureFilter)
|
||||
element_filter, FALSE, &data);
|
||||
|
||||
/* convert to an array */
|
||||
for (walk = list; walk; walk = g_list_next (walk)) {
|
||||
|
@ -86,104 +181,26 @@ get_feature_array (GstPluginFeatureFilter filter)
|
|||
return result;
|
||||
}
|
||||
|
||||
/* the filter function for selecting the elements we can use in
|
||||
* autoplugging */
|
||||
static gboolean
|
||||
decoders_filter (GstPluginFeature * feature)
|
||||
{
|
||||
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));
|
||||
/* only demuxers, decoders, depayloaders and parsers can play */
|
||||
if (strstr (klass, "Demux") == NULL &&
|
||||
strstr (klass, "Decoder") == NULL &&
|
||||
strstr (klass, "Depayloader") == NULL &&
|
||||
strstr (klass, "Parse") == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* only select elements with autoplugging rank */
|
||||
rank = gst_plugin_feature_get_rank (feature);
|
||||
if (rank < GST_RANK_MARGINAL)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* the filter function for selecting the elements we can use in
|
||||
* autoplugging */
|
||||
static gboolean
|
||||
sinks_filter (GstPluginFeature * feature)
|
||||
{
|
||||
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));
|
||||
/* only sinks can play */
|
||||
if (strstr (klass, "Sink") == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* must be audio or video sink */
|
||||
if (strstr (klass, "Audio") == NULL && strstr (klass, "Video") == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* only select elements with autoplugging rank */
|
||||
rank = gst_plugin_feature_get_rank (feature);
|
||||
if (rank < GST_RANK_MARGINAL)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_factory_list_get_decoders:
|
||||
* gst_factory_list_debug:
|
||||
* @array: an array of element factories
|
||||
*
|
||||
* Get a sorted list of factories that can be used in decoding pipelines.
|
||||
*
|
||||
* Returns: a #GValueArray of #GstElementFactory elements. Use
|
||||
* g_value_array_free() after usage.
|
||||
* Debug the element factory names in @array.
|
||||
*/
|
||||
GValueArray *
|
||||
gst_factory_list_get_decoders (void)
|
||||
void
|
||||
gst_factory_list_debug (GValueArray * array)
|
||||
{
|
||||
GValueArray *result;
|
||||
gint i;
|
||||
|
||||
/* first filter out the interesting element factories */
|
||||
result = get_feature_array ((GstPluginFeatureFilter) decoders_filter);
|
||||
for (i = 0; i < array->n_values; i++) {
|
||||
GValue *value;
|
||||
GstPluginFeature *feature;
|
||||
|
||||
return result;
|
||||
}
|
||||
value = g_value_array_get_nth (array, i);
|
||||
feature = g_value_get_object (value);
|
||||
|
||||
/**
|
||||
* gst_factory_list_get_sinks:
|
||||
*
|
||||
* Get a sorted list of factories that can be used as sinks in a decoding
|
||||
* pipeline.
|
||||
*
|
||||
* Returns: a #GValueArray of #GstElementFactory elements. Use
|
||||
* g_value_array_free() after usage.
|
||||
*/
|
||||
GValueArray *
|
||||
gst_factory_list_get_sinks (void)
|
||||
{
|
||||
GValueArray *result;
|
||||
|
||||
/* first filter out the interesting element factories */
|
||||
result = get_feature_array ((GstPluginFeatureFilter) sinks_filter);
|
||||
|
||||
return result;
|
||||
GST_DEBUG ("%s", gst_plugin_feature_get_name (feature));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
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");
|
||||
}
|
||||
|
||||
pad = gst_element_get_pad (chain->conv, "sink");
|
||||
chain->chain.sinkpad = gst_ghost_pad_new ("sink", pad);
|
||||
gst_object_unref (pad);
|
||||
gst_element_add_pad (chain->chain.bin, chain->chain.sinkpad);
|
||||
|
@ -817,7 +827,7 @@ no_overlay:
|
|||
* +-------------------------------------------------------------+
|
||||
*/
|
||||
static GstPlayChain *
|
||||
gen_audio_chain (GstPlaySink * play_sink)
|
||||
gen_audio_chain (GstPlaySink * play_sink, gboolean raw)
|
||||
{
|
||||
GstPlayAudioChain *chain;
|
||||
GstBin *bin;
|
||||
|
@ -843,27 +853,32 @@ gen_audio_chain (GstPlaySink * play_sink)
|
|||
gst_object_sink (bin);
|
||||
gst_bin_add (bin, chain->sink);
|
||||
|
||||
chain->conv = gst_element_factory_make ("audioconvert", "aconv");
|
||||
if (chain->conv == NULL)
|
||||
goto no_audioconvert;
|
||||
gst_bin_add (bin, chain->conv);
|
||||
if (raw) {
|
||||
chain->conv = gst_element_factory_make ("audioconvert", "aconv");
|
||||
if (chain->conv == NULL)
|
||||
goto no_audioconvert;
|
||||
gst_bin_add (bin, chain->conv);
|
||||
|
||||
chain->resample = gst_element_factory_make ("audioresample", "aresample");
|
||||
if (chain->resample == NULL)
|
||||
goto no_audioresample;
|
||||
gst_bin_add (bin, chain->resample);
|
||||
chain->resample = gst_element_factory_make ("audioresample", "aresample");
|
||||
if (chain->resample == NULL)
|
||||
goto no_audioresample;
|
||||
gst_bin_add (bin, chain->resample);
|
||||
|
||||
chain->volume = gst_element_factory_make ("volume", "volume");
|
||||
g_object_set (G_OBJECT (chain->volume), "volume", play_sink->volume, NULL);
|
||||
gst_bin_add (bin, chain->volume);
|
||||
chain->volume = gst_element_factory_make ("volume", "volume");
|
||||
g_object_set (G_OBJECT (chain->volume), "volume", play_sink->volume, NULL);
|
||||
gst_bin_add (bin, chain->volume);
|
||||
|
||||
res = gst_element_link_pads (chain->conv, "src", chain->resample, "sink");
|
||||
res &= gst_element_link_pads (chain->resample, "src", chain->volume, "sink");
|
||||
res &= gst_element_link_pads (chain->volume, "src", chain->sink, NULL);
|
||||
if (!res)
|
||||
goto link_failed;
|
||||
res = gst_element_link_pads (chain->conv, "src", chain->resample, "sink");
|
||||
res &=
|
||||
gst_element_link_pads (chain->resample, "src", chain->volume, "sink");
|
||||
res &= gst_element_link_pads (chain->volume, "src", chain->sink, NULL);
|
||||
if (!res)
|
||||
goto link_failed;
|
||||
|
||||
pad = gst_element_get_pad (chain->conv, "sink");
|
||||
pad = gst_element_get_pad (chain->conv, "sink");
|
||||
} else {
|
||||
pad = gst_element_get_pad (chain->sink, "sink");
|
||||
}
|
||||
chain->chain.sinkpad = gst_ghost_pad_new ("sink", pad);
|
||||
gst_object_unref (pad);
|
||||
gst_element_add_pad (chain->chain.bin, chain->chain.sinkpad);
|
||||
|
@ -1078,7 +1093,8 @@ gst_play_sink_set_mode (GstPlaySink * playsink, GstPlaySinkMode mode)
|
|||
{
|
||||
if (mode & GST_PLAY_SINK_MODE_AUDIO && playsink->audio_pad) {
|
||||
if (!playsink->audiochain)
|
||||
playsink->audiochain = gen_audio_chain (playsink);
|
||||
playsink->audiochain =
|
||||
gen_audio_chain (playsink, playsink->audio_pad_raw);
|
||||
add_chain (playsink->audiochain, TRUE);
|
||||
activate_chain (playsink->audiochain, TRUE);
|
||||
gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (playsink->audio_pad),
|
||||
|
@ -1094,7 +1110,8 @@ gst_play_sink_set_mode (GstPlaySink * playsink, GstPlaySinkMode mode)
|
|||
|
||||
if (mode & GST_PLAY_SINK_MODE_VIDEO && playsink->video_pad) {
|
||||
if (!playsink->videochain)
|
||||
playsink->videochain = gen_video_chain (playsink);
|
||||
playsink->videochain =
|
||||
gen_video_chain (playsink, playsink->video_pad_raw);
|
||||
add_chain (playsink->videochain, TRUE);
|
||||
activate_chain (playsink->videochain, TRUE);
|
||||
gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (playsink->video_pad),
|
||||
|
@ -1118,22 +1135,29 @@ gst_play_sink_request_pad (GstPlaySink * playsink, GstPlaySinkType type)
|
|||
{
|
||||
GstPad *res = NULL;
|
||||
gboolean created = FALSE;
|
||||
gboolean raw = FALSE;
|
||||
|
||||
switch (type) {
|
||||
case GST_PLAY_SINK_TYPE_AUDIO_RAW:
|
||||
raw = TRUE;
|
||||
case GST_PLAY_SINK_TYPE_AUDIO:
|
||||
if (!playsink->audio_pad) {
|
||||
playsink->audio_pad =
|
||||
gst_ghost_pad_new_no_target ("audio_sink", GST_PAD_SINK);
|
||||
created = TRUE;
|
||||
}
|
||||
playsink->audio_pad_raw = raw;
|
||||
res = playsink->audio_pad;
|
||||
break;
|
||||
case GST_PLAY_SINK_TYPE_VIDEO_RAW:
|
||||
raw = TRUE;
|
||||
case GST_PLAY_SINK_TYPE_VIDEO:
|
||||
if (!playsink->video_pad) {
|
||||
playsink->video_pad =
|
||||
gst_ghost_pad_new_no_target ("video_sink", GST_PAD_SINK);
|
||||
created = TRUE;
|
||||
}
|
||||
playsink->video_pad_raw = raw;
|
||||
res = playsink->video_pad;
|
||||
break;
|
||||
case GST_PLAY_SINK_TYPE_TEXT:
|
||||
|
|
|
@ -45,17 +45,30 @@ G_BEGIN_DECLS
|
|||
* Features to enable in the sink.
|
||||
*/
|
||||
typedef enum {
|
||||
GST_PLAY_SINK_MODE_VIDEO = (1 << 0),
|
||||
GST_PLAY_SINK_MODE_AUDIO = (1 << 1),
|
||||
GST_PLAY_SINK_MODE_TEXT = (1 << 2),
|
||||
GST_PLAY_SINK_MODE_VIS = (1 << 3)
|
||||
GST_PLAY_SINK_MODE_VIDEO = (1 << 0),
|
||||
GST_PLAY_SINK_MODE_AUDIO = (1 << 1),
|
||||
GST_PLAY_SINK_MODE_TEXT = (1 << 2),
|
||||
GST_PLAY_SINK_MODE_VIS = (1 << 3)
|
||||
} GstPlaySinkMode;
|
||||
|
||||
/**
|
||||
* GstPlaySinkType:
|
||||
* @GST_PLAY_SINK_TYPE_AUDIO: A non-raw audio pad
|
||||
* @GST_PLAY_SINK_TYPE_AUDIO_RAW: a raw audio pad
|
||||
* @GST_PLAY_SINK_TYPE_VIDEO: a non-raw video pad
|
||||
* @GST_PLAY_SINK_TYPE_VIDEO_RAW: a raw video pad
|
||||
* @GST_PLAY_SINK_TYPE_TEXT: a raw text pad
|
||||
* @GST_PLAY_SINK_TYPE_LAST: the last type
|
||||
*
|
||||
* Types of pads that can be requested from the sinks.
|
||||
*/
|
||||
typedef enum {
|
||||
GST_PLAY_SINK_TYPE_AUDIO = 0,
|
||||
GST_PLAY_SINK_TYPE_VIDEO = 1,
|
||||
GST_PLAY_SINK_TYPE_TEXT = 2,
|
||||
GST_PLAY_SINK_TYPE_LAST = 3
|
||||
GST_PLAY_SINK_TYPE_AUDIO = 0,
|
||||
GST_PLAY_SINK_TYPE_AUDIO_RAW = 1,
|
||||
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
|
||||
} GstPlaySinkType;
|
||||
|
||||
typedef struct _GstPlaySink GstPlaySink;
|
||||
|
@ -66,6 +79,10 @@ GType gst_play_sink_get_type (void);
|
|||
GstPad * gst_play_sink_request_pad (GstPlaySink *playsink, GstPlaySinkType type);
|
||||
void gst_play_sink_release_pad (GstPlaySink *playsink, GstPad *pad);
|
||||
|
||||
void gst_play_sink_set_video_sink (GstPlaySink * play_sink, GstElement * sink);
|
||||
void gst_play_sink_set_audio_sink (GstPlaySink * play_sink, GstElement * sink);
|
||||
void gst_play_sink_set_vis_plugin (GstPlaySink * play_sink, GstElement * vis);
|
||||
|
||||
GstPlaySinkMode gst_play_sink_get_mode (GstPlaySink *playsink);
|
||||
gboolean gst_play_sink_set_mode (GstPlaySink *playsink, GstPlaySinkMode mode);
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <gst/gst-i18n-plugin.h>
|
||||
|
||||
#include "gstplay-marshal.h"
|
||||
#include "gstplay-enum.h"
|
||||
|
||||
#define GST_TYPE_URI_DECODE_BIN \
|
||||
(gst_uri_decode_bin_get_type())
|
||||
|
@ -85,8 +86,8 @@ struct _GstURIDecodeBinClass
|
|||
GValueArray *(*autoplug_factories) (GstElement * element, GstPad * pad,
|
||||
GstCaps * caps);
|
||||
/* signal fired to select from the proposed list of factories */
|
||||
gint (*autoplug_select) (GstElement * element, GstPad * pad, GstCaps * caps,
|
||||
GValueArray * factories);
|
||||
GstAutoplugSelectResult (*autoplug_select) (GstElement * element,
|
||||
GstPad * pad, GstCaps * caps, GValueArray * factories);
|
||||
|
||||
/* emited when all data is decoded */
|
||||
void (*drained) (GstElement * element);
|
||||
|
@ -174,6 +175,32 @@ _gst_boolean_accumulator (GSignalInvocationHint * ihint,
|
|||
return myboolean;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_gst_array_accumulator (GSignalInvocationHint * ihint,
|
||||
GValue * return_accu, const GValue * handler_return, gpointer dummy)
|
||||
{
|
||||
gpointer array;
|
||||
|
||||
array = g_value_get_boxed (handler_return);
|
||||
if (!(ihint->run_type & G_SIGNAL_RUN_CLEANUP))
|
||||
g_value_set_boxed (return_accu, array);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_gst_select_accumulator (GSignalInvocationHint * ihint,
|
||||
GValue * return_accu, const GValue * handler_return, gpointer dummy)
|
||||
{
|
||||
GstAutoplugSelectResult res;
|
||||
|
||||
res = g_value_get_enum (handler_return);
|
||||
if (!(ihint->run_type & G_SIGNAL_RUN_CLEANUP))
|
||||
g_value_set_enum (return_accu, res);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_uri_decode_bin_autoplug_continue (GstElement * element, GstPad * pad,
|
||||
GstCaps * caps)
|
||||
|
@ -267,7 +294,7 @@ gst_uri_decode_bin_class_init (GstURIDecodeBinClass * klass)
|
|||
gst_uri_decode_bin_signals[SIGNAL_AUTOPLUG_FACTORIES] =
|
||||
g_signal_new ("autoplug-factories", G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstURIDecodeBinClass,
|
||||
autoplug_factories), NULL, NULL,
|
||||
autoplug_factories), _gst_array_accumulator, NULL,
|
||||
gst_play_marshal_BOXED__OBJECT_OBJECT, G_TYPE_VALUE_ARRAY, 2,
|
||||
GST_TYPE_PAD, GST_TYPE_CAPS);
|
||||
|
||||
|
@ -289,9 +316,10 @@ gst_uri_decode_bin_class_init (GstURIDecodeBinClass * klass)
|
|||
gst_uri_decode_bin_signals[SIGNAL_AUTOPLUG_SELECT] =
|
||||
g_signal_new ("autoplug-select", G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstURIDecodeBinClass,
|
||||
autoplug_select), NULL, NULL,
|
||||
gst_play_marshal_INT__OBJECT_OBJECT_BOXED, G_TYPE_INT, 3, GST_TYPE_PAD,
|
||||
GST_TYPE_CAPS, G_TYPE_VALUE_ARRAY);
|
||||
autoplug_select), _gst_select_accumulator, NULL,
|
||||
gst_play_marshal_ENUM__OBJECT_OBJECT_OBJECT,
|
||||
GST_TYPE_AUTOPLUG_SELECT_RESULT, 3, GST_TYPE_PAD, GST_TYPE_CAPS,
|
||||
GST_TYPE_ELEMENT_FACTORY);
|
||||
|
||||
/**
|
||||
* GstURIDecodeBin::drained:
|
||||
|
@ -871,14 +899,14 @@ proxy_autoplug_factories_signal (GstElement * element, GstPad * pad,
|
|||
return result;
|
||||
}
|
||||
|
||||
static gint
|
||||
static GstAutoplugSelectResult
|
||||
proxy_autoplug_select_signal (GstElement * element, GstPad * pad,
|
||||
GstCaps * caps, GValueArray * array, GstURIDecodeBin * dec)
|
||||
GstCaps * caps, GstElementFactory * factory, GstURIDecodeBin * dec)
|
||||
{
|
||||
gint result;
|
||||
GstAutoplugSelectResult result;
|
||||
|
||||
g_signal_emit (G_OBJECT (dec),
|
||||
gst_uri_decode_bin_signals[SIGNAL_AUTOPLUG_SELECT], 0, pad, caps, array,
|
||||
gst_uri_decode_bin_signals[SIGNAL_AUTOPLUG_SELECT], 0, pad, caps, factory,
|
||||
&result);
|
||||
|
||||
GST_DEBUG_OBJECT (dec, "autoplug-select returned %d", result);
|
||||
|
@ -1558,8 +1586,10 @@ setup_failed:
|
|||
}
|
||||
}
|
||||
|
||||
gboolean gst_decode_bin_plugin_init (GstPlugin * plugin);
|
||||
|
||||
static gboolean
|
||||
plugin_init (GstPlugin * plugin)
|
||||
gst_uri_decode_bin_plugin_init (GstPlugin * plugin)
|
||||
{
|
||||
GST_DEBUG_CATEGORY_INIT (gst_uri_decode_bin_debug, "uridecodebin", 0,
|
||||
"URI decoder element");
|
||||
|
@ -1574,6 +1604,17 @@ plugin_init (GstPlugin * plugin)
|
|||
GST_TYPE_URI_DECODE_BIN);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
plugin_init (GstPlugin * plugin)
|
||||
{
|
||||
if (!gst_decode_bin_plugin_init (plugin))
|
||||
return FALSE;
|
||||
if (!gst_uri_decode_bin_plugin_init (plugin))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
|
||||
GST_VERSION_MINOR,
|
||||
"uridecodebin",
|
||||
|
|
Loading…
Reference in a new issue