/* prepare will also lock the two pads */
result = gst_pad_link_prepare (srcpad, sinkpad, flags);
- if (G_UNLIKELY (result != GST_PAD_LINK_OK))
+ if (G_UNLIKELY (result != GST_PAD_LINK_OK)) {
+ GST_CAT_INFO (GST_CAT_PADS, "link between %s:%s and %s:%s failed: %s",
+ GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad),
+ gst_pad_link_get_name (result));
goto done;
+ }
/* must set peers before calling the link function */
GST_PAD_PEER (srcpad) = sinkpad;
{
GST_DEBUG_OBJECT (pad, "no parent");
GST_OBJECT_UNLOCK (pad);
- return FALSE;
+ return NULL;
}
}
* The EOS event will pause the task associated with @pad before it is forwarded
* to all internally linked pads,
*
- * The the event is sent to all pads internally linked to @pad. This function
+ * The event is sent to all pads internally linked to @pad. This function
* takes ownership of @event.
*
* Returns: %TRUE if the event was sent successfully.
return TRUE;
}
+/* Default latency implementation */
+typedef struct
+{
+ gboolean live;
+ GstClockTime min, max;
+} LatencyFoldData;
+
+static gboolean
+query_latency_default_fold (const GValue * item, GValue * ret,
+ gpointer user_data)
+{
+ GstPad *pad = g_value_get_object (item), *peer;
+ LatencyFoldData *fold_data = user_data;
+ GstQuery *query;
+ gboolean res = FALSE;
+
+ query = gst_query_new_latency ();
+
+ peer = gst_pad_get_peer (pad);
+ if (peer) {
+ res = gst_pad_peer_query (pad, query);
+ } else {
+ GST_LOG_OBJECT (pad, "No peer pad found, ignoring this pad");
+ }
+
+ if (res) {
+ gboolean live;
+ GstClockTime min, max;
+
+ gst_query_parse_latency (query, &live, &min, &max);
+
+ GST_LOG_OBJECT (pad, "got latency live:%s min:%" G_GINT64_FORMAT
+ " max:%" G_GINT64_FORMAT, live ? "true" : "false", min, max);
+
+ if (live) {
+ if (min > fold_data->min)
+ fold_data->min = min;
+
+ if (fold_data->max == GST_CLOCK_TIME_NONE)
+ fold_data->max = max;
+ else if (max < fold_data->max)
+ fold_data->max = max;
+
+ fold_data->live = TRUE;
+ }
+ } else if (peer) {
+ GST_DEBUG_OBJECT (pad, "latency query failed");
+ g_value_set_boolean (ret, FALSE);
+ }
+
+ gst_query_unref (query);
+ if (peer)
+ gst_object_unref (peer);
+
+ return TRUE;
+}
+
+static gboolean
+gst_pad_query_latency_default (GstPad * pad, GstQuery * query)
+{
+ GstIterator *it;
+ GstIteratorResult res;
+ GValue ret = G_VALUE_INIT;
+ gboolean query_ret;
+ LatencyFoldData fold_data;
+
+ it = gst_pad_iterate_internal_links (pad);
+ if (!it) {
+ GST_DEBUG_OBJECT (pad, "Can't iterate internal links");
+ return FALSE;
+ }
+
+ g_value_init (&ret, G_TYPE_BOOLEAN);
+
+retry:
+ fold_data.live = FALSE;
+ fold_data.min = 0;
+ fold_data.max = GST_CLOCK_TIME_NONE;
+
+ g_value_set_boolean (&ret, TRUE);
+ res = gst_iterator_fold (it, query_latency_default_fold, &ret, &fold_data);
+ switch (res) {
+ case GST_ITERATOR_OK:
+ g_assert_not_reached ();
+ break;
+ case GST_ITERATOR_DONE:
+ break;
+ case GST_ITERATOR_ERROR:
+ g_value_set_boolean (&ret, FALSE);
+ break;
+ case GST_ITERATOR_RESYNC:
+ gst_iterator_resync (it);
+ goto retry;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ gst_iterator_free (it);
+
+ query_ret = g_value_get_boolean (&ret);
+ if (query_ret) {
+ GST_LOG_OBJECT (pad, "got latency live:%s min:%" G_GINT64_FORMAT
+ " max:%" G_GINT64_FORMAT, fold_data.live ? "true" : "false",
+ fold_data.min, fold_data.max);
+
+ if (fold_data.min > fold_data.max) {
+ GST_ERROR_OBJECT (pad, "minimum latency bigger than maximum latency");
+ }
+
+ gst_query_set_latency (query, fold_data.live, fold_data.min, fold_data.max);
+ } else {
+ GST_LOG_OBJECT (pad, "latency query failed");
+ }
+
+ return query_ret;
+}
+
typedef struct
{
GstQuery *query;
ret = gst_pad_query_caps_default (pad, query);
forward = FALSE;
break;
+ case GST_QUERY_LATENCY:
+ ret = gst_pad_query_latency_default (pad, query);
+ forward = FALSE;
+ break;
case GST_QUERY_POSITION:
case GST_QUERY_SEEKING:
case GST_QUERY_FORMATS:
- case GST_QUERY_LATENCY:
case GST_QUERY_JITTER:
case GST_QUERY_RATE:
case GST_QUERY_CONVERT:
GstPadProbeType type, flags;
GstPadProbeCallback callback;
GstPadProbeReturn ret;
+ gpointer original_data;
/* if we have called this callback, do nothing */
if (PROBE_COOKIE (hook) == data->cookie) {
flags = hook->flags >> G_HOOK_FLAG_USER_SHIFT;
type = info->type;
+ original_data = info->data;
/* one of the data types for non-idle probes */
if ((type & GST_PAD_PROBE_TYPE_IDLE) == 0
GST_OBJECT_LOCK (pad);
+ if (original_data != NULL && info->data == NULL) {
+ GST_DEBUG_OBJECT (pad, "data item in pad probe info was dropped");
+ info->type = GST_PAD_PROBE_TYPE_INVALID;
+ data->dropped = TRUE;
+ }
+
switch (ret) {
case GST_PAD_PROBE_REMOVE:
/* remove the probe */
GstBuffer *buffer;
GstFlowReturn ret;
- GST_INFO_OBJECT (pad, "chaining each group in list as a merged buffer");
+ GST_INFO_OBJECT (pad, "chaining each buffer in list individually");
len = gst_buffer_list_length (list);
GST_OBJECT_UNLOCK (pad);
pad->ABI.abi.last_flowret =
ret == GST_FLOW_CUSTOM_SUCCESS ? GST_FLOW_OK : ret;
- gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
+ if (data != NULL)
+ gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
switch (ret) {
case GST_FLOW_CUSTOM_SUCCESS: