gst/playback/: Post missing-plugin messages on the bus for missing sources and missing decoders/demuxers/depayloaders...

Original commit message from CVS:
* gst/playback/Makefile.am:
* gst/playback/gstplaybasebin.c: (string_arr_has_str),
(unknown_type), (setup_subtitle), (gen_source_element):
* gst/playback/gstplaybin.c: (plugin_init):
Post missing-plugin messages on the bus for missing sources and
missing decoders/demuxers/depayloaders; fix error code used when
we're missing an URI handler source; for media types that we are not
handling on purpose at the moment, don't print "don't know how to
handle xyz" messages to the terminal or post missing-plugin
messages on the bus.
* tests/check/elements/playbin.c: (create_playbin),
(GST_START_TEST), (gst_codec_src_uri_get_type),
(gst_codec_src_uri_get_protocols), (gst_codec_src_uri_get_uri),
(gst_codec_src_uri_set_uri), (gst_codec_src_uri_handler_init),
(gst_codec_src_init_type), (gst_codec_src_base_init),
(gst_codec_src_create), (gst_codec_src_class_init),
(gst_codec_src_init), (plugin_init), (playbin_suite):
Add some tests for the missing-plugin stuff.
This commit is contained in:
Tim-Philipp Müller 2007-01-09 14:33:24 +00:00
parent 1450f0fb18
commit 686ad73bfe
5 changed files with 321 additions and 10 deletions

View file

@ -1,3 +1,25 @@
2007-01-09 Tim-Philipp Müller <tim at centricular dot net>
* gst/playback/Makefile.am:
* gst/playback/gstplaybasebin.c: (string_arr_has_str),
(unknown_type), (setup_subtitle), (gen_source_element):
* gst/playback/gstplaybin.c: (plugin_init):
Post missing-plugin messages on the bus for missing sources and
missing decoders/demuxers/depayloaders; fix error code used when
we're missing an URI handler source; for media types that we are not
handling on purpose at the moment, don't print "don't know how to
handle xyz" messages to the terminal or post missing-plugin
messages on the bus.
* tests/check/elements/playbin.c: (create_playbin),
(GST_START_TEST), (gst_codec_src_uri_get_type),
(gst_codec_src_uri_get_protocols), (gst_codec_src_uri_get_uri),
(gst_codec_src_uri_set_uri), (gst_codec_src_uri_handler_init),
(gst_codec_src_init_type), (gst_codec_src_base_init),
(gst_codec_src_create), (gst_codec_src_class_init),
(gst_codec_src_init), (plugin_init), (playbin_suite):
Add some tests for the missing-plugin stuff.
2007-01-09 Tim-Philipp Müller <tim at centricular dot net> 2007-01-09 Tim-Philipp Müller <tim at centricular dot net>
* configure.ac: * configure.ac:

View file

@ -18,7 +18,9 @@ libgstplaybin_la_SOURCES = \
nodist_libgstplaybin_la_SOURCES = $(built_sources) nodist_libgstplaybin_la_SOURCES = $(built_sources)
libgstplaybin_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) libgstplaybin_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS)
libgstplaybin_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstplaybin_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstplaybin_la_LIBADD = $(GST_LIBS) libgstplaybin_la_LIBADD = \
$(top_builddir)/gst-libs/gst/utils/libgstbaseutils-@GST_MAJORMINOR@.la \
$(GST_LIBS)
libgstdecodebin_la_SOURCES = gstdecodebin.c libgstdecodebin_la_SOURCES = gstdecodebin.c
nodist_libgstdecodebin_la_SOURCES = $(built_sources) nodist_libgstdecodebin_la_SOURCES = $(built_sources)

View file

