diff --git a/docs/faq/general.xml b/docs/faq/general.xml index 1e6641cf30..60e9b7ddcc 100644 --- a/docs/faq/general.xml +++ b/docs/faq/general.xml @@ -77,7 +77,7 @@ on the GStreamer project website. GStreamer aims to support every format imaginable, but that doesn't mean the developers have managed to achieve that aim yet. If a GStreamer enabled application doesn't play back your files, you can help us solve that problem -by filing an enhancement request +by filing an enhancement request bug for that format. If you have it, please provide: links to other players, preferrably Open Source and working diff --git a/gst/gstelement.h b/gst/gstelement.h index 7cf8fda72a..0fc81ad421 100644 --- a/gst/gstelement.h +++ b/gst/gstelement.h @@ -85,8 +85,8 @@ G_BEGIN_DECLS * cannot produce data in %GST_STATE_PAUSED. * This typically happens with live sources. * - * The possible return values from a state change function. Only - * @GST_STATE_CHANGE_FAILURE is a real failure. + * The possible return values from a state change function such as + * gst_element_set_state(). Only @GST_STATE_CHANGE_FAILURE is a real failure. */ typedef enum { GST_STATE_CHANGE_FAILURE = 0, @@ -195,17 +195,17 @@ typedef enum { * Streaming threads are started. * * - * Some elements might need to return ASYNC and complete the state change - * when they have enough information. It is a requirement for sinks to - * return ASYNC and complete the state change when they receive the first - * buffer or EOS event (preroll). Sinks also block the dataflow when in - * PAUSED. + * Some elements might need to return %GST_STATE_CHANGE_ASYNC and complete + * the state change when they have enough information. It is a requirement + * for sinks to return %GST_STATE_CHANGE_ASYNC and complete the state change + * when they receive the first buffer or %GST_EVENT_EOS (preroll). + * Sinks also block the dataflow when in PAUSED. * * * A pipeline resets the running_time to 0. * * - * Live sources return NO_PREROLL and don't generate data. + * Live sources return %GST_STATE_CHANGE_NO_PREROLL and don't generate data. * * * @GST_STATE_CHANGE_PAUSED_TO_PLAYING: state change from PAUSED to PLAYING. @@ -214,12 +214,12 @@ typedef enum { * Most elements ignore this state change. * * - * The pipeline selects a clock and distributes this to all the children + * The pipeline selects a #GstClock and distributes this to all the children * before setting them to PLAYING. This means that it is only alowed to - * synchronize on the clock in the PLAYING state. + * synchronize on the #GstClock in the PLAYING state. * * - * The pipeline uses the clock and the running_time to calculate the + * The pipeline uses the #GstClock and the running_time to calculate the * base_time. The base_time is distributed to all children when performing * the state change. * @@ -228,15 +228,15 @@ typedef enum { * rendering the data. * * - * Sinks can post the EOS message in the PLAYING state. It is not allowed to - * post EOS when not in the PLAYING state. + * Sinks can post %GST_MESSAGE_EOS in the PLAYING state. It is not allowed + * to post %GST_MESSAGE_EOS when not in the PLAYING state. * * * While streaming in PAUSED or PLAYING elements can create and remove * sometimes pads. * * - * Live sources start generating data and return SUCCESS. + * Live sources start generating data and return %GST_STATE_CHANGE_SUCCESS. * * * @GST_STATE_CHANGE_PLAYING_TO_PAUSED: state change from PLAYING to PAUSED. @@ -245,24 +245,25 @@ typedef enum { * Most elements ignore this state change. * * - * The pipeline calculates the running_time based on the last selected clock - * and the base_time. It stores this information to continue playback when - * going back to the PLAYING state. + * The pipeline calculates the running_time based on the last selected + * #GstClock and the base_time. It stores this information to continue + * playback when going back to the PLAYING state. * * - * Sinks unblock any clock wait calls. + * Sinks unblock any #GstClock wait calls. * * - * When a sink does not have a pending buffer to play, it returns ASYNC from - * this state change and completes the state change when it receives a new - * buffer or an EOS event. + * When a sink does not have a pending buffer to play, it returns + * %GST_STATE_CHANGE_ASYNC from this state change and completes the state + * change when it receives a new buffer or an %GST_EVENT_EOS. * * - * Any queued EOS messages are removed since they will be reposted when going - * back to the PLAYING state. The EOS messages are queued in GstBins. + * Any queued %GST_MESSAGE_EOS items are removed since they will be reposted + * when going back to the PLAYING state. The EOS messages are queued in + * #GstBin containers. * * - * Live sources stop generating data and return NO_PREROLL. + * Live sources stop generating data and return %GST_STATE_CHANGE_NO_PREROLL. * * * @GST_STATE_CHANGE_PAUSED_TO_READY : state change from PAUSED to READY. @@ -274,7 +275,7 @@ typedef enum { * Elements unblock any waits on devices * * - * Chain or get_range functions return WRONG_STATE. + * Chain or get_range functions return %GST_FLOW_WRONG_STATE. * * * The element pads are deactivated so that streaming becomes impossible and diff --git a/gst/gstmessage.h b/gst/gstmessage.h index 2b50558ad8..f529bf88d2 100644 --- a/gst/gstmessage.h +++ b/gst/gstmessage.h @@ -73,11 +73,11 @@ typedef struct _GstMessage GstMessage; * @GST_MESSAGE_SEGMENT_START posted a GST_MESSAGE_SEGMENT_DONE message. * @GST_MESSAGE_DURATION: The duration of a pipeline changed. The application * can get the new duration with a duration query. - * @GST_MESSAGE_ASYNC_START: Posted by elements when they start an ASYNC state - * change. This message is not forwarded to the application but is used + * @GST_MESSAGE_ASYNC_START: Posted by elements when they start an ASYNC + * #GstStateChange. This message is not forwarded to the application but is used * internally. Since: 0.10.13. - * @GST_MESSAGE_ASYNC_DONE: Posted by elements when they complete an ASYNC state - * change. The application will only receive this message from the toplevel + * @GST_MESSAGE_ASYNC_DONE: Posted by elements when they complete an ASYNC + * #GstStateChange. The application will only receive this message from the toplevel * pipeline. Since: 0.10.13 * @GST_MESSAGE_LATENCY: Posted by elements when their latency changes. The * application should recalculate and distribute a new latency. Since: 0.10.12 diff --git a/gst/gststructure.c b/gst/gststructure.c index a1b58a9ea0..d209b21655 100644 --- a/gst/gststructure.c +++ b/gst/gststructure.c @@ -3130,11 +3130,48 @@ gst_caps_structure_is_subset_field (GQuark field_id, const GValue * value, GstStructure *superset = user_data; GValue subtraction = { 0, }; const GValue *other; + GType ltype; if (!(other = gst_structure_id_get_value (superset, field_id))) /* field is missing in the superset => is subset */ return TRUE; + /* Special case: lists and scalar values + * "{ 1 }" and "1" subsets of each other + * but not strictly equal */ + ltype = gst_value_list_get_type (); + if (G_VALUE_HOLDS (other, ltype) && !G_VALUE_HOLDS (value, ltype)) { + const GValue *elt; + gint i, n; + gboolean all_equal = TRUE; + + n = gst_value_list_get_size (other); + for (i = 0; i < n; i++) { + elt = gst_value_list_get_value (other, 0); + if (gst_value_compare (elt, value) != GST_VALUE_EQUAL) { + all_equal = FALSE; + break; + } + } + if (all_equal) + return TRUE; + } else if (G_VALUE_HOLDS (value, ltype) && !G_VALUE_HOLDS (other, ltype)) { + const GValue *elt; + gint i, n; + gboolean all_equal = TRUE; + + n = gst_value_list_get_size (value); + for (i = 0; i < n; i++) { + elt = gst_value_list_get_value (value, 0); + if (gst_value_compare (elt, other) != GST_VALUE_EQUAL) { + all_equal = FALSE; + break; + } + } + if (all_equal) + return TRUE; + } + /* equal values are subset */ if (gst_value_compare (other, value) == GST_VALUE_EQUAL) return TRUE; diff --git a/tests/check/gst/gstcaps.c b/tests/check/gst/gstcaps.c index 2be03f533a..ab18800fec 100644 --- a/tests/check/gst/gstcaps.c +++ b/tests/check/gst/gstcaps.c @@ -346,6 +346,23 @@ GST_START_TEST (test_subset) fail_if (gst_caps_is_subset (c1, c2)); gst_caps_unref (c1); gst_caps_unref (c2); + + c1 = gst_caps_from_string ("audio/x-raw-int, channels=(int) {1}"); + c2 = gst_caps_from_string ("audio/x-raw-int, channels=(int)1"); + fail_unless (gst_caps_is_subset (c2, c1)); + fail_unless (gst_caps_is_subset (c1, c2)); + fail_unless (gst_caps_is_equal (c1, c2)); + gst_caps_unref (c1); + gst_caps_unref (c2); + + c1 = gst_caps_from_string + ("audio/x-raw-int, rate=(int)44100, channels=(int)3, endianness=(int)1234, width=(int)16, depth=(int)16, signed=(boolean)false"); + c2 = gst_caps_from_string + ("audio/x-raw-int, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], endianness=(int){ 1234, 4321 }, width=(int)16, depth=(int)[ 1, 16 ], signed=(boolean){ true, false }"); + fail_unless (gst_caps_is_subset (c1, c2)); + fail_if (gst_caps_is_subset (c2, c1)); + gst_caps_unref (c1); + gst_caps_unref (c2); } GST_END_TEST; diff --git a/tools/gst-launch.c b/tools/gst-launch.c index 1844f4df41..c224b0815c 100644 --- a/tools/gst-launch.c +++ b/tools/gst-launch.c @@ -330,6 +330,24 @@ print_index_stats (GPtrArray * index_stats) } } +/* Kids, use the functions from libgstpbutils in gst-plugins-base in your + * own code (we can't do that here because it would introduce a circular + * dependency) */ +static gboolean +gst_is_missing_plugin_message (GstMessage * msg) +{ + if (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_ELEMENT || msg->structure == NULL) + return FALSE; + + return gst_structure_has_name (msg->structure, "missing-plugin"); +} + +static const gchar * +gst_missing_plugin_message_get_description (GstMessage * msg) +{ + return gst_structure_get_string (msg->structure, "name"); +} + static void print_error_message (GstMessage * msg) { @@ -747,6 +765,16 @@ event_loop (GstElement * pipeline, gboolean blocking, GstState target_state) res = ELR_INTERRUPT; goto exit; } + break; + } + case GST_MESSAGE_ELEMENT:{ + if (gst_is_missing_plugin_message (message)) { + const gchar *desc; + + desc = gst_missing_plugin_message_get_description (message); + PRINT (_("Missing element: %s\n"), desc ? desc : "(no description)"); + } + break; } default: /* just be quiet by default */