mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-24 02:31:03 +00:00
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:
parent
1450f0fb18
commit
686ad73bfe
5 changed files with 321 additions and 10 deletions
22
ChangeLog
22
ChangeLog
|
@ -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>
|
||||
|
||||
* configure.ac:
|
||||
|
|
|
@ -18,7 +18,9 @@ libgstplaybin_la_SOURCES = \
|
|||
nodist_libgstplaybin_la_SOURCES = $(built_sources)
|
||||
libgstplaybin_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS)
|
||||
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
|
||||
nodist_libgstdecodebin_la_SOURCES = $(built_sources)
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
#include "gststreamselector.h"
|
||||
#include "gstplay-marshal.h"
|
||||
|
||||
#include <gst/utils/base-utils.h>
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (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
|
||||
* UNKNOWN streaminfo object.
|
||||
|
@ -919,14 +942,28 @@ static void
|
|||
unknown_type (GstElement * element, GstPad * pad, GstCaps * caps,
|
||||
GstPlayBaseBin * play_base_bin)
|
||||
{
|
||||
gchar *capsstr;
|
||||
const gchar *type_name;
|
||||
GstStreamInfo *info;
|
||||
GstPlayBaseGroup *group;
|
||||
|
||||
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);
|
||||
type_name = gst_structure_get_name (gst_caps_get_structure (caps, 0));
|
||||
if (type_name && !IS_BLACKLISTED_MIME (type_name)) {
|
||||
GstMessage *msg;
|
||||
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);
|
||||
|
||||
|
@ -939,8 +976,6 @@ unknown_type (GstElement * element, GstPad * pad, GstCaps * caps,
|
|||
add_stream (group, info);
|
||||
|
||||
GROUP_UNLOCK (play_base_bin);
|
||||
|
||||
g_free (capsstr);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
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));
|
||||
g_free (prot);
|
||||
} else
|
||||
|
@ -1503,7 +1538,13 @@ no_source:
|
|||
/* whoops, could not create the source element, dig a little deeper to
|
||||
* figure out what might be wrong. */
|
||||
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));
|
||||
g_free (prot);
|
||||
} else
|
||||
|
|
|
@ -241,6 +241,7 @@
|
|||
#include <gst/gst.h>
|
||||
|
||||
#include <gst/gst-i18n-plugin.h>
|
||||
#include <gst/utils/base-utils.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_base_utils_init ();
|
||||
|
||||
#ifdef ENABLE_NLS
|
||||
GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
|
||||
LOCALEDIR);
|
||||
|
|
|
@ -161,6 +161,134 @@ GST_START_TEST (test_suburi_error_wrongproto)
|
|||
|
||||
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
|
||||
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
|
||||
plugin_init (GstPlugin * plugin)
|
||||
{
|
||||
|
@ -275,6 +506,10 @@ plugin_init (GstPlugin * plugin)
|
|||
gst_red_video_src_get_type ())) {
|
||||
return FALSE;
|
||||
}
|
||||
if (!gst_element_register (plugin, "codecsrc", GST_RANK_PRIMARY,
|
||||
gst_codec_src_get_type ())) {
|
||||
return FALSE;
|
||||
}
|
||||
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_invalidfile);
|
||||
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
|
||||
|
||||
return s;
|
||||
|
|
Loading…
Reference in a new issue