@ -27,6 +27,8 @@
#include "gststreamselector.h" #include "gststreamselector.h"
#include "gstplay-marshal.h" #include "gstplay-marshal.h"
#include <gst/utils/base-utils.h>
GST_DEBUG_CATEGORY_STATIC (gst_play_base_bin_debug); GST_DEBUG_CATEGORY_STATIC (gst_play_base_bin_debug);
#define GST_CAT_DEFAULT gst_play_base_bin_debug #define GST_CAT_DEFAULT gst_play_base_bin_debug
@ -911,6 +913,27 @@ add_stream (GstPlayBaseGroup * group, GstStreamInfo * info)
} }
} }
static gboolean
string_arr_has_str (const gchar * values[], const gchar * value)
{
if (values && value) {
while (*values != NULL) {
if (strcmp (value, *values) == 0)
return TRUE;
++values;
}
}
return FALSE;
}
/* mime types we are not handling on purpose right now, don't post a
* missing-plugin message for these */
static const gchar *blacklisted_mimes[] = {
"video/x-dvd-subpicture", NULL
};
#define IS_BLACKLISTED_MIME(type) (string_arr_has_str(blacklisted_mimes,type))
/* /*
* signal fired when an unknown stream is found. We create a new * signal fired when an unknown stream is found. We create a new
* UNKNOWN streaminfo object. * UNKNOWN streaminfo object.
@ -919,14 +942,28 @@ static void
unknown_type (GstElement * element, GstPad * pad, GstCaps * caps, unknown_type (GstElement * element, GstPad * pad, GstCaps * caps,
GstPlayBaseBin * play_base_bin) GstPlayBaseBin * play_base_bin)
{ {
gchar *capsstr; const gchar *type_name;
GstStreamInfo *info; GstStreamInfo *info;
GstPlayBaseGroup *group; GstPlayBaseGroup *group;
capsstr = gst_caps_to_string (caps); type_name = gst_structure_get_name (gst_caps_get_structure (caps, 0));
GST_DEBUG_OBJECT (play_base_bin, "don't know how to handle %s", capsstr); if (type_name && !IS_BLACKLISTED_MIME (type_name)) {
/* FIXME, g_message() ? */ GstMessage *msg;
g_message ("don't know how to handle %s", capsstr); gchar *capsstr;
capsstr = gst_caps_to_string (caps);
GST_DEBUG_OBJECT (play_base_bin, "don't know how to handle %s", capsstr);
/* FIXME, g_message() ? */
g_message ("don't know how to handle %s", capsstr);
g_free (capsstr);
msg = gst_missing_decoder_message_new (GST_ELEMENT (play_base_bin), caps);
gst_element_post_message (GST_ELEMENT_CAST (play_base_bin), msg);
} else {
/* don't spew stuff to the terminal or send message if it's blacklisted */
GST_DEBUG_OBJECT (play_base_bin, "media type %s not handled on purpose, "
"not posting a missing-plugin message on the bus", type_name);
}
GROUP_LOCK (play_base_bin); GROUP_LOCK (play_base_bin);
@ -939,8 +976,6 @@ unknown_type (GstElement * element, GstPad * pad, GstCaps * caps,
add_stream (group, info); add_stream (group, info);
GROUP_UNLOCK (play_base_bin); GROUP_UNLOCK (play_base_bin);
g_free (capsstr);
} }
/* add a streaminfo that indicates that the stream is handled by the /* add a streaminfo that indicates that the stream is handled by the
@ -1386,7 +1421,7 @@ unknown_uri:
gchar *prot = gst_uri_get_protocol (sub_uri); gchar *prot = gst_uri_get_protocol (sub_uri);
if (prot) { if (prot) {
GST_ELEMENT_ERROR (play_base_bin, RESOURCE, FAILED, GST_ELEMENT_ERROR (play_base_bin, CORE, MISSING_PLUGIN,
(_("No URI handler implemented for \"%s\"."), prot), (NULL)); (_("No URI handler implemented for \"%s\"."), prot), (NULL));
g_free (prot); g_free (prot);
} else } else
@ -1503,7 +1538,13 @@ no_source:
/* whoops, could not create the source element, dig a little deeper to /* whoops, could not create the source element, dig a little deeper to
* figure out what might be wrong. */ * figure out what might be wrong. */
if (prot) { if (prot) {
GST_ELEMENT_ERROR (play_base_bin, RESOURCE, FAILED, GstElement *this = GST_ELEMENT_CAST (play_base_bin);
GstMessage *msg;
msg = gst_missing_uri_source_message_new (this, prot);
gst_element_post_message (this, msg);
GST_ELEMENT_ERROR (play_base_bin, CORE, MISSING_PLUGIN,
(_("No URI handler implemented for \"%s\"."), prot), (NULL)); (_("No URI handler implemented for \"%s\"."), prot), (NULL));
g_free (prot); g_free (prot);
} else } else

View file

@ -241,6 +241,7 @@
#include <gst/gst.h> #include <gst/gst.h>
#include <gst/gst-i18n-plugin.h> #include <gst/gst-i18n-plugin.h>
#include <gst/utils/base-utils.h>
#include "gstplaybasebin.h" #include "gstplaybasebin.h"
@ -1879,6 +1880,8 @@ plugin_init (GstPlugin * plugin)
{ {
GST_DEBUG_CATEGORY_INIT (gst_play_bin_debug, "playbin", 0, "play bin"); GST_DEBUG_CATEGORY_INIT (gst_play_bin_debug, "playbin", 0, "play bin");
gst_base_utils_init ();
#ifdef ENABLE_NLS #ifdef ENABLE_NLS
GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE, GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
LOCALEDIR); LOCALEDIR);

View file

@ -161,6 +161,134 @@ GST_START_TEST (test_suburi_error_wrongproto)
GST_END_TEST; GST_END_TEST;
static GstElement *
create_playbin (const gchar * uri)
{
GstElement *playbin, *fakesink1, *fakesink2;
playbin = gst_element_factory_make ("playbin", "playbin");
fail_unless (playbin != NULL, "Failed to create playbin element");
fakesink1 = gst_element_factory_make ("fakesink", NULL);
fail_unless (fakesink1 != NULL, "Failed to create fakesink element #1");
fakesink2 = gst_element_factory_make ("fakesink", NULL);
fail_unless (fakesink2 != NULL, "Failed to create fakesink element #2");
/* make them behave like normal sinks, even if not needed for the test */
g_object_set (fakesink1, "sync", TRUE, NULL);
g_object_set (fakesink2, "sync", TRUE, NULL);
g_object_set (playbin, "video-sink", fakesink1, NULL);
g_object_set (playbin, "audio-sink", fakesink2, NULL);
g_object_set (playbin, "uri", uri, NULL);
return playbin;
}
GST_START_TEST (test_missing_urisource_handler)
{
GstStructure *s;
GstMessage *msg;
GstElement *playbin;
GError *err = NULL;
GstBus *bus;
playbin = create_playbin ("chocchipcookie://withahint.of/cinnamon");
fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_READY),
GST_STATE_CHANGE_SUCCESS);
fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_PAUSED),
GST_STATE_CHANGE_FAILURE);
/* there should be at least a missing-plugin message on the bus now and an
* error message; the missing-plugin message should be first */
bus = gst_element_get_bus (playbin);
msg = gst_bus_poll (bus, GST_MESSAGE_ELEMENT | GST_MESSAGE_ERROR, -1);
fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_ELEMENT);
fail_unless (msg->structure != NULL);
s = msg->structure;
fail_unless (gst_structure_has_name (s, "missing-plugin"));
fail_unless (gst_structure_has_field_typed (s, "detail", G_TYPE_STRING));
fail_unless_equals_string (gst_structure_get_string (s, "detail"),
"chocchipcookie");
fail_unless (gst_structure_has_field_typed (s, "type", G_TYPE_STRING));
fail_unless_equals_string (gst_structure_get_string (s, "type"), "urisource");
gst_message_unref (msg);
msg = gst_bus_poll (bus, GST_MESSAGE_ERROR, -1);
fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_ERROR);
/* make sure the error is a CORE MISSING_PLUGIN one */
gst_message_parse_error (msg, &err, NULL);
fail_unless (err != NULL);
fail_unless (err->domain == GST_CORE_ERROR, "error has wrong error domain "
"%s instead of core-error-quark", g_quark_to_string (err->domain));
fail_unless (err->code == GST_CORE_ERROR_MISSING_PLUGIN, "error has wrong "
"code %u instead of GST_CORE_ERROR_MISSING_PLUGIN", err->code);
g_error_free (err);
gst_message_unref (msg);
gst_object_unref (bus);
gst_element_set_state (playbin, GST_STATE_NULL);
gst_object_unref (playbin);
}
GST_END_TEST;
GST_START_TEST (test_missing_primary_decoder)
{
GstStructure *s;
GstMessage *msg;
GstElement *playbin;
GError *err = NULL;
GstBus *bus;
playbin = create_playbin ("codec://");
fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_READY),
GST_STATE_CHANGE_SUCCESS);
fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_PAUSED),
GST_STATE_CHANGE_ASYNC);
/* there should soon be at least a missing-plugin message on the bus and an
* error message; the missing-plugin message should be first */
bus = gst_element_get_bus (playbin);
msg = gst_bus_poll (bus, GST_MESSAGE_ELEMENT | GST_MESSAGE_ERROR, -1);
fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_ELEMENT);
fail_unless (msg->structure != NULL);
s = msg->structure;
fail_unless (gst_structure_has_name (s, "missing-plugin"));
fail_unless (gst_structure_has_field_typed (s, "type", G_TYPE_STRING));
fail_unless_equals_string (gst_structure_get_string (s, "type"), "decoder");
fail_unless (gst_structure_has_field_typed (s, "detail", GST_TYPE_CAPS));
gst_message_unref (msg);
msg = gst_bus_poll (bus, GST_MESSAGE_ERROR, -1);
fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_ERROR);
/* make sure the error is a STREAM CODEC_NOT_FOUND one */
gst_message_parse_error (msg, &err, NULL);
fail_unless (err != NULL);
fail_unless (err->domain == GST_STREAM_ERROR, "error has wrong error domain "
"%s instead of stream-error-quark", g_quark_to_string (err->domain));
fail_unless (err->code == GST_STREAM_ERROR_CODEC_NOT_FOUND, "error has wrong "
"code %u instead of GST_STREAM_ERROR_CODEC_NOT_FOUND", err->code);
g_error_free (err);
gst_message_unref (msg);
gst_object_unref (bus);
gst_element_set_state (playbin, GST_STATE_NULL);
gst_object_unref (playbin);
}
GST_END_TEST;
/*** redvideo:// source ***/
static guint static guint
gst_red_video_src_uri_get_type (void) gst_red_video_src_uri_get_type (void)
{ {
@ -268,6 +396,109 @@ gst_red_video_src_init (GstRedVideoSrc * src, GstRedVideoSrcClass * klass)
{ {
} }
/*** codec:// source ***/
static guint
gst_codec_src_uri_get_type (void)
{
return GST_URI_SRC;
}
static gchar **
gst_codec_src_uri_get_protocols (void)
{
static gchar *protocols[] = { "codec", NULL };
return protocols;
}
static const gchar *
gst_codec_src_uri_get_uri (GstURIHandler * handler)
{
return "codec://";
}
static gboolean
gst_codec_src_uri_set_uri (GstURIHandler * handler, const gchar * uri)
{
return (uri != NULL && g_str_has_prefix (uri, "codec:"));
}
static void
gst_codec_src_uri_handler_init (gpointer g_iface, gpointer iface_data)
{
GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
iface->get_type = gst_codec_src_uri_get_type;
iface->get_protocols = gst_codec_src_uri_get_protocols;
iface->get_uri = gst_codec_src_uri_get_uri;
iface->set_uri = gst_codec_src_uri_set_uri;
}
static void
gst_codec_src_init_type (GType type)
{
static const GInterfaceInfo uri_hdlr_info = {
gst_codec_src_uri_handler_init, NULL, NULL
};
g_type_add_interface_static (type, GST_TYPE_URI_HANDLER, &uri_hdlr_info);
}
#undef parent_class
#define parent_class codec_src_parent_class
typedef GstPushSrc GstCodecSrc;
typedef GstPushSrcClass GstCodecSrcClass;
GST_BOILERPLATE_FULL (GstCodecSrc, gst_codec_src, GstPushSrc,
GST_TYPE_PUSH_SRC, gst_codec_src_init_type);
static void
gst_codec_src_base_init (gpointer klass)
{
static const GstElementDetails details =
GST_ELEMENT_DETAILS ("Codec Src", "Source/Video", "yep", "me");
static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC, GST_PAD_ALWAYS,
GST_STATIC_CAPS ("application/x-codec")
);
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&src_templ));
gst_element_class_set_details (element_class, &details);
}
static GstFlowReturn
gst_codec_src_create (GstPushSrc * src, GstBuffer ** p_buf)
{
GstBuffer *buf;
GstCaps *caps;
buf = gst_buffer_new_and_alloc (20);
memset (GST_BUFFER_DATA (buf), 0, GST_BUFFER_SIZE (buf));
caps = gst_caps_new_simple ("application/x-codec", NULL);
gst_buffer_set_caps (buf, caps);
gst_caps_unref (caps);
*p_buf = buf;
return GST_FLOW_OK;
}
static void
gst_codec_src_class_init (GstCodecSrcClass * klass)
{
GstPushSrcClass *pushsrc_class = GST_PUSH_SRC_CLASS (klass);
pushsrc_class->create = gst_codec_src_create;
}
static void
gst_codec_src_init (GstCodecSrc * src, GstCodecSrcClass * klass)
{
}
static gboolean static gboolean
plugin_init (GstPlugin * plugin) plugin_init (GstPlugin * plugin)
{ {
@ -275,6 +506,10 @@ plugin_init (GstPlugin * plugin)
gst_red_video_src_get_type ())) { gst_red_video_src_get_type ())) {
return FALSE; return FALSE;
} }
if (!gst_element_register (plugin, "codecsrc", GST_RANK_PRIMARY,
gst_codec_src_get_type ())) {
return FALSE;
}
return TRUE; return TRUE;
} }
@ -300,6 +535,14 @@ playbin_suite (void)
tcase_add_test (tc_chain, test_suburi_error_wrongproto); tcase_add_test (tc_chain, test_suburi_error_wrongproto);
tcase_add_test (tc_chain, test_suburi_error_invalidfile); tcase_add_test (tc_chain, test_suburi_error_invalidfile);
tcase_add_test (tc_chain, test_suburi_error_unknowntype); tcase_add_test (tc_chain, test_suburi_error_unknowntype);
tcase_add_test (tc_chain, test_missing_urisource_handler);
tcase_add_test (tc_chain, test_missing_primary_decoder);
/* one day we might also want to have the following checks:
* tcase_add_test (tc_chain, test_missing_secondary_decoder_one_fatal);
* tcase_add_test (tc_chain, test_missing_secondary_decoder_two_fatal);
* tcase_add_test (tc_chain, test_missing_secondary_decoder_two_with_preroll);
*/
#endif #endif
return s; return s